ember

11Error analysis

The run has 128 misses. Each card shows the evidence ember saw, the gold label and its rationale, ember's full answer, and what an agent following the kit would have done with it. Reviewers can use this section as the label-review queue.

What the kit does with the missMisses
deferred: treated as unsure76
acted on a wrong answer52

tag_assignment-code-tools-mcpvault: domain/tooling

Tag assignment · dev
Gold
The note calls for `domain/tooling`: Build, CI, observer, TTS pipeline, dev-time tools (True)
ember
The note has no reason to carry `domain/tooling` (False)
Signal
P(true) 0.29 (unsure)
Kit outcome
deferred: treated as unsure
Why this gold label
Mined from Code/Tools — mcpvault.md at 692f4bb58b7f62105aeb73fba8dfee12bfdecd53; gold is the note's own vocabulary tags.
Tools — mcpvault

The `@bitbonsai/mcpvault` MCP server provides agents with filesystem-based read/write access to the vault at `docs/vault/`, without requiring an Obsidian instance to be running. Configured via `opencode.json` at the repository root; invoked automatically by OpenCode at session start.

## Entry Point

```
npx -y @bitbonsai/mcpvault@0.11.0 {vault_absolute_path}
```

## Inputs

- Absolute filesystem path to `docs/vault/`
- MCP tool calls from the connected agent (via `opencode.json` MCP config block)

## Outputs

- Note content (read operations: `read_note`, `read_multiple_notes`, `search_notes`)
- Write confirmations (write/append: `write_note`, `append_to_note`, `patch_note`)
- Frontmatter updates (AST-aware: `update_frontmatter`, `manage_tags`)
- Vault structure (list: `list_vault`, `list_all_tags`)

## Dependencies

- Node.js ≥ 18.0.0 (invoked via `npx`; no global install required)
- `@bitbonsai/mcpvault` v0.11.0 (pinned; latest available as of 2026-04-21)

## Configuration

Configured in `opencode.json` at the repository root (project-local; additive relative to Concourse global config):

```json
{
  "mcp": {
    "obsidian": {
      "type": "local",
      "command": ["npx", "-y", "@bitbonsai/mcpvault@0.11.0", "/path/to/docs/vault"],
      "enabled": true
    }
  }
}
```

This does NOT interact with `.concourse.json` (Concourse's repo-profile hook for github/gdai-mcp-server/gdscript) — the two files serve different systems and are independent.

Does NOT ship in the game binary. Dev-time only.

## Key Tool Surface (15 tools)

| Tool | Purpose |
|------|---------|
| `read_note` | Read single note by path |
| `search_notes` | BM25 full-text search with frontmatter filters |
| `write_note` | Create note with YAML validation |
| `append_to_note` | Append content (backlinks, session logs) |
| `list_vault` | Enumerate vault files (orphan-check) |
| `update_frontmatter` | AST-aware field update (no field corruption) |
| `read_multiple_notes` | Batch read for context injection |
| `list_all_tags` | Enumerate all tags in vault |
| `manage_tags` | Add/remove tags without overwriting frontmatter |
| `patch_note` | Surgical section replacement |
| soft-delete | `trashMode` parameter — never use on session logs |

See `docs/vault/Specs/080 Agent Vault Knowledge Graph/contracts/mcp-tools.md` for the full tool surface contract.

## Agent Write Protocol

Agents MUST follow the write-back protocol in AGENTS.md (Vault Knowledge Graph section) before calling `write_note`. Key rules:

- All 9 required frontmatter fields must be populated before writing
- `related:` must contain ≥1 link resolving to a hub note in `Systems/`, `Design/`, or `Governance/`
- No inline code excerpts in note bodies
- Notes start at `status: draft`; agents may self-promote to `reviewed` (same session)

## MCP Selection Rationale

Selected over `revanp/obsidian-md-mcp` (disqualified: 6 tools, `write_note` passes raw strings with no frontmatter preservation — silent corruption risk). See `docs/vault/Specs/080 Agent Vault Knowledge Graph/research.md` R-001.

## Related

- [[Tools — Agent Skills & MCP]] — broader inventory of OpenCode skills and all MCP servers (mcpvault is one of four)
- [[Tools — Vault Audit]] — mechanical and semantic audit pipeline that complements the MCP write protocol
- [[Tools — Development Workbench]] — meta-architecture showing how mcpvault fits with personas, agents, and CI

Controlled tag vocabulary (as read):
type/*:
- `type/code` — Code architecture, autoloads, conventions, tooling. Carries `code-refs:`. (e.g. `Code/Autoloads — Disturbance.md`)
- `type/decision` — Architectural or design decision made by an agent during a session. Written to `docs/vault/Decisions/`. (Agent notes only — spec 080.)
- `type/design` — Design intent, player-facing concepts, world lore. (e.g. `Design/World Model.md`)
- `type/discovery` — Non-obvious constraint, gap, or conflict found by an agent during a session. Written to `docs/vault/Discoveries/`. (Agent notes only — spec 080.)
- `type/moc` — Map of Content at any of three tiers (folder / domain / concept). (e.g. `Audio.md`)
- `type/principle` — Governance and constitutional notes. Non-negotiable rules. (e.g. `Governance/Constitution.md`)
- `type/reference` — Glossary, decision log, open questions, epics. (e.g. `Reference/Glossary.md`)
- `type/session-log` — Session activity log; permanent audit trail. Written to `docs/vault/Sessions/`. Append-only, never pruned. (Agent notes only — spec 080.)
- `type/spec` — Spec document at `docs/vault/Specs/NNN Title/spec.md`. Carries `spec-refs:`. (e.g. `Specs/047 Car Radio/spec.md`)
- `type/system` — A bounded subsystem with implementation. Carries `code-refs`, `spec-refs`, `implements:` frontmatter. (e.g. `Systems/Audio — Car Radio.md`)
- `type/vision` — Strategic / vision-layer decision. Written to `docs/vault/Vision/`. Human-authored or agent-proposed with human ratification before promotion to `status: reviewed`. (Per triage #3 — spec 133 autonomous-company redesign.)
domain/*:
- `domain/anomalies` — Anomaly taxonomy, individual anomaly systems, spawn, behavior
- `domain/art` — Visual direction, palettes, references, asset pipeline
- `domain/audio` — Audio systems: world ambient, radio, transmissions, buses, pipeline
- `domain/autonomous-company` — Autonomous company v0.1 experiment: Slack infra, persona middleware, Letta integration, restart recovery
- `domain/build` — Build system, packaging, export, release automation
- `domain/governance` — Constitution, phased spec, policies
- `domain/infrastructure` — Infrastructure provisioning: CI/CD, hosting, deployment tooling, secrets management
- `domain/narrative` — Tone, horror register, forest transmissions narrative, Gary/KTLK
- `domain/player` — Player mode, input, controls, camera, exit/entry
- `domain/systems` — Cross-cutting system architecture and integration work
- `domain/tooling` — Build, CI, observer, TTS pipeline, dev-time tools
- `domain/vehicle` — The Samba: vehicle physics, dashboard, damage, panels
- `domain/world` — World model, biomes, terrain, procedural generation, weather
status/*:
- `status/canonical` — Fully authoritative; promoted by humans only. Highest trust. (Agent notes only — spec 080.)
- `status/draft` — Authoring in progress, not yet verified
- `status/reviewed` — Agent-created note verified against codebase within its creating session. Eligible for auto-injection in subsequent task dispatches. (Agent notes only — spec 080.)
- `status/stale` — Known out of date; cannot update immediately. Pairs with `> [!warning] STALE — needs update` callout.
- `status/superseded` — Replaced by another note. Terminal state. Pairs with `> [!warning] SUPERSEDED` callout.
- `status/wip` — Stable but under active revision
layer/*:
- `layer/content` — Content assets (audio, models, textures, audio provenance)
- `layer/gdext` — gdext wrapper layer (`rust/gdext-wrapper/`)
- `layer/gdscript` — GDScript (Godot scene-tier logic)
- `layer/infra` — Build, CI, deployment infrastructure
- `layer/python` — Python development tooling (`tools/`)
- `layer/rust-core` — Engine-agnostic Rust core (`rust/rust-core/`)
concept/*:
- `concept/biome` — Biome-reactive behavior across systems
- `concept/contamination` — Across-runs panel and garage degradation; the slow-horror mechanic that doesn't reset with the world
- `concept/diegetic` — Diegetic audio / UI / world-sourced design
- `concept/disturbance` — The disturbance mechanic thread (Article X)
- `concept/ephemeral-world` — Run-reset, transient worlds (Article IV Rules 6–7)
- `concept/governance` — Constitutional and governance concepts
- `concept/horror` — Horror register and dread design
- `concept/procedural` — Procedural generation, seed determinism
- `concept/rendering` — Visual rendering quality, shader correctness, Terrain3D integration, mesh fidelity, LOD, Z-fighting
- `concept/terrain` — Terrain generation, heightmap, Terrain3D regions, roughness, playability constraints
ember's answer for tag_assignment-code-tools-mcpvault, domain/toolingP(true) placed on the no, unsure, and yes zones.nounsureyesgold: yesP = 0.29

tag_assignment-code-tools-mcpvault: layer/infra

Tag assignment · dev
Gold
The note calls for `layer/infra`: Build, CI, deployment infrastructure (True)
ember
The note has no reason to carry `layer/infra` (False)
Signal
P(true) 0.06 (no)
Kit outcome
acted on a wrong answer
Why this gold label
Mined from Code/Tools — mcpvault.md at 692f4bb58b7f62105aeb73fba8dfee12bfdecd53; gold is the note's own vocabulary tags.
Tools — mcpvault

The `@bitbonsai/mcpvault` MCP server provides agents with filesystem-based read/write access to the vault at `docs/vault/`, without requiring an Obsidian instance to be running. Configured via `opencode.json` at the repository root; invoked automatically by OpenCode at session start.

## Entry Point

```
npx -y @bitbonsai/mcpvault@0.11.0 {vault_absolute_path}
```

## Inputs

- Absolute filesystem path to `docs/vault/`
- MCP tool calls from the connected agent (via `opencode.json` MCP config block)

## Outputs

- Note content (read operations: `read_note`, `read_multiple_notes`, `search_notes`)
- Write confirmations (write/append: `write_note`, `append_to_note`, `patch_note`)
- Frontmatter updates (AST-aware: `update_frontmatter`, `manage_tags`)
- Vault structure (list: `list_vault`, `list_all_tags`)

## Dependencies

- Node.js ≥ 18.0.0 (invoked via `npx`; no global install required)
- `@bitbonsai/mcpvault` v0.11.0 (pinned; latest available as of 2026-04-21)

## Configuration

Configured in `opencode.json` at the repository root (project-local; additive relative to Concourse global config):

```json
{
  "mcp": {
    "obsidian": {
      "type": "local",
      "command": ["npx", "-y", "@bitbonsai/mcpvault@0.11.0", "/path/to/docs/vault"],
      "enabled": true
    }
  }
}
```

This does NOT interact with `.concourse.json` (Concourse's repo-profile hook for github/gdai-mcp-server/gdscript) — the two files serve different systems and are independent.

Does NOT ship in the game binary. Dev-time only.

## Key Tool Surface (15 tools)

| Tool | Purpose |
|------|---------|
| `read_note` | Read single note by path |
| `search_notes` | BM25 full-text search with frontmatter filters |
| `write_note` | Create note with YAML validation |
| `append_to_note` | Append content (backlinks, session logs) |
| `list_vault` | Enumerate vault files (orphan-check) |
| `update_frontmatter` | AST-aware field update (no field corruption) |
| `read_multiple_notes` | Batch read for context injection |
| `list_all_tags` | Enumerate all tags in vault |
| `manage_tags` | Add/remove tags without overwriting frontmatter |
| `patch_note` | Surgical section replacement |
| soft-delete | `trashMode` parameter — never use on session logs |

See `docs/vault/Specs/080 Agent Vault Knowledge Graph/contracts/mcp-tools.md` for the full tool surface contract.

## Agent Write Protocol

Agents MUST follow the write-back protocol in AGENTS.md (Vault Knowledge Graph section) before calling `write_note`. Key rules:

- All 9 required frontmatter fields must be populated before writing
- `related:` must contain ≥1 link resolving to a hub note in `Systems/`, `Design/`, or `Governance/`
- No inline code excerpts in note bodies
- Notes start at `status: draft`; agents may self-promote to `reviewed` (same session)

## MCP Selection Rationale

Selected over `revanp/obsidian-md-mcp` (disqualified: 6 tools, `write_note` passes raw strings with no frontmatter preservation — silent corruption risk). See `docs/vault/Specs/080 Agent Vault Knowledge Graph/research.md` R-001.

## Related

- [[Tools — Agent Skills & MCP]] — broader inventory of OpenCode skills and all MCP servers (mcpvault is one of four)
- [[Tools — Vault Audit]] — mechanical and semantic audit pipeline that complements the MCP write protocol
- [[Tools — Development Workbench]] — meta-architecture showing how mcpvault fits with personas, agents, and CI

Controlled tag vocabulary (as read):
type/*:
- `type/code` — Code architecture, autoloads, conventions, tooling. Carries `code-refs:`. (e.g. `Code/Autoloads — Disturbance.md`)
- `type/decision` — Architectural or design decision made by an agent during a session. Written to `docs/vault/Decisions/`. (Agent notes only — spec 080.)
- `type/design` — Design intent, player-facing concepts, world lore. (e.g. `Design/World Model.md`)
- `type/discovery` — Non-obvious constraint, gap, or conflict found by an agent during a session. Written to `docs/vault/Discoveries/`. (Agent notes only — spec 080.)
- `type/moc` — Map of Content at any of three tiers (folder / domain / concept). (e.g. `Audio.md`)
- `type/principle` — Governance and constitutional notes. Non-negotiable rules. (e.g. `Governance/Constitution.md`)
- `type/reference` — Glossary, decision log, open questions, epics. (e.g. `Reference/Glossary.md`)
- `type/session-log` — Session activity log; permanent audit trail. Written to `docs/vault/Sessions/`. Append-only, never pruned. (Agent notes only — spec 080.)
- `type/spec` — Spec document at `docs/vault/Specs/NNN Title/spec.md`. Carries `spec-refs:`. (e.g. `Specs/047 Car Radio/spec.md`)
- `type/system` — A bounded subsystem with implementation. Carries `code-refs`, `spec-refs`, `implements:` frontmatter. (e.g. `Systems/Audio — Car Radio.md`)
- `type/vision` — Strategic / vision-layer decision. Written to `docs/vault/Vision/`. Human-authored or agent-proposed with human ratification before promotion to `status: reviewed`. (Per triage #3 — spec 133 autonomous-company redesign.)
domain/*:
- `domain/anomalies` — Anomaly taxonomy, individual anomaly systems, spawn, behavior
- `domain/art` — Visual direction, palettes, references, asset pipeline
- `domain/audio` — Audio systems: world ambient, radio, transmissions, buses, pipeline
- `domain/autonomous-company` — Autonomous company v0.1 experiment: Slack infra, persona middleware, Letta integration, restart recovery
- `domain/build` — Build system, packaging, export, release automation
- `domain/governance` — Constitution, phased spec, policies
- `domain/infrastructure` — Infrastructure provisioning: CI/CD, hosting, deployment tooling, secrets management
- `domain/narrative` — Tone, horror register, forest transmissions narrative, Gary/KTLK
- `domain/player` — Player mode, input, controls, camera, exit/entry
- `domain/systems` — Cross-cutting system architecture and integration work
- `domain/tooling` — Build, CI, observer, TTS pipeline, dev-time tools
- `domain/vehicle` — The Samba: vehicle physics, dashboard, damage, panels
- `domain/world` — World model, biomes, terrain, procedural generation, weather
status/*:
- `status/canonical` — Fully authoritative; promoted by humans only. Highest trust. (Agent notes only — spec 080.)
- `status/draft` — Authoring in progress, not yet verified
- `status/reviewed` — Agent-created note verified against codebase within its creating session. Eligible for auto-injection in subsequent task dispatches. (Agent notes only — spec 080.)
- `status/stale` — Known out of date; cannot update immediately. Pairs with `> [!warning] STALE — needs update` callout.
- `status/superseded` — Replaced by another note. Terminal state. Pairs with `> [!warning] SUPERSEDED` callout.
- `status/wip` — Stable but under active revision
layer/*:
- `layer/content` — Content assets (audio, models, textures, audio provenance)
- `layer/gdext` — gdext wrapper layer (`rust/gdext-wrapper/`)
- `layer/gdscript` — GDScript (Godot scene-tier logic)
- `layer/infra` — Build, CI, deployment infrastructure
- `layer/python` — Python development tooling (`tools/`)
- `layer/rust-core` — Engine-agnostic Rust core (`rust/rust-core/`)
concept/*:
- `concept/biome` — Biome-reactive behavior across systems
- `concept/contamination` — Across-runs panel and garage degradation; the slow-horror mechanic that doesn't reset with the world
- `concept/diegetic` — Diegetic audio / UI / world-sourced design
- `concept/disturbance` — The disturbance mechanic thread (Article X)
- `concept/ephemeral-world` — Run-reset, transient worlds (Article IV Rules 6–7)
- `concept/governance` — Constitutional and governance concepts
- `concept/horror` — Horror register and dread design
- `concept/procedural` — Procedural generation, seed determinism
- `concept/rendering` — Visual rendering quality, shader correctness, Terrain3D integration, mesh fidelity, LOD, Z-fighting
- `concept/terrain` — Terrain generation, heightmap, Terrain3D regions, roughness, playability constraints
ember's answer for tag_assignment-code-tools-mcpvault, layer/infraP(true) placed on the no, unsure, and yes zones.nounsureyesgold: yesP = 0.06

tag_assignment-code-tools-mcpvault: type/code

Tag assignment · dev
Gold
The note calls for `type/code`: Code architecture, autoloads, conventions, tooling. Carries `code-refs:`. (e.g. `Code/Autoloads — Disturbance.md`) (True)
ember
The note has no reason to carry `type/code` (False)
Signal
P(true) 0.15 (no)
Kit outcome
acted on a wrong answer
Why this gold label
Mined from Code/Tools — mcpvault.md at 692f4bb58b7f62105aeb73fba8dfee12bfdecd53; gold is the note's own vocabulary tags.
Tools — mcpvault

The `@bitbonsai/mcpvault` MCP server provides agents with filesystem-based read/write access to the vault at `docs/vault/`, without requiring an Obsidian instance to be running. Configured via `opencode.json` at the repository root; invoked automatically by OpenCode at session start.

## Entry Point

```
npx -y @bitbonsai/mcpvault@0.11.0 {vault_absolute_path}
```

## Inputs

- Absolute filesystem path to `docs/vault/`
- MCP tool calls from the connected agent (via `opencode.json` MCP config block)

## Outputs

- Note content (read operations: `read_note`, `read_multiple_notes`, `search_notes`)
- Write confirmations (write/append: `write_note`, `append_to_note`, `patch_note`)
- Frontmatter updates (AST-aware: `update_frontmatter`, `manage_tags`)
- Vault structure (list: `list_vault`, `list_all_tags`)

## Dependencies

- Node.js ≥ 18.0.0 (invoked via `npx`; no global install required)
- `@bitbonsai/mcpvault` v0.11.0 (pinned; latest available as of 2026-04-21)

## Configuration

Configured in `opencode.json` at the repository root (project-local; additive relative to Concourse global config):

```json
{
  "mcp": {
    "obsidian": {
      "type": "local",
      "command": ["npx", "-y", "@bitbonsai/mcpvault@0.11.0", "/path/to/docs/vault"],
      "enabled": true
    }
  }
}
```

This does NOT interact with `.concourse.json` (Concourse's repo-profile hook for github/gdai-mcp-server/gdscript) — the two files serve different systems and are independent.

Does NOT ship in the game binary. Dev-time only.

## Key Tool Surface (15 tools)

| Tool | Purpose |
|------|---------|
| `read_note` | Read single note by path |
| `search_notes` | BM25 full-text search with frontmatter filters |
| `write_note` | Create note with YAML validation |
| `append_to_note` | Append content (backlinks, session logs) |
| `list_vault` | Enumerate vault files (orphan-check) |
| `update_frontmatter` | AST-aware field update (no field corruption) |
| `read_multiple_notes` | Batch read for context injection |
| `list_all_tags` | Enumerate all tags in vault |
| `manage_tags` | Add/remove tags without overwriting frontmatter |
| `patch_note` | Surgical section replacement |
| soft-delete | `trashMode` parameter — never use on session logs |

See `docs/vault/Specs/080 Agent Vault Knowledge Graph/contracts/mcp-tools.md` for the full tool surface contract.

## Agent Write Protocol

Agents MUST follow the write-back protocol in AGENTS.md (Vault Knowledge Graph section) before calling `write_note`. Key rules:

- All 9 required frontmatter fields must be populated before writing
- `related:` must contain ≥1 link resolving to a hub note in `Systems/`, `Design/`, or `Governance/`
- No inline code excerpts in note bodies
- Notes start at `status: draft`; agents may self-promote to `reviewed` (same session)

## MCP Selection Rationale

Selected over `revanp/obsidian-md-mcp` (disqualified: 6 tools, `write_note` passes raw strings with no frontmatter preservation — silent corruption risk). See `docs/vault/Specs/080 Agent Vault Knowledge Graph/research.md` R-001.

## Related

- [[Tools — Agent Skills & MCP]] — broader inventory of OpenCode skills and all MCP servers (mcpvault is one of four)
- [[Tools — Vault Audit]] — mechanical and semantic audit pipeline that complements the MCP write protocol
- [[Tools — Development Workbench]] — meta-architecture showing how mcpvault fits with personas, agents, and CI

Controlled tag vocabulary (as read):
type/*:
- `type/code` — Code architecture, autoloads, conventions, tooling. Carries `code-refs:`. (e.g. `Code/Autoloads — Disturbance.md`)
- `type/decision` — Architectural or design decision made by an agent during a session. Written to `docs/vault/Decisions/`. (Agent notes only — spec 080.)
- `type/design` — Design intent, player-facing concepts, world lore. (e.g. `Design/World Model.md`)
- `type/discovery` — Non-obvious constraint, gap, or conflict found by an agent during a session. Written to `docs/vault/Discoveries/`. (Agent notes only — spec 080.)
- `type/moc` — Map of Content at any of three tiers (folder / domain / concept). (e.g. `Audio.md`)
- `type/principle` — Governance and constitutional notes. Non-negotiable rules. (e.g. `Governance/Constitution.md`)
- `type/reference` — Glossary, decision log, open questions, epics. (e.g. `Reference/Glossary.md`)
- `type/session-log` — Session activity log; permanent audit trail. Written to `docs/vault/Sessions/`. Append-only, never pruned. (Agent notes only — spec 080.)
- `type/spec` — Spec document at `docs/vault/Specs/NNN Title/spec.md`. Carries `spec-refs:`. (e.g. `Specs/047 Car Radio/spec.md`)
- `type/system` — A bounded subsystem with implementation. Carries `code-refs`, `spec-refs`, `implements:` frontmatter. (e.g. `Systems/Audio — Car Radio.md`)
- `type/vision` — Strategic / vision-layer decision. Written to `docs/vault/Vision/`. Human-authored or agent-proposed with human ratification before promotion to `status: reviewed`. (Per triage #3 — spec 133 autonomous-company redesign.)
domain/*:
- `domain/anomalies` — Anomaly taxonomy, individual anomaly systems, spawn, behavior
- `domain/art` — Visual direction, palettes, references, asset pipeline
- `domain/audio` — Audio systems: world ambient, radio, transmissions, buses, pipeline
- `domain/autonomous-company` — Autonomous company v0.1 experiment: Slack infra, persona middleware, Letta integration, restart recovery
- `domain/build` — Build system, packaging, export, release automation
- `domain/governance` — Constitution, phased spec, policies
- `domain/infrastructure` — Infrastructure provisioning: CI/CD, hosting, deployment tooling, secrets management
- `domain/narrative` — Tone, horror register, forest transmissions narrative, Gary/KTLK
- `domain/player` — Player mode, input, controls, camera, exit/entry
- `domain/systems` — Cross-cutting system architecture and integration work
- `domain/tooling` — Build, CI, observer, TTS pipeline, dev-time tools
- `domain/vehicle` — The Samba: vehicle physics, dashboard, damage, panels
- `domain/world` — World model, biomes, terrain, procedural generation, weather
status/*:
- `status/canonical` — Fully authoritative; promoted by humans only. Highest trust. (Agent notes only — spec 080.)
- `status/draft` — Authoring in progress, not yet verified
- `status/reviewed` — Agent-created note verified against codebase within its creating session. Eligible for auto-injection in subsequent task dispatches. (Agent notes only — spec 080.)
- `status/stale` — Known out of date; cannot update immediately. Pairs with `> [!warning] STALE — needs update` callout.
- `status/superseded` — Replaced by another note. Terminal state. Pairs with `> [!warning] SUPERSEDED` callout.
- `status/wip` — Stable but under active revision
layer/*:
- `layer/content` — Content assets (audio, models, textures, audio provenance)
- `layer/gdext` — gdext wrapper layer (`rust/gdext-wrapper/`)
- `layer/gdscript` — GDScript (Godot scene-tier logic)
- `layer/infra` — Build, CI, deployment infrastructure
- `layer/python` — Python development tooling (`tools/`)
- `layer/rust-core` — Engine-agnostic Rust core (`rust/rust-core/`)
concept/*:
- `concept/biome` — Biome-reactive behavior across systems
- `concept/contamination` — Across-runs panel and garage degradation; the slow-horror mechanic that doesn't reset with the world
- `concept/diegetic` — Diegetic audio / UI / world-sourced design
- `concept/disturbance` — The disturbance mechanic thread (Article X)
- `concept/ephemeral-world` — Run-reset, transient worlds (Article IV Rules 6–7)
- `concept/governance` — Constitutional and governance concepts
- `concept/horror` — Horror register and dread design
- `concept/procedural` — Procedural generation, seed determinism
- `concept/rendering` — Visual rendering quality, shader correctness, Terrain3D integration, mesh fidelity, LOD, Z-fighting
- `concept/terrain` — Terrain generation, heightmap, Terrain3D regions, roughness, playability constraints
ember's answer for tag_assignment-code-tools-mcpvault, type/codeP(true) placed on the no, unsure, and yes zones.nounsureyesgold: yesP = 0.15

tag_assignment-design-horror-register: type/design

Tag assignment · test
Gold
The note calls for `type/design`: Design intent, player-facing concepts, world lore. (e.g. `Design/World Model.md`) (True)
ember
The note has no reason to carry `type/design` (False)
Signal
P(true) 0.44 (unsure)
Kit outcome
deferred: treated as unsure
Why this gold label
Mined from Design/Horror Register.md at 692f4bb58b7f62105aeb73fba8dfee12bfdecd53; gold is the note's own vocabulary tags.
Horror Register

The operational vocabulary for evaluating whether a design choice, visual asset, sound, or interaction belongs in Old Growth. The Horror Register defines what is *in* and what is *out* — used as a filter at every phase of production.

This note is the checklist companion to [[Design/Tone and Horror]], which contains the full philosophical grounding, three horror pillars, and film lineage. Read that note first.

## In Register

These are valid in Old Growth:

- **Dread before revelation** — the feeling of wrongness before anything has happened
- **Environmental hostility** — the forest registers the player's presence; it does not react, it accumulates
- **Material horror** — biological, geological, ancient; never supernatural in the conventional sense
- **Indifference** — the threat does not want the player dead; it does not want anything
- **Wrong-but-almost-natural** — anomalies that are uncanny, not impossible; disturbing because they *almost* fit
- **Sanctuary contrast** — the bus is safe, the outside is not; this contrast is load-bearing
- **Diegetic unease** — all feedback through the world itself (dashboard, audio, road feel); no HUD screaming
- **Accumulation** — disturbance, contamination, degradation build across time without announcement
- **Scale** — the forest is older than roads; the player's presence is trivially small

## Out of Register

These break the tone and must be avoided:

- **Jump scares as primary tool** — habituate within minutes; structural horror does not rely on them
- **Legible monster** — anything with a personality, a motive, or legible anger becomes manageable
- **Gore-as-shock** — visceral imagery deployed for disgust or instant reaction is out of register; biological horror that is *wrong-beautiful* (contamination, calcification, spore film) is within the "Flesh as Horror" pillar and is valid
- **Narrative exposition** — the forest is never explained; characters do not describe what it is
- **Defeat** — the condition cannot be mastered; any design implying "beat the forest" breaks the thesis
- **Cartoon or anime aesthetic** — visual direction is painterly Pacific Northwest, editorial documentary
- **Comedy or irony** — the game takes itself seriously; no winking at the player
- **Combat as solution** — on foot the player has no tools that change outcomes; a thrown rock is noise displaced elsewhere, a flare redirects attention, found firearms are empty or corroded; any mechanic implying the condition can be fought breaks the thesis

## Application

When evaluating a new feature, asset, or interaction:

1. Does it reinforce dread or does it release tension prematurely?
2. Does it make the threat feel more indifferent or more intentional?
3. Does it make the bus feel safer or erode sanctuary?
4. Does it fit the "wrong-but-almost-natural" uncanny register?

If a design choice fails two or more of these, reconsider before implementing.

## Related

- [[Design/Tone and Horror]] — the full horror taxonomy, three pillars, film lineage, directorial discipline
- [[Design/Core Mechanics]] — how horror register maps to mechanical design
- [[Systems/Disturbance]] — the primary accumulation mechanic
- [[The Disturbance Thread]] — how the mechanics express the horror

Controlled tag vocabulary (as read):
type/*:
- `type/code` — Code architecture, autoloads, conventions, tooling. Carries `code-refs:`. (e.g. `Code/Autoloads — Disturbance.md`)
- `type/decision` — Architectural or design decision made by an agent during a session. Written to `docs/vault/Decisions/`. (Agent notes only — spec 080.)
- `type/design` — Design intent, player-facing concepts, world lore. (e.g. `Design/World Model.md`)
- `type/discovery` — Non-obvious constraint, gap, or conflict found by an agent during a session. Written to `docs/vault/Discoveries/`. (Agent notes only — spec 080.)
- `type/moc` — Map of Content at any of three tiers (folder / domain / concept). (e.g. `Audio.md`)
- `type/principle` — Governance and constitutional notes. Non-negotiable rules. (e.g. `Governance/Constitution.md`)
- `type/reference` — Glossary, decision log, open questions, epics. (e.g. `Reference/Glossary.md`)
- `type/session-log` — Session activity log; permanent audit trail. Written to `docs/vault/Sessions/`. Append-only, never pruned. (Agent notes only — spec 080.)
- `type/spec` — Spec document at `docs/vault/Specs/NNN Title/spec.md`. Carries `spec-refs:`. (e.g. `Specs/047 Car Radio/spec.md`)
- `type/system` — A bounded subsystem with implementation. Carries `code-refs`, `spec-refs`, `implements:` frontmatter. (e.g. `Systems/Audio — Car Radio.md`)
- `type/vision` — Strategic / vision-layer decision. Written to `docs/vault/Vision/`. Human-authored or agent-proposed with human ratification before promotion to `status: reviewed`. (Per triage #3 — spec 133 autonomous-company redesign.)
domain/*:
- `domain/anomalies` — Anomaly taxonomy, individual anomaly systems, spawn, behavior
- `domain/art` — Visual direction, palettes, references, asset pipeline
- `domain/audio` — Audio systems: world ambient, radio, transmissions, buses, pipeline
- `domain/autonomous-company` — Autonomous company v0.1 experiment: Slack infra, persona middleware, Letta integration, restart recovery
- `domain/build` — Build system, packaging, export, release automation
- `domain/governance` — Constitution, phased spec, policies
- `domain/infrastructure` — Infrastructure provisioning: CI/CD, hosting, deployment tooling, secrets management
- `domain/narrative` — Tone, horror register, forest transmissions narrative, Gary/KTLK
- `domain/player` — Player mode, input, controls, camera, exit/entry
- `domain/systems` — Cross-cutting system architecture and integration work
- `domain/tooling` — Build, CI, observer, TTS pipeline, dev-time tools
- `domain/vehicle` — The Samba: vehicle physics, dashboard, damage, panels
- `domain/world` — World model, biomes, terrain, procedural generation, weather
status/*:
- `status/canonical` — Fully authoritative; promoted by humans only. Highest trust. (Agent notes only — spec 080.)
- `status/draft` — Authoring in progress, not yet verified
- `status/reviewed` — Agent-created note verified against codebase within its creating session. Eligible for auto-injection in subsequent task dispatches. (Agent notes only — spec 080.)
- `status/stale` — Known out of date; cannot update immediately. Pairs with `> [!warning] STALE — needs update` callout.
- `status/superseded` — Replaced by another note. Terminal state. Pairs with `> [!warning] SUPERSEDED` callout.
- `status/wip` — Stable but under active revision
layer/*:
- `layer/content` — Content assets (audio, models, textures, audio provenance)
- `layer/gdext` — gdext wrapper layer (`rust/gdext-wrapper/`)
- `layer/gdscript` — GDScript (Godot scene-tier logic)
- `layer/infra` — Build, CI, deployment infrastructure
- `layer/python` — Python development tooling (`tools/`)
- `layer/rust-core` — Engine-agnostic Rust core (`rust/rust-core/`)
concept/*:
- `concept/biome` — Biome-reactive behavior across systems
- `concept/contamination` — Across-runs panel and garage degradation; the slow-horror mechanic that doesn't reset with the world
- `concept/diegetic` — Diegetic audio / UI / world-sourced design
- `concept/disturbance` — The disturbance mechanic thread (Article X)
- `concept/ephemeral-world` — Run-reset, transient worlds (Article IV Rules 6–7)
- `concept/governance` — Constitutional and governance concepts
- `concept/horror` — Horror register and dread design
- `concept/procedural` — Procedural generation, seed determinism
- `concept/rendering` — Visual rendering quality, shader correctness, Terrain3D integration, mesh fidelity, LOD, Z-fighting
- `concept/terrain` — Terrain generation, heightmap, Terrain3D regions, roughness, playability constraints
ember's answer for tag_assignment-design-horror-register, type/designP(true) placed on the no, unsure, and yes zones.nounsureyesgold: yesP = 0.44

tag_assignment-governance-tech-stack-review: domain/governance

Tag assignment · dev
Gold
The note calls for `domain/governance`: Constitution, phased spec, policies (True)
ember
The note has no reason to carry `domain/governance` (False)
Signal
P(true) 0.30 (unsure)
Kit outcome
deferred: treated as unsure
Why this gold label
Mined from Governance/Tech Stack Review.md at 692f4bb58b7f62105aeb73fba8dfee12bfdecd53; gold is the note's own vocabulary tags.
Tech Stack Review

The technology stack decisions for Old Growth — what was chosen, what was evaluated and rejected, and where the open risks are. The authoritative approved stack lives in constitution Appendix A; this note captures the *why* behind each decision.

## Overview

Old Growth's stack is deliberately conservative where possible and opinionated where necessary. The engine and scripting language are locked by constitution (Article III). Vehicle physics, terrain, procedural generation, and audio are locked with strong alternative-assessment. A handful of visual effects and content questions remain open.

**Status legend:**
- 🟢 **Locked** — researched, tested compatibility, no meaningful alternative
- 🟡 **Strong lean** — best option found but alternatives exist worth discussing
- 🟠 **Open** — decision made but could reasonably go another way
- 🔴 **Unresolved** — no decision yet or significant uncertainty

## Key Decisions — Core Stack (all 🟢)

| System | Pick | Why |
|--------|------|-----|
| Game engine | Godot 4.6+ | Native Metal renderer, plaintext GDScript (agent-readable), MIT, Jolt built-in, strong macOS export |
| Scripting | GDScript + Rust (gdext) | GDScript for scene glue; Rust for performance-critical (Article III Rule 17) |
| Physics | Jolt (native in 4.6+) | More stable vehicle sim than Godot Physics; GEVP-compatible |
| Target platform | macOS Universal Binary | Scope constraint; Apple Silicon (Metal) + Intel Macs |
| Physics tick | 120 Hz | GEVP requires 120+; 60 causes instability; 240 is unnecessary |

## Vehicle Physics

- **Vehicle controller**: GEVP (vendored in `addons/`, MIT). Raycast-based, keyboard-friendly, single-script, simcade preset. Needs tuning for 1963 VW Samba feel (rear-engine RWD, ~1100 kg, ~50 HP, high CoG, soft suspension, long braking distances).
- **Engine audio**: Pitch-scaled `AudioStreamPlayer3D` loops (🟠). Simplest approach; may upgrade to multi-sample crossfade in audio polish.

## Terrain & Roads

- **Terrain system**: Terrain3D (C++ GDExtension, MIT). GPU clipmap, foliage instancer, 32 textures, Road Generator connector.
- **Road generation**: Godot Road Generator (🟡). Designed for hand-placed roads; procedural usage is supported but less documented. **Technical risk for spec 053 remediation.**
- **Foliage**: Terrain3D built-in instancer (🟡). Must handle biome-specific vegetation swaps.
- **Heightmap**: FastNoiseLite (Godot built-in). Sufficient for ~2km² worlds.

## Weather & Atmosphere

- Rain-on-Glass shader (🟡), custom wiper integration (🟠)
- Volumetric fog: Godot 4 built-in (🟢)
- Sky: ProceduralSkyMaterial (🟡) — must produce three distinct biome sky feels
- Weather zones: Voronoi/grid subdivision (🟡, novel system)

## Visual Effects & Post-Processing

- Post-processing: ArseniyMirniy Color Correction (🟢, vendored)
- Windshield crack overlay (🟠), Storm wall shader (🟠), biome transition blending (🟡)

## Anomaly Systems

Most anomalies use standard Godot primitives (AnimationPlayer, Area3D, GPUParticles3D, OmniLight3D, MeshInstance3D). See [[Anomalies]] for design specifications; tech choices here are typically 🟢 Locked.

## Audio

- **Audio management**: Godot native (🟢). Sound Manager (nathanhoad) evaluated and rejected (insufficient — no AudioStreamPlayer3D, no AudioEffect manipulation, ambient pool limited to 1 stream).
- **Bus architecture**: 7 buses planned per constitution Appendix A (Master → Ambience, Proximity, Interior, Horror, Radio, RadioDegraded). Currently only Master + Radio + RadioDegraded exist in `src/default_bus_layout.tres`; the remaining buses are being built incrementally through the audio specs. See [[Audio — Overview]] for the CONFLICT callout and [[Conflicts]] for the indexed entry.
- **Positional**: `AudioStreamPlayer3D` built-in (🟢)

## On-Foot Systems

- CharacterBody3D + custom FPS controller (🟡)
- Car entry/exit: custom camera reparent + input context switch (🟠) — **highest-risk custom system**, ~200 lines
- Combat: melee raycast + ranged hitscan/projectile (🟢) — per Article II, on-foot scope is strictly bounded
- Enemy AI: StateMachine + NavigationAgent3D (🟡) — **must verify NavMesh bakes on Terrain3D at runtime**

## Disturbance & Storm

- Disturbance meter: autoload with add(amount, source) + threshold signals (🟢, matches Article X)
- Disturbance HUD: organic visual indicator (🟠, creative risk)
- Storm wall direction: spawn opposite nearest exit, advance toward player (🟢)

## Persistence & Architecture

- **Save**: Godot Resource serialization (`.tres`) (🟡). World state NOT saved — only garage/player state (Article IV Rule 6).
- **Settings**: `ConfigFile` at `user://settings.cfg` (🟢)
- **Cross-system communication**: Signal bus autoload (`events.gd`) (🟢, Article VI)
- **Game state**: `GameState` autoload + enum states (🟡)

## Assets & Pipeline

- **3D format**: glTF 2.0 (.glb) (🟢)
- **VW Samba model**: Placeholder (Kenney) → custom/purchased (🟠). No perfect free 1963 VW Type 2 Samba (23-window, V-nose, two-tone, curved skylight).
- **PBR textures**: CC0 (ambientCG, cgbookcase, Polyhaven) (🟢)
- **Audio assets**: CC0 (Freesound, OpenGameArt, Kenney) (🟡) — fungal/stone SFX may need original recording
- **Radio music**: 🔴 UNRESOLVED. Need 30+ min across multiple genres. CC0 music is rare; AI-generated is an option; doesn't block until audio polish phase.

## macOS Packaging

- Code signing: Apple Developer ID ($99/yr) or ad-hoc (🟠)
- Distribution: DMG with drag-to-Applications (🟢)
- Game controller: Godot GameController built-in (🟢)

## Highest-Risk Open Questions

The source doc identifies six items as the highest technical risks:

1. **Procedural road algorithm** — connected road network from a seed over ~2km² (spec 053)
2. **NavMesh on Terrain3D** — does NavigationAgent3D bake reliably? If not, fall back to raycast steering.
3. **Biome texture swap in Terrain3D** — texture-set-per-region capability
4. **World generation performance** — ~2km² world in <5 seconds on M4 Max (Article V)
5. **Petrified Zone screen-space shader** — selective desaturation of meshes in a 3D area without affecting HUD
6. **Storm wall directional shader** — dramatic shader for an advancing flat plane

## Summary Counts (per source)

- **🟢 Locked**: 26 decisions
- **🟡 Strong lean**: 15 decisions
- **🟠 Open**: 8 decisions
- **🔴 Unresolved**: 1 decision (radio music content)

## Related

- [[Constitution]] — Article III and Appendix A are the authoritative source
- [[Component SemVer Policy]] — how these components are versioned
- [[Governance]] — folder MOC
- [[Build System]] — the CI pipeline that enforces these choices

## Agent Notes (backlinks)

- [[Decisions/Rust-GDScript Split Architecture]] — Rust/GDScript split decision with operational constraints
- [[Audio Generation Pipeline Constraints & Patterns]] — TTS engine selection, Python 3.11 requirement, provenance schema, ElevenLabs SFX V2 pipeline
- [[Vault Tooling — Constraints and Patterns]] — vault audit, Observer QA, asset export safety
- Vault Tooling — Constraints and Patterns — vault audit, asset export, Observer QA, development constraints

Controlled tag vocabulary (as read):
type/*:
- `type/code` — Code architecture, autoloads, conventions, tooling. Carries `code-refs:`. (e.g. `Code/Autoloads — Disturbance.md`)
- `type/decision` — Architectural or design decision made by an agent during a session. Written to `docs/vault/Decisions/`. (Agent notes only — spec 080.)
- `type/design` — Design intent, player-facing concepts, world lore. (e.g. `Design/World Model.md`)
- `type/discovery` — Non-obvious constraint, gap, or conflict found by an agent during a session. Written to `docs/vault/Discoveries/`. (Agent notes only — spec 080.)
- `type/moc` — Map of Content at any of three tiers (folder / domain / concept). (e.g. `Audio.md`)
- `type/principle` — Governance and constitutional notes. Non-negotiable rules. (e.g. `Governance/Constitution.md`)
- `type/reference` — Glossary, decision log, open questions, epics. (e.g. `Reference/Glossary.md`)
- `type/session-log` — Session activity log; permanent audit trail. Written to `docs/vault/Sessions/`. Append-only, never pruned. (Agent notes only — spec 080.)
- `type/spec` — Spec document at `docs/vault/Specs/NNN Title/spec.md`. Carries `spec-refs:`. (e.g. `Specs/047 Car Radio/spec.md`)
- `type/system` — A bounded subsystem with implementation. Carries `code-refs`, `spec-refs`, `implements:` frontmatter. (e.g. `Systems/Audio — Car Radio.md`)
- `type/vision` — Strategic / vision-layer decision. Written to `docs/vault/Vision/`. Human-authored or agent-proposed with human ratification before promotion to `status: reviewed`. (Per triage #3 — spec 133 autonomous-company redesign.)
domain/*:
- `domain/anomalies` — Anomaly taxonomy, individual anomaly systems, spawn, behavior
- `domain/art` — Visual direction, palettes, references, asset pipeline
- `domain/audio` — Audio systems: world ambient, radio, transmissions, buses, pipeline
- `domain/autonomous-company` — Autonomous company v0.1 experiment: Slack infra, persona middleware, Letta integration, restart recovery
- `domain/build` — Build system, packaging, export, release automation
- `domain/governance` — Constitution, phased spec, policies
- `domain/infrastructure` — Infrastructure provisioning: CI/CD, hosting, deployment tooling, secrets management
- `domain/narrative` — Tone, horror register, forest transmissions narrative, Gary/KTLK
- `domain/player` — Player mode, input, controls, camera, exit/entry
- `domain/systems` — Cross-cutting system architecture and integration work
- `domain/tooling` — Build, CI, observer, TTS pipeline, dev-time tools
- `domain/vehicle` — The Samba: vehicle physics, dashboard, damage, panels
- `domain/world` — World model, biomes, terrain, procedural generation, weather
status/*:
- `status/canonical` — Fully authoritative; promoted by humans only. Highest trust. (Agent notes only — spec 080.)
- `status/draft` — Authoring in progress, not yet verified
- `status/reviewed` — Agent-created note verified against codebase within its creating session. Eligible for auto-injection in subsequent task dispatches. (Agent notes only — spec 080.)
- `status/stale` — Known out of date; cannot update immediately. Pairs with `> [!warning] STALE — needs update` callout.
- `status/superseded` — Replaced by another note. Terminal state. Pairs with `> [!warning] SUPERSEDED` callout.
- `status/wip` — Stable but under active revision
layer/*:
- `layer/content` — Content assets (audio, models, textures, audio provenance)
- `layer/gdext` — gdext wrapper layer (`rust/gdext-wrapper/`)
- `layer/gdscript` — GDScript (Godot scene-tier logic)
- `layer/infra` — Build, CI, deployment infrastructure
- `layer/python` — Python development tooling (`tools/`)
- `layer/rust-core` — Engine-agnostic Rust core (`rust/rust-core/`)
concept/*:
- `concept/biome` — Biome-reactive behavior across systems
- `concept/contamination` — Across-runs panel and garage degradation; the slow-horror mechanic that doesn't reset with the world
- `concept/diegetic` — Diegetic audio / UI / world-sourced design
- `concept/disturbance` — The disturbance mechanic thread (Article X)
- `concept/ephemeral-world` — Run-reset, transient worlds (Article IV Rules 6–7)
- `concept/governance` — Constitutional and governance concepts
- `concept/horror` — Horror register and dread design
- `concept/procedural` — Procedural generation, seed determinism
- `concept/rendering` — Visual rendering quality, shader correctness, Terrain3D integration, mesh fidelity, LOD, Z-fighting
- `concept/terrain` — Terrain generation, heightmap, Terrain3D regions, roughness, playability constraints
ember's answer for tag_assignment-governance-tech-stack-review, domain/governanceP(true) placed on the no, unsure, and yes zones.nounsureyesgold: yesP = 0.30

tag_assignment-governance-tech-stack-review: type/principle

Tag assignment · dev
Gold
The note calls for `type/principle`: Governance and constitutional notes. Non-negotiable rules. (e.g. `Governance/Constitution.md`) (True)
ember
The note has no reason to carry `type/principle` (False)
Signal
P(true) 0.05 (no)
Kit outcome
acted on a wrong answer
Why this gold label
Mined from Governance/Tech Stack Review.md at 692f4bb58b7f62105aeb73fba8dfee12bfdecd53; gold is the note's own vocabulary tags.
Tech Stack Review

The technology stack decisions for Old Growth — what was chosen, what was evaluated and rejected, and where the open risks are. The authoritative approved stack lives in constitution Appendix A; this note captures the *why* behind each decision.

## Overview

Old Growth's stack is deliberately conservative where possible and opinionated where necessary. The engine and scripting language are locked by constitution (Article III). Vehicle physics, terrain, procedural generation, and audio are locked with strong alternative-assessment. A handful of visual effects and content questions remain open.

**Status legend:**
- 🟢 **Locked** — researched, tested compatibility, no meaningful alternative
- 🟡 **Strong lean** — best option found but alternatives exist worth discussing
- 🟠 **Open** — decision made but could reasonably go another way
- 🔴 **Unresolved** — no decision yet or significant uncertainty

## Key Decisions — Core Stack (all 🟢)

| System | Pick | Why |
|--------|------|-----|
| Game engine | Godot 4.6+ | Native Metal renderer, plaintext GDScript (agent-readable), MIT, Jolt built-in, strong macOS export |
| Scripting | GDScript + Rust (gdext) | GDScript for scene glue; Rust for performance-critical (Article III Rule 17) |
| Physics | Jolt (native in 4.6+) | More stable vehicle sim than Godot Physics; GEVP-compatible |
| Target platform | macOS Universal Binary | Scope constraint; Apple Silicon (Metal) + Intel Macs |
| Physics tick | 120 Hz | GEVP requires 120+; 60 causes instability; 240 is unnecessary |

## Vehicle Physics

- **Vehicle controller**: GEVP (vendored in `addons/`, MIT). Raycast-based, keyboard-friendly, single-script, simcade preset. Needs tuning for 1963 VW Samba feel (rear-engine RWD, ~1100 kg, ~50 HP, high CoG, soft suspension, long braking distances).
- **Engine audio**: Pitch-scaled `AudioStreamPlayer3D` loops (🟠). Simplest approach; may upgrade to multi-sample crossfade in audio polish.

## Terrain & Roads

- **Terrain system**: Terrain3D (C++ GDExtension, MIT). GPU clipmap, foliage instancer, 32 textures, Road Generator connector.
- **Road generation**: Godot Road Generator (🟡). Designed for hand-placed roads; procedural usage is supported but less documented. **Technical risk for spec 053 remediation.**
- **Foliage**: Terrain3D built-in instancer (🟡). Must handle biome-specific vegetation swaps.
- **Heightmap**: FastNoiseLite (Godot built-in). Sufficient for ~2km² worlds.

## Weather & Atmosphere

- Rain-on-Glass shader (🟡), custom wiper integration (🟠)
- Volumetric fog: Godot 4 built-in (🟢)
- Sky: ProceduralSkyMaterial (🟡) — must produce three distinct biome sky feels
- Weather zones: Voronoi/grid subdivision (🟡, novel system)

## Visual Effects & Post-Processing

- Post-processing: ArseniyMirniy Color Correction (🟢, vendored)
- Windshield crack overlay (🟠), Storm wall shader (🟠), biome transition blending (🟡)

## Anomaly Systems

Most anomalies use standard Godot primitives (AnimationPlayer, Area3D, GPUParticles3D, OmniLight3D, MeshInstance3D). See [[Anomalies]] for design specifications; tech choices here are typically 🟢 Locked.

## Audio

- **Audio management**: Godot native (🟢). Sound Manager (nathanhoad) evaluated and rejected (insufficient — no AudioStreamPlayer3D, no AudioEffect manipulation, ambient pool limited to 1 stream).
- **Bus architecture**: 7 buses planned per constitution Appendix A (Master → Ambience, Proximity, Interior, Horror, Radio, RadioDegraded). Currently only Master + Radio + RadioDegraded exist in `src/default_bus_layout.tres`; the remaining buses are being built incrementally through the audio specs. See [[Audio — Overview]] for the CONFLICT callout and [[Conflicts]] for the indexed entry.
- **Positional**: `AudioStreamPlayer3D` built-in (🟢)

## On-Foot Systems

- CharacterBody3D + custom FPS controller (🟡)
- Car entry/exit: custom camera reparent + input context switch (🟠) — **highest-risk custom system**, ~200 lines
- Combat: melee raycast + ranged hitscan/projectile (🟢) — per Article II, on-foot scope is strictly bounded
- Enemy AI: StateMachine + NavigationAgent3D (🟡) — **must verify NavMesh bakes on Terrain3D at runtime**

## Disturbance & Storm

- Disturbance meter: autoload with add(amount, source) + threshold signals (🟢, matches Article X)
- Disturbance HUD: organic visual indicator (🟠, creative risk)
- Storm wall direction: spawn opposite nearest exit, advance toward player (🟢)

## Persistence & Architecture

- **Save**: Godot Resource serialization (`.tres`) (🟡). World state NOT saved — only garage/player state (Article IV Rule 6).
- **Settings**: `ConfigFile` at `user://settings.cfg` (🟢)
- **Cross-system communication**: Signal bus autoload (`events.gd`) (🟢, Article VI)
- **Game state**: `GameState` autoload + enum states (🟡)

## Assets & Pipeline

- **3D format**: glTF 2.0 (.glb) (🟢)
- **VW Samba model**: Placeholder (Kenney) → custom/purchased (🟠). No perfect free 1963 VW Type 2 Samba (23-window, V-nose, two-tone, curved skylight).
- **PBR textures**: CC0 (ambientCG, cgbookcase, Polyhaven) (🟢)
- **Audio assets**: CC0 (Freesound, OpenGameArt, Kenney) (🟡) — fungal/stone SFX may need original recording
- **Radio music**: 🔴 UNRESOLVED. Need 30+ min across multiple genres. CC0 music is rare; AI-generated is an option; doesn't block until audio polish phase.

## macOS Packaging

- Code signing: Apple Developer ID ($99/yr) or ad-hoc (🟠)
- Distribution: DMG with drag-to-Applications (🟢)
- Game controller: Godot GameController built-in (🟢)

## Highest-Risk Open Questions

The source doc identifies six items as the highest technical risks:

1. **Procedural road algorithm** — connected road network from a seed over ~2km² (spec 053)
2. **NavMesh on Terrain3D** — does NavigationAgent3D bake reliably? If not, fall back to raycast steering.
3. **Biome texture swap in Terrain3D** — texture-set-per-region capability
4. **World generation performance** — ~2km² world in <5 seconds on M4 Max (Article V)
5. **Petrified Zone screen-space shader** — selective desaturation of meshes in a 3D area without affecting HUD
6. **Storm wall directional shader** — dramatic shader for an advancing flat plane

## Summary Counts (per source)

- **🟢 Locked**: 26 decisions
- **🟡 Strong lean**: 15 decisions
- **🟠 Open**: 8 decisions
- **🔴 Unresolved**: 1 decision (radio music content)

## Related

- [[Constitution]] — Article III and Appendix A are the authoritative source
- [[Component SemVer Policy]] — how these components are versioned
- [[Governance]] — folder MOC
- [[Build System]] — the CI pipeline that enforces these choices

## Agent Notes (backlinks)

- [[Decisions/Rust-GDScript Split Architecture]] — Rust/GDScript split decision with operational constraints
- [[Audio Generation Pipeline Constraints & Patterns]] — TTS engine selection, Python 3.11 requirement, provenance schema, ElevenLabs SFX V2 pipeline
- [[Vault Tooling — Constraints and Patterns]] — vault audit, Observer QA, asset export safety
- Vault Tooling — Constraints and Patterns — vault audit, asset export, Observer QA, development constraints

Controlled tag vocabulary (as read):
type/*:
- `type/code` — Code architecture, autoloads, conventions, tooling. Carries `code-refs:`. (e.g. `Code/Autoloads — Disturbance.md`)
- `type/decision` — Architectural or design decision made by an agent during a session. Written to `docs/vault/Decisions/`. (Agent notes only — spec 080.)
- `type/design` — Design intent, player-facing concepts, world lore. (e.g. `Design/World Model.md`)
- `type/discovery` — Non-obvious constraint, gap, or conflict found by an agent during a session. Written to `docs/vault/Discoveries/`. (Agent notes only — spec 080.)
- `type/moc` — Map of Content at any of three tiers (folder / domain / concept). (e.g. `Audio.md`)
- `type/principle` — Governance and constitutional notes. Non-negotiable rules. (e.g. `Governance/Constitution.md`)
- `type/reference` — Glossary, decision log, open questions, epics. (e.g. `Reference/Glossary.md`)
- `type/session-log` — Session activity log; permanent audit trail. Written to `docs/vault/Sessions/`. Append-only, never pruned. (Agent notes only — spec 080.)
- `type/spec` — Spec document at `docs/vault/Specs/NNN Title/spec.md`. Carries `spec-refs:`. (e.g. `Specs/047 Car Radio/spec.md`)
- `type/system` — A bounded subsystem with implementation. Carries `code-refs`, `spec-refs`, `implements:` frontmatter. (e.g. `Systems/Audio — Car Radio.md`)
- `type/vision` — Strategic / vision-layer decision. Written to `docs/vault/Vision/`. Human-authored or agent-proposed with human ratification before promotion to `status: reviewed`. (Per triage #3 — spec 133 autonomous-company redesign.)
domain/*:
- `domain/anomalies` — Anomaly taxonomy, individual anomaly systems, spawn, behavior
- `domain/art` — Visual direction, palettes, references, asset pipeline
- `domain/audio` — Audio systems: world ambient, radio, transmissions, buses, pipeline
- `domain/autonomous-company` — Autonomous company v0.1 experiment: Slack infra, persona middleware, Letta integration, restart recovery
- `domain/build` — Build system, packaging, export, release automation
- `domain/governance` — Constitution, phased spec, policies
- `domain/infrastructure` — Infrastructure provisioning: CI/CD, hosting, deployment tooling, secrets management
- `domain/narrative` — Tone, horror register, forest transmissions narrative, Gary/KTLK
- `domain/player` — Player mode, input, controls, camera, exit/entry
- `domain/systems` — Cross-cutting system architecture and integration work
- `domain/tooling` — Build, CI, observer, TTS pipeline, dev-time tools
- `domain/vehicle` — The Samba: vehicle physics, dashboard, damage, panels
- `domain/world` — World model, biomes, terrain, procedural generation, weather
status/*:
- `status/canonical` — Fully authoritative; promoted by humans only. Highest trust. (Agent notes only — spec 080.)
- `status/draft` — Authoring in progress, not yet verified
- `status/reviewed` — Agent-created note verified against codebase within its creating session. Eligible for auto-injection in subsequent task dispatches. (Agent notes only — spec 080.)
- `status/stale` — Known out of date; cannot update immediately. Pairs with `> [!warning] STALE — needs update` callout.
- `status/superseded` — Replaced by another note. Terminal state. Pairs with `> [!warning] SUPERSEDED` callout.
- `status/wip` — Stable but under active revision
layer/*:
- `layer/content` — Content assets (audio, models, textures, audio provenance)
- `layer/gdext` — gdext wrapper layer (`rust/gdext-wrapper/`)
- `layer/gdscript` — GDScript (Godot scene-tier logic)
- `layer/infra` — Build, CI, deployment infrastructure
- `layer/python` — Python development tooling (`tools/`)
- `layer/rust-core` — Engine-agnostic Rust core (`rust/rust-core/`)
concept/*:
- `concept/biome` — Biome-reactive behavior across systems
- `concept/contamination` — Across-runs panel and garage degradation; the slow-horror mechanic that doesn't reset with the world
- `concept/diegetic` — Diegetic audio / UI / world-sourced design
- `concept/disturbance` — The disturbance mechanic thread (Article X)
- `concept/ephemeral-world` — Run-reset, transient worlds (Article IV Rules 6–7)
- `concept/governance` — Constitutional and governance concepts
- `concept/horror` — Horror register and dread design
- `concept/procedural` — Procedural generation, seed determinism
- `concept/rendering` — Visual rendering quality, shader correctness, Terrain3D integration, mesh fidelity, LOD, Z-fighting
- `concept/terrain` — Terrain generation, heightmap, Terrain3D regions, roughness, playability constraints
ember's answer for tag_assignment-governance-tech-stack-review, type/principleP(true) placed on the no, unsure, and yes zones.nounsureyesgold: yesP = 0.05

tag_assignment-governance-tech-stack-review: type/reference

Tag assignment · dev
Gold
The note has no reason to carry `type/reference` (False)
ember
The note calls for `type/reference`: Glossary, decision log, open questions, epics. (e.g. `Reference/Glossary.md`) (True)
Signal
P(true) 0.65 (unsure)
Kit outcome
deferred: treated as unsure
Why this gold label
Mined from Governance/Tech Stack Review.md at 692f4bb58b7f62105aeb73fba8dfee12bfdecd53; gold is the note's own vocabulary tags.
Tech Stack Review

The technology stack decisions for Old Growth — what was chosen, what was evaluated and rejected, and where the open risks are. The authoritative approved stack lives in constitution Appendix A; this note captures the *why* behind each decision.

## Overview

Old Growth's stack is deliberately conservative where possible and opinionated where necessary. The engine and scripting language are locked by constitution (Article III). Vehicle physics, terrain, procedural generation, and audio are locked with strong alternative-assessment. A handful of visual effects and content questions remain open.

**Status legend:**
- 🟢 **Locked** — researched, tested compatibility, no meaningful alternative
- 🟡 **Strong lean** — best option found but alternatives exist worth discussing
- 🟠 **Open** — decision made but could reasonably go another way
- 🔴 **Unresolved** — no decision yet or significant uncertainty

## Key Decisions — Core Stack (all 🟢)

| System | Pick | Why |
|--------|------|-----|
| Game engine | Godot 4.6+ | Native Metal renderer, plaintext GDScript (agent-readable), MIT, Jolt built-in, strong macOS export |
| Scripting | GDScript + Rust (gdext) | GDScript for scene glue; Rust for performance-critical (Article III Rule 17) |
| Physics | Jolt (native in 4.6+) | More stable vehicle sim than Godot Physics; GEVP-compatible |
| Target platform | macOS Universal Binary | Scope constraint; Apple Silicon (Metal) + Intel Macs |
| Physics tick | 120 Hz | GEVP requires 120+; 60 causes instability; 240 is unnecessary |

## Vehicle Physics

- **Vehicle controller**: GEVP (vendored in `addons/`, MIT). Raycast-based, keyboard-friendly, single-script, simcade preset. Needs tuning for 1963 VW Samba feel (rear-engine RWD, ~1100 kg, ~50 HP, high CoG, soft suspension, long braking distances).
- **Engine audio**: Pitch-scaled `AudioStreamPlayer3D` loops (🟠). Simplest approach; may upgrade to multi-sample crossfade in audio polish.

## Terrain & Roads

- **Terrain system**: Terrain3D (C++ GDExtension, MIT). GPU clipmap, foliage instancer, 32 textures, Road Generator connector.
- **Road generation**: Godot Road Generator (🟡). Designed for hand-placed roads; procedural usage is supported but less documented. **Technical risk for spec 053 remediation.**
- **Foliage**: Terrain3D built-in instancer (🟡). Must handle biome-specific vegetation swaps.
- **Heightmap**: FastNoiseLite (Godot built-in). Sufficient for ~2km² worlds.

## Weather & Atmosphere

- Rain-on-Glass shader (🟡), custom wiper integration (🟠)
- Volumetric fog: Godot 4 built-in (🟢)
- Sky: ProceduralSkyMaterial (🟡) — must produce three distinct biome sky feels
- Weather zones: Voronoi/grid subdivision (🟡, novel system)

## Visual Effects & Post-Processing

- Post-processing: ArseniyMirniy Color Correction (🟢, vendored)
- Windshield crack overlay (🟠), Storm wall shader (🟠), biome transition blending (🟡)

## Anomaly Systems

Most anomalies use standard Godot primitives (AnimationPlayer, Area3D, GPUParticles3D, OmniLight3D, MeshInstance3D). See [[Anomalies]] for design specifications; tech choices here are typically 🟢 Locked.

## Audio

- **Audio management**: Godot native (🟢). Sound Manager (nathanhoad) evaluated and rejected (insufficient — no AudioStreamPlayer3D, no AudioEffect manipulation, ambient pool limited to 1 stream).
- **Bus architecture**: 7 buses planned per constitution Appendix A (Master → Ambience, Proximity, Interior, Horror, Radio, RadioDegraded). Currently only Master + Radio + RadioDegraded exist in `src/default_bus_layout.tres`; the remaining buses are being built incrementally through the audio specs. See [[Audio — Overview]] for the CONFLICT callout and [[Conflicts]] for the indexed entry.
- **Positional**: `AudioStreamPlayer3D` built-in (🟢)

## On-Foot Systems

- CharacterBody3D + custom FPS controller (🟡)
- Car entry/exit: custom camera reparent + input context switch (🟠) — **highest-risk custom system**, ~200 lines
- Combat: melee raycast + ranged hitscan/projectile (🟢) — per Article II, on-foot scope is strictly bounded
- Enemy AI: StateMachine + NavigationAgent3D (🟡) — **must verify NavMesh bakes on Terrain3D at runtime**

## Disturbance & Storm

- Disturbance meter: autoload with add(amount, source) + threshold signals (🟢, matches Article X)
- Disturbance HUD: organic visual indicator (🟠, creative risk)
- Storm wall direction: spawn opposite nearest exit, advance toward player (🟢)

## Persistence & Architecture

- **Save**: Godot Resource serialization (`.tres`) (🟡). World state NOT saved — only garage/player state (Article IV Rule 6).
- **Settings**: `ConfigFile` at `user://settings.cfg` (🟢)
- **Cross-system communication**: Signal bus autoload (`events.gd`) (🟢, Article VI)
- **Game state**: `GameState` autoload + enum states (🟡)

## Assets & Pipeline

- **3D format**: glTF 2.0 (.glb) (🟢)
- **VW Samba model**: Placeholder (Kenney) → custom/purchased (🟠). No perfect free 1963 VW Type 2 Samba (23-window, V-nose, two-tone, curved skylight).
- **PBR textures**: CC0 (ambientCG, cgbookcase, Polyhaven) (🟢)
- **Audio assets**: CC0 (Freesound, OpenGameArt, Kenney) (🟡) — fungal/stone SFX may need original recording
- **Radio music**: 🔴 UNRESOLVED. Need 30+ min across multiple genres. CC0 music is rare; AI-generated is an option; doesn't block until audio polish phase.

## macOS Packaging

- Code signing: Apple Developer ID ($99/yr) or ad-hoc (🟠)
- Distribution: DMG with drag-to-Applications (🟢)
- Game controller: Godot GameController built-in (🟢)

## Highest-Risk Open Questions

The source doc identifies six items as the highest technical risks:

1. **Procedural road algorithm** — connected road network from a seed over ~2km² (spec 053)
2. **NavMesh on Terrain3D** — does NavigationAgent3D bake reliably? If not, fall back to raycast steering.
3. **Biome texture swap in Terrain3D** — texture-set-per-region capability
4. **World generation performance** — ~2km² world in <5 seconds on M4 Max (Article V)
5. **Petrified Zone screen-space shader** — selective desaturation of meshes in a 3D area without affecting HUD
6. **Storm wall directional shader** — dramatic shader for an advancing flat plane

## Summary Counts (per source)

- **🟢 Locked**: 26 decisions
- **🟡 Strong lean**: 15 decisions
- **🟠 Open**: 8 decisions
- **🔴 Unresolved**: 1 decision (radio music content)

## Related

- [[Constitution]] — Article III and Appendix A are the authoritative source
- [[Component SemVer Policy]] — how these components are versioned
- [[Governance]] — folder MOC
- [[Build System]] — the CI pipeline that enforces these choices

## Agent Notes (backlinks)

- [[Decisions/Rust-GDScript Split Architecture]] — Rust/GDScript split decision with operational constraints
- [[Audio Generation Pipeline Constraints & Patterns]] — TTS engine selection, Python 3.11 requirement, provenance schema, ElevenLabs SFX V2 pipeline
- [[Vault Tooling — Constraints and Patterns]] — vault audit, Observer QA, asset export safety
- Vault Tooling — Constraints and Patterns — vault audit, asset export, Observer QA, development constraints

Controlled tag vocabulary (as read):
type/*:
- `type/code` — Code architecture, autoloads, conventions, tooling. Carries `code-refs:`. (e.g. `Code/Autoloads — Disturbance.md`)
- `type/decision` — Architectural or design decision made by an agent during a session. Written to `docs/vault/Decisions/`. (Agent notes only — spec 080.)
- `type/design` — Design intent, player-facing concepts, world lore. (e.g. `Design/World Model.md`)
- `type/discovery` — Non-obvious constraint, gap, or conflict found by an agent during a session. Written to `docs/vault/Discoveries/`. (Agent notes only — spec 080.)
- `type/moc` — Map of Content at any of three tiers (folder / domain / concept). (e.g. `Audio.md`)
- `type/principle` — Governance and constitutional notes. Non-negotiable rules. (e.g. `Governance/Constitution.md`)
- `type/reference` — Glossary, decision log, open questions, epics. (e.g. `Reference/Glossary.md`)
- `type/session-log` — Session activity log; permanent audit trail. Written to `docs/vault/Sessions/`. Append-only, never pruned. (Agent notes only — spec 080.)
- `type/spec` — Spec document at `docs/vault/Specs/NNN Title/spec.md`. Carries `spec-refs:`. (e.g. `Specs/047 Car Radio/spec.md`)
- `type/system` — A bounded subsystem with implementation. Carries `code-refs`, `spec-refs`, `implements:` frontmatter. (e.g. `Systems/Audio — Car Radio.md`)
- `type/vision` — Strategic / vision-layer decision. Written to `docs/vault/Vision/`. Human-authored or agent-proposed with human ratification before promotion to `status: reviewed`. (Per triage #3 — spec 133 autonomous-company redesign.)
domain/*:
- `domain/anomalies` — Anomaly taxonomy, individual anomaly systems, spawn, behavior
- `domain/art` — Visual direction, palettes, references, asset pipeline
- `domain/audio` — Audio systems: world ambient, radio, transmissions, buses, pipeline
- `domain/autonomous-company` — Autonomous company v0.1 experiment: Slack infra, persona middleware, Letta integration, restart recovery
- `domain/build` — Build system, packaging, export, release automation
- `domain/governance` — Constitution, phased spec, policies
- `domain/infrastructure` — Infrastructure provisioning: CI/CD, hosting, deployment tooling, secrets management
- `domain/narrative` — Tone, horror register, forest transmissions narrative, Gary/KTLK
- `domain/player` — Player mode, input, controls, camera, exit/entry
- `domain/systems` — Cross-cutting system architecture and integration work
- `domain/tooling` — Build, CI, observer, TTS pipeline, dev-time tools
- `domain/vehicle` — The Samba: vehicle physics, dashboard, damage, panels
- `domain/world` — World model, biomes, terrain, procedural generation, weather
status/*:
- `status/canonical` — Fully authoritative; promoted by humans only. Highest trust. (Agent notes only — spec 080.)
- `status/draft` — Authoring in progress, not yet verified
- `status/reviewed` — Agent-created note verified against codebase within its creating session. Eligible for auto-injection in subsequent task dispatches. (Agent notes only — spec 080.)
- `status/stale` — Known out of date; cannot update immediately. Pairs with `> [!warning] STALE — needs update` callout.
- `status/superseded` — Replaced by another note. Terminal state. Pairs with `> [!warning] SUPERSEDED` callout.
- `status/wip` — Stable but under active revision
layer/*:
- `layer/content` — Content assets (audio, models, textures, audio provenance)
- `layer/gdext` — gdext wrapper layer (`rust/gdext-wrapper/`)
- `layer/gdscript` — GDScript (Godot scene-tier logic)
- `layer/infra` — Build, CI, deployment infrastructure
- `layer/python` — Python development tooling (`tools/`)
- `layer/rust-core` — Engine-agnostic Rust core (`rust/rust-core/`)
concept/*:
- `concept/biome` — Biome-reactive behavior across systems
- `concept/contamination` — Across-runs panel and garage degradation; the slow-horror mechanic that doesn't reset with the world
- `concept/diegetic` — Diegetic audio / UI / world-sourced design
- `concept/disturbance` — The disturbance mechanic thread (Article X)
- `concept/ephemeral-world` — Run-reset, transient worlds (Article IV Rules 6–7)
- `concept/governance` — Constitutional and governance concepts
- `concept/horror` — Horror register and dread design
- `concept/procedural` — Procedural generation, seed determinism
- `concept/rendering` — Visual rendering quality, shader correctness, Terrain3D integration, mesh fidelity, LOD, Z-fighting
- `concept/terrain` — Terrain generation, heightmap, Terrain3D regions, roughness, playability constraints
ember's answer for tag_assignment-governance-tech-stack-review, type/referenceP(true) placed on the no, unsure, and yes zones.nounsureyesgold: noP = 0.65

tag_assignment-decisions-noisehelper-utility-class-design: domain/tooling

Tag assignment · dev
Gold
The note calls for `domain/tooling`: Build, CI, observer, TTS pipeline, dev-time tools (True)
ember
The note has no reason to carry `domain/tooling` (False)
Signal
P(true) 0.16 (no)
Kit outcome
acted on a wrong answer
Why this gold label
Mined from Decisions/NoiseHelper Utility Class Design.md at 692f4bb58b7f62105aeb73fba8dfee12bfdecd53; gold is the note's own vocabulary tags.
NoiseHelper Utility Class Design

This note records the structural decisions made for noise_helper.gd during spec 081 (Code Dedup Consolidation) that are non-obvious from the code alone.

## No extends, No class_name

noise_helper.gd declares neither extends nor class_name. It is accessed exclusively via a preload constant in each consuming file:

    const NoiseHelper = preload("res://scripts/generation/noise_helper.gd")

This pattern was chosen over class_name for two reasons. First, the class_name restriction from the constitution applies to autoloads because of Godot 4.6 singleton name conflicts — noise_helper.gd is not an autoload, so class_name would technically be valid. However, making it a named class creates a global symbol that pollutes the project namespace for what is a narrow utility. Preload constants keep the dependency explicit and local. Second, unlike OGTestBase (which uses class_name intentionally so test files can extend it by name), noise_helper.gd has no inheritance use case — callers call its static factory methods, they do not extend it.

## Dictionary Parameter Convention

The create_roughness_noise factory method accepts all parameters via a Dictionary rather than positional arguments. This means every caller must pass their own @export values explicitly:

    NoiseHelper.create_roughness_noise({"octaves": octaves, "frequency": frequency, ...})

No default values are baked into the helper. This was intentional: the helper exists to eliminate duplicate noise setup code, not to encode defaults. If defaults lived inside the helper, callers that relied on them would become silently coupled to the helper's internal values rather than to their own @export variables. The Dictionary convention keeps designer-tunable parameters visible in the caller's inspector.

## References

- src/scripts/generation/noise_helper.gd
- src/scripts/generation/terrain_generator.gd (consumer)
- src/scripts/generation/heightmap_proxy.gd (consumer)
- docs/vault/Sessions/Spec 081 Implementation Session.md

Controlled tag vocabulary (as read):
type/*:
- `type/code` — Code architecture, autoloads, conventions, tooling. Carries `code-refs:`. (e.g. `Code/Autoloads — Disturbance.md`)
- `type/decision` — Architectural or design decision made by an agent during a session. Written to `docs/vault/Decisions/`. (Agent notes only — spec 080.)
- `type/design` — Design intent, player-facing concepts, world lore. (e.g. `Design/World Model.md`)
- `type/discovery` — Non-obvious constraint, gap, or conflict found by an agent during a session. Written to `docs/vault/Discoveries/`. (Agent notes only — spec 080.)
- `type/moc` — Map of Content at any of three tiers (folder / domain / concept). (e.g. `Audio.md`)
- `type/principle` — Governance and constitutional notes. Non-negotiable rules. (e.g. `Governance/Constitution.md`)
- `type/reference` — Glossary, decision log, open questions, epics. (e.g. `Reference/Glossary.md`)
- `type/session-log` — Session activity log; permanent audit trail. Written to `docs/vault/Sessions/`. Append-only, never pruned. (Agent notes only — spec 080.)
- `type/spec` — Spec document at `docs/vault/Specs/NNN Title/spec.md`. Carries `spec-refs:`. (e.g. `Specs/047 Car Radio/spec.md`)
- `type/system` — A bounded subsystem with implementation. Carries `code-refs`, `spec-refs`, `implements:` frontmatter. (e.g. `Systems/Audio — Car Radio.md`)
- `type/vision` — Strategic / vision-layer decision. Written to `docs/vault/Vision/`. Human-authored or agent-proposed with human ratification before promotion to `status: reviewed`. (Per triage #3 — spec 133 autonomous-company redesign.)
domain/*:
- `domain/anomalies` — Anomaly taxonomy, individual anomaly systems, spawn, behavior
- `domain/art` — Visual direction, palettes, references, asset pipeline
- `domain/audio` — Audio systems: world ambient, radio, transmissions, buses, pipeline
- `domain/autonomous-company` — Autonomous company v0.1 experiment: Slack infra, persona middleware, Letta integration, restart recovery
- `domain/build` — Build system, packaging, export, release automation
- `domain/governance` — Constitution, phased spec, policies
- `domain/infrastructure` — Infrastructure provisioning: CI/CD, hosting, deployment tooling, secrets management
- `domain/narrative` — Tone, horror register, forest transmissions narrative, Gary/KTLK
- `domain/player` — Player mode, input, controls, camera, exit/entry
- `domain/systems` — Cross-cutting system architecture and integration work
- `domain/tooling` — Build, CI, observer, TTS pipeline, dev-time tools
- `domain/vehicle` — The Samba: vehicle physics, dashboard, damage, panels
- `domain/world` — World model, biomes, terrain, procedural generation, weather
status/*:
- `status/canonical` — Fully authoritative; promoted by humans only. Highest trust. (Agent notes only — spec 080.)
- `status/draft` — Authoring in progress, not yet verified
- `status/reviewed` — Agent-created note verified against codebase within its creating session. Eligible for auto-injection in subsequent task dispatches. (Agent notes only — spec 080.)
- `status/stale` — Known out of date; cannot update immediately. Pairs with `> [!warning] STALE — needs update` callout.
- `status/superseded` — Replaced by another note. Terminal state. Pairs with `> [!warning] SUPERSEDED` callout.
- `status/wip` — Stable but under active revision
layer/*:
- `layer/content` — Content assets (audio, models, textures, audio provenance)
- `layer/gdext` — gdext wrapper layer (`rust/gdext-wrapper/`)
- `layer/gdscript` — GDScript (Godot scene-tier logic)
- `layer/infra` — Build, CI, deployment infrastructure
- `layer/python` — Python development tooling (`tools/`)
- `layer/rust-core` — Engine-agnostic Rust core (`rust/rust-core/`)
concept/*:
- `concept/biome` — Biome-reactive behavior across systems
- `concept/contamination` — Across-runs panel and garage degradation; the slow-horror mechanic that doesn't reset with the world
- `concept/diegetic` — Diegetic audio / UI / world-sourced design
- `concept/disturbance` — The disturbance mechanic thread (Article X)
- `concept/ephemeral-world` — Run-reset, transient worlds (Article IV Rules 6–7)
- `concept/governance` — Constitutional and governance concepts
- `concept/horror` — Horror register and dread design
- `concept/procedural` — Procedural generation, seed determinism
- `concept/rendering` — Visual rendering quality, shader correctness, Terrain3D integration, mesh fidelity, LOD, Z-fighting
- `concept/terrain` — Terrain generation, heightmap, Terrain3D regions, roughness, playability constraints
ember's answer for tag_assignment-decisions-noisehelper-utility-class-design, domain/toolingP(true) placed on the no, unsure, and yes zones.nounsureyesgold: yesP = 0.16

tag_assignment-decisions-noisehelper-utility-class-design: domain/world

Tag assignment · dev
Gold
The note calls for `domain/world`: World model, biomes, terrain, procedural generation, weather (True)
ember
The note has no reason to carry `domain/world` (False)
Signal
P(true) 0.35 (unsure)
Kit outcome
deferred: treated as unsure
Why this gold label
Mined from Decisions/NoiseHelper Utility Class Design.md at 692f4bb58b7f62105aeb73fba8dfee12bfdecd53; gold is the note's own vocabulary tags.
NoiseHelper Utility Class Design

This note records the structural decisions made for noise_helper.gd during spec 081 (Code Dedup Consolidation) that are non-obvious from the code alone.

## No extends, No class_name

noise_helper.gd declares neither extends nor class_name. It is accessed exclusively via a preload constant in each consuming file:

    const NoiseHelper = preload("res://scripts/generation/noise_helper.gd")

This pattern was chosen over class_name for two reasons. First, the class_name restriction from the constitution applies to autoloads because of Godot 4.6 singleton name conflicts — noise_helper.gd is not an autoload, so class_name would technically be valid. However, making it a named class creates a global symbol that pollutes the project namespace for what is a narrow utility. Preload constants keep the dependency explicit and local. Second, unlike OGTestBase (which uses class_name intentionally so test files can extend it by name), noise_helper.gd has no inheritance use case — callers call its static factory methods, they do not extend it.

## Dictionary Parameter Convention

The create_roughness_noise factory method accepts all parameters via a Dictionary rather than positional arguments. This means every caller must pass their own @export values explicitly:

    NoiseHelper.create_roughness_noise({"octaves": octaves, "frequency": frequency, ...})

No default values are baked into the helper. This was intentional: the helper exists to eliminate duplicate noise setup code, not to encode defaults. If defaults lived inside the helper, callers that relied on them would become silently coupled to the helper's internal values rather than to their own @export variables. The Dictionary convention keeps designer-tunable parameters visible in the caller's inspector.

## References

- src/scripts/generation/noise_helper.gd
- src/scripts/generation/terrain_generator.gd (consumer)
- src/scripts/generation/heightmap_proxy.gd (consumer)
- docs/vault/Sessions/Spec 081 Implementation Session.md

Controlled tag vocabulary (as read):
type/*:
- `type/code` — Code architecture, autoloads, conventions, tooling. Carries `code-refs:`. (e.g. `Code/Autoloads — Disturbance.md`)
- `type/decision` — Architectural or design decision made by an agent during a session. Written to `docs/vault/Decisions/`. (Agent notes only — spec 080.)
- `type/design` — Design intent, player-facing concepts, world lore. (e.g. `Design/World Model.md`)
- `type/discovery` — Non-obvious constraint, gap, or conflict found by an agent during a session. Written to `docs/vault/Discoveries/`. (Agent notes only — spec 080.)
- `type/moc` — Map of Content at any of three tiers (folder / domain / concept). (e.g. `Audio.md`)
- `type/principle` — Governance and constitutional notes. Non-negotiable rules. (e.g. `Governance/Constitution.md`)
- `type/reference` — Glossary, decision log, open questions, epics. (e.g. `Reference/Glossary.md`)
- `type/session-log` — Session activity log; permanent audit trail. Written to `docs/vault/Sessions/`. Append-only, never pruned. (Agent notes only — spec 080.)
- `type/spec` — Spec document at `docs/vault/Specs/NNN Title/spec.md`. Carries `spec-refs:`. (e.g. `Specs/047 Car Radio/spec.md`)
- `type/system` — A bounded subsystem with implementation. Carries `code-refs`, `spec-refs`, `implements:` frontmatter. (e.g. `Systems/Audio — Car Radio.md`)
- `type/vision` — Strategic / vision-layer decision. Written to `docs/vault/Vision/`. Human-authored or agent-proposed with human ratification before promotion to `status: reviewed`. (Per triage #3 — spec 133 autonomous-company redesign.)
domain/*:
- `domain/anomalies` — Anomaly taxonomy, individual anomaly systems, spawn, behavior
- `domain/art` — Visual direction, palettes, references, asset pipeline
- `domain/audio` — Audio systems: world ambient, radio, transmissions, buses, pipeline
- `domain/autonomous-company` — Autonomous company v0.1 experiment: Slack infra, persona middleware, Letta integration, restart recovery
- `domain/build` — Build system, packaging, export, release automation
- `domain/governance` — Constitution, phased spec, policies
- `domain/infrastructure` — Infrastructure provisioning: CI/CD, hosting, deployment tooling, secrets management
- `domain/narrative` — Tone, horror register, forest transmissions narrative, Gary/KTLK
- `domain/player` — Player mode, input, controls, camera, exit/entry
- `domain/systems` — Cross-cutting system architecture and integration work
- `domain/tooling` — Build, CI, observer, TTS pipeline, dev-time tools
- `domain/vehicle` — The Samba: vehicle physics, dashboard, damage, panels
- `domain/world` — World model, biomes, terrain, procedural generation, weather
status/*:
- `status/canonical` — Fully authoritative; promoted by humans only. Highest trust. (Agent notes only — spec 080.)
- `status/draft` — Authoring in progress, not yet verified
- `status/reviewed` — Agent-created note verified against codebase within its creating session. Eligible for auto-injection in subsequent task dispatches. (Agent notes only — spec 080.)
- `status/stale` — Known out of date; cannot update immediately. Pairs with `> [!warning] STALE — needs update` callout.
- `status/superseded` — Replaced by another note. Terminal state. Pairs with `> [!warning] SUPERSEDED` callout.
- `status/wip` — Stable but under active revision
layer/*:
- `layer/content` — Content assets (audio, models, textures, audio provenance)
- `layer/gdext` — gdext wrapper layer (`rust/gdext-wrapper/`)
- `layer/gdscript` — GDScript (Godot scene-tier logic)
- `layer/infra` — Build, CI, deployment infrastructure
- `layer/python` — Python development tooling (`tools/`)
- `layer/rust-core` — Engine-agnostic Rust core (`rust/rust-core/`)
concept/*:
- `concept/biome` — Biome-reactive behavior across systems
- `concept/contamination` — Across-runs panel and garage degradation; the slow-horror mechanic that doesn't reset with the world
- `concept/diegetic` — Diegetic audio / UI / world-sourced design
- `concept/disturbance` — The disturbance mechanic thread (Article X)
- `concept/ephemeral-world` — Run-reset, transient worlds (Article IV Rules 6–7)
- `concept/governance` — Constitutional and governance concepts
- `concept/horror` — Horror register and dread design
- `concept/procedural` — Procedural generation, seed determinism
- `concept/rendering` — Visual rendering quality, shader correctness, Terrain3D integration, mesh fidelity, LOD, Z-fighting
- `concept/terrain` — Terrain generation, heightmap, Terrain3D regions, roughness, playability constraints
ember's answer for tag_assignment-decisions-noisehelper-utility-class-design, domain/worldP(true) placed on the no, unsure, and yes zones.nounsureyesgold: yesP = 0.35

tag_assignment-decisions-noisehelper-utility-class-design: type/code

Tag assignment · dev
Gold
The note has no reason to carry `type/code` (False)
ember
The note calls for `type/code`: Code architecture, autoloads, conventions, tooling. Carries `code-refs:`. (e.g. `Code/Autoloads — Disturbance.md`) (True)
Signal
P(true) 0.97 (yes)
Kit outcome
acted on a wrong answer
Why this gold label
Mined from Decisions/NoiseHelper Utility Class Design.md at 692f4bb58b7f62105aeb73fba8dfee12bfdecd53; gold is the note's own vocabulary tags.
NoiseHelper Utility Class Design

This note records the structural decisions made for noise_helper.gd during spec 081 (Code Dedup Consolidation) that are non-obvious from the code alone.

## No extends, No class_name

noise_helper.gd declares neither extends nor class_name. It is accessed exclusively via a preload constant in each consuming file:

    const NoiseHelper = preload("res://scripts/generation/noise_helper.gd")

This pattern was chosen over class_name for two reasons. First, the class_name restriction from the constitution applies to autoloads because of Godot 4.6 singleton name conflicts — noise_helper.gd is not an autoload, so class_name would technically be valid. However, making it a named class creates a global symbol that pollutes the project namespace for what is a narrow utility. Preload constants keep the dependency explicit and local. Second, unlike OGTestBase (which uses class_name intentionally so test files can extend it by name), noise_helper.gd has no inheritance use case — callers call its static factory methods, they do not extend it.

## Dictionary Parameter Convention

The create_roughness_noise factory method accepts all parameters via a Dictionary rather than positional arguments. This means every caller must pass their own @export values explicitly:

    NoiseHelper.create_roughness_noise({"octaves": octaves, "frequency": frequency, ...})

No default values are baked into the helper. This was intentional: the helper exists to eliminate duplicate noise setup code, not to encode defaults. If defaults lived inside the helper, callers that relied on them would become silently coupled to the helper's internal values rather than to their own @export variables. The Dictionary convention keeps designer-tunable parameters visible in the caller's inspector.

## References

- src/scripts/generation/noise_helper.gd
- src/scripts/generation/terrain_generator.gd (consumer)
- src/scripts/generation/heightmap_proxy.gd (consumer)
- docs/vault/Sessions/Spec 081 Implementation Session.md

Controlled tag vocabulary (as read):
type/*:
- `type/code` — Code architecture, autoloads, conventions, tooling. Carries `code-refs:`. (e.g. `Code/Autoloads — Disturbance.md`)
- `type/decision` — Architectural or design decision made by an agent during a session. Written to `docs/vault/Decisions/`. (Agent notes only — spec 080.)
- `type/design` — Design intent, player-facing concepts, world lore. (e.g. `Design/World Model.md`)
- `type/discovery` — Non-obvious constraint, gap, or conflict found by an agent during a session. Written to `docs/vault/Discoveries/`. (Agent notes only — spec 080.)
- `type/moc` — Map of Content at any of three tiers (folder / domain / concept). (e.g. `Audio.md`)
- `type/principle` — Governance and constitutional notes. Non-negotiable rules. (e.g. `Governance/Constitution.md`)
- `type/reference` — Glossary, decision log, open questions, epics. (e.g. `Reference/Glossary.md`)
- `type/session-log` — Session activity log; permanent audit trail. Written to `docs/vault/Sessions/`. Append-only, never pruned. (Agent notes only — spec 080.)
- `type/spec` — Spec document at `docs/vault/Specs/NNN Title/spec.md`. Carries `spec-refs:`. (e.g. `Specs/047 Car Radio/spec.md`)
- `type/system` — A bounded subsystem with implementation. Carries `code-refs`, `spec-refs`, `implements:` frontmatter. (e.g. `Systems/Audio — Car Radio.md`)
- `type/vision` — Strategic / vision-layer decision. Written to `docs/vault/Vision/`. Human-authored or agent-proposed with human ratification before promotion to `status: reviewed`. (Per triage #3 — spec 133 autonomous-company redesign.)
domain/*:
- `domain/anomalies` — Anomaly taxonomy, individual anomaly systems, spawn, behavior
- `domain/art` — Visual direction, palettes, references, asset pipeline
- `domain/audio` — Audio systems: world ambient, radio, transmissions, buses, pipeline
- `domain/autonomous-company` — Autonomous company v0.1 experiment: Slack infra, persona middleware, Letta integration, restart recovery
- `domain/build` — Build system, packaging, export, release automation
- `domain/governance` — Constitution, phased spec, policies
- `domain/infrastructure` — Infrastructure provisioning: CI/CD, hosting, deployment tooling, secrets management
- `domain/narrative` — Tone, horror register, forest transmissions narrative, Gary/KTLK
- `domain/player` — Player mode, input, controls, camera, exit/entry
- `domain/systems` — Cross-cutting system architecture and integration work
- `domain/tooling` — Build, CI, observer, TTS pipeline, dev-time tools
- `domain/vehicle` — The Samba: vehicle physics, dashboard, damage, panels
- `domain/world` — World model, biomes, terrain, procedural generation, weather
status/*:
- `status/canonical` — Fully authoritative; promoted by humans only. Highest trust. (Agent notes only — spec 080.)
- `status/draft` — Authoring in progress, not yet verified
- `status/reviewed` — Agent-created note verified against codebase within its creating session. Eligible for auto-injection in subsequent task dispatches. (Agent notes only — spec 080.)
- `status/stale` — Known out of date; cannot update immediately. Pairs with `> [!warning] STALE — needs update` callout.
- `status/superseded` — Replaced by another note. Terminal state. Pairs with `> [!warning] SUPERSEDED` callout.
- `status/wip` — Stable but under active revision
layer/*:
- `layer/content` — Content assets (audio, models, textures, audio provenance)
- `layer/gdext` — gdext wrapper layer (`rust/gdext-wrapper/`)
- `layer/gdscript` — GDScript (Godot scene-tier logic)
- `layer/infra` — Build, CI, deployment infrastructure
- `layer/python` — Python development tooling (`tools/`)
- `layer/rust-core` — Engine-agnostic Rust core (`rust/rust-core/`)
concept/*:
- `concept/biome` — Biome-reactive behavior across systems
- `concept/contamination` — Across-runs panel and garage degradation; the slow-horror mechanic that doesn't reset with the world
- `concept/diegetic` — Diegetic audio / UI / world-sourced design
- `concept/disturbance` — The disturbance mechanic thread (Article X)
- `concept/ephemeral-world` — Run-reset, transient worlds (Article IV Rules 6–7)
- `concept/governance` — Constitutional and governance concepts
- `concept/horror` — Horror register and dread design
- `concept/procedural` — Procedural generation, seed determinism
- `concept/rendering` — Visual rendering quality, shader correctness, Terrain3D integration, mesh fidelity, LOD, Z-fighting
- `concept/terrain` — Terrain generation, heightmap, Terrain3D regions, roughness, playability constraints
ember's answer for tag_assignment-decisions-noisehelper-utility-class-design, type/codeP(true) placed on the no, unsure, and yes zones.nounsureyesgold: noP = 0.97

tag_assignment-decisions-noisehelper-utility-class-design: type/decision

Tag assignment · dev
Gold
The note calls for `type/decision`: Architectural or design decision made by an agent during a session. Written to `docs/vault/Decisions/`. (Agent notes only — spec 080.) (True)
ember
The note has no reason to carry `type/decision` (False)
Signal
P(true) 0.27 (unsure)
Kit outcome
deferred: treated as unsure
Why this gold label
Mined from Decisions/NoiseHelper Utility Class Design.md at 692f4bb58b7f62105aeb73fba8dfee12bfdecd53; gold is the note's own vocabulary tags.
NoiseHelper Utility Class Design

This note records the structural decisions made for noise_helper.gd during spec 081 (Code Dedup Consolidation) that are non-obvious from the code alone.

## No extends, No class_name

noise_helper.gd declares neither extends nor class_name. It is accessed exclusively via a preload constant in each consuming file:

    const NoiseHelper = preload("res://scripts/generation/noise_helper.gd")

This pattern was chosen over class_name for two reasons. First, the class_name restriction from the constitution applies to autoloads because of Godot 4.6 singleton name conflicts — noise_helper.gd is not an autoload, so class_name would technically be valid. However, making it a named class creates a global symbol that pollutes the project namespace for what is a narrow utility. Preload constants keep the dependency explicit and local. Second, unlike OGTestBase (which uses class_name intentionally so test files can extend it by name), noise_helper.gd has no inheritance use case — callers call its static factory methods, they do not extend it.

## Dictionary Parameter Convention

The create_roughness_noise factory method accepts all parameters via a Dictionary rather than positional arguments. This means every caller must pass their own @export values explicitly:

    NoiseHelper.create_roughness_noise({"octaves": octaves, "frequency": frequency, ...})

No default values are baked into the helper. This was intentional: the helper exists to eliminate duplicate noise setup code, not to encode defaults. If defaults lived inside the helper, callers that relied on them would become silently coupled to the helper's internal values rather than to their own @export variables. The Dictionary convention keeps designer-tunable parameters visible in the caller's inspector.

## References

- src/scripts/generation/noise_helper.gd
- src/scripts/generation/terrain_generator.gd (consumer)
- src/scripts/generation/heightmap_proxy.gd (consumer)
- docs/vault/Sessions/Spec 081 Implementation Session.md

Controlled tag vocabulary (as read):
type/*:
- `type/code` — Code architecture, autoloads, conventions, tooling. Carries `code-refs:`. (e.g. `Code/Autoloads — Disturbance.md`)
- `type/decision` — Architectural or design decision made by an agent during a session. Written to `docs/vault/Decisions/`. (Agent notes only — spec 080.)
- `type/design` — Design intent, player-facing concepts, world lore. (e.g. `Design/World Model.md`)
- `type/discovery` — Non-obvious constraint, gap, or conflict found by an agent during a session. Written to `docs/vault/Discoveries/`. (Agent notes only — spec 080.)
- `type/moc` — Map of Content at any of three tiers (folder / domain / concept). (e.g. `Audio.md`)
- `type/principle` — Governance and constitutional notes. Non-negotiable rules. (e.g. `Governance/Constitution.md`)
- `type/reference` — Glossary, decision log, open questions, epics. (e.g. `Reference/Glossary.md`)
- `type/session-log` — Session activity log; permanent audit trail. Written to `docs/vault/Sessions/`. Append-only, never pruned. (Agent notes only — spec 080.)
- `type/spec` — Spec document at `docs/vault/Specs/NNN Title/spec.md`. Carries `spec-refs:`. (e.g. `Specs/047 Car Radio/spec.md`)
- `type/system` — A bounded subsystem with implementation. Carries `code-refs`, `spec-refs`, `implements:` frontmatter. (e.g. `Systems/Audio — Car Radio.md`)
- `type/vision` — Strategic / vision-layer decision. Written to `docs/vault/Vision/`. Human-authored or agent-proposed with human ratification before promotion to `status: reviewed`. (Per triage #3 — spec 133 autonomous-company redesign.)
domain/*:
- `domain/anomalies` — Anomaly taxonomy, individual anomaly systems, spawn, behavior
- `domain/art` — Visual direction, palettes, references, asset pipeline
- `domain/audio` — Audio systems: world ambient, radio, transmissions, buses, pipeline
- `domain/autonomous-company` — Autonomous company v0.1 experiment: Slack infra, persona middleware, Letta integration, restart recovery
- `domain/build` — Build system, packaging, export, release automation
- `domain/governance` — Constitution, phased spec, policies
- `domain/infrastructure` — Infrastructure provisioning: CI/CD, hosting, deployment tooling, secrets management
- `domain/narrative` — Tone, horror register, forest transmissions narrative, Gary/KTLK
- `domain/player` — Player mode, input, controls, camera, exit/entry
- `domain/systems` — Cross-cutting system architecture and integration work
- `domain/tooling` — Build, CI, observer, TTS pipeline, dev-time tools
- `domain/vehicle` — The Samba: vehicle physics, dashboard, damage, panels
- `domain/world` — World model, biomes, terrain, procedural generation, weather
status/*:
- `status/canonical` — Fully authoritative; promoted by humans only. Highest trust. (Agent notes only — spec 080.)
- `status/draft` — Authoring in progress, not yet verified
- `status/reviewed` — Agent-created note verified against codebase within its creating session. Eligible for auto-injection in subsequent task dispatches. (Agent notes only — spec 080.)
- `status/stale` — Known out of date; cannot update immediately. Pairs with `> [!warning] STALE — needs update` callout.
- `status/superseded` — Replaced by another note. Terminal state. Pairs with `> [!warning] SUPERSEDED` callout.
- `status/wip` — Stable but under active revision
layer/*:
- `layer/content` — Content assets (audio, models, textures, audio provenance)
- `layer/gdext` — gdext wrapper layer (`rust/gdext-wrapper/`)
- `layer/gdscript` — GDScript (Godot scene-tier logic)
- `layer/infra` — Build, CI, deployment infrastructure
- `layer/python` — Python development tooling (`tools/`)
- `layer/rust-core` — Engine-agnostic Rust core (`rust/rust-core/`)
concept/*:
- `concept/biome` — Biome-reactive behavior across systems
- `concept/contamination` — Across-runs panel and garage degradation; the slow-horror mechanic that doesn't reset with the world
- `concept/diegetic` — Diegetic audio / UI / world-sourced design
- `concept/disturbance` — The disturbance mechanic thread (Article X)
- `concept/ephemeral-world` — Run-reset, transient worlds (Article IV Rules 6–7)
- `concept/governance` — Constitutional and governance concepts
- `concept/horror` — Horror register and dread design
- `concept/procedural` — Procedural generation, seed determinism
- `concept/rendering` — Visual rendering quality, shader correctness, Terrain3D integration, mesh fidelity, LOD, Z-fighting
- `concept/terrain` — Terrain generation, heightmap, Terrain3D regions, roughness, playability constraints
ember's answer for tag_assignment-decisions-noisehelper-utility-class-design, type/decisionP(true) placed on the no, unsure, and yes zones.nounsureyesgold: yesP = 0.27

tag_assignment-design-disturbance-system: domain/world

Tag assignment · test
Gold
The note calls for `domain/world`: World model, biomes, terrain, procedural generation, weather (True)
ember
The note has no reason to carry `domain/world` (False)
Signal
P(true) 0.19 (no)
Kit outcome
acted on a wrong answer
Why this gold label
Mined from Design/Disturbance System.md at 692f4bb58b7f62105aeb73fba8dfee12bfdecd53; gold is the note's own vocabulary tags.
Disturbance System

The disturbance meter is Old Growth's central tension engine. It is not a health bar, not a resource gauge — it is a hidden 0–100 metric that measures how much the forest notices the player. This note captures the design intent AND the full mechanical specification (biological states, disturbance costs, diegetic indicators, Storm behavior). Implementation: [[Autoloads — Disturbance]].

## Overview

The forest does not have a temper. It has a metabolism.

Everything in the woods is input to a process that runs continuously and has been running since before the first road was cut through this watershed. The player's presence feeds this process from the moment they enter the tree line. Every action — collection, combustion, impact, noise — is an input the forest attends to, and attendance accelerates the process.

## Design Intent

This is not punishment. A fallen log feeds the same process. The player is simply a more active source. The disturbance system exists to make the **condition visible through its consequences** rather than through a dedicated UI display. The forest does not provide one. It expects you to have been paying attention.

The constitutional basis is Article X — The Disturbance Is the Design:
> The disturbance system is the primary tension engine. Tension MUST be cycled — not held at a constant level. The forest MUST have moments of apparent safety (negative feedback loop releasing) before escalating again.

## Key Decisions

### Meter

| Property | Value |
|---|---|
| Range | 0 – 100 |
| Display | None. Never shown directly. |
| In-run reset | None. Never resets during a run. |
| Cross-run behavior | Resets to 0 at run start |
| Read mechanism | Bus behavior, condition presence, audio register shifts, instrument reliability |

Players read disturbance state through environmental cues, not through any HUD element.

### Biological States

| State | Meter Range | Bus Behavior | Condition Presence | Audio |
|---|---|---|---|---|
| Calm | 0–30 | Normal | Ambient, diffuse | Normal biome ambience |
| Uneasy | 30–60 | Instruments drift slightly | Heightened, directional | Ambience shifts register, lower frequencies |
| Agitated | 60–85 | Instruments unreliable, engine hesitant | Dense, attending | Ambience becomes directional, pulse-like |
| Storm | 85–100 | Electrical instability | Maximum concentration | All frequencies collapse inward |

At 85, the Storm spawns regardless of player position. The Storm state does not have a stable ceiling — it triggers immediately.

### Disturbance Costs (complete table)

| Action | Disturbance Added |
|---|---|
| Fuel canister collected | +3 |
| Repair kit collected | +4 |
| Medkit collected | +5 |
| Flashlight battery collected | +3 |
| Flare gun collected | +3 |
| Flare gun fired | +6 |
| Rock thrown | +0.5 |
| Road contact at speed (condition dispersal) | +5 |
| Engine revving (high RPM) | +1 per second |
| Headlights active | +0.2 per second |
| Flashlight active | +0.2 per second |
| Horn | +3 |
| Player sprinting on foot | +0.5 per second |
| Exiting vehicle | +2 |
| Vehicle collision | +2 |
| Mycelium Network contact | +4 |
| Deadfall triggered | +2 |
| Entering Petrifold (first crossing per run) | +3 |
| Entering Fungal Depths (first crossing per run) | +0 — transition is passive |

### Diegetic Disturbance Indicators

No HUD. Players learn to read:

- **Bus instruments**: drift and jitter increase with disturbance state. At Agitated, instruments become unreliable.
- **Engine audio**: hesitation and irregularity at Agitated. Instability at Storm.
- **Ambient audio**: low-frequency content increases. The forest gets quieter in the wrong way. The sense of being attended-to increases, though this cannot be instrumented.
- **Radio**: signal degradation is driven by both biome depth AND disturbance. Heavy static in Verdant indicates Uneasy or higher. In Fungal Depths, signal degradation is biome-baseline regardless of disturbance — its absence there is not a reliable disturbance indicator.
- **Windshield accumulation**: particulate and biological matter accumulate faster at higher disturbance.
- **Perception**: at high disturbance AND high exposure, familiar routes feel different. Whether this is the condition or the player is not distinguishable by any available instrument.

### Tension-Release Cycles (Article X Rule)

Tension MUST be cycled — not held at a constant level. The forest MUST have moments of apparent safety (negative feedback loop releasing) before escalating again. Per Article XII-J: a horror experience that never releases becomes numbing within minutes.

Within a run, the meter can only climb — but the *experienced* tension releases when the player finds moments of momentum (driving cleanly, avoiding a Deadfall), audio pockets of quiet (between anomaly zones), or successful on-foot collection. The metabolism continues; the player's felt-state relaxes briefly before the next climb.

### Biome-Reactive Response

Each [[Biomes|biome]] has a distinct disturbance response profile (see [[Biome Behavior]] concept thread). The same player action may feed the process differently in Fungal Depths than in Verdant Old Growth. The audio arc, radio degradation curve, and anomaly expression all vary per biome even for the same disturbance level.

### The Storm (Finishing State)

The Storm spawns when the disturbance meter reaches 85. It cannot be cancelled or reversed after spawning.

| Property | Value |
|---|---|
| Trigger threshold | 85 disturbance |
| Spawn location | Crater rim, opposite side from nearest exit corridor (terraforming energy radiates inward from the reshape boundary) |
| Initial speed | 20 km/h |
| Speed acceleration | +5 km/h per 20 seconds |
| Maximum speed | 80 km/h (reached at ~4 minutes) |
| Width | Full crater width — no flanking |
| Player damage inside | 30 HP/sec |
| Van damage inside | 15 HP/sec |
| Tree behavior in path | Incorporated (visual effect, not obstacle) |
| Audio pre-visualization | Subsonic rumble → ambience collapse → silence → Storm |

**Survival window**: from spawn, the player has a meaningful survival window if already near an exit. The window narrows based on distance from exit and current speed. A player at the far end of the map must drive hard and without detours to extract.

The Storm is not avoidable through off-road detours — it spans the full crater width. The only variable is speed toward an exit corridor.

If the player is caught and survives the initial damage (possible at full health), the bus will be destroyed within seconds. On-foot survival inside the Storm is not possible.

### Designer-Tunable

Per Article VI Rule 3 / Article XII-J: tension-release cycles MUST be tunable via `@export` variables. Thresholds for Ambient → Directed → Cascade → Finishing (implemented as Calm → Uneasy → Agitated → Storm) are exposed for design iteration. Config lives in `res://resources/config/disturbance_config.tres` per spec 078.

### Irreversibility

The process never resets during a run. Inputs already fed cannot be recalled. The forest does not forget in the way that implies it was paying attention to begin with — it simply continues, and what has already entered the system has already changed the system.

Across runs, the condition accumulates via the garage contamination axis (see [[World Model]] / [[Narrative Direction]]) — a persistent value the player has no direct way to read but which progressively changes the garage and the bus.

## How It Appears In-Game

The player does not see a number. They see (and hear) consequences:

- Audio degrades on the radio; the bus sounds change
- Anomalies intensify
- Weather worsens
- What moves in the wood gets closer and less cautious
- Eventually, the Storm spawns from the ridgeline and moves toward the player

The Storm is the disturbance reaching Finishing — see [[The Player Causes the Storm]].

## Related

- [[The Crater]] — the origin event whose dimensional energy the disturbance meter measures
- [[The Temporal Fracture]] — disturbance as temporal destabilization; the Storm as ongoing insertion unfiltered
- [[World Model]] — the world the disturbance operates in
- [[Tone and Horror]] — dread-over-shock framing
- [[Core Mechanics]] — the run loop that drives disturbance accumulation
- [[Autoloads — Disturbance]] — the GDScript + Rust implementation
- [[Audio — Car Radio]] — radio degradation as diegetic disturbance readout
- [[Audio — World Audio]] — four-state ambient audio arc
- [[The Disturbance Thread]] — cross-cutting concept thread
- [[The Player Causes the Storm]] — the endgame manifestation
- [[Constitution]] — Article X is the authoritative source, Article XII-J (horror rhythm)

Controlled tag vocabulary (as read):
type/*:
- `type/code` — Code architecture, autoloads, conventions, tooling. Carries `code-refs:`. (e.g. `Code/Autoloads — Disturbance.md`)
- `type/decision` — Architectural or design decision made by an agent during a session. Written to `docs/vault/Decisions/`. (Agent notes only — spec 080.)
- `type/design` — Design intent, player-facing concepts, world lore. (e.g. `Design/World Model.md`)
- `type/discovery` — Non-obvious constraint, gap, or conflict found by an agent during a session. Written to `docs/vault/Discoveries/`. (Agent notes only — spec 080.)
- `type/moc` — Map of Content at any of three tiers (folder / domain / concept). (e.g. `Audio.md`)
- `type/principle` — Governance and constitutional notes. Non-negotiable rules. (e.g. `Governance/Constitution.md`)
- `type/reference` — Glossary, decision log, open questions, epics. (e.g. `Reference/Glossary.md`)
- `type/session-log` — Session activity log; permanent audit trail. Written to `docs/vault/Sessions/`. Append-only, never pruned. (Agent notes only — spec 080.)
- `type/spec` — Spec document at `docs/vault/Specs/NNN Title/spec.md`. Carries `spec-refs:`. (e.g. `Specs/047 Car Radio/spec.md`)
- `type/system` — A bounded subsystem with implementation. Carries `code-refs`, `spec-refs`, `implements:` frontmatter. (e.g. `Systems/Audio — Car Radio.md`)
- `type/vision` — Strategic / vision-layer decision. Written to `docs/vault/Vision/`. Human-authored or agent-proposed with human ratification before promotion to `status: reviewed`. (Per triage #3 — spec 133 autonomous-company redesign.)
domain/*:
- `domain/anomalies` — Anomaly taxonomy, individual anomaly systems, spawn, behavior
- `domain/art` — Visual direction, palettes, references, asset pipeline
- `domain/audio` — Audio systems: world ambient, radio, transmissions, buses, pipeline
- `domain/autonomous-company` — Autonomous company v0.1 experiment: Slack infra, persona middleware, Letta integration, restart recovery
- `domain/build` — Build system, packaging, export, release automation
- `domain/governance` — Constitution, phased spec, policies
- `domain/infrastructure` — Infrastructure provisioning: CI/CD, hosting, deployment tooling, secrets management
- `domain/narrative` — Tone, horror register, forest transmissions narrative, Gary/KTLK
- `domain/player` — Player mode, input, controls, camera, exit/entry
- `domain/systems` — Cross-cutting system architecture and integration work
- `domain/tooling` — Build, CI, observer, TTS pipeline, dev-time tools
- `domain/vehicle` — The Samba: vehicle physics, dashboard, damage, panels
- `domain/world` — World model, biomes, terrain, procedural generation, weather
status/*:
- `status/canonical` — Fully authoritative; promoted by humans only. Highest trust. (Agent notes only — spec 080.)
- `status/draft` — Authoring in progress, not yet verified
- `status/reviewed` — Agent-created note verified against codebase within its creating session. Eligible for auto-injection in subsequent task dispatches. (Agent notes only — spec 080.)
- `status/stale` — Known out of date; cannot update immediately. Pairs with `> [!warning] STALE — needs update` callout.
- `status/superseded` — Replaced by another note. Terminal state. Pairs with `> [!warning] SUPERSEDED` callout.
- `status/wip` — Stable but under active revision
layer/*:
- `layer/content` — Content assets (audio, models, textures, audio provenance)
- `layer/gdext` — gdext wrapper layer (`rust/gdext-wrapper/`)
- `layer/gdscript` — GDScript (Godot scene-tier logic)
- `layer/infra` — Build, CI, deployment infrastructure
- `layer/python` — Python development tooling (`tools/`)
- `layer/rust-core` — Engine-agnostic Rust core (`rust/rust-core/`)
concept/*:
- `concept/biome` — Biome-reactive behavior across systems
- `concept/contamination` — Across-runs panel and garage degradation; the slow-horror mechanic that doesn't reset with the world
- `concept/diegetic` — Diegetic audio / UI / world-sourced design
- `concept/disturbance` — The disturbance mechanic thread (Article X)
- `concept/ephemeral-world` — Run-reset, transient worlds (Article IV Rules 6–7)
- `concept/governance` — Constitutional and governance concepts
- `concept/horror` — Horror register and dread design
- `concept/procedural` — Procedural generation, seed determinism
- `concept/rendering` — Visual rendering quality, shader correctness, Terrain3D integration, mesh fidelity, LOD, Z-fighting
- `concept/terrain` — Terrain generation, heightmap, Terrain3D regions, roughness, playability constraints
ember's answer for tag_assignment-design-disturbance-system, domain/worldP(true) placed on the no, unsure, and yes zones.nounsureyesgold: yesP = 0.19

tag_assignment-design-disturbance-system: type/code

Tag assignment · test
Gold
The note has no reason to carry `type/code` (False)
ember
The note calls for `type/code`: Code architecture, autoloads, conventions, tooling. Carries `code-refs:`. (e.g. `Code/Autoloads — Disturbance.md`) (True)
Signal
P(true) 0.63 (unsure)
Kit outcome
deferred: treated as unsure
Why this gold label
Mined from Design/Disturbance System.md at 692f4bb58b7f62105aeb73fba8dfee12bfdecd53; gold is the note's own vocabulary tags.
Disturbance System

The disturbance meter is Old Growth's central tension engine. It is not a health bar, not a resource gauge — it is a hidden 0–100 metric that measures how much the forest notices the player. This note captures the design intent AND the full mechanical specification (biological states, disturbance costs, diegetic indicators, Storm behavior). Implementation: [[Autoloads — Disturbance]].

## Overview

The forest does not have a temper. It has a metabolism.

Everything in the woods is input to a process that runs continuously and has been running since before the first road was cut through this watershed. The player's presence feeds this process from the moment they enter the tree line. Every action — collection, combustion, impact, noise — is an input the forest attends to, and attendance accelerates the process.

## Design Intent

This is not punishment. A fallen log feeds the same process. The player is simply a more active source. The disturbance system exists to make the **condition visible through its consequences** rather than through a dedicated UI display. The forest does not provide one. It expects you to have been paying attention.

The constitutional basis is Article X — The Disturbance Is the Design:
> The disturbance system is the primary tension engine. Tension MUST be cycled — not held at a constant level. The forest MUST have moments of apparent safety (negative feedback loop releasing) before escalating again.

## Key Decisions

### Meter

| Property | Value |
|---|---|
| Range | 0 – 100 |
| Display | None. Never shown directly. |
| In-run reset | None. Never resets during a run. |
| Cross-run behavior | Resets to 0 at run start |
| Read mechanism | Bus behavior, condition presence, audio register shifts, instrument reliability |

Players read disturbance state through environmental cues, not through any HUD element.

### Biological States

| State | Meter Range | Bus Behavior | Condition Presence | Audio |
|---|---|---|---|---|
| Calm | 0–30 | Normal | Ambient, diffuse | Normal biome ambience |
| Uneasy | 30–60 | Instruments drift slightly | Heightened, directional | Ambience shifts register, lower frequencies |
| Agitated | 60–85 | Instruments unreliable, engine hesitant | Dense, attending | Ambience becomes directional, pulse-like |
| Storm | 85–100 | Electrical instability | Maximum concentration | All frequencies collapse inward |

At 85, the Storm spawns regardless of player position. The Storm state does not have a stable ceiling — it triggers immediately.

### Disturbance Costs (complete table)

| Action | Disturbance Added |
|---|---|
| Fuel canister collected | +3 |
| Repair kit collected | +4 |
| Medkit collected | +5 |
| Flashlight battery collected | +3 |
| Flare gun collected | +3 |
| Flare gun fired | +6 |
| Rock thrown | +0.5 |
| Road contact at speed (condition dispersal) | +5 |
| Engine revving (high RPM) | +1 per second |
| Headlights active | +0.2 per second |
| Flashlight active | +0.2 per second |
| Horn | +3 |
| Player sprinting on foot | +0.5 per second |
| Exiting vehicle | +2 |
| Vehicle collision | +2 |
| Mycelium Network contact | +4 |
| Deadfall triggered | +2 |
| Entering Petrifold (first crossing per run) | +3 |
| Entering Fungal Depths (first crossing per run) | +0 — transition is passive |

### Diegetic Disturbance Indicators

No HUD. Players learn to read:

- **Bus instruments**: drift and jitter increase with disturbance state. At Agitated, instruments become unreliable.
- **Engine audio**: hesitation and irregularity at Agitated. Instability at Storm.
- **Ambient audio**: low-frequency content increases. The forest gets quieter in the wrong way. The sense of being attended-to increases, though this cannot be instrumented.
- **Radio**: signal degradation is driven by both biome depth AND disturbance. Heavy static in Verdant indicates Uneasy or higher. In Fungal Depths, signal degradation is biome-baseline regardless of disturbance — its absence there is not a reliable disturbance indicator.
- **Windshield accumulation**: particulate and biological matter accumulate faster at higher disturbance.
- **Perception**: at high disturbance AND high exposure, familiar routes feel different. Whether this is the condition or the player is not distinguishable by any available instrument.

### Tension-Release Cycles (Article X Rule)

Tension MUST be cycled — not held at a constant level. The forest MUST have moments of apparent safety (negative feedback loop releasing) before escalating again. Per Article XII-J: a horror experience that never releases becomes numbing within minutes.

Within a run, the meter can only climb — but the *experienced* tension releases when the player finds moments of momentum (driving cleanly, avoiding a Deadfall), audio pockets of quiet (between anomaly zones), or successful on-foot collection. The metabolism continues; the player's felt-state relaxes briefly before the next climb.

### Biome-Reactive Response

Each [[Biomes|biome]] has a distinct disturbance response profile (see [[Biome Behavior]] concept thread). The same player action may feed the process differently in Fungal Depths than in Verdant Old Growth. The audio arc, radio degradation curve, and anomaly expression all vary per biome even for the same disturbance level.

### The Storm (Finishing State)

The Storm spawns when the disturbance meter reaches 85. It cannot be cancelled or reversed after spawning.

| Property | Value |
|---|---|
| Trigger threshold | 85 disturbance |
| Spawn location | Crater rim, opposite side from nearest exit corridor (terraforming energy radiates inward from the reshape boundary) |
| Initial speed | 20 km/h |
| Speed acceleration | +5 km/h per 20 seconds |
| Maximum speed | 80 km/h (reached at ~4 minutes) |
| Width | Full crater width — no flanking |
| Player damage inside | 30 HP/sec |
| Van damage inside | 15 HP/sec |
| Tree behavior in path | Incorporated (visual effect, not obstacle) |
| Audio pre-visualization | Subsonic rumble → ambience collapse → silence → Storm |

**Survival window**: from spawn, the player has a meaningful survival window if already near an exit. The window narrows based on distance from exit and current speed. A player at the far end of the map must drive hard and without detours to extract.

The Storm is not avoidable through off-road detours — it spans the full crater width. The only variable is speed toward an exit corridor.

If the player is caught and survives the initial damage (possible at full health), the bus will be destroyed within seconds. On-foot survival inside the Storm is not possible.

### Designer-Tunable

Per Article VI Rule 3 / Article XII-J: tension-release cycles MUST be tunable via `@export` variables. Thresholds for Ambient → Directed → Cascade → Finishing (implemented as Calm → Uneasy → Agitated → Storm) are exposed for design iteration. Config lives in `res://resources/config/disturbance_config.tres` per spec 078.

### Irreversibility

The process never resets during a run. Inputs already fed cannot be recalled. The forest does not forget in the way that implies it was paying attention to begin with — it simply continues, and what has already entered the system has already changed the system.

Across runs, the condition accumulates via the garage contamination axis (see [[World Model]] / [[Narrative Direction]]) — a persistent value the player has no direct way to read but which progressively changes the garage and the bus.

## How It Appears In-Game

The player does not see a number. They see (and hear) consequences:

- Audio degrades on the radio; the bus sounds change
- Anomalies intensify
- Weather worsens
- What moves in the wood gets closer and less cautious
- Eventually, the Storm spawns from the ridgeline and moves toward the player

The Storm is the disturbance reaching Finishing — see [[The Player Causes the Storm]].

## Related

- [[The Crater]] — the origin event whose dimensional energy the disturbance meter measures
- [[The Temporal Fracture]] — disturbance as temporal destabilization; the Storm as ongoing insertion unfiltered
- [[World Model]] — the world the disturbance operates in
- [[Tone and Horror]] — dread-over-shock framing
- [[Core Mechanics]] — the run loop that drives disturbance accumulation
- [[Autoloads — Disturbance]] — the GDScript + Rust implementation
- [[Audio — Car Radio]] — radio degradation as diegetic disturbance readout
- [[Audio — World Audio]] — four-state ambient audio arc
- [[The Disturbance Thread]] — cross-cutting concept thread
- [[The Player Causes the Storm]] — the endgame manifestation
- [[Constitution]] — Article X is the authoritative source, Article XII-J (horror rhythm)

Controlled tag vocabulary (as read):
type/*:
- `type/code` — Code architecture, autoloads, conventions, tooling. Carries `code-refs:`. (e.g. `Code/Autoloads — Disturbance.md`)
- `type/decision` — Architectural or design decision made by an agent during a session. Written to `docs/vault/Decisions/`. (Agent notes only — spec 080.)
- `type/design` — Design intent, player-facing concepts, world lore. (e.g. `Design/World Model.md`)
- `type/discovery` — Non-obvious constraint, gap, or conflict found by an agent during a session. Written to `docs/vault/Discoveries/`. (Agent notes only — spec 080.)
- `type/moc` — Map of Content at any of three tiers (folder / domain / concept). (e.g. `Audio.md`)
- `type/principle` — Governance and constitutional notes. Non-negotiable rules. (e.g. `Governance/Constitution.md`)
- `type/reference` — Glossary, decision log, open questions, epics. (e.g. `Reference/Glossary.md`)
- `type/session-log` — Session activity log; permanent audit trail. Written to `docs/vault/Sessions/`. Append-only, never pruned. (Agent notes only — spec 080.)
- `type/spec` — Spec document at `docs/vault/Specs/NNN Title/spec.md`. Carries `spec-refs:`. (e.g. `Specs/047 Car Radio/spec.md`)
- `type/system` — A bounded subsystem with implementation. Carries `code-refs`, `spec-refs`, `implements:` frontmatter. (e.g. `Systems/Audio — Car Radio.md`)
- `type/vision` — Strategic / vision-layer decision. Written to `docs/vault/Vision/`. Human-authored or agent-proposed with human ratification before promotion to `status: reviewed`. (Per triage #3 — spec 133 autonomous-company redesign.)
domain/*:
- `domain/anomalies` — Anomaly taxonomy, individual anomaly systems, spawn, behavior
- `domain/art` — Visual direction, palettes, references, asset pipeline
- `domain/audio` — Audio systems: world ambient, radio, transmissions, buses, pipeline
- `domain/autonomous-company` — Autonomous company v0.1 experiment: Slack infra, persona middleware, Letta integration, restart recovery
- `domain/build` — Build system, packaging, export, release automation
- `domain/governance` — Constitution, phased spec, policies
- `domain/infrastructure` — Infrastructure provisioning: CI/CD, hosting, deployment tooling, secrets management
- `domain/narrative` — Tone, horror register, forest transmissions narrative, Gary/KTLK
- `domain/player` — Player mode, input, controls, camera, exit/entry
- `domain/systems` — Cross-cutting system architecture and integration work
- `domain/tooling` — Build, CI, observer, TTS pipeline, dev-time tools
- `domain/vehicle` — The Samba: vehicle physics, dashboard, damage, panels
- `domain/world` — World model, biomes, terrain, procedural generation, weather
status/*:
- `status/canonical` — Fully authoritative; promoted by humans only. Highest trust. (Agent notes only — spec 080.)
- `status/draft` — Authoring in progress, not yet verified
- `status/reviewed` — Agent-created note verified against codebase within its creating session. Eligible for auto-injection in subsequent task dispatches. (Agent notes only — spec 080.)
- `status/stale` — Known out of date; cannot update immediately. Pairs with `> [!warning] STALE — needs update` callout.
- `status/superseded` — Replaced by another note. Terminal state. Pairs with `> [!warning] SUPERSEDED` callout.
- `status/wip` — Stable but under active revision
layer/*:
- `layer/content` — Content assets (audio, models, textures, audio provenance)
- `layer/gdext` — gdext wrapper layer (`rust/gdext-wrapper/`)
- `layer/gdscript` — GDScript (Godot scene-tier logic)
- `layer/infra` — Build, CI, deployment infrastructure
- `layer/python` — Python development tooling (`tools/`)
- `layer/rust-core` — Engine-agnostic Rust core (`rust/rust-core/`)
concept/*:
- `concept/biome` — Biome-reactive behavior across systems
- `concept/contamination` — Across-runs panel and garage degradation; the slow-horror mechanic that doesn't reset with the world
- `concept/diegetic` — Diegetic audio / UI / world-sourced design
- `concept/disturbance` — The disturbance mechanic thread (Article X)
- `concept/ephemeral-world` — Run-reset, transient worlds (Article IV Rules 6–7)
- `concept/governance` — Constitutional and governance concepts
- `concept/horror` — Horror register and dread design
- `concept/procedural` — Procedural generation, seed determinism
- `concept/rendering` — Visual rendering quality, shader correctness, Terrain3D integration, mesh fidelity, LOD, Z-fighting
- `concept/terrain` — Terrain generation, heightmap, Terrain3D regions, roughness, playability constraints
ember's answer for tag_assignment-design-disturbance-system, type/codeP(true) placed on the no, unsure, and yes zones.nounsureyesgold: noP = 0.63

tag_assignment-design-disturbance-system: type/design

Tag assignment · test
Gold
The note calls for `type/design`: Design intent, player-facing concepts, world lore. (e.g. `Design/World Model.md`) (True)
ember
The note has no reason to carry `type/design` (False)
Signal
P(true) 0.47 (unsure)
Kit outcome
deferred: treated as unsure
Why this gold label
Mined from Design/Disturbance System.md at 692f4bb58b7f62105aeb73fba8dfee12bfdecd53; gold is the note's own vocabulary tags.
Disturbance System

The disturbance meter is Old Growth's central tension engine. It is not a health bar, not a resource gauge — it is a hidden 0–100 metric that measures how much the forest notices the player. This note captures the design intent AND the full mechanical specification (biological states, disturbance costs, diegetic indicators, Storm behavior). Implementation: [[Autoloads — Disturbance]].

## Overview

The forest does not have a temper. It has a metabolism.

Everything in the woods is input to a process that runs continuously and has been running since before the first road was cut through this watershed. The player's presence feeds this process from the moment they enter the tree line. Every action — collection, combustion, impact, noise — is an input the forest attends to, and attendance accelerates the process.

## Design Intent

This is not punishment. A fallen log feeds the same process. The player is simply a more active source. The disturbance system exists to make the **condition visible through its consequences** rather than through a dedicated UI display. The forest does not provide one. It expects you to have been paying attention.

The constitutional basis is Article X — The Disturbance Is the Design:
> The disturbance system is the primary tension engine. Tension MUST be cycled — not held at a constant level. The forest MUST have moments of apparent safety (negative feedback loop releasing) before escalating again.

## Key Decisions

### Meter

| Property | Value |
|---|---|
| Range | 0 – 100 |
| Display | None. Never shown directly. |
| In-run reset | None. Never resets during a run. |
| Cross-run behavior | Resets to 0 at run start |
| Read mechanism | Bus behavior, condition presence, audio register shifts, instrument reliability |

Players read disturbance state through environmental cues, not through any HUD element.

### Biological States

| State | Meter Range | Bus Behavior | Condition Presence | Audio |
|---|---|---|---|---|
| Calm | 0–30 | Normal | Ambient, diffuse | Normal biome ambience |
| Uneasy | 30–60 | Instruments drift slightly | Heightened, directional | Ambience shifts register, lower frequencies |
| Agitated | 60–85 | Instruments unreliable, engine hesitant | Dense, attending | Ambience becomes directional, pulse-like |
| Storm | 85–100 | Electrical instability | Maximum concentration | All frequencies collapse inward |

At 85, the Storm spawns regardless of player position. The Storm state does not have a stable ceiling — it triggers immediately.

### Disturbance Costs (complete table)

| Action | Disturbance Added |
|---|---|
| Fuel canister collected | +3 |
| Repair kit collected | +4 |
| Medkit collected | +5 |
| Flashlight battery collected | +3 |
| Flare gun collected | +3 |
| Flare gun fired | +6 |
| Rock thrown | +0.5 |
| Road contact at speed (condition dispersal) | +5 |
| Engine revving (high RPM) | +1 per second |
| Headlights active | +0.2 per second |
| Flashlight active | +0.2 per second |
| Horn | +3 |
| Player sprinting on foot | +0.5 per second |
| Exiting vehicle | +2 |
| Vehicle collision | +2 |
| Mycelium Network contact | +4 |
| Deadfall triggered | +2 |
| Entering Petrifold (first crossing per run) | +3 |
| Entering Fungal Depths (first crossing per run) | +0 — transition is passive |

### Diegetic Disturbance Indicators

No HUD. Players learn to read:

- **Bus instruments**: drift and jitter increase with disturbance state. At Agitated, instruments become unreliable.
- **Engine audio**: hesitation and irregularity at Agitated. Instability at Storm.
- **Ambient audio**: low-frequency content increases. The forest gets quieter in the wrong way. The sense of being attended-to increases, though this cannot be instrumented.
- **Radio**: signal degradation is driven by both biome depth AND disturbance. Heavy static in Verdant indicates Uneasy or higher. In Fungal Depths, signal degradation is biome-baseline regardless of disturbance — its absence there is not a reliable disturbance indicator.
- **Windshield accumulation**: particulate and biological matter accumulate faster at higher disturbance.
- **Perception**: at high disturbance AND high exposure, familiar routes feel different. Whether this is the condition or the player is not distinguishable by any available instrument.

### Tension-Release Cycles (Article X Rule)

Tension MUST be cycled — not held at a constant level. The forest MUST have moments of apparent safety (negative feedback loop releasing) before escalating again. Per Article XII-J: a horror experience that never releases becomes numbing within minutes.

Within a run, the meter can only climb — but the *experienced* tension releases when the player finds moments of momentum (driving cleanly, avoiding a Deadfall), audio pockets of quiet (between anomaly zones), or successful on-foot collection. The metabolism continues; the player's felt-state relaxes briefly before the next climb.

### Biome-Reactive Response

Each [[Biomes|biome]] has a distinct disturbance response profile (see [[Biome Behavior]] concept thread). The same player action may feed the process differently in Fungal Depths than in Verdant Old Growth. The audio arc, radio degradation curve, and anomaly expression all vary per biome even for the same disturbance level.

### The Storm (Finishing State)

The Storm spawns when the disturbance meter reaches 85. It cannot be cancelled or reversed after spawning.

| Property | Value |
|---|---|
| Trigger threshold | 85 disturbance |
| Spawn location | Crater rim, opposite side from nearest exit corridor (terraforming energy radiates inward from the reshape boundary) |
| Initial speed | 20 km/h |
| Speed acceleration | +5 km/h per 20 seconds |
| Maximum speed | 80 km/h (reached at ~4 minutes) |
| Width | Full crater width — no flanking |
| Player damage inside | 30 HP/sec |
| Van damage inside | 15 HP/sec |
| Tree behavior in path | Incorporated (visual effect, not obstacle) |
| Audio pre-visualization | Subsonic rumble → ambience collapse → silence → Storm |

**Survival window**: from spawn, the player has a meaningful survival window if already near an exit. The window narrows based on distance from exit and current speed. A player at the far end of the map must drive hard and without detours to extract.

The Storm is not avoidable through off-road detours — it spans the full crater width. The only variable is speed toward an exit corridor.

If the player is caught and survives the initial damage (possible at full health), the bus will be destroyed within seconds. On-foot survival inside the Storm is not possible.

### Designer-Tunable

Per Article VI Rule 3 / Article XII-J: tension-release cycles MUST be tunable via `@export` variables. Thresholds for Ambient → Directed → Cascade → Finishing (implemented as Calm → Uneasy → Agitated → Storm) are exposed for design iteration. Config lives in `res://resources/config/disturbance_config.tres` per spec 078.

### Irreversibility

The process never resets during a run. Inputs already fed cannot be recalled. The forest does not forget in the way that implies it was paying attention to begin with — it simply continues, and what has already entered the system has already changed the system.

Across runs, the condition accumulates via the garage contamination axis (see [[World Model]] / [[Narrative Direction]]) — a persistent value the player has no direct way to read but which progressively changes the garage and the bus.

## How It Appears In-Game

The player does not see a number. They see (and hear) consequences:

- Audio degrades on the radio; the bus sounds change
- Anomalies intensify
- Weather worsens
- What moves in the wood gets closer and less cautious
- Eventually, the Storm spawns from the ridgeline and moves toward the player

The Storm is the disturbance reaching Finishing — see [[The Player Causes the Storm]].

## Related

- [[The Crater]] — the origin event whose dimensional energy the disturbance meter measures
- [[The Temporal Fracture]] — disturbance as temporal destabilization; the Storm as ongoing insertion unfiltered
- [[World Model]] — the world the disturbance operates in
- [[Tone and Horror]] — dread-over-shock framing
- [[Core Mechanics]] — the run loop that drives disturbance accumulation
- [[Autoloads — Disturbance]] — the GDScript + Rust implementation
- [[Audio — Car Radio]] — radio degradation as diegetic disturbance readout
- [[Audio — World Audio]] — four-state ambient audio arc
- [[The Disturbance Thread]] — cross-cutting concept thread
- [[The Player Causes the Storm]] — the endgame manifestation
- [[Constitution]] — Article X is the authoritative source, Article XII-J (horror rhythm)

Controlled tag vocabulary (as read):
type/*:
- `type/code` — Code architecture, autoloads, conventions, tooling. Carries `code-refs:`. (e.g. `Code/Autoloads — Disturbance.md`)
- `type/decision` — Architectural or design decision made by an agent during a session. Written to `docs/vault/Decisions/`. (Agent notes only — spec 080.)
- `type/design` — Design intent, player-facing concepts, world lore. (e.g. `Design/World Model.md`)
- `type/discovery` — Non-obvious constraint, gap, or conflict found by an agent during a session. Written to `docs/vault/Discoveries/`. (Agent notes only — spec 080.)
- `type/moc` — Map of Content at any of three tiers (folder / domain / concept). (e.g. `Audio.md`)
- `type/principle` — Governance and constitutional notes. Non-negotiable rules. (e.g. `Governance/Constitution.md`)
- `type/reference` — Glossary, decision log, open questions, epics. (e.g. `Reference/Glossary.md`)
- `type/session-log` — Session activity log; permanent audit trail. Written to `docs/vault/Sessions/`. Append-only, never pruned. (Agent notes only — spec 080.)
- `type/spec` — Spec document at `docs/vault/Specs/NNN Title/spec.md`. Carries `spec-refs:`. (e.g. `Specs/047 Car Radio/spec.md`)
- `type/system` — A bounded subsystem with implementation. Carries `code-refs`, `spec-refs`, `implements:` frontmatter. (e.g. `Systems/Audio — Car Radio.md`)
- `type/vision` — Strategic / vision-layer decision. Written to `docs/vault/Vision/`. Human-authored or agent-proposed with human ratification before promotion to `status: reviewed`. (Per triage #3 — spec 133 autonomous-company redesign.)
domain/*:
- `domain/anomalies` — Anomaly taxonomy, individual anomaly systems, spawn, behavior
- `domain/art` — Visual direction, palettes, references, asset pipeline
- `domain/audio` — Audio systems: world ambient, radio, transmissions, buses, pipeline
- `domain/autonomous-company` — Autonomous company v0.1 experiment: Slack infra, persona middleware, Letta integration, restart recovery
- `domain/build` — Build system, packaging, export, release automation
- `domain/governance` — Constitution, phased spec, policies
- `domain/infrastructure` — Infrastructure provisioning: CI/CD, hosting, deployment tooling, secrets management
- `domain/narrative` — Tone, horror register, forest transmissions narrative, Gary/KTLK
- `domain/player` — Player mode, input, controls, camera, exit/entry
- `domain/systems` — Cross-cutting system architecture and integration work
- `domain/tooling` — Build, CI, observer, TTS pipeline, dev-time tools
- `domain/vehicle` — The Samba: vehicle physics, dashboard, damage, panels
- `domain/world` — World model, biomes, terrain, procedural generation, weather
status/*:
- `status/canonical` — Fully authoritative; promoted by humans only. Highest trust. (Agent notes only — spec 080.)
- `status/draft` — Authoring in progress, not yet verified
- `status/reviewed` — Agent-created note verified against codebase within its creating session. Eligible for auto-injection in subsequent task dispatches. (Agent notes only — spec 080.)
- `status/stale` — Known out of date; cannot update immediately. Pairs with `> [!warning] STALE — needs update` callout.
- `status/superseded` — Replaced by another note. Terminal state. Pairs with `> [!warning] SUPERSEDED` callout.
- `status/wip` — Stable but under active revision
layer/*:
- `layer/content` — Content assets (audio, models, textures, audio provenance)
- `layer/gdext` — gdext wrapper layer (`rust/gdext-wrapper/`)
- `layer/gdscript` — GDScript (Godot scene-tier logic)
- `layer/infra` — Build, CI, deployment infrastructure
- `layer/python` — Python development tooling (`tools/`)
- `layer/rust-core` — Engine-agnostic Rust core (`rust/rust-core/`)
concept/*:
- `concept/biome` — Biome-reactive behavior across systems
- `concept/contamination` — Across-runs panel and garage degradation; the slow-horror mechanic that doesn't reset with the world
- `concept/diegetic` — Diegetic audio / UI / world-sourced design
- `concept/disturbance` — The disturbance mechanic thread (Article X)
- `concept/ephemeral-world` — Run-reset, transient worlds (Article IV Rules 6–7)
- `concept/governance` — Constitutional and governance concepts
- `concept/horror` — Horror register and dread design
- `concept/procedural` — Procedural generation, seed determinism
- `concept/rendering` — Visual rendering quality, shader correctness, Terrain3D integration, mesh fidelity, LOD, Z-fighting
- `concept/terrain` — Terrain generation, heightmap, Terrain3D regions, roughness, playability constraints
ember's answer for tag_assignment-design-disturbance-system, type/designP(true) placed on the no, unsure, and yes zones.nounsureyesgold: yesP = 0.47

tag_assignment-design-disturbance-system: type/spec

Tag assignment · test
Gold
The note has no reason to carry `type/spec` (False)
ember
The note calls for `type/spec`: Spec document at `docs/vault/Specs/NNN Title/spec.md`. Carries `spec-refs:`. (e.g. `Specs/047 Car Radio/spec.md`) (True)
Signal
P(true) 0.55 (unsure)
Kit outcome
deferred: treated as unsure
Why this gold label
Mined from Design/Disturbance System.md at 692f4bb58b7f62105aeb73fba8dfee12bfdecd53; gold is the note's own vocabulary tags.
Disturbance System

The disturbance meter is Old Growth's central tension engine. It is not a health bar, not a resource gauge — it is a hidden 0–100 metric that measures how much the forest notices the player. This note captures the design intent AND the full mechanical specification (biological states, disturbance costs, diegetic indicators, Storm behavior). Implementation: [[Autoloads — Disturbance]].

## Overview

The forest does not have a temper. It has a metabolism.

Everything in the woods is input to a process that runs continuously and has been running since before the first road was cut through this watershed. The player's presence feeds this process from the moment they enter the tree line. Every action — collection, combustion, impact, noise — is an input the forest attends to, and attendance accelerates the process.

## Design Intent

This is not punishment. A fallen log feeds the same process. The player is simply a more active source. The disturbance system exists to make the **condition visible through its consequences** rather than through a dedicated UI display. The forest does not provide one. It expects you to have been paying attention.

The constitutional basis is Article X — The Disturbance Is the Design:
> The disturbance system is the primary tension engine. Tension MUST be cycled — not held at a constant level. The forest MUST have moments of apparent safety (negative feedback loop releasing) before escalating again.

## Key Decisions

### Meter

| Property | Value |
|---|---|
| Range | 0 – 100 |
| Display | None. Never shown directly. |
| In-run reset | None. Never resets during a run. |
| Cross-run behavior | Resets to 0 at run start |
| Read mechanism | Bus behavior, condition presence, audio register shifts, instrument reliability |

Players read disturbance state through environmental cues, not through any HUD element.

### Biological States

| State | Meter Range | Bus Behavior | Condition Presence | Audio |
|---|---|---|---|---|
| Calm | 0–30 | Normal | Ambient, diffuse | Normal biome ambience |
| Uneasy | 30–60 | Instruments drift slightly | Heightened, directional | Ambience shifts register, lower frequencies |
| Agitated | 60–85 | Instruments unreliable, engine hesitant | Dense, attending | Ambience becomes directional, pulse-like |
| Storm | 85–100 | Electrical instability | Maximum concentration | All frequencies collapse inward |

At 85, the Storm spawns regardless of player position. The Storm state does not have a stable ceiling — it triggers immediately.

### Disturbance Costs (complete table)

| Action | Disturbance Added |
|---|---|
| Fuel canister collected | +3 |
| Repair kit collected | +4 |
| Medkit collected | +5 |
| Flashlight battery collected | +3 |
| Flare gun collected | +3 |
| Flare gun fired | +6 |
| Rock thrown | +0.5 |
| Road contact at speed (condition dispersal) | +5 |
| Engine revving (high RPM) | +1 per second |
| Headlights active | +0.2 per second |
| Flashlight active | +0.2 per second |
| Horn | +3 |
| Player sprinting on foot | +0.5 per second |
| Exiting vehicle | +2 |
| Vehicle collision | +2 |
| Mycelium Network contact | +4 |
| Deadfall triggered | +2 |
| Entering Petrifold (first crossing per run) | +3 |
| Entering Fungal Depths (first crossing per run) | +0 — transition is passive |

### Diegetic Disturbance Indicators

No HUD. Players learn to read:

- **Bus instruments**: drift and jitter increase with disturbance state. At Agitated, instruments become unreliable.
- **Engine audio**: hesitation and irregularity at Agitated. Instability at Storm.
- **Ambient audio**: low-frequency content increases. The forest gets quieter in the wrong way. The sense of being attended-to increases, though this cannot be instrumented.
- **Radio**: signal degradation is driven by both biome depth AND disturbance. Heavy static in Verdant indicates Uneasy or higher. In Fungal Depths, signal degradation is biome-baseline regardless of disturbance — its absence there is not a reliable disturbance indicator.
- **Windshield accumulation**: particulate and biological matter accumulate faster at higher disturbance.
- **Perception**: at high disturbance AND high exposure, familiar routes feel different. Whether this is the condition or the player is not distinguishable by any available instrument.

### Tension-Release Cycles (Article X Rule)

Tension MUST be cycled — not held at a constant level. The forest MUST have moments of apparent safety (negative feedback loop releasing) before escalating again. Per Article XII-J: a horror experience that never releases becomes numbing within minutes.

Within a run, the meter can only climb — but the *experienced* tension releases when the player finds moments of momentum (driving cleanly, avoiding a Deadfall), audio pockets of quiet (between anomaly zones), or successful on-foot collection. The metabolism continues; the player's felt-state relaxes briefly before the next climb.

### Biome-Reactive Response

Each [[Biomes|biome]] has a distinct disturbance response profile (see [[Biome Behavior]] concept thread). The same player action may feed the process differently in Fungal Depths than in Verdant Old Growth. The audio arc, radio degradation curve, and anomaly expression all vary per biome even for the same disturbance level.

### The Storm (Finishing State)

The Storm spawns when the disturbance meter reaches 85. It cannot be cancelled or reversed after spawning.

| Property | Value |
|---|---|
| Trigger threshold | 85 disturbance |
| Spawn location | Crater rim, opposite side from nearest exit corridor (terraforming energy radiates inward from the reshape boundary) |
| Initial speed | 20 km/h |
| Speed acceleration | +5 km/h per 20 seconds |
| Maximum speed | 80 km/h (reached at ~4 minutes) |
| Width | Full crater width — no flanking |
| Player damage inside | 30 HP/sec |
| Van damage inside | 15 HP/sec |
| Tree behavior in path | Incorporated (visual effect, not obstacle) |
| Audio pre-visualization | Subsonic rumble → ambience collapse → silence → Storm |

**Survival window**: from spawn, the player has a meaningful survival window if already near an exit. The window narrows based on distance from exit and current speed. A player at the far end of the map must drive hard and without detours to extract.

The Storm is not avoidable through off-road detours — it spans the full crater width. The only variable is speed toward an exit corridor.

If the player is caught and survives the initial damage (possible at full health), the bus will be destroyed within seconds. On-foot survival inside the Storm is not possible.

### Designer-Tunable

Per Article VI Rule 3 / Article XII-J: tension-release cycles MUST be tunable via `@export` variables. Thresholds for Ambient → Directed → Cascade → Finishing (implemented as Calm → Uneasy → Agitated → Storm) are exposed for design iteration. Config lives in `res://resources/config/disturbance_config.tres` per spec 078.

### Irreversibility

The process never resets during a run. Inputs already fed cannot be recalled. The forest does not forget in the way that implies it was paying attention to begin with — it simply continues, and what has already entered the system has already changed the system.

Across runs, the condition accumulates via the garage contamination axis (see [[World Model]] / [[Narrative Direction]]) — a persistent value the player has no direct way to read but which progressively changes the garage and the bus.

## How It Appears In-Game

The player does not see a number. They see (and hear) consequences:

- Audio degrades on the radio; the bus sounds change
- Anomalies intensify
- Weather worsens
- What moves in the wood gets closer and less cautious
- Eventually, the Storm spawns from the ridgeline and moves toward the player

The Storm is the disturbance reaching Finishing — see [[The Player Causes the Storm]].

## Related

- [[The Crater]] — the origin event whose dimensional energy the disturbance meter measures
- [[The Temporal Fracture]] — disturbance as temporal destabilization; the Storm as ongoing insertion unfiltered
- [[World Model]] — the world the disturbance operates in
- [[Tone and Horror]] — dread-over-shock framing
- [[Core Mechanics]] — the run loop that drives disturbance accumulation
- [[Autoloads — Disturbance]] — the GDScript + Rust implementation
- [[Audio — Car Radio]] — radio degradation as diegetic disturbance readout
- [[Audio — World Audio]] — four-state ambient audio arc
- [[The Disturbance Thread]] — cross-cutting concept thread
- [[The Player Causes the Storm]] — the endgame manifestation
- [[Constitution]] — Article X is the authoritative source, Article XII-J (horror rhythm)

Controlled tag vocabulary (as read):
type/*:
- `type/code` — Code architecture, autoloads, conventions, tooling. Carries `code-refs:`. (e.g. `Code/Autoloads — Disturbance.md`)
- `type/decision` — Architectural or design decision made by an agent during a session. Written to `docs/vault/Decisions/`. (Agent notes only — spec 080.)
- `type/design` — Design intent, player-facing concepts, world lore. (e.g. `Design/World Model.md`)
- `type/discovery` — Non-obvious constraint, gap, or conflict found by an agent during a session. Written to `docs/vault/Discoveries/`. (Agent notes only — spec 080.)
- `type/moc` — Map of Content at any of three tiers (folder / domain / concept). (e.g. `Audio.md`)
- `type/principle` — Governance and constitutional notes. Non-negotiable rules. (e.g. `Governance/Constitution.md`)
- `type/reference` — Glossary, decision log, open questions, epics. (e.g. `Reference/Glossary.md`)
- `type/session-log` — Session activity log; permanent audit trail. Written to `docs/vault/Sessions/`. Append-only, never pruned. (Agent notes only — spec 080.)
- `type/spec` — Spec document at `docs/vault/Specs/NNN Title/spec.md`. Carries `spec-refs:`. (e.g. `Specs/047 Car Radio/spec.md`)
- `type/system` — A bounded subsystem with implementation. Carries `code-refs`, `spec-refs`, `implements:` frontmatter. (e.g. `Systems/Audio — Car Radio.md`)
- `type/vision` — Strategic / vision-layer decision. Written to `docs/vault/Vision/`. Human-authored or agent-proposed with human ratification before promotion to `status: reviewed`. (Per triage #3 — spec 133 autonomous-company redesign.)
domain/*:
- `domain/anomalies` — Anomaly taxonomy, individual anomaly systems, spawn, behavior
- `domain/art` — Visual direction, palettes, references, asset pipeline
- `domain/audio` — Audio systems: world ambient, radio, transmissions, buses, pipeline
- `domain/autonomous-company` — Autonomous company v0.1 experiment: Slack infra, persona middleware, Letta integration, restart recovery
- `domain/build` — Build system, packaging, export, release automation
- `domain/governance` — Constitution, phased spec, policies
- `domain/infrastructure` — Infrastructure provisioning: CI/CD, hosting, deployment tooling, secrets management
- `domain/narrative` — Tone, horror register, forest transmissions narrative, Gary/KTLK
- `domain/player` — Player mode, input, controls, camera, exit/entry
- `domain/systems` — Cross-cutting system architecture and integration work
- `domain/tooling` — Build, CI, observer, TTS pipeline, dev-time tools
- `domain/vehicle` — The Samba: vehicle physics, dashboard, damage, panels
- `domain/world` — World model, biomes, terrain, procedural generation, weather
status/*:
- `status/canonical` — Fully authoritative; promoted by humans only. Highest trust. (Agent notes only — spec 080.)
- `status/draft` — Authoring in progress, not yet verified
- `status/reviewed` — Agent-created note verified against codebase within its creating session. Eligible for auto-injection in subsequent task dispatches. (Agent notes only — spec 080.)
- `status/stale` — Known out of date; cannot update immediately. Pairs with `> [!warning] STALE — needs update` callout.
- `status/superseded` — Replaced by another note. Terminal state. Pairs with `> [!warning] SUPERSEDED` callout.
- `status/wip` — Stable but under active revision
layer/*:
- `layer/content` — Content assets (audio, models, textures, audio provenance)
- `layer/gdext` — gdext wrapper layer (`rust/gdext-wrapper/`)
- `layer/gdscript` — GDScript (Godot scene-tier logic)
- `layer/infra` — Build, CI, deployment infrastructure
- `layer/python` — Python development tooling (`tools/`)
- `layer/rust-core` — Engine-agnostic Rust core (`rust/rust-core/`)
concept/*:
- `concept/biome` — Biome-reactive behavior across systems
- `concept/contamination` — Across-runs panel and garage degradation; the slow-horror mechanic that doesn't reset with the world
- `concept/diegetic` — Diegetic audio / UI / world-sourced design
- `concept/disturbance` — The disturbance mechanic thread (Article X)
- `concept/ephemeral-world` — Run-reset, transient worlds (Article IV Rules 6–7)
- `concept/governance` — Constitutional and governance concepts
- `concept/horror` — Horror register and dread design
- `concept/procedural` — Procedural generation, seed determinism
- `concept/rendering` — Visual rendering quality, shader correctness, Terrain3D integration, mesh fidelity, LOD, Z-fighting
- `concept/terrain` — Terrain generation, heightmap, Terrain3D regions, roughness, playability constraints
ember's answer for tag_assignment-design-disturbance-system, type/specP(true) placed on the no, unsure, and yes zones.nounsureyesgold: noP = 0.55

tag_assignment-decisions-implementation-choices-and-architecture-decisions: type/code

Tag assignment · dev
Gold
The note has no reason to carry `type/code` (False)
ember
The note calls for `type/code`: Code architecture, autoloads, conventions, tooling. Carries `code-refs:`. (e.g. `Code/Autoloads — Disturbance.md`) (True)
Signal
P(true) 0.61 (unsure)
Kit outcome
deferred: treated as unsure
Why this gold label
Mined from Decisions/Implementation Choices and Architecture Decisions.md at 692f4bb58b7f62105aeb73fba8dfee12bfdecd53; gold is the note's own vocabulary tags.
Implementation Choices and Architecture Decisions

Core architectural rules that apply across all implementation work. These are constitutional constraints (Article I, III), not decisions made during any single session.

## Core Architectural Rules

### 1. Signal-Driven Architecture

- **Rule**: All cross-system communication via the `Events` autoload signal bus only. Systems must not call methods on nodes they do not own.
- **Source**: Constitution Article I / `Governance/Constitution.md`
- **Enforcement**: `gdlint` catches direct node references across system boundaries; code review.

### 2. Seeded Randomness

- **Rule**: All procedural systems use `RandomNumberGenerator` seeded from `GameState.current_seed`. Never use global `randf()` / `randi()`.
- **Source**: Constitution Article III Rule 4
- **Enforcement**: SC-001 baseline (seed=1250827250 → trees=1452, ferns=5300, logs=3061; post-spec-103 per-tree-clearance, 2026-04-26 per AGENTS.md); `make test` headless run.

### 3. Asset Export Safety

- **Rule**: Non-shippable directories under `src/assets/` must contain a `.gdignore` file. The shippable allowlist lives in `scripts/ci/check_asset_gdignore.sh`.
- **Source**: AGENTS.md § Asset Export Safety; `Discoveries/Asset Export Safety — gdignore.md`
- **Enforcement**: `make gdignore-check` (CI-gated).

### 4. Component SemVer

- **Rule**: Every file under `src/` maps to a component in `src/component_versions.json`. Modifying any file in a component's path requires bumping that component's version.
- **Source**: Constitution Article III Rule 15; `Governance/Component SemVer Policy.md`
- **Enforcement**: `make semver` (CI-gated).

Controlled tag vocabulary (as read):
type/*:
- `type/code` — Code architecture, autoloads, conventions, tooling. Carries `code-refs:`. (e.g. `Code/Autoloads — Disturbance.md`)
- `type/decision` — Architectural or design decision made by an agent during a session. Written to `docs/vault/Decisions/`. (Agent notes only — spec 080.)
- `type/design` — Design intent, player-facing concepts, world lore. (e.g. `Design/World Model.md`)
- `type/discovery` — Non-obvious constraint, gap, or conflict found by an agent during a session. Written to `docs/vault/Discoveries/`. (Agent notes only — spec 080.)
- `type/moc` — Map of Content at any of three tiers (folder / domain / concept). (e.g. `Audio.md`)
- `type/principle` — Governance and constitutional notes. Non-negotiable rules. (e.g. `Governance/Constitution.md`)
- `type/reference` — Glossary, decision log, open questions, epics. (e.g. `Reference/Glossary.md`)
- `type/session-log` — Session activity log; permanent audit trail. Written to `docs/vault/Sessions/`. Append-only, never pruned. (Agent notes only — spec 080.)
- `type/spec` — Spec document at `docs/vault/Specs/NNN Title/spec.md`. Carries `spec-refs:`. (e.g. `Specs/047 Car Radio/spec.md`)
- `type/system` — A bounded subsystem with implementation. Carries `code-refs`, `spec-refs`, `implements:` frontmatter. (e.g. `Systems/Audio — Car Radio.md`)
- `type/vision` — Strategic / vision-layer decision. Written to `docs/vault/Vision/`. Human-authored or agent-proposed with human ratification before promotion to `status: reviewed`. (Per triage #3 — spec 133 autonomous-company redesign.)
domain/*:
- `domain/anomalies` — Anomaly taxonomy, individual anomaly systems, spawn, behavior
- `domain/art` — Visual direction, palettes, references, asset pipeline
- `domain/audio` — Audio systems: world ambient, radio, transmissions, buses, pipeline
- `domain/autonomous-company` — Autonomous company v0.1 experiment: Slack infra, persona middleware, Letta integration, restart recovery
- `domain/build` — Build system, packaging, export, release automation
- `domain/governance` — Constitution, phased spec, policies
- `domain/infrastructure` — Infrastructure provisioning: CI/CD, hosting, deployment tooling, secrets management
- `domain/narrative` — Tone, horror register, forest transmissions narrative, Gary/KTLK
- `domain/player` — Player mode, input, controls, camera, exit/entry
- `domain/systems` — Cross-cutting system architecture and integration work
- `domain/tooling` — Build, CI, observer, TTS pipeline, dev-time tools
- `domain/vehicle` — The Samba: vehicle physics, dashboard, damage, panels
- `domain/world` — World model, biomes, terrain, procedural generation, weather
status/*:
- `status/canonical` — Fully authoritative; promoted by humans only. Highest trust. (Agent notes only — spec 080.)
- `status/draft` — Authoring in progress, not yet verified
- `status/reviewed` — Agent-created note verified against codebase within its creating session. Eligible for auto-injection in subsequent task dispatches. (Agent notes only — spec 080.)
- `status/stale` — Known out of date; cannot update immediately. Pairs with `> [!warning] STALE — needs update` callout.
- `status/superseded` — Replaced by another note. Terminal state. Pairs with `> [!warning] SUPERSEDED` callout.
- `status/wip` — Stable but under active revision
layer/*:
- `layer/content` — Content assets (audio, models, textures, audio provenance)
- `layer/gdext` — gdext wrapper layer (`rust/gdext-wrapper/`)
- `layer/gdscript` — GDScript (Godot scene-tier logic)
- `layer/infra` — Build, CI, deployment infrastructure
- `layer/python` — Python development tooling (`tools/`)
- `layer/rust-core` — Engine-agnostic Rust core (`rust/rust-core/`)
concept/*:
- `concept/biome` — Biome-reactive behavior across systems
- `concept/contamination` — Across-runs panel and garage degradation; the slow-horror mechanic that doesn't reset with the world
- `concept/diegetic` — Diegetic audio / UI / world-sourced design
- `concept/disturbance` — The disturbance mechanic thread (Article X)
- `concept/ephemeral-world` — Run-reset, transient worlds (Article IV Rules 6–7)
- `concept/governance` — Constitutional and governance concepts
- `concept/horror` — Horror register and dread design
- `concept/procedural` — Procedural generation, seed determinism
- `concept/rendering` — Visual rendering quality, shader correctness, Terrain3D integration, mesh fidelity, LOD, Z-fighting
- `concept/terrain` — Terrain generation, heightmap, Terrain3D regions, roughness, playability constraints
ember's answer for tag_assignment-decisions-implementation-choices-and-architecture-decisions, type/codeP(true) placed on the no, unsure, and yes zones.nounsureyesgold: noP = 0.61

tag_assignment-decisions-implementation-choices-and-architecture-decisions: type/decision

Tag assignment · dev
Gold
The note calls for `type/decision`: Architectural or design decision made by an agent during a session. Written to `docs/vault/Decisions/`. (Agent notes only — spec 080.) (True)
ember
The note has no reason to carry `type/decision` (False)
Signal
P(true) 0.09 (no)
Kit outcome
acted on a wrong answer
Why this gold label
Mined from Decisions/Implementation Choices and Architecture Decisions.md at 692f4bb58b7f62105aeb73fba8dfee12bfdecd53; gold is the note's own vocabulary tags.
Implementation Choices and Architecture Decisions

Core architectural rules that apply across all implementation work. These are constitutional constraints (Article I, III), not decisions made during any single session.

## Core Architectural Rules

### 1. Signal-Driven Architecture

- **Rule**: All cross-system communication via the `Events` autoload signal bus only. Systems must not call methods on nodes they do not own.
- **Source**: Constitution Article I / `Governance/Constitution.md`
- **Enforcement**: `gdlint` catches direct node references across system boundaries; code review.

### 2. Seeded Randomness

- **Rule**: All procedural systems use `RandomNumberGenerator` seeded from `GameState.current_seed`. Never use global `randf()` / `randi()`.
- **Source**: Constitution Article III Rule 4
- **Enforcement**: SC-001 baseline (seed=1250827250 → trees=1452, ferns=5300, logs=3061; post-spec-103 per-tree-clearance, 2026-04-26 per AGENTS.md); `make test` headless run.

### 3. Asset Export Safety

- **Rule**: Non-shippable directories under `src/assets/` must contain a `.gdignore` file. The shippable allowlist lives in `scripts/ci/check_asset_gdignore.sh`.
- **Source**: AGENTS.md § Asset Export Safety; `Discoveries/Asset Export Safety — gdignore.md`
- **Enforcement**: `make gdignore-check` (CI-gated).

### 4. Component SemVer

- **Rule**: Every file under `src/` maps to a component in `src/component_versions.json`. Modifying any file in a component's path requires bumping that component's version.
- **Source**: Constitution Article III Rule 15; `Governance/Component SemVer Policy.md`
- **Enforcement**: `make semver` (CI-gated).

Controlled tag vocabulary (as read):
type/*:
- `type/code` — Code architecture, autoloads, conventions, tooling. Carries `code-refs:`. (e.g. `Code/Autoloads — Disturbance.md`)
- `type/decision` — Architectural or design decision made by an agent during a session. Written to `docs/vault/Decisions/`. (Agent notes only — spec 080.)
- `type/design` — Design intent, player-facing concepts, world lore. (e.g. `Design/World Model.md`)
- `type/discovery` — Non-obvious constraint, gap, or conflict found by an agent during a session. Written to `docs/vault/Discoveries/`. (Agent notes only — spec 080.)
- `type/moc` — Map of Content at any of three tiers (folder / domain / concept). (e.g. `Audio.md`)
- `type/principle` — Governance and constitutional notes. Non-negotiable rules. (e.g. `Governance/Constitution.md`)
- `type/reference` — Glossary, decision log, open questions, epics. (e.g. `Reference/Glossary.md`)
- `type/session-log` — Session activity log; permanent audit trail. Written to `docs/vault/Sessions/`. Append-only, never pruned. (Agent notes only — spec 080.)
- `type/spec` — Spec document at `docs/vault/Specs/NNN Title/spec.md`. Carries `spec-refs:`. (e.g. `Specs/047 Car Radio/spec.md`)
- `type/system` — A bounded subsystem with implementation. Carries `code-refs`, `spec-refs`, `implements:` frontmatter. (e.g. `Systems/Audio — Car Radio.md`)
- `type/vision` — Strategic / vision-layer decision. Written to `docs/vault/Vision/`. Human-authored or agent-proposed with human ratification before promotion to `status: reviewed`. (Per triage #3 — spec 133 autonomous-company redesign.)
domain/*:
- `domain/anomalies` — Anomaly taxonomy, individual anomaly systems, spawn, behavior
- `domain/art` — Visual direction, palettes, references, asset pipeline
- `domain/audio` — Audio systems: world ambient, radio, transmissions, buses, pipeline
- `domain/autonomous-company` — Autonomous company v0.1 experiment: Slack infra, persona middleware, Letta integration, restart recovery
- `domain/build` — Build system, packaging, export, release automation
- `domain/governance` — Constitution, phased spec, policies
- `domain/infrastructure` — Infrastructure provisioning: CI/CD, hosting, deployment tooling, secrets management
- `domain/narrative` — Tone, horror register, forest transmissions narrative, Gary/KTLK
- `domain/player` — Player mode, input, controls, camera, exit/entry
- `domain/systems` — Cross-cutting system architecture and integration work
- `domain/tooling` — Build, CI, observer, TTS pipeline, dev-time tools
- `domain/vehicle` — The Samba: vehicle physics, dashboard, damage, panels
- `domain/world` — World model, biomes, terrain, procedural generation, weather
status/*:
- `status/canonical` — Fully authoritative; promoted by humans only. Highest trust. (Agent notes only — spec 080.)
- `status/draft` — Authoring in progress, not yet verified
- `status/reviewed` — Agent-created note verified against codebase within its creating session. Eligible for auto-injection in subsequent task dispatches. (Agent notes only — spec 080.)
- `status/stale` — Known out of date; cannot update immediately. Pairs with `> [!warning] STALE — needs update` callout.
- `status/superseded` — Replaced by another note. Terminal state. Pairs with `> [!warning] SUPERSEDED` callout.
- `status/wip` — Stable but under active revision
layer/*:
- `layer/content` — Content assets (audio, models, textures, audio provenance)
- `layer/gdext` — gdext wrapper layer (`rust/gdext-wrapper/`)
- `layer/gdscript` — GDScript (Godot scene-tier logic)
- `layer/infra` — Build, CI, deployment infrastructure
- `layer/python` — Python development tooling (`tools/`)
- `layer/rust-core` — Engine-agnostic Rust core (`rust/rust-core/`)
concept/*:
- `concept/biome` — Biome-reactive behavior across systems
- `concept/contamination` — Across-runs panel and garage degradation; the slow-horror mechanic that doesn't reset with the world
- `concept/diegetic` — Diegetic audio / UI / world-sourced design
- `concept/disturbance` — The disturbance mechanic thread (Article X)
- `concept/ephemeral-world` — Run-reset, transient worlds (Article IV Rules 6–7)
- `concept/governance` — Constitutional and governance concepts
- `concept/horror` — Horror register and dread design
- `concept/procedural` — Procedural generation, seed determinism
- `concept/rendering` — Visual rendering quality, shader correctness, Terrain3D integration, mesh fidelity, LOD, Z-fighting
- `concept/terrain` — Terrain generation, heightmap, Terrain3D regions, roughness, playability constraints
ember's answer for tag_assignment-decisions-implementation-choices-and-architecture-decisions, type/decisionP(true) placed on the no, unsure, and yes zones.nounsureyesgold: yesP = 0.09

tag_assignment-decisions-implementation-choices-and-architecture-decisions: type/principle

Tag assignment · dev
Gold
The note has no reason to carry `type/principle` (False)
ember
The note calls for `type/principle`: Governance and constitutional notes. Non-negotiable rules. (e.g. `Governance/Constitution.md`) (True)
Signal
P(true) 0.74 (unsure)
Kit outcome
deferred: treated as unsure
Why this gold label
Mined from Decisions/Implementation Choices and Architecture Decisions.md at 692f4bb58b7f62105aeb73fba8dfee12bfdecd53; gold is the note's own vocabulary tags.
Implementation Choices and Architecture Decisions

Core architectural rules that apply across all implementation work. These are constitutional constraints (Article I, III), not decisions made during any single session.

## Core Architectural Rules

### 1. Signal-Driven Architecture

- **Rule**: All cross-system communication via the `Events` autoload signal bus only. Systems must not call methods on nodes they do not own.
- **Source**: Constitution Article I / `Governance/Constitution.md`
- **Enforcement**: `gdlint` catches direct node references across system boundaries; code review.

### 2. Seeded Randomness

- **Rule**: All procedural systems use `RandomNumberGenerator` seeded from `GameState.current_seed`. Never use global `randf()` / `randi()`.
- **Source**: Constitution Article III Rule 4
- **Enforcement**: SC-001 baseline (seed=1250827250 → trees=1452, ferns=5300, logs=3061; post-spec-103 per-tree-clearance, 2026-04-26 per AGENTS.md); `make test` headless run.

### 3. Asset Export Safety

- **Rule**: Non-shippable directories under `src/assets/` must contain a `.gdignore` file. The shippable allowlist lives in `scripts/ci/check_asset_gdignore.sh`.
- **Source**: AGENTS.md § Asset Export Safety; `Discoveries/Asset Export Safety — gdignore.md`
- **Enforcement**: `make gdignore-check` (CI-gated).

### 4. Component SemVer

- **Rule**: Every file under `src/` maps to a component in `src/component_versions.json`. Modifying any file in a component's path requires bumping that component's version.
- **Source**: Constitution Article III Rule 15; `Governance/Component SemVer Policy.md`
- **Enforcement**: `make semver` (CI-gated).

Controlled tag vocabulary (as read):
type/*:
- `type/code` — Code architecture, autoloads, conventions, tooling. Carries `code-refs:`. (e.g. `Code/Autoloads — Disturbance.md`)
- `type/decision` — Architectural or design decision made by an agent during a session. Written to `docs/vault/Decisions/`. (Agent notes only — spec 080.)
- `type/design` — Design intent, player-facing concepts, world lore. (e.g. `Design/World Model.md`)
- `type/discovery` — Non-obvious constraint, gap, or conflict found by an agent during a session. Written to `docs/vault/Discoveries/`. (Agent notes only — spec 080.)
- `type/moc` — Map of Content at any of three tiers (folder / domain / concept). (e.g. `Audio.md`)
- `type/principle` — Governance and constitutional notes. Non-negotiable rules. (e.g. `Governance/Constitution.md`)
- `type/reference` — Glossary, decision log, open questions, epics. (e.g. `Reference/Glossary.md`)
- `type/session-log` — Session activity log; permanent audit trail. Written to `docs/vault/Sessions/`. Append-only, never pruned. (Agent notes only — spec 080.)
- `type/spec` — Spec document at `docs/vault/Specs/NNN Title/spec.md`. Carries `spec-refs:`. (e.g. `Specs/047 Car Radio/spec.md`)
- `type/system` — A bounded subsystem with implementation. Carries `code-refs`, `spec-refs`, `implements:` frontmatter. (e.g. `Systems/Audio — Car Radio.md`)
- `type/vision` — Strategic / vision-layer decision. Written to `docs/vault/Vision/`. Human-authored or agent-proposed with human ratification before promotion to `status: reviewed`. (Per triage #3 — spec 133 autonomous-company redesign.)
domain/*:
- `domain/anomalies` — Anomaly taxonomy, individual anomaly systems, spawn, behavior
- `domain/art` — Visual direction, palettes, references, asset pipeline
- `domain/audio` — Audio systems: world ambient, radio, transmissions, buses, pipeline
- `domain/autonomous-company` — Autonomous company v0.1 experiment: Slack infra, persona middleware, Letta integration, restart recovery
- `domain/build` — Build system, packaging, export, release automation
- `domain/governance` — Constitution, phased spec, policies
- `domain/infrastructure` — Infrastructure provisioning: CI/CD, hosting, deployment tooling, secrets management
- `domain/narrative` — Tone, horror register, forest transmissions narrative, Gary/KTLK
- `domain/player` — Player mode, input, controls, camera, exit/entry
- `domain/systems` — Cross-cutting system architecture and integration work
- `domain/tooling` — Build, CI, observer, TTS pipeline, dev-time tools
- `domain/vehicle` — The Samba: vehicle physics, dashboard, damage, panels
- `domain/world` — World model, biomes, terrain, procedural generation, weather
status/*:
- `status/canonical` — Fully authoritative; promoted by humans only. Highest trust. (Agent notes only — spec 080.)
- `status/draft` — Authoring in progress, not yet verified
- `status/reviewed` — Agent-created note verified against codebase within its creating session. Eligible for auto-injection in subsequent task dispatches. (Agent notes only — spec 080.)
- `status/stale` — Known out of date; cannot update immediately. Pairs with `> [!warning] STALE — needs update` callout.
- `status/superseded` — Replaced by another note. Terminal state. Pairs with `> [!warning] SUPERSEDED` callout.
- `status/wip` — Stable but under active revision
layer/*:
- `layer/content` — Content assets (audio, models, textures, audio provenance)
- `layer/gdext` — gdext wrapper layer (`rust/gdext-wrapper/`)
- `layer/gdscript` — GDScript (Godot scene-tier logic)
- `layer/infra` — Build, CI, deployment infrastructure
- `layer/python` — Python development tooling (`tools/`)
- `layer/rust-core` — Engine-agnostic Rust core (`rust/rust-core/`)
concept/*:
- `concept/biome` — Biome-reactive behavior across systems
- `concept/contamination` — Across-runs panel and garage degradation; the slow-horror mechanic that doesn't reset with the world
- `concept/diegetic` — Diegetic audio / UI / world-sourced design
- `concept/disturbance` — The disturbance mechanic thread (Article X)
- `concept/ephemeral-world` — Run-reset, transient worlds (Article IV Rules 6–7)
- `concept/governance` — Constitutional and governance concepts
- `concept/horror` — Horror register and dread design
- `concept/procedural` — Procedural generation, seed determinism
- `concept/rendering` — Visual rendering quality, shader correctness, Terrain3D integration, mesh fidelity, LOD, Z-fighting
- `concept/terrain` — Terrain generation, heightmap, Terrain3D regions, roughness, playability constraints
ember's answer for tag_assignment-decisions-implementation-choices-and-architecture-decisions, type/principleP(true) placed on the no, unsure, and yes zones.nounsureyesgold: noP = 0.74

tag_assignment-governance-phased-spec: type/principle

Tag assignment · test
Gold
The note calls for `type/principle`: Governance and constitutional notes. Non-negotiable rules. (e.g. `Governance/Constitution.md`) (True)
ember
The note has no reason to carry `type/principle` (False)
Signal
P(true) 0.12 (no)
Kit outcome
acted on a wrong answer
Why this gold label
Mined from Governance/Phased Spec.md at 692f4bb58b7f62105aeb73fba8dfee12bfdecd53; gold is the note's own vocabulary tags.
Phased Spec

> [!warning] SUPERSEDED
> The Phased Development Spec v3.1 (`docs/old-growth-phased-spec.md`) is superseded. The canonical ordering is now the per-spec subdirectories in `docs/vault/Specs/` with status tracked in each spec's `spec_status` frontmatter field. This note is retained as the historical phased plan and for references to "Phase N" naming in older commits.

A historical snapshot of the 26-phase development plan that guided Old Growth's initial scope planning. Individual phases have been decomposed into feature-specific specs under `docs/vault/Specs/NNN Title/` subdirectories; the canonical status source is each spec's `spec_status` frontmatter.

## Status

This spec is **superseded**. Do not treat its content as authoritative. For current project status, query vault spec frontmatter via the Specs MOC.

## Context

Old Growth's original development plan was a 26-phase "Phased Development Spec v3.1" — a linear plan that guided initial scope but has been decomposed into the per-feature subdirectories now tracked in `docs/vault/Specs/`. Earlier variants under different project names ("Dead Mileage", "Exclusion Drive") are also superseded and retained only for historical authorship.

Constitution Appendix B lists these documents as `SUPERSEDED`. The authoritative current-status source is each spec's `spec_status` frontmatter field, which this vault surfaces via Specs.

**What replaced the phased spec**: the spec-kit workflow — each significant feature gets a `docs/vault/Specs/NNN Title/` subdirectory with its own `spec.md`, `plan.md`, and `tasks.md`. The "phase" concept now lives at the spec-epic level, not as a single project-wide linear plan. See [[Epics]] for the current epic-level view.

## Related

- [[Governance]] — folder MOC
- Specs — the authoritative current status
- [[Constitution]] — Appendix B lists this as SUPERSEDED
- [[Milestones]] — project milestone tracking

Controlled tag vocabulary (as read):
type/*:
- `type/code` — Code architecture, autoloads, conventions, tooling. Carries `code-refs:`. (e.g. `Code/Autoloads — Disturbance.md`)
- `type/decision` — Architectural or design decision made by an agent during a session. Written to `docs/vault/Decisions/`. (Agent notes only — spec 080.)
- `type/design` — Design intent, player-facing concepts, world lore. (e.g. `Design/World Model.md`)
- `type/discovery` — Non-obvious constraint, gap, or conflict found by an agent during a session. Written to `docs/vault/Discoveries/`. (Agent notes only — spec 080.)
- `type/moc` — Map of Content at any of three tiers (folder / domain / concept). (e.g. `Audio.md`)
- `type/principle` — Governance and constitutional notes. Non-negotiable rules. (e.g. `Governance/Constitution.md`)
- `type/reference` — Glossary, decision log, open questions, epics. (e.g. `Reference/Glossary.md`)
- `type/session-log` — Session activity log; permanent audit trail. Written to `docs/vault/Sessions/`. Append-only, never pruned. (Agent notes only — spec 080.)
- `type/spec` — Spec document at `docs/vault/Specs/NNN Title/spec.md`. Carries `spec-refs:`. (e.g. `Specs/047 Car Radio/spec.md`)
- `type/system` — A bounded subsystem with implementation. Carries `code-refs`, `spec-refs`, `implements:` frontmatter. (e.g. `Systems/Audio — Car Radio.md`)
- `type/vision` — Strategic / vision-layer decision. Written to `docs/vault/Vision/`. Human-authored or agent-proposed with human ratification before promotion to `status: reviewed`. (Per triage #3 — spec 133 autonomous-company redesign.)
domain/*:
- `domain/anomalies` — Anomaly taxonomy, individual anomaly systems, spawn, behavior
- `domain/art` — Visual direction, palettes, references, asset pipeline
- `domain/audio` — Audio systems: world ambient, radio, transmissions, buses, pipeline
- `domain/autonomous-company` — Autonomous company v0.1 experiment: Slack infra, persona middleware, Letta integration, restart recovery
- `domain/build` — Build system, packaging, export, release automation
- `domain/governance` — Constitution, phased spec, policies
- `domain/infrastructure` — Infrastructure provisioning: CI/CD, hosting, deployment tooling, secrets management
- `domain/narrative` — Tone, horror register, forest transmissions narrative, Gary/KTLK
- `domain/player` — Player mode, input, controls, camera, exit/entry
- `domain/systems` — Cross-cutting system architecture and integration work
- `domain/tooling` — Build, CI, observer, TTS pipeline, dev-time tools
- `domain/vehicle` — The Samba: vehicle physics, dashboard, damage, panels
- `domain/world` — World model, biomes, terrain, procedural generation, weather
status/*:
- `status/canonical` — Fully authoritative; promoted by humans only. Highest trust. (Agent notes only — spec 080.)
- `status/draft` — Authoring in progress, not yet verified
- `status/reviewed` — Agent-created note verified against codebase within its creating session. Eligible for auto-injection in subsequent task dispatches. (Agent notes only — spec 080.)
- `status/stale` — Known out of date; cannot update immediately. Pairs with `> [!warning] STALE — needs update` callout.
- `status/superseded` — Replaced by another note. Terminal state. Pairs with `> [!warning] SUPERSEDED` callout.
- `status/wip` — Stable but under active revision
layer/*:
- `layer/content` — Content assets (audio, models, textures, audio provenance)
- `layer/gdext` — gdext wrapper layer (`rust/gdext-wrapper/`)
- `layer/gdscript` — GDScript (Godot scene-tier logic)
- `layer/infra` — Build, CI, deployment infrastructure
- `layer/python` — Python development tooling (`tools/`)
- `layer/rust-core` — Engine-agnostic Rust core (`rust/rust-core/`)
concept/*:
- `concept/biome` — Biome-reactive behavior across systems
- `concept/contamination` — Across-runs panel and garage degradation; the slow-horror mechanic that doesn't reset with the world
- `concept/diegetic` — Diegetic audio / UI / world-sourced design
- `concept/disturbance` — The disturbance mechanic thread (Article X)
- `concept/ephemeral-world` — Run-reset, transient worlds (Article IV Rules 6–7)
- `concept/governance` — Constitutional and governance concepts
- `concept/horror` — Horror register and dread design
- `concept/procedural` — Procedural generation, seed determinism
- `concept/rendering` — Visual rendering quality, shader correctness, Terrain3D integration, mesh fidelity, LOD, Z-fighting
- `concept/terrain` — Terrain generation, heightmap, Terrain3D regions, roughness, playability constraints
ember's answer for tag_assignment-governance-phased-spec, type/principleP(true) placed on the no, unsure, and yes zones.nounsureyesgold: yesP = 0.12

tag_assignment-design-controls: type/design

Tag assignment · dev
Gold
The note calls for `type/design`: Design intent, player-facing concepts, world lore. (e.g. `Design/World Model.md`) (True)
ember
The note has no reason to carry `type/design` (False)
Signal
P(true) 0.47 (unsure)
Kit outcome
deferred: treated as unsure
Why this gold label
Mined from Design/Controls.md at 692f4bb58b7f62105aeb73fba8dfee12bfdecd53; gold is the note's own vocabulary tags.
Controls

The control scheme for Old Growth: driving, on-foot, radio, vehicle systems, and debug. Controls are designed to stay out of the way — everything is a simple keyboard action directly mapped to a diegetic interaction with the Samba or the forest.

## Overview

Old Growth uses keyboard+mouse. All controls are direct: no chord inputs, no menus-within-menus, no modifier keys. The cabin view is the HUD; interactions surface when the player looks at the relevant object (radio, dome light).

## Design Intent

Input design serves diegesis (Article XII-G). Looking at the radio to activate its controls is the rule, not the exception — the player interacts with *the thing*, not with an abstraction of the thing. The control map is minimal because the game's complexity lives in the world, not in the input bindings.

## Key Decisions

### Driving

| Key | Action |
|-----|--------|
| W | Accelerate |
| S | Brake / Reverse |
| A | Steer left |
| D | Steer right |
| Space | Handbrake |
| Shift | Toggle gear (forward / reverse) |
| Mouse | Look around cabin |
| Esc | Toggle mouse cursor (captured / free) |

### Vehicle Systems

| Key | Action |
|-----|--------|
| H | Toggle headlights |
| L | Toggle high beams |
| J | Cycle wipers (off / slow / fast) |
| E | Toggle dome light (when focused) |

### Radio

Look at the radio on the dashboard to activate controls.

| Key | Action |
|-----|--------|
| E | Toggle radio power |
| T | Tune frequency up |
| Y | Tune frequency down |
| = | Volume up |
| - | Volume down |

### On Foot

| Key | Action |
|-----|--------|
| W/A/S/D | Move |
| Shift | Sprint |
| Ctrl | Crouch |
| E | Interact |
| F | Toggle flashlight |
| G | Enter / exit vehicle |
| Mouse | Look around |

### General

| Key | Action |
|-----|--------|
| R | Restart scene |
| Esc | Toggle mouse cursor |
| F12 | Take screenshot (saved to `~/Pictures/Old Growth/`) |

### Debug (debug builds only)

| Key | Action |
|-----|--------|
| F1 | Toggle debug overlay (game) / preview info overlay (world preview) |
| F3 | Toggle road spine overlay (game and world preview) |

## How It Appears In-Game

Controls are learned by doing. The game does not display a control reference; the player discovers them through the environment (dashboard labels on the Samba, subtle cues in the garage). On-foot movement is quieter than running; the mycelium notices sprinting — this is a control decision with tonal consequences.

## Related

- [[Core Mechanics]] — the run loop that controls drive
- [[Vehicle — Samba]] — the interactions controls invoke
- [[Audio — Car Radio]] — radio controls are diegetic
- [[Design]] — folder MOC

Controlled tag vocabulary (as read):
type/*:
- `type/code` — Code architecture, autoloads, conventions, tooling. Carries `code-refs:`. (e.g. `Code/Autoloads — Disturbance.md`)
- `type/decision` — Architectural or design decision made by an agent during a session. Written to `docs/vault/Decisions/`. (Agent notes only — spec 080.)
- `type/design` — Design intent, player-facing concepts, world lore. (e.g. `Design/World Model.md`)
- `type/discovery` — Non-obvious constraint, gap, or conflict found by an agent during a session. Written to `docs/vault/Discoveries/`. (Agent notes only — spec 080.)
- `type/moc` — Map of Content at any of three tiers (folder / domain / concept). (e.g. `Audio.md`)
- `type/principle` — Governance and constitutional notes. Non-negotiable rules. (e.g. `Governance/Constitution.md`)
- `type/reference` — Glossary, decision log, open questions, epics. (e.g. `Reference/Glossary.md`)
- `type/session-log` — Session activity log; permanent audit trail. Written to `docs/vault/Sessions/`. Append-only, never pruned. (Agent notes only — spec 080.)
- `type/spec` — Spec document at `docs/vault/Specs/NNN Title/spec.md`. Carries `spec-refs:`. (e.g. `Specs/047 Car Radio/spec.md`)
- `type/system` — A bounded subsystem with implementation. Carries `code-refs`, `spec-refs`, `implements:` frontmatter. (e.g. `Systems/Audio — Car Radio.md`)
- `type/vision` — Strategic / vision-layer decision. Written to `docs/vault/Vision/`. Human-authored or agent-proposed with human ratification before promotion to `status: reviewed`. (Per triage #3 — spec 133 autonomous-company redesign.)
domain/*:
- `domain/anomalies` — Anomaly taxonomy, individual anomaly systems, spawn, behavior
- `domain/art` — Visual direction, palettes, references, asset pipeline
- `domain/audio` — Audio systems: world ambient, radio, transmissions, buses, pipeline
- `domain/autonomous-company` — Autonomous company v0.1 experiment: Slack infra, persona middleware, Letta integration, restart recovery
- `domain/build` — Build system, packaging, export, release automation
- `domain/governance` — Constitution, phased spec, policies
- `domain/infrastructure` — Infrastructure provisioning: CI/CD, hosting, deployment tooling, secrets management
- `domain/narrative` — Tone, horror register, forest transmissions narrative, Gary/KTLK
- `domain/player` — Player mode, input, controls, camera, exit/entry
- `domain/systems` — Cross-cutting system architecture and integration work
- `domain/tooling` — Build, CI, observer, TTS pipeline, dev-time tools
- `domain/vehicle` — The Samba: vehicle physics, dashboard, damage, panels
- `domain/world` — World model, biomes, terrain, procedural generation, weather
status/*:
- `status/canonical` — Fully authoritative; promoted by humans only. Highest trust. (Agent notes only — spec 080.)
- `status/draft` — Authoring in progress, not yet verified
- `status/reviewed` — Agent-created note verified against codebase within its creating session. Eligible for auto-injection in subsequent task dispatches. (Agent notes only — spec 080.)
- `status/stale` — Known out of date; cannot update immediately. Pairs with `> [!warning] STALE — needs update` callout.
- `status/superseded` — Replaced by another note. Terminal state. Pairs with `> [!warning] SUPERSEDED` callout.
- `status/wip` — Stable but under active revision
layer/*:
- `layer/content` — Content assets (audio, models, textures, audio provenance)
- `layer/gdext` — gdext wrapper layer (`rust/gdext-wrapper/`)
- `layer/gdscript` — GDScript (Godot scene-tier logic)
- `layer/infra` — Build, CI, deployment infrastructure
- `layer/python` — Python development tooling (`tools/`)
- `layer/rust-core` — Engine-agnostic Rust core (`rust/rust-core/`)
concept/*:
- `concept/biome` — Biome-reactive behavior across systems
- `concept/contamination` — Across-runs panel and garage degradation; the slow-horror mechanic that doesn't reset with the world
- `concept/diegetic` — Diegetic audio / UI / world-sourced design
- `concept/disturbance` — The disturbance mechanic thread (Article X)
- `concept/ephemeral-world` — Run-reset, transient worlds (Article IV Rules 6–7)
- `concept/governance` — Constitutional and governance concepts
- `concept/horror` — Horror register and dread design
- `concept/procedural` — Procedural generation, seed determinism
- `concept/rendering` — Visual rendering quality, shader correctness, Terrain3D integration, mesh fidelity, LOD, Z-fighting
- `concept/terrain` — Terrain generation, heightmap, Terrain3D regions, roughness, playability constraints
ember's answer for tag_assignment-design-controls, type/designP(true) placed on the no, unsure, and yes zones.nounsureyesgold: yesP = 0.47

tag_assignment-sessions-spec-099-sfx-pipeline-implementation-apr-25-2026: status/reviewed

Tag assignment · dev
Gold
The note calls for `status/reviewed`: Agent-created note verified against codebase within its creating session. Eligible for auto-injection in subsequent task dispatches. (Agent notes only — spec 080.) (True)
ember
The note has no reason to carry `status/reviewed` (False)
Signal
P(true) 0.25 (unsure)
Kit outcome
deferred: treated as unsure
Why this gold label
Mined from Sessions/Spec 099 SFX Pipeline Implementation — Apr 25 2026.md at 692f4bb58b7f62105aeb73fba8dfee12bfdecd53; gold is the note's own vocabulary tags.
Spec 099 SFX Pipeline Implementation — Apr 25 2026

This session log records the full implementation of spec 099 (SFX Pipeline Expansion), executed in 8 phases across a single work session on 2026-04-25.

## What Was Done

### Phase 1 — Tooling Infrastructure (T001–T011C)
Makefile sfx-generate / sfx-master / sfx-loop-ogg / sfx-oneshot-ogg / sfx-install targets added to tools/tts/Makefile, parameterized by CATEGORY and OUTPUT. Two new CI validation scripts created: tools/tts/validate_sfx_naming.sh and tools/tts/validate_sfx_provenance.sh. The ambient_process.sh script was extended with --gold-dir / --install-dir arguments (backward-compatible with existing ambient-weather-* callers). Two new audio buses added to src/default_bus_layout.tres: VehicleSFX (Compressor + EQ10) and SFX (Reverb + LowPassFilter). AudioBusConfig resource extended with 8 new @export fields. Events.disturbance_level_changed signal added and emitted from both code paths in Disturbance.add(). SfxBusModulator GDScript created and wired into main.tscn.

### Phase 2 — Gold Directory Scaffolding (T012–T021)
90 provenance JSON stubs created across 37 categories (schema 1.3, ElevenLabs generator, PENDING sha256s). All gold/ directories created with .gdignore files. ElevenLabs minimum duration constraint discovered: 0.5s minimum — all stubs with sub-0.5s duration_seconds values were patched before generation.

### Phase 3 — Tier 1 Vehicle SFX + sfx/ Retirement (T022–T032B)
6 Tier 1 assets generated via ElevenLabs SFX V2 and installed: vehicle_engine_idle.ogg (loop), vehicle_wiper_squeak.ogg (oneshot), vehicle_rim_scrape.ogg (loop), vehicle_tire_pop.ogg (oneshot), vehicle_splash_loop.ogg (loop), interaction_toggle_click.ogg (oneshot). Legacy src/assets/audio/sfx/ directory removed (5 files: engine_idle, rim_scrape, splash_loop, tire_pop, wiper_squeak). Code paths updated: tire_damage_driver.gd, samba_bus.tscn (ext_resource paths + DomeLightControl.toggle_sfx). SplashAudio AudioStreamPlayer3D added to SplashController with vehicle_splash_loop.ogg; splash_particles.gd extended to play/stop audio on particle activation state.

A Makefile bug was discovered and fixed: sfx-generate was incorrectly passing --output with the full path and .wav extension instead of just the basename. This caused the provenance JSON lookup to fail with "not found: vehicle_engine_idle.wav.json".

### Phase 4 — Structure Break SFX + Lightning Wiring (T033–T040)
3 Tier 2 world/anomalies break assets generated: world_prop_break.ogg, world_guardrail_break.ogg, world_power_pole_fall.ogg. BreakAudio AudioStreamPlayer3D nodes added to 7 breakable_prop scenes, 1 guardrail scene, and 1 power_pole scene (9 scenes total). T038 was pre-complete: LightningController stream arrays (thunder, thunder_interior, crackle, radio_static) were already fully wired in generated_world.tscn.

### Phase 5 — Player Footsteps (T041–T051)
20 footstep OGGs generated (5 surfaces × 4 variants): asphalt, grass, gravel, soil, fungal. Events.player_footstep(surface_type: String) signal added to events.gd. footstep_surface_detector.gd created with 5-pool dynamic load() system (not preload — files may be missing at parse time), 3-re-roll anti-repetition variant picker. on_foot_controller.gd extended with step_interval timer (0.45s) and speed-threshold footstep emit. FootstepDetector + FootstepAudio nodes wired into on_foot_player.tscn.

### Phase 6 — World Ambient SFX (T052–T060)
20 world ambient assets generated: verdant/fungal/petrifold biome detail oneshots, disturbance pulses, storm oneshots, anomaly oneshots, hollow ambient loops (universal/fungal/verdant/petrifold). T059 (SfxBusModulator verification) passed: all bus indices, effect slots, signal binding, and parameter defaults confirmed correct. T055–T058 (world biome detail/hollow/disturbance pulse/storm wiring) deferred — no WorldDetailAudio, HollowAmbient, DisturbancePulseAudio, or WorldStormOneshot controller scripts exist. These are pending a future spec phase.

### Phase 7 — Interaction, Breathing, UI, Combat SFX (T061–T071D)
27 assets generated: 10 interaction oneshots (door, gear, ignition, loot, repair, window), 3 breathing loops (calm/tense/scared), 4 UI oneshots (select/confirm/back/error), 1 garage loop, 2 gate oneshots, 7 combat oneshots (melee x3, ranged x2, throw x2). All 27 OGGs installed and imported cleanly (make headless exit 0). All wiring deferred — no AudioStreamPlayer nodes exist in UI scenes, no interaction/breathing/garage/gate/combat controller scripts exist.

### Phase 8 — Validation and Finalization
make all confirmed 7 pre-existing test failures (test_on_foot_rain_particles, test_weather_effects_controller — spec-098 tests, not caused by spec-099 changes). make validate-provenance: 0 errors across all sampled categories. All 88 tasks marked complete in tasks.md.

## Key Constraints Discovered

ElevenLabs SFX V2 rejects duration_seconds values below 0.5s with HTTP 400. All initial stubs for footstep variants (0.3s/0.35s) and UI sounds (0.2s) were patched to 0.5s before generation. This constraint should be noted in any future ElevenLabs generation tooling.

The sfx-generate Makefile target had a bug: --output was receiving the full path + extension instead of the basename. Fixed in Phase 3.

## Deferred Work (Not Blocking Spec 099 Core Pipeline)

Phases 6 and 7 wiring is deferred because the underlying controller systems do not exist. All OGG assets are on disk and ready — only the GDScript controllers are missing. Gap analysis completed 2026-04-28; all systems are now accounted for in specs:

| System | Resolution |
|---|---|
| World biome detail ambient scheduler | Covered by spec 104 (Biome Ambient Audio) FR-005 |
| Hollow proximity audio controller | Added to spec 104 as FR-014, FR-015, FR-016 |
| Disturbance pulse audio controller | Covered by spec 105 (Disturbance Arc Audio) |
| World storm oneshot scheduler | Covered by spec 107 (Storm Audio System) |
| Interaction audio controller (door/gear/ignition/etc.) | Covered by spec 113 (Player And World Interaction Audio) FR-007 |
| Player breathing controller | Covered by spec 113 FR-004, FR-006 |
| UI audio manager | Added to spec 087 (Main Menu Polish) as FR-015, FR-016, FR-017 |
| Combat audio system | Intentionally dormant — combat removed from GDD; see [[Audio Asset Provenance & Status Management]] |

## References

- specs/099-sfx-pipeline-expansion/spec.md
- specs/099-sfx-pipeline-expansion/tasks.md
- tools/tts/Makefile
- tools/tts/validate_sfx_naming.sh
- tools/tts/validate_sfx_provenance.sh
- src/scripts/systems/sfx_bus_modulator.gd
- src/scripts/systems/footstep_surface_detector.gd
- src/scripts/bus/splash_particles.gd
- src/autoloads/events.gd
- src/default_bus_layout.tres
- src/resources/config/audio_bus_config.gd

Controlled tag vocabulary (as read):
type/*:
- `type/code` — Code architecture, autoloads, conventions, tooling. Carries `code-refs:`. (e.g. `Code/Autoloads — Disturbance.md`)
- `type/decision` — Architectural or design decision made by an agent during a session. Written to `docs/vault/Decisions/`. (Agent notes only — spec 080.)
- `type/design` — Design intent, player-facing concepts, world lore. (e.g. `Design/World Model.md`)
- `type/discovery` — Non-obvious constraint, gap, or conflict found by an agent during a session. Written to `docs/vault/Discoveries/`. (Agent notes only — spec 080.)
- `type/moc` — Map of Content at any of three tiers (folder / domain / concept). (e.g. `Audio.md`)
- `type/principle` — Governance and constitutional notes. Non-negotiable rules. (e.g. `Governance/Constitution.md`)
- `type/reference` — Glossary, decision log, open questions, epics. (e.g. `Reference/Glossary.md`)
- `type/session-log` — Session activity log; permanent audit trail. Written to `docs/vault/Sessions/`. Append-only, never pruned. (Agent notes only — spec 080.)
- `type/spec` — Spec document at `docs/vault/Specs/NNN Title/spec.md`. Carries `spec-refs:`. (e.g. `Specs/047 Car Radio/spec.md`)
- `type/system` — A bounded subsystem with implementation. Carries `code-refs`, `spec-refs`, `implements:` frontmatter. (e.g. `Systems/Audio — Car Radio.md`)
- `type/vision` — Strategic / vision-layer decision. Written to `docs/vault/Vision/`. Human-authored or agent-proposed with human ratification before promotion to `status: reviewed`. (Per triage #3 — spec 133 autonomous-company redesign.)
domain/*:
- `domain/anomalies` — Anomaly taxonomy, individual anomaly systems, spawn, behavior
- `domain/art` — Visual direction, palettes, references, asset pipeline
- `domain/audio` — Audio systems: world ambient, radio, transmissions, buses, pipeline
- `domain/autonomous-company` — Autonomous company v0.1 experiment: Slack infra, persona middleware, Letta integration, restart recovery
- `domain/build` — Build system, packaging, export, release automation
- `domain/governance` — Constitution, phased spec, policies
- `domain/infrastructure` — Infrastructure provisioning: CI/CD, hosting, deployment tooling, secrets management
- `domain/narrative` — Tone, horror register, forest transmissions narrative, Gary/KTLK
- `domain/player` — Player mode, input, controls, camera, exit/entry
- `domain/systems` — Cross-cutting system architecture and integration work
- `domain/tooling` — Build, CI, observer, TTS pipeline, dev-time tools
- `domain/vehicle` — The Samba: vehicle physics, dashboard, damage, panels
- `domain/world` — World model, biomes, terrain, procedural generation, weather
status/*:
- `status/canonical` — Fully authoritative; promoted by humans only. Highest trust. (Agent notes only — spec 080.)
- `status/draft` — Authoring in progress, not yet verified
- `status/reviewed` — Agent-created note verified against codebase within its creating session. Eligible for auto-injection in subsequent task dispatches. (Agent notes only — spec 080.)
- `status/stale` — Known out of date; cannot update immediately. Pairs with `> [!warning] STALE — needs update` callout.
- `status/superseded` — Replaced by another note. Terminal state. Pairs with `> [!warning] SUPERSEDED` callout.
- `status/wip` — Stable but under active revision
layer/*:
- `layer/content` — Content assets (audio, models, textures, audio provenance)
- `layer/gdext` — gdext wrapper layer (`rust/gdext-wrapper/`)
- `layer/gdscript` — GDScript (Godot scene-tier logic)
- `layer/infra` — Build, CI, deployment infrastructure
- `layer/python` — Python development tooling (`tools/`)
- `layer/rust-core` — Engine-agnostic Rust core (`rust/rust-core/`)
concept/*:
- `concept/biome` — Biome-reactive behavior across systems
- `concept/contamination` — Across-runs panel and garage degradation; the slow-horror mechanic that doesn't reset with the world
- `concept/diegetic` — Diegetic audio / UI / world-sourced design
- `concept/disturbance` — The disturbance mechanic thread (Article X)
- `concept/ephemeral-world` — Run-reset, transient worlds (Article IV Rules 6–7)
- `concept/governance` — Constitutional and governance concepts
- `concept/horror` — Horror register and dread design
- `concept/procedural` — Procedural generation, seed determinism
- `concept/rendering` — Visual rendering quality, shader correctness, Terrain3D integration, mesh fidelity, LOD, Z-fighting
- `concept/terrain` — Terrain generation, heightmap, Terrain3D regions, roughness, playability constraints
ember's answer for tag_assignment-sessions-spec-099-sfx-pipeline-implementation-apr-25-2026, status/reviewedP(true) placed on the no, unsure, and yes zones.nounsureyesgold: yesP = 0.25

tag_assignment-systems-audio-buses: layer/gdscript

Tag assignment · test
Gold
The note calls for `layer/gdscript`: GDScript (Godot scene-tier logic) (True)
ember
The note has no reason to carry `layer/gdscript` (False)
Signal
P(true) 0.15 (no)
Kit outcome
acted on a wrong answer
Why this gold label
Mined from Systems/Audio — Buses.md at 692f4bb58b7f62105aeb73fba8dfee12bfdecd53; gold is the note's own vocabulary tags.
Audio — Buses

The Godot AudioServer bus architecture for Old Growth defines how all in-game audio is routed, processed, and mixed. Buses are configured in src/default_bus_layout.tres and applied at runtime by AudioBusManager.

## Bus Layout

The project uses 6 audio buses (`src/default_bus_layout.tres`) as of spec 128. Buses are listed below with their current effect chains:

| Bus | Parent | Effects | Purpose |
|---|---|---|---|---|
| Master | — | Limiter | Final output mix |
| Radio | Master | Highpass 300Hz, Lowpass 3500Hz, EQ 1kHz presence | AM radio signal simulation |
| RadioDegraded | Master | Highpass 500Hz, Lowpass 2800Hz, Echo 500ms | Degraded/distorted radio signal |
| VehicleSFX | Master | AudioEffectCompressor (threshold=-18dB, ratio=4:1), AudioEffectEQ10 (low-mid boost) | Vehicle-specific audio with dynamic compression |
| SFX | Master | AudioEffectReverb (wet=0.05), AudioEffectLowPassFilter (cutoff=20000Hz) | World and player SFX with disturbance-responsive DSP |
| UI | Master | — | All menu button clicks and UI navigation sounds (spec 128) |

## Effect Indices

Effect slot indices are constants in src/scripts/systems/audio_bus_manager.gd:

- VehicleSFX bus: slot 0 = AudioEffectCompressor, slot 1 = AudioEffectEQ
- SFX bus: slot 0 = AudioEffectReverb, slot 1 = AudioEffectLowPassFilter
- Radio bus: RADIO_REVERB_EFFECT_IDX = existing constant

## AudioBusManager

src/scripts/systems/audio_bus_manager.gd is an autoload-adjacent Node that applies the AudioBusConfig resource (src/resources/config/audio_bus_config.gd) to the AudioServer at scene start. It reads exported parameters and sets compressor thresholds, EQ band gains, reverb wet values, and LPF cutoffs on the live AudioServer buses.

Key exported config fields (added in spec 099):
- vehicle_compressor_threshold_db = -18.0
- vehicle_compressor_ratio = 4.0
- vehicle_compressor_gain_db = 2.0
- vehicle_eq_low_mid_gain_db = 2.0
- sfx_reverb_wet_min = 0.05
- sfx_reverb_wet_max = 0.40
- sfx_lpf_cutoff_min_hz = 800.0
- sfx_lpf_cutoff_max_hz = 20000.0

## SfxBusModulator

src/scripts/systems/sfx_bus_modulator.gd is a Node in src/scenes/main.tscn that drives disturbance-responsive DSP on the SFX bus. It connects to Events.disturbance_level_changed (not directly to Disturbance — Art VI R1) and linearly interpolates reverb wet and LPF cutoff as Disturbance climbs from 0 to 100.

At Disturbance = 0: reverb wet = sfx_reverb_wet_min (0.05), LPF cutoff = sfx_lpf_cutoff_max_hz (20000 Hz — fully open)
At Disturbance = 100: reverb wet = sfx_reverb_wet_max (0.40), LPF cutoff = sfx_lpf_cutoff_min_hz (800 Hz — muffled)

This creates a continuous sonic environment that communicates danger through increasing reverb and muffling without any UI element.

## Bus Assignments by Asset Category

- VehicleSFX: vehicle/engine, vehicle/tire, vehicle/exhaust, vehicle/wind, vehicle/damage, vehicle/collision/*, interaction/*
- SFX: player/footsteps, player/breathing, world/*, combat/*, garage, gate, ui

## Future Bus Expansion (spec 111 — not yet implemented)

[[111 Audio Bus Architecture]] gates the addition of 4 buses required by the world audio system (specs 104–110). **None of these buses exist in the current `default_bus_layout.tres`:**

| Bus | Effects | Purpose |
|---|---|---|
| Ambience | Large-room reverb | Biome beds, weather beds, all ambient layers |
| Proximity | Medium-room reverb | 3D-spatialized anomaly and L4 detail audio |
| Interior | Low-pass 800 Hz + small-room reverb | Ambience and Proximity routed through here when player is inside the bus |
| Horror | None — raw signal | Stingers, tension drone, Storm audio, The Silence heartbeat — bypasses all occlusion |

Until spec 111 is implemented, AudioStreamPlayers referencing these future buses silently fall through to Master.

## UI Bus (Spec 128)

A sixth bus named `UI` was added to `src/default_bus_layout.tres` by spec 128 (User Settings Persistence). It has no effects and routes directly to Master.

| Bus | Parent | Effects | Purpose |
|---|---|---|---|
| UI | Master | — | All menu button clicks and UI navigation sounds |

All button click sounds in the settings UI and main menu route through this bus via `UITheme.play_click()`. The bus volume is exposed as a slider in the Audio settings panel so players can independently mute or reduce interface sounds.

The `Settings` autoload creates the UI bus programmatically at runtime if it is absent from the editor's cached bus layout (i.e. sessions that predate spec 128).

## History

- Specs 001-047: 4 buses (Master, Radio, RadioDegraded, Ambience, Interior) — note: Ambience/Interior existed in planning but were never in the actual bus layout
- Spec 078: AudioBusConfig resource introduced for hardcoded-values remediation
- Spec 098: Radio + RadioDegraded buses formalized with effect constants in AudioBusManager
- Spec 099: VehicleSFX and SFX buses added; SfxBusModulator created; AudioBusConfig extended with 8 new fields
- Spec 128: UI bus added for interface sounds (menu clicks, button feedback)
- Spec 111 (pending): Ambience, Proximity, Interior, Horror buses — prerequisite for specs 104–110

## References

- src/default_bus_layout.tres
- src/scripts/systems/audio_bus_manager.gd
- src/scripts/systems/sfx_bus_modulator.gd
- src/resources/config/audio_bus_config.gd
- docs/vault/Specs/099 Sfx Pipeline Expansion/spec.md
- Constitution Appendix A (bus architecture)

Controlled tag vocabulary (as read):
type/*:
- `type/code` — Code architecture, autoloads, conventions, tooling. Carries `code-refs:`. (e.g. `Code/Autoloads — Disturbance.md`)
- `type/decision` — Architectural or design decision made by an agent during a session. Written to `docs/vault/Decisions/`. (Agent notes only — spec 080.)
- `type/design` — Design intent, player-facing concepts, world lore. (e.g. `Design/World Model.md`)
- `type/discovery` — Non-obvious constraint, gap, or conflict found by an agent during a session. Written to `docs/vault/Discoveries/`. (Agent notes only — spec 080.)
- `type/moc` — Map of Content at any of three tiers (folder / domain / concept). (e.g. `Audio.md`)
- `type/principle` — Governance and constitutional notes. Non-negotiable rules. (e.g. `Governance/Constitution.md`)
- `type/reference` — Glossary, decision log, open questions, epics. (e.g. `Reference/Glossary.md`)
- `type/session-log` — Session activity log; permanent audit trail. Written to `docs/vault/Sessions/`. Append-only, never pruned. (Agent notes only — spec 080.)
- `type/spec` — Spec document at `docs/vault/Specs/NNN Title/spec.md`. Carries `spec-refs:`. (e.g. `Specs/047 Car Radio/spec.md`)
- `type/system` — A bounded subsystem with implementation. Carries `code-refs`, `spec-refs`, `implements:` frontmatter. (e.g. `Systems/Audio — Car Radio.md`)
- `type/vision` — Strategic / vision-layer decision. Written to `docs/vault/Vision/`. Human-authored or agent-proposed with human ratification before promotion to `status: reviewed`. (Per triage #3 — spec 133 autonomous-company redesign.)
domain/*:
- `domain/anomalies` — Anomaly taxonomy, individual anomaly systems, spawn, behavior
- `domain/art` — Visual direction, palettes, references, asset pipeline
- `domain/audio` — Audio systems: world ambient, radio, transmissions, buses, pipeline
- `domain/autonomous-company` — Autonomous company v0.1 experiment: Slack infra, persona middleware, Letta integration, restart recovery
- `domain/build` — Build system, packaging, export, release automation
- `domain/governance` — Constitution, phased spec, policies
- `domain/infrastructure` — Infrastructure provisioning: CI/CD, hosting, deployment tooling, secrets management
- `domain/narrative` — Tone, horror register, forest transmissions narrative, Gary/KTLK
- `domain/player` — Player mode, input, controls, camera, exit/entry
- `domain/systems` — Cross-cutting system architecture and integration work
- `domain/tooling` — Build, CI, observer, TTS pipeline, dev-time tools
- `domain/vehicle` — The Samba: vehicle physics, dashboard, damage, panels
- `domain/world` — World model, biomes, terrain, procedural generation, weather
status/*:
- `status/canonical` — Fully authoritative; promoted by humans only. Highest trust. (Agent notes only — spec 080.)
- `status/draft` — Authoring in progress, not yet verified
- `status/reviewed` — Agent-created note verified against codebase within its creating session. Eligible for auto-injection in subsequent task dispatches. (Agent notes only — spec 080.)
- `status/stale` — Known out of date; cannot update immediately. Pairs with `> [!warning] STALE — needs update` callout.
- `status/superseded` — Replaced by another note. Terminal state. Pairs with `> [!warning] SUPERSEDED` callout.
- `status/wip` — Stable but under active revision
layer/*:
- `layer/content` — Content assets (audio, models, textures, audio provenance)
- `layer/gdext` — gdext wrapper layer (`rust/gdext-wrapper/`)
- `layer/gdscript` — GDScript (Godot scene-tier logic)
- `layer/infra` — Build, CI, deployment infrastructure
- `layer/python` — Python development tooling (`tools/`)
- `layer/rust-core` — Engine-agnostic Rust core (`rust/rust-core/`)
concept/*:
- `concept/biome` — Biome-reactive behavior across systems
- `concept/contamination` — Across-runs panel and garage degradation; the slow-horror mechanic that doesn't reset with the world
- `concept/diegetic` — Diegetic audio / UI / world-sourced design
- `concept/disturbance` — The disturbance mechanic thread (Article X)
- `concept/ephemeral-world` — Run-reset, transient worlds (Article IV Rules 6–7)
- `concept/governance` — Constitutional and governance concepts
- `concept/horror` — Horror register and dread design
- `concept/procedural` — Procedural generation, seed determinism
- `concept/rendering` — Visual rendering quality, shader correctness, Terrain3D integration, mesh fidelity, LOD, Z-fighting
- `concept/terrain` — Terrain generation, heightmap, Terrain3D regions, roughness, playability constraints
ember's answer for tag_assignment-systems-audio-buses, layer/gdscriptP(true) placed on the no, unsure, and yes zones.nounsureyesgold: yesP = 0.15

tag_assignment-systems-audio-buses: status/reviewed

Tag assignment · test
Gold
The note calls for `status/reviewed`: Agent-created note verified against codebase within its creating session. Eligible for auto-injection in subsequent task dispatches. (Agent notes only — spec 080.) (True)
ember
The note has no reason to carry `status/reviewed` (False)
Signal
P(true) 0.35 (unsure)
Kit outcome
deferred: treated as unsure
Why this gold label
Mined from Systems/Audio — Buses.md at 692f4bb58b7f62105aeb73fba8dfee12bfdecd53; gold is the note's own vocabulary tags.
Audio — Buses

The Godot AudioServer bus architecture for Old Growth defines how all in-game audio is routed, processed, and mixed. Buses are configured in src/default_bus_layout.tres and applied at runtime by AudioBusManager.

## Bus Layout

The project uses 6 audio buses (`src/default_bus_layout.tres`) as of spec 128. Buses are listed below with their current effect chains:

| Bus | Parent | Effects | Purpose |
|---|---|---|---|---|
| Master | — | Limiter | Final output mix |
| Radio | Master | Highpass 300Hz, Lowpass 3500Hz, EQ 1kHz presence | AM radio signal simulation |
| RadioDegraded | Master | Highpass 500Hz, Lowpass 2800Hz, Echo 500ms | Degraded/distorted radio signal |
| VehicleSFX | Master | AudioEffectCompressor (threshold=-18dB, ratio=4:1), AudioEffectEQ10 (low-mid boost) | Vehicle-specific audio with dynamic compression |
| SFX | Master | AudioEffectReverb (wet=0.05), AudioEffectLowPassFilter (cutoff=20000Hz) | World and player SFX with disturbance-responsive DSP |
| UI | Master | — | All menu button clicks and UI navigation sounds (spec 128) |

## Effect Indices

Effect slot indices are constants in src/scripts/systems/audio_bus_manager.gd:

- VehicleSFX bus: slot 0 = AudioEffectCompressor, slot 1 = AudioEffectEQ
- SFX bus: slot 0 = AudioEffectReverb, slot 1 = AudioEffectLowPassFilter
- Radio bus: RADIO_REVERB_EFFECT_IDX = existing constant

## AudioBusManager

src/scripts/systems/audio_bus_manager.gd is an autoload-adjacent Node that applies the AudioBusConfig resource (src/resources/config/audio_bus_config.gd) to the AudioServer at scene start. It reads exported parameters and sets compressor thresholds, EQ band gains, reverb wet values, and LPF cutoffs on the live AudioServer buses.

Key exported config fields (added in spec 099):
- vehicle_compressor_threshold_db = -18.0
- vehicle_compressor_ratio = 4.0
- vehicle_compressor_gain_db = 2.0
- vehicle_eq_low_mid_gain_db = 2.0
- sfx_reverb_wet_min = 0.05
- sfx_reverb_wet_max = 0.40
- sfx_lpf_cutoff_min_hz = 800.0
- sfx_lpf_cutoff_max_hz = 20000.0

## SfxBusModulator

src/scripts/systems/sfx_bus_modulator.gd is a Node in src/scenes/main.tscn that drives disturbance-responsive DSP on the SFX bus. It connects to Events.disturbance_level_changed (not directly to Disturbance — Art VI R1) and linearly interpolates reverb wet and LPF cutoff as Disturbance climbs from 0 to 100.

At Disturbance = 0: reverb wet = sfx_reverb_wet_min (0.05), LPF cutoff = sfx_lpf_cutoff_max_hz (20000 Hz — fully open)
At Disturbance = 100: reverb wet = sfx_reverb_wet_max (0.40), LPF cutoff = sfx_lpf_cutoff_min_hz (800 Hz — muffled)

This creates a continuous sonic environment that communicates danger through increasing reverb and muffling without any UI element.

## Bus Assignments by Asset Category

- VehicleSFX: vehicle/engine, vehicle/tire, vehicle/exhaust, vehicle/wind, vehicle/damage, vehicle/collision/*, interaction/*
- SFX: player/footsteps, player/breathing, world/*, combat/*, garage, gate, ui

## Future Bus Expansion (spec 111 — not yet implemented)

[[111 Audio Bus Architecture]] gates the addition of 4 buses required by the world audio system (specs 104–110). **None of these buses exist in the current `default_bus_layout.tres`:**

| Bus | Effects | Purpose |
|---|---|---|
| Ambience | Large-room reverb | Biome beds, weather beds, all ambient layers |
| Proximity | Medium-room reverb | 3D-spatialized anomaly and L4 detail audio |
| Interior | Low-pass 800 Hz + small-room reverb | Ambience and Proximity routed through here when player is inside the bus |
| Horror | None — raw signal | Stingers, tension drone, Storm audio, The Silence heartbeat — bypasses all occlusion |

Until spec 111 is implemented, AudioStreamPlayers referencing these future buses silently fall through to Master.

## UI Bus (Spec 128)

A sixth bus named `UI` was added to `src/default_bus_layout.tres` by spec 128 (User Settings Persistence). It has no effects and routes directly to Master.

| Bus | Parent | Effects | Purpose |
|---|---|---|---|
| UI | Master | — | All menu button clicks and UI navigation sounds |

All button click sounds in the settings UI and main menu route through this bus via `UITheme.play_click()`. The bus volume is exposed as a slider in the Audio settings panel so players can independently mute or reduce interface sounds.

The `Settings` autoload creates the UI bus programmatically at runtime if it is absent from the editor's cached bus layout (i.e. sessions that predate spec 128).

## History

- Specs 001-047: 4 buses (Master, Radio, RadioDegraded, Ambience, Interior) — note: Ambience/Interior existed in planning but were never in the actual bus layout
- Spec 078: AudioBusConfig resource introduced for hardcoded-values remediation
- Spec 098: Radio + RadioDegraded buses formalized with effect constants in AudioBusManager
- Spec 099: VehicleSFX and SFX buses added; SfxBusModulator created; AudioBusConfig extended with 8 new fields
- Spec 128: UI bus added for interface sounds (menu clicks, button feedback)
- Spec 111 (pending): Ambience, Proximity, Interior, Horror buses — prerequisite for specs 104–110

## References

- src/default_bus_layout.tres
- src/scripts/systems/audio_bus_manager.gd
- src/scripts/systems/sfx_bus_modulator.gd
- src/resources/config/audio_bus_config.gd
- docs/vault/Specs/099 Sfx Pipeline Expansion/spec.md
- Constitution Appendix A (bus architecture)

Controlled tag vocabulary (as read):
type/*:
- `type/code` — Code architecture, autoloads, conventions, tooling. Carries `code-refs:`. (e.g. `Code/Autoloads — Disturbance.md`)
- `type/decision` — Architectural or design decision made by an agent during a session. Written to `docs/vault/Decisions/`. (Agent notes only — spec 080.)
- `type/design` — Design intent, player-facing concepts, world lore. (e.g. `Design/World Model.md`)
- `type/discovery` — Non-obvious constraint, gap, or conflict found by an agent during a session. Written to `docs/vault/Discoveries/`. (Agent notes only — spec 080.)
- `type/moc` — Map of Content at any of three tiers (folder / domain / concept). (e.g. `Audio.md`)
- `type/principle` — Governance and constitutional notes. Non-negotiable rules. (e.g. `Governance/Constitution.md`)
- `type/reference` — Glossary, decision log, open questions, epics. (e.g. `Reference/Glossary.md`)
- `type/session-log` — Session activity log; permanent audit trail. Written to `docs/vault/Sessions/`. Append-only, never pruned. (Agent notes only — spec 080.)
- `type/spec` — Spec document at `docs/vault/Specs/NNN Title/spec.md`. Carries `spec-refs:`. (e.g. `Specs/047 Car Radio/spec.md`)
- `type/system` — A bounded subsystem with implementation. Carries `code-refs`, `spec-refs`, `implements:` frontmatter. (e.g. `Systems/Audio — Car Radio.md`)
- `type/vision` — Strategic / vision-layer decision. Written to `docs/vault/Vision/`. Human-authored or agent-proposed with human ratification before promotion to `status: reviewed`. (Per triage #3 — spec 133 autonomous-company redesign.)
domain/*:
- `domain/anomalies` — Anomaly taxonomy, individual anomaly systems, spawn, behavior
- `domain/art` — Visual direction, palettes, references, asset pipeline
- `domain/audio` — Audio systems: world ambient, radio, transmissions, buses, pipeline
- `domain/autonomous-company` — Autonomous company v0.1 experiment: Slack infra, persona middleware, Letta integration, restart recovery
- `domain/build` — Build system, packaging, export, release automation
- `domain/governance` — Constitution, phased spec, policies
- `domain/infrastructure` — Infrastructure provisioning: CI/CD, hosting, deployment tooling, secrets management
- `domain/narrative` — Tone, horror register, forest transmissions narrative, Gary/KTLK
- `domain/player` — Player mode, input, controls, camera, exit/entry
- `domain/systems` — Cross-cutting system architecture and integration work
- `domain/tooling` — Build, CI, observer, TTS pipeline, dev-time tools
- `domain/vehicle` — The Samba: vehicle physics, dashboard, damage, panels
- `domain/world` — World model, biomes, terrain, procedural generation, weather
status/*:
- `status/canonical` — Fully authoritative; promoted by humans only. Highest trust. (Agent notes only — spec 080.)
- `status/draft` — Authoring in progress, not yet verified
- `status/reviewed` — Agent-created note verified against codebase within its creating session. Eligible for auto-injection in subsequent task dispatches. (Agent notes only — spec 080.)
- `status/stale` — Known out of date; cannot update immediately. Pairs with `> [!warning] STALE — needs update` callout.
- `status/superseded` — Replaced by another note. Terminal state. Pairs with `> [!warning] SUPERSEDED` callout.
- `status/wip` — Stable but under active revision
layer/*:
- `layer/content` — Content assets (audio, models, textures, audio provenance)
- `layer/gdext` — gdext wrapper layer (`rust/gdext-wrapper/`)
- `layer/gdscript` — GDScript (Godot scene-tier logic)
- `layer/infra` — Build, CI, deployment infrastructure
- `layer/python` — Python development tooling (`tools/`)
- `layer/rust-core` — Engine-agnostic Rust core (`rust/rust-core/`)
concept/*:
- `concept/biome` — Biome-reactive behavior across systems
- `concept/contamination` — Across-runs panel and garage degradation; the slow-horror mechanic that doesn't reset with the world
- `concept/diegetic` — Diegetic audio / UI / world-sourced design
- `concept/disturbance` — The disturbance mechanic thread (Article X)
- `concept/ephemeral-world` — Run-reset, transient worlds (Article IV Rules 6–7)
- `concept/governance` — Constitutional and governance concepts
- `concept/horror` — Horror register and dread design
- `concept/procedural` — Procedural generation, seed determinism
- `concept/rendering` — Visual rendering quality, shader correctness, Terrain3D integration, mesh fidelity, LOD, Z-fighting
- `concept/terrain` — Terrain generation, heightmap, Terrain3D regions, roughness, playability constraints
ember's answer for tag_assignment-systems-audio-buses, status/reviewedP(true) placed on the no, unsure, and yes zones.nounsureyesgold: yesP = 0.35

tag_assignment-systems-audio-buses: type/system

Tag assignment · test
Gold
The note calls for `type/system`: A bounded subsystem with implementation. Carries `code-refs`, `spec-refs`, `implements:` frontmatter. (e.g. `Systems/Audio — Car Radio.md`) (True)
ember
The note has no reason to carry `type/system` (False)
Signal
P(true) 0.42 (unsure)
Kit outcome
deferred: treated as unsure
Why this gold label
Mined from Systems/Audio — Buses.md at 692f4bb58b7f62105aeb73fba8dfee12bfdecd53; gold is the note's own vocabulary tags.
Audio — Buses

The Godot AudioServer bus architecture for Old Growth defines how all in-game audio is routed, processed, and mixed. Buses are configured in src/default_bus_layout.tres and applied at runtime by AudioBusManager.

## Bus Layout

The project uses 6 audio buses (`src/default_bus_layout.tres`) as of spec 128. Buses are listed below with their current effect chains:

| Bus | Parent | Effects | Purpose |
|---|---|---|---|---|
| Master | — | Limiter | Final output mix |
| Radio | Master | Highpass 300Hz, Lowpass 3500Hz, EQ 1kHz presence | AM radio signal simulation |
| RadioDegraded | Master | Highpass 500Hz, Lowpass 2800Hz, Echo 500ms | Degraded/distorted radio signal |
| VehicleSFX | Master | AudioEffectCompressor (threshold=-18dB, ratio=4:1), AudioEffectEQ10 (low-mid boost) | Vehicle-specific audio with dynamic compression |
| SFX | Master | AudioEffectReverb (wet=0.05), AudioEffectLowPassFilter (cutoff=20000Hz) | World and player SFX with disturbance-responsive DSP |
| UI | Master | — | All menu button clicks and UI navigation sounds (spec 128) |

## Effect Indices

Effect slot indices are constants in src/scripts/systems/audio_bus_manager.gd:

- VehicleSFX bus: slot 0 = AudioEffectCompressor, slot 1 = AudioEffectEQ
- SFX bus: slot 0 = AudioEffectReverb, slot 1 = AudioEffectLowPassFilter
- Radio bus: RADIO_REVERB_EFFECT_IDX = existing constant

## AudioBusManager

src/scripts/systems/audio_bus_manager.gd is an autoload-adjacent Node that applies the AudioBusConfig resource (src/resources/config/audio_bus_config.gd) to the AudioServer at scene start. It reads exported parameters and sets compressor thresholds, EQ band gains, reverb wet values, and LPF cutoffs on the live AudioServer buses.

Key exported config fields (added in spec 099):
- vehicle_compressor_threshold_db = -18.0
- vehicle_compressor_ratio = 4.0
- vehicle_compressor_gain_db = 2.0
- vehicle_eq_low_mid_gain_db = 2.0
- sfx_reverb_wet_min = 0.05
- sfx_reverb_wet_max = 0.40
- sfx_lpf_cutoff_min_hz = 800.0
- sfx_lpf_cutoff_max_hz = 20000.0

## SfxBusModulator

src/scripts/systems/sfx_bus_modulator.gd is a Node in src/scenes/main.tscn that drives disturbance-responsive DSP on the SFX bus. It connects to Events.disturbance_level_changed (not directly to Disturbance — Art VI R1) and linearly interpolates reverb wet and LPF cutoff as Disturbance climbs from 0 to 100.

At Disturbance = 0: reverb wet = sfx_reverb_wet_min (0.05), LPF cutoff = sfx_lpf_cutoff_max_hz (20000 Hz — fully open)
At Disturbance = 100: reverb wet = sfx_reverb_wet_max (0.40), LPF cutoff = sfx_lpf_cutoff_min_hz (800 Hz — muffled)

This creates a continuous sonic environment that communicates danger through increasing reverb and muffling without any UI element.

## Bus Assignments by Asset Category

- VehicleSFX: vehicle/engine, vehicle/tire, vehicle/exhaust, vehicle/wind, vehicle/damage, vehicle/collision/*, interaction/*
- SFX: player/footsteps, player/breathing, world/*, combat/*, garage, gate, ui

## Future Bus Expansion (spec 111 — not yet implemented)

[[111 Audio Bus Architecture]] gates the addition of 4 buses required by the world audio system (specs 104–110). **None of these buses exist in the current `default_bus_layout.tres`:**

| Bus | Effects | Purpose |
|---|---|---|
| Ambience | Large-room reverb | Biome beds, weather beds, all ambient layers |
| Proximity | Medium-room reverb | 3D-spatialized anomaly and L4 detail audio |
| Interior | Low-pass 800 Hz + small-room reverb | Ambience and Proximity routed through here when player is inside the bus |
| Horror | None — raw signal | Stingers, tension drone, Storm audio, The Silence heartbeat — bypasses all occlusion |

Until spec 111 is implemented, AudioStreamPlayers referencing these future buses silently fall through to Master.

## UI Bus (Spec 128)

A sixth bus named `UI` was added to `src/default_bus_layout.tres` by spec 128 (User Settings Persistence). It has no effects and routes directly to Master.

| Bus | Parent | Effects | Purpose |
|---|---|---|---|
| UI | Master | — | All menu button clicks and UI navigation sounds |

All button click sounds in the settings UI and main menu route through this bus via `UITheme.play_click()`. The bus volume is exposed as a slider in the Audio settings panel so players can independently mute or reduce interface sounds.

The `Settings` autoload creates the UI bus programmatically at runtime if it is absent from the editor's cached bus layout (i.e. sessions that predate spec 128).

## History

- Specs 001-047: 4 buses (Master, Radio, RadioDegraded, Ambience, Interior) — note: Ambience/Interior existed in planning but were never in the actual bus layout
- Spec 078: AudioBusConfig resource introduced for hardcoded-values remediation
- Spec 098: Radio + RadioDegraded buses formalized with effect constants in AudioBusManager
- Spec 099: VehicleSFX and SFX buses added; SfxBusModulator created; AudioBusConfig extended with 8 new fields
- Spec 128: UI bus added for interface sounds (menu clicks, button feedback)
- Spec 111 (pending): Ambience, Proximity, Interior, Horror buses — prerequisite for specs 104–110

## References

- src/default_bus_layout.tres
- src/scripts/systems/audio_bus_manager.gd
- src/scripts/systems/sfx_bus_modulator.gd
- src/resources/config/audio_bus_config.gd
- docs/vault/Specs/099 Sfx Pipeline Expansion/spec.md
- Constitution Appendix A (bus architecture)

Controlled tag vocabulary (as read):
type/*:
- `type/code` — Code architecture, autoloads, conventions, tooling. Carries `code-refs:`. (e.g. `Code/Autoloads — Disturbance.md`)
- `type/decision` — Architectural or design decision made by an agent during a session. Written to `docs/vault/Decisions/`. (Agent notes only — spec 080.)
- `type/design` — Design intent, player-facing concepts, world lore. (e.g. `Design/World Model.md`)
- `type/discovery` — Non-obvious constraint, gap, or conflict found by an agent during a session. Written to `docs/vault/Discoveries/`. (Agent notes only — spec 080.)
- `type/moc` — Map of Content at any of three tiers (folder / domain / concept). (e.g. `Audio.md`)
- `type/principle` — Governance and constitutional notes. Non-negotiable rules. (e.g. `Governance/Constitution.md`)
- `type/reference` — Glossary, decision log, open questions, epics. (e.g. `Reference/Glossary.md`)
- `type/session-log` — Session activity log; permanent audit trail. Written to `docs/vault/Sessions/`. Append-only, never pruned. (Agent notes only — spec 080.)
- `type/spec` — Spec document at `docs/vault/Specs/NNN Title/spec.md`. Carries `spec-refs:`. (e.g. `Specs/047 Car Radio/spec.md`)
- `type/system` — A bounded subsystem with implementation. Carries `code-refs`, `spec-refs`, `implements:` frontmatter. (e.g. `Systems/Audio — Car Radio.md`)
- `type/vision` — Strategic / vision-layer decision. Written to `docs/vault/Vision/`. Human-authored or agent-proposed with human ratification before promotion to `status: reviewed`. (Per triage #3 — spec 133 autonomous-company redesign.)
domain/*:
- `domain/anomalies` — Anomaly taxonomy, individual anomaly systems, spawn, behavior
- `domain/art` — Visual direction, palettes, references, asset pipeline
- `domain/audio` — Audio systems: world ambient, radio, transmissions, buses, pipeline
- `domain/autonomous-company` — Autonomous company v0.1 experiment: Slack infra, persona middleware, Letta integration, restart recovery
- `domain/build` — Build system, packaging, export, release automation
- `domain/governance` — Constitution, phased spec, policies
- `domain/infrastructure` — Infrastructure provisioning: CI/CD, hosting, deployment tooling, secrets management
- `domain/narrative` — Tone, horror register, forest transmissions narrative, Gary/KTLK
- `domain/player` — Player mode, input, controls, camera, exit/entry
- `domain/systems` — Cross-cutting system architecture and integration work
- `domain/tooling` — Build, CI, observer, TTS pipeline, dev-time tools
- `domain/vehicle` — The Samba: vehicle physics, dashboard, damage, panels
- `domain/world` — World model, biomes, terrain, procedural generation, weather
status/*:
- `status/canonical` — Fully authoritative; promoted by humans only. Highest trust. (Agent notes only — spec 080.)
- `status/draft` — Authoring in progress, not yet verified
- `status/reviewed` — Agent-created note verified against codebase within its creating session. Eligible for auto-injection in subsequent task dispatches. (Agent notes only — spec 080.)
- `status/stale` — Known out of date; cannot update immediately. Pairs with `> [!warning] STALE — needs update` callout.
- `status/superseded` — Replaced by another note. Terminal state. Pairs with `> [!warning] SUPERSEDED` callout.
- `status/wip` — Stable but under active revision
layer/*:
- `layer/content` — Content assets (audio, models, textures, audio provenance)
- `layer/gdext` — gdext wrapper layer (`rust/gdext-wrapper/`)
- `layer/gdscript` — GDScript (Godot scene-tier logic)
- `layer/infra` — Build, CI, deployment infrastructure
- `layer/python` — Python development tooling (`tools/`)
- `layer/rust-core` — Engine-agnostic Rust core (`rust/rust-core/`)
concept/*:
- `concept/biome` — Biome-reactive behavior across systems
- `concept/contamination` — Across-runs panel and garage degradation; the slow-horror mechanic that doesn't reset with the world
- `concept/diegetic` — Diegetic audio / UI / world-sourced design
- `concept/disturbance` — The disturbance mechanic thread (Article X)
- `concept/ephemeral-world` — Run-reset, transient worlds (Article IV Rules 6–7)
- `concept/governance` — Constitutional and governance concepts
- `concept/horror` — Horror register and dread design
- `concept/procedural` — Procedural generation, seed determinism
- `concept/rendering` — Visual rendering quality, shader correctness, Terrain3D integration, mesh fidelity, LOD, Z-fighting
- `concept/terrain` — Terrain generation, heightmap, Terrain3D regions, roughness, playability constraints
ember's answer for tag_assignment-systems-audio-buses, type/systemP(true) placed on the no, unsure, and yes zones.nounsureyesgold: yesP = 0.42

tag_assignment-code-tools-development-workbench: domain/governance

Tag assignment · dev
Gold
The note calls for `domain/governance`: Constitution, phased spec, policies (True)
ember
The note has no reason to carry `domain/governance` (False)
Signal
P(true) 0.30 (unsure)
Kit outcome
deferred: treated as unsure
Why this gold label
Mined from Code/Tools — Development Workbench.md at 692f4bb58b7f62105aeb73fba8dfee12bfdecd53; gold is the note's own vocabulary tags.
Tools — Development Workbench

The generative domain workbench is the entire development ecosystem that produces Old Growth. It spans persistent AI agents (personas), session-based AI agents (OpenCode + subagents), the vault knowledge graph, CI/CD automation, external infrastructure, and the in-game generation pipeline itself. This note maps every layer, their connections, and data flows — the meta-architecture of how the game is built.

## Layer Overview

```
┌──────────────────────────────────────────────────────────────────────┐
│                        HUMAN INTERFACE                               │
│       Slack (@mentions)      GitHub (PRs/Issues)      Terminal       │
└──────────┬──────────────────────────┬──────────────────────┬──────────┘
           │                          │                      │
           ▼                          ▼                      ▼
┌──────────────────────┐  ┌──────────────────────┐  ┌──────────────────┐
│  PERSISTENT AI       │  │  SESSION AI           │  │  DEV TOOLS       │
│  (Persona Layer)     │  │  (Agent Layer)        │  │  (Human-op)      │
├──────────────────────┤  ├──────────────────────┤  ├──────────────────┤
│  Coordinator Persona │  │  Sisyphus             │  │  Godot Editor    │
│  ─ routes tasks via  │  │  ─ orchestrator       │  │  gh CLI          │
│    Slack @mentions   │  │  sub-agents:          │  │  make targets    │
│                      │  │  explore, librarian,  │  │  cargo / pytest  │
│  GTM Persona         │  │  oracle, metis, momus │  │  obsidian        │
│  ─ release notes +   │  │  Sisyphus-Junior      │  │  blender         │
│    approval workflow │  │  Skills system        │  │  comfyui         │
│                      │  │  MCP servers          │  │                  │
│  Engineer (v0.5)     │  │                       │  │  launchd         │
│  Narrative (v0.2)    │  │                       │  │  ngrok           │
│  Playtest (v0.5)     │  │                       │  │  valkey          │
├──────────────────────┤  ├──────────────────────┤  └──────────────────┘
│  Letta Server        │  │  OpenCode + omo       │
│  (persistent memory) │  │  MCP servers:         │
│  Core/Archival/      │  │  vault, gdai-mcp,    │
│  Recall memory       │  │  blender, comfyui     │
└──────────┬───────────┘  └──────────┬────────────┘
           │                         │
           ▼                         ▼
┌──────────────────────────────────────────────────────────────────────┐
│                     KNOWLEDGE / SPEC LAYER                            │
├──────────────────────────────────────────────────────────────────────┤
│  ┌──────────────────────────────────────────────────────────────┐    │
│  │                    VAULT KNOWLEDGE GRAPH                      │    │
│  │  docs/vault/ — 1000+ notes organized in 3 tiers:              │    │
│  │  Tier 1: Governance, Design, Systems, Code, Specs,           │    │
│  │          Reference, Sessions, Decisions, Discoveries          │    │
│  │  Tier 2: Audio, Vehicle, World, Player, Anomalies,           │    │
│  │          Narrative, Tooling                                   │    │
│  │  Tier 3: Disturbance, Biome, Horror, Diegesis,               │    │
│  │          Ephemerality, Procedural Generation, Contamination   │    │
│  │  Read/write via mcpvault MCP server (opencode.json)          │    │
│  └──────────────────────────────────────────────────────────────┘    │
│                                                                      │
│ ┌─────────────────────────┐ ┌─────────────────────────────────┐   │
│ │  SPEC KIT (speckit.*)   │ │  CONSTITUTION (Governance/)     │   │
│ │  clarify → specify →    │ │  Supreme authority:             │   │
│ │  plan → tasks → implement│ │  Constitution > Design > Specs  │   │
│ │  → analyze               │ │  Personas cannot amend          │   │
│ │  139 specs in            │ │  Human-only: version bumps,      │   │
│ │  docs/vault/Specs/NNN/   │ │  merges, canonical status       │   │
│ └─────────────────────────┘ └─────────────────────────────────┘   │
│                                                                      │
│ ┌──────────────────────────────────────────────────────────────┐   │
│ │  AGENTS.md — Behavioral constitution for all agents          │   │
│ │  ─ Agent Behavior Foundation (4 principles)                 │   │
│ │  ─ Architecture rules, vault read/write protocol            │   │
│ │  ─ Code style, testing conventions, build commands          │   │
│ └──────────────────────────────────────────────────────────────┘   │
│                                                                      │
│ ┌──────────────────────────────────────────────────────────────┐   │
│ │  SEMANTIC DRIFT PIPELINE (spec 088)                          │   │
│  │  Phase 1 (Mechanical): vault_audit.py                        │   │
│  │    — schema validation, wikilink resolution, code-refs check │   │
│  │  Phase 2 (Auto-fix): --apply flag                            │   │
│  │    — stale markers, broken refs, missing spec stubs          │   │
│  │  Phase 3 (Semantic): vault-audit-semantic agent              │   │
│  │    — claim taxonomy (exact/range/approx/list/description)    │   │
│  │  CI: weekly Sunday + per-PR on docs/vault/ changes           │   │
│  │  Output: rolling vault/audit PR with auto-fixes              │   │
│  └──────────────────────────────────────────────────────────────┘   │
│                                                                      │
└──────────────────────────────────────────────────────────────────────┘
           │
           ▼
┌──────────────────────────────────────────────────────────────────────┐
│                    CI/CD / AUTOMATION LAYER                           │
├──────────────────────────────────────────────────────────────────────┤
│                                                                      │
│  ┌────────────────────────────────┐  ┌────────────────────────────┐  │
│  │  GitHub Actions (8 workflows)  │  │  Makefile (40+ targets)    │  │
│  │                                │  │                            │  │
│  │  ci-fast — merge gate         │  │  make all — full CI        │  │
│  │  ci-basics — full pipeline    │  │  make pre-commit — fast    │  │
│  │    (manual approval gate)     │  │  make test — GUT headless  │  │
│  │  release — ship DMG + R2      │  │  make rust-build/test      │  │
│  │  vault-audit — PR + weekly    │  │  make world-preview/qa     │  │
│  │  deploy-site — GitHub Pages   │  │  make observer-* — QA     │  │
│  │  persona-tests — middleware   │  │  make personas-up/down     │  │
│  │  auto-bump — safety net       │  │  make bump-patch/minor/mjr │  │
│  │  component-semver-autofix     │  │  make wiki-serve/build     │  │
│  └────────────────────────────────┘  └────────────────────────────┘  │
│                                                                      │
│  ┌──────────────────────────────────────────────────────────────┐   │
│  │  Pre-commit Hook (scripts/hooks/pre-commit)                  │   │
│  │  ├── Component SemVer auto-bump (patch)                     │   │
│  │  ├── Game version format check                               │   │
│  │  ├── Asset .gdignore check                                   │   │
│  │  ├── GDScript format-check + lint                            │   │
│  │  └── Rust tests + clippy (optional)                          │   │
│  └──────────────────────────────────────────────────────────────┘   │
│                                                                      │
└──────────────────────────────────────────────────────────────────────┘
           │
           ▼
┌──────────────────────────────────────────────────────────────────────┐
│                      INFRASTRUCTURE LAYER                              │
├──────────────────────────────────────────────────────────────────────┤
│                                                                      │
│  ┌────────────────────┐  ┌──────────────────┐  ┌─────────────────┐  │
│  │  macOS Dev Machine  │  │  Cloudflare R2   │  │  GitHub Pages   │  │
│  │  (all-local)        │  │  ─ releases      │  │  ─ Jekyll site  │  │
│  │                     │  │  ─ sccache cache │  │                 │  │
│  │  Valkey 8.0:6379   │  │  ─ downloads.    │  │  ─ shapeandshare│  │
│  │  Letta Docker:8283 │  │    playoldgrowth  │  │    .github.io   │  │
│  │  OTel Collector    │  └──────────────────┘  └─────────────────┘  │
│  │  ngrok tunnel      │                                             │
│  │  OpenCode serve    │  ┌──────────────────┐  ┌─────────────────┐  │
│  └────────────────────┘  │  LLM Providers   │  │  Slack           │  │
│                          │  ─ OpenRouter    │  │  ─ Socket Mode   │  │
│  launchd Services        │  ─ Anthropic     │  │  ─ Per-persona   │  │
│  ├── Letta server        │    (failover)    │  │    apps          │  │
│  ├── Coordinator runtime │  └──────────────────┘  └─────────────────┘  │
│  ├── GTM runtime         │                                             │
│  ├── ngrok agent         │  ┌──────────────────────────────────────┐  │
│  ├── OTel collector      │  │  Apple Services                      │  │
│  └── (future: more)      │  │  ─ Developer ID signing              │  │
│                          │  │  ─ Notarization                      │  │
│                          │  │  ─ DMG packaging                     │  │
│                          │  └──────────────────────────────────────┘  │
│                                                                      │
└──────────────────────────────────────────────────────────────────────┘
           │
           ▼
┌──────────────────────────────────────────────────────────────────────┐
│                  GENERATIVE CONTENT PIPELINES                         │
├──────────────────────────────────────────────────────────────────────┤
│  ┌───────────────┐  ┌───────────────┐  ┌───────────────┐            │
│  │  TTS Pipeline  │  │  Music        │  │  Blender 3D   │            │
│  │  tools/tts/    │  │  Pipeline     │  │  tools/blender/│            │
│  │  Kokoro,       │  │  Suno → genre │  │  Python mesh  │            │
│  │  Chatterbox,   │  │  filter chain │  │  separation,  │            │
│  │  ElevenLabs SFX│  │  → audio      │  │  LOD, GLB     │            │
│  │  → radio clips │  │    submodule  │  │  → game assets│            │
│  └───────┬───────┘  └───────┬───────┘  └───────┬───────┘            │
│          │                  │                  │                     │
│  ┌───────┴───────┐  ┌──────┴────────┐  ┌──────┴────────┐           │
│  │  ComfyUI      │  │  Observer QA  │  │  DMG Builder   │           │
│  │  tools/comfyui │  │  tools/observer│  │  tools/dmg/    │           │
│  │  SDXL img2img │  │  Claude screenshot│  │  Background  │           │
│  │  → PBR textures│  │  + audio analysis  │  │  .DS_Store   │           │
│  │  → submodule   │  │  → ci quality gate│  │  → signed DMG │           │
│  └───────────────┘  └─────────────────┘  └────────────────┘           │
│                                                                      │
└──────────────────────────────────────────────────────────────────────┘
           │
           ▼
┌──────────────────────────────────────────────────────────────────────┐
│                     GENERATED OUTPUT (THE GAME)                       │
├──────────────────────────────────────────────────────────────────────┤
│  In-game world generation pipeline, runtime systems, autoloads,     │
│  shipped assets (audio OGGs, 3D GLBs, textures, radio data)          │
│  (see [[World — Procedural Generation]] and [[Generation Subsystem Pairs]] for the │
│  full in-game architecture)                                                          │
└──────────────────────────────────────────────────────────────────────┘
```

## Layer Details

### 1. Persistent AI Layer (Personas)

Two active persona runtimes, with three more planned (v0.5):

| Persona | Role | Status | Agent ID | Port |
|---|---|---|---|---|
| Coordinator | Task routing, human↔system bridge | Active | `agent-420c0db8-...` | 9100 |
| GTM | Release notes, devlog drafting, approval workflow | Active | `agent-ccd29034-...` | 9101 |
| Engineer | Code implementation, spec shepherding | v0.5 | — | — |
| Narrative Director | Tone, canon, KTLK voice | v0.2 | — | — |
| Playtest Coordinator | Determinism verification, regression detection | v0.5 | — | — |

Each persona has structured identity files in `docs/vault/Reference/Autonomous Company/personas/<name>/`:
- `SOUL.md` — identity, voice, tone
- `CHARTER.md` — authority boundaries, permitted actions
- `INTENT.md` — priorities and goals
- `AGENTS.md` — operational runbook
- `MEMORY.md` — conversation history (via Letta)

**Runtime architecture** (Python, in `personas/`):
- `runtime.py` — Bolt framework with Socket Mode WebSocket connection
- `letta_bridge.py` — forwards Slack @mentions to Letta REST API (`http://localhost:8283`)
- `letta_agents.json` — maps persona name to Letta agent ID
- `opencode_client.py` — HTTP client for OpenCode serve (`http://localhost:8080`)
- `telemetry.py` — OTel span emission, Prometheus `/metrics`
- `shutdown.py` — graceful shutdown on token revocation (kill-switch)
- `approval_callback.py` — GTM's class-B approval workflow handler
- `config.py` — .env-based configuration (Slack tokens, API keys, ports)

**Data flows**:
- `@mention` → Slack Socket Mode → runtime.py → letta_bridge.py → Letta agent → LLM (OpenRouter/Anthropic) → response → Slack
- Code-touching tasks → OpenCode HTTP API → session (create/send/poll/close) → result → Slack

### 2. Session AI Layer (OpenCode + Subagents)

| Component | Description |
|---|---|
| Sisyphus | Primary orchestrator agent — decomposes tasks, delegates to subagents, verifies output |
| explore | Contextual grep — finds code patterns, module structure, cross-layer dependencies |
| librarian | External reference grep — searches docs, OSS examples, API specs |
| oracle | Read-only high-IQ consultant — complex architecture, debugging, tradeoff analysis |
| metis | Pre-planning consultant — identifies hidden intentions, ambiguities, AI failure points |
| momus | Plan critic — evaluates work plans for clarity, verifiability, completeness |
| Sisyphus-Junior | Focused task executor (same discipline, no delegation) — used across categories |
| multimodal-looker | Visual analysis of screenshots via Claude vision |

**Task categories** (domain-optimized models): `visual-engineering`, `artistry`, `ultrabrain`, `deep`, `quick`, `unspecified-low/high`, `writing`

**MCP servers** (configured in `opencode.json`):
- `gdai-mcp-server` — Godot editor runtime access (play scene, screenshot, editor scripts, node search)
- `mcpvault` (obsidian MCP) — vault read/write, note search, graph queries
- `blender` — 3D asset pipeline automation
- `comfyui` — AI image generation

**Skills system** (`.opencode/skills/`):
- `observer-qa` — Visual QA pipeline, agent trigger matrix, screenshot analysis
- `audio-assets` — TTS generation, audio submodule, provenance
- `introspection` — Vault health checks, semantic drift analysis
- `spec-management` — Spec creation, repositioning, specify workflow
- `blog-posts` — Jekyll devlog authoring, time-release scheduling

### 3. Knowledge / Spec Layer

See `docs/vault/README.md` and the vault structure at `docs/vault/` for full documentation. Key subsystems:

- **Vault knowledge graph**: 260+ notes across 15+ top-level directories, controlled vocabulary (`_meta/tags.md`), 3-tier MOC structure, agent note template (`_meta/templates/agent-note.md`)
- **Spec Kit**: `speckit.*` commands in `.opencode/command/` — clarify → specify → plan → tasks → implement → analyze workflow. 139 specs in `docs/vault/Specs/NNN Title/` with artifacts (plan.md, tasks.md, research.md, data-model.md, contracts/)
- **Semantic drift pipeline**: Three-phase audit (mechanical → auto-fix → semantic) with CI integration, weekly Sunday runs, rolling `vault/audit` PR
- **Constitution**: `docs/vault/Governance/Constitution.md` — supreme authority, Article III (Rust-first), Article IV (seed determinism), Article XIV (vault governance)

### 4. CI/CD Layer

Eight GitHub Actions workflows orchestrate all automation:

| Workflow | Trigger | Purpose | Required for merge |
|---|---|---|---|
| `ci-fast.yml` | PR to main | Fast checks: workflow lint, version bump, semver, GDScript quality, Rust clippy | Yes |
| `ci-basics.yml` | PR to main | Full pipeline: manual gate, Rust tests, GUT + headless (Linux), macOS smoke | Yes (human PRs) |
| `release.yml` | Version change on main | Universal DMG: build, sign, notarize, upload to R2, publish release | No (post-merge) |
| `vault-audit.yml` | PR on docs/vault/ + weekly Sun | Mechanical audit + optional semantic drift → rolling PR | Yes (vault changes) |
| `deploy-site.yml` | Push on site/ changes + daily | Jekyll build → GitHub Pages deploy | No |
| `persona-tests.yml` | PR on personas/ | pytest middleware tests | Yes (persona changes) |
| `auto-bump.yml` | Merge to main (conditional) | Safety-net: auto patch bump PR if missing | No |
| `component-semver-autofix.yml` | PR on mapped files | Auto-bump component versions if stale | No |

**Pre-commit hook** (`scripts/hooks/pre-commit`): runs semver, game-version-check, gdignore-check, format-check, lint — with auto-bump for component versions.

**Component SemVer** (`src/component_versions.json`): files mapped to components with version enforcement. Pre-commit hook auto-bumps patch; CI rejects un-bumped changes.

### 5. Infrastructure Layer

| Service | Purpose | Auth | Connection |
|---|---|---|---|
| Valkey 8.0 | Local event bus, `releases.shipped` stream | `requirepass` | Local port 6379, ngrok tunnel 24971 |
| Letta Server | Persistent agent memory (Docker) | None (localhost) | Port 8283 |
| OTel Collector | Observability spans (gRPC) | None (localhost) | Port 4317 |
| ngrok | TCP tunnel for CI → local Valkey | Auth token | `1.tcp.us-cal-1.ngrok.io:24971` |
| OpenCode serve | REST API for agent sessions | Bearer token | Port 8080 |
| Cloudflare R2 | Build artifact storage + sccache cache | R2 API keys | `downloads.playoldgrowth.com` |
| GitHub Pages | Jekyll site (`shapeandshare.github.io`) | OIDC | Automatic deploy |
| Slack (Socket Mode) | Persona communication surface | Bot tokens (xoxb-) | Outbound WebSocket |
| OpenRouter | Primary LLM provider | API key | Outbound HTTPS |
| Anthropic | LLM failover provider | API key | Outbound HTTPS |
| Apple Developer ID | Code signing + notarization | Cert + app password | Per-release CI |

**launchd-managed services** (auto-start on login):
- Letta Docker server
- Coordinator runtime (port 9100)
- GTM runtime (port 9101 + `/internal/approval-callback`)
- ngrok agent (TCP tunnel)
- OTel collector (gRPC ingest)

**Environment management**:
- `.env` — runtime secrets (Slack tokens, API keys, Valkey auth)
- GitHub Secrets — CI secrets (R2 keys, Apple certs, BUMP_PAT)
- `~/Library/Keychains/` — Apple Developer ID certificate (CI-imported)
- `docs/vault/Reference/Autonomous Company/Slack App Registration Runbook.md` — token provisioning

### 6. In-Game Generation Layer

The output of the workbench. See for full architecture:
- [[World — Procedural Generation]] — 11-step pipeline, RNG sub-seed derivation, subsystem details
- [[Generation Subsystem Pairs]] — complete inventory of every GDScript+Rust+bridge triple

### 7. Generative Content Pipelines

Six content creation pipelines produce game assets that ship in the `src/assets/` submodule. All are dev-time only — none run in the game binary.

#### TTS Pipeline (`tools/tts/`)

Three TTS engines, one post-processing chain, one submodule install step:

```
┌──────────────┐   ┌──────────────┐   ┌──────────────────┐
│  Kokoro 82M  │   │  Chatterbox  │   │  ElevenLabs SFX  │
│  (neutral)   │   │  (character) │   │  (ambient SFX)   │
│  .venv, no   │   │  conda, GPU  │   │  REST API        │
│  GPU needed  │   │  required    │   │  key in .env     │
└──────┬───────┘   └──────┬───────┘   └───────┬──────────┘
       │                  │                    │
       ▼                  ▼                    ▼
┌────────────────────────────────────────────────────────────┐
│  Gold WAV (48 kHz / 24-bit)                                │
│  → postprocess.sh (ffmpeg) → Master OGG                    │
│                               → HQ OGG (320 kbps)          │
│                               → LQ OGG (96 kbps)           │
│  → install to oldgrowth-assets submodule                   │
│  → validate naming + provenance                            │
└────────────────────────────────────────────────────────────┘
```

**Engines**: Kokoro 82M (neutral voice, lightweight, CPU), Chatterbox (voice cloning via conda+GPU for Gary/character voices), ElevenLabs SFX V2 API (weather ambient soundscapes)

**Script manifests**: 9 DJ station manifests (KOLD, KHRN, KFRO, KDRM, KDRN, KPGN, KJAZ, KVPR, KGSP), KTLK Gary dialogue (94 clips across 4 tiers), news scripts, music discovery manifests

**Validation**: 6 validate scripts (`validate_provenance.sh`, `validate_naming.sh`, etc.) for naming conventions and provenance metadata schema

**Makefile targets**: `make tts-gary`, `make tts-status`, `make tts-generate-all`

Key vault docs: [[Tools — TTS]], [[Audio — Pipeline]]

#### Music Pipeline (`tools/tts/music_process.sh`)

Suno-generated music → gold master → genre-specific post-processing → OGG ship → submodule install.

```
Suno (Pro/Premier for commercial rights)
  → Download MP3 → Convert to 48 kHz/24-bit WAV gold master
    → 11 genre-specific ffmpeg filter chains (per-station EQ/compression/character)
      → Master OGG + HQ OGG + LQ OGG
        → Install to oldgrowth-assets submodule
```

**Target**: 13 stations total (11 music + KTLK talk + KNWS news) — ~200–260 music tracks**

**Per-genre filter chains** (11 music stations): Dark Folk, Haunted Americana, Nordic Experimental, Dream Pop, Dark Ambient, Pagan Folk, Jazz, Vaporwave, Dark Gospel, Blues-Punk, PNW Garage-Psych (Note: KTLK 93.3 and KNWS 103.7 are talk/news — no music filter chains)

**Per-genre filter chains**: Dark Folk, Haunted Americana, Nordic Experimental, Dream Pop, Dark Ambient, Pagan Folk, Jazz, Vaporwave, Dark Gospel, Blues-Punk, PNW Garage-Psych

Key vault docs: [[Tools — Music Pipeline]], [[Audio — Radio Stations]]

#### Blender 3D Pipeline (`tools/blender/`)

Python automation for 3D asset processing, executed via MCP (`blender` in `opencode.json`):

```
bus_modified.blend
  → t011_separate_panels.py — 44 panel mesh separation from 8 sources
  → t012_uv_unwrap.py — UV0_Damage layer + Smart UV Project
  → t013_transforms.py — world-space matrix bake, dimension verify
  → t014_lod.py — LOD0/LOD1/LOD2 with Decimate modifiers
  → t015_export_glbs.py — GLB export with embedded materials
  → t016_renders.py — texture reference renders
```

**Makefile**: `make blender-pipeline`, `make blender-stage STAGE=t014`

Key vault doc: [[Tools — Blender]]

#### ComfyUI AI Texture Pipeline (`tools/comfyui/`)

AI-assisted PBR texture generation via SDXL + upscaler:

```
Blender renders (1024×1024 PNG)
  → ComfyUI Desktop (localhost:8000) via MCP or filesystem copy
    → SDXL img2img (sd_xl_base_1.0.safetensors)
    → RealESRGAN_x4plus 4× upscale → 4096×4096
    → Derive roughness/normal/metallic PBR maps
  → Install to src/assets/bus_model/textures/varieties/<variety>/
  → Commit to oldgrowth-assets submodule
```

Key vault doc: [[Tools — ComfyUI]]

#### Observer Visual QA Pipeline (`tools/observer/`)

Anthropic Claude-powered visual QA for generation changes:

```
Capture modes:
  make observer-snapshot-qa — 1 frame, immediate analysis
  make observer-sequence-qa — 32 frames @ 8fps, temporal analysis
  make observer-ci — CI quality gate (exits 2 on failure)

Analysis:
  analyze.py → schema v1.2 JSON output
    - overall_quality (good/acceptable/degraded/broken)
    - recommendation (ship_it/review_required/fix_before_merge/blocking_issue)
    - bugs array with severity (critical/high/medium/low)
    - scene_description, audio_quality (when frame.wav present)

Decision matrix (from `observer-qa` skill):
  | Quality | Recommendation | Action |
  |---|---|---|
  | good    | ship_it        | No action |
  | good    | review_required| Post PR comment; do not block |
  | acceptable | ship_it     | No action |
  | acceptable | review_required | Post PR comment; do not block |
  | acceptable | fix_before_merge | Create issue, note in PR, block merge |
  | poor    | any            | Create issue, block merge, investigate |
  | any     | blocking_issue | Halt, file critical issue, escalate to human |
  | any     | (bug severity: critical) | Escalate regardless of recommendation |
  | any     | (scene_correct: false) | Treat as at least fix_before_merge |
  | any     | (clipping_detected: true with high-severity bug) | Treat as fix_before_merge |
```

Key vault docs: [[Tools — Observer]], `.opencode/skills/SKILL.md` (observer-qa skill)

#### DMG Builder Pipeline (`tools/dmg/`)

macOS installer packaging tools:
- `generate_background.py` — DMG background image generation
- `fix_ds_store.py` — .DS_Store position restoration
- `validate_assets.py` — DMG asset integrity check

Used by `make dmg` and `make dmg-signed` targets (wraps `scripts/ci/sign_dmg.sh`).

## Key Data Flows

### Release flow

```
Developer bumps version in src/project.godot
  → Commit + merge to main
    → release.yml triggered
      → Build universal Rust dylib (aarch64 + x86_64 via lipo)
      → Export Godot app (macOS preset)
      → Sign with Developer ID
      → Notarize via Apple
      → Package DMG
      → Upload to Cloudflare R2 (releases bucket)
      → Publish GitHub Release (draft → published)
      → XADD releases.shipped → Valkey stream (via ngrok tunnel)
        → GTM runtime polls Valkey (XREADGROUP)
          → Draft release notes via LLM
          → Post to #announce-releases with Approve/Reject buttons
          → On approval: push Jekyll devlog post
      → Push release metadata PR (site/_data/release.yml)
```

### Vault audit flow

```
PR touches docs/vault/ or weekly Sunday 6am UTC
  → vault-audit.yml triggered
    → Phase 1: python vault_audit.py --apply
      → Schema validation, wikilink fixes, code-refs check
    → Phase 2 (weekly only): opencode vault-audit-semantic
      → Claim taxonomy analysis on notes with code-refs
    → Commit to vault/audit branch
    → Create/update rolling PR against main
```

### Development session flow

```
Human request (Slack @mention or terminal)
  → Persona runtime (Coordinator)
    → If code-touching task:
      → OpenCode HTTP API → session created
        → Sisyphus orchestrator activates
          → Decomposes task → spawns subagents (explore, librarian, oracle)
          → Delegates implementation to Sisyphus-Junior agents
          → Verifies results (LSP diagnostics, make targets)
          → Vault write-back for discoveries/decisions
        → Returns result to persona runtime
      → Response posted to Slack
    → If non-code task:
      → Letta agent processes directly
      → Response posted to Slack
```

## Network Port Map

| Port | Service | Protocol | Auth | Notes |
|---|---|---|---|---|
| 6379 | Valkey | TCP/RESP | requirepass | Local data store |
| 8283 | Letta Server | HTTP/REST | None (localhost) | Agent memory + LLM dispatch |
| 8080 | OpenCode serve | HTTP/REST | Bearer token | Session/message API |
| 9100 | Coordinator health | HTTP | None | `/metrics` for Prometheus |
| 9101 | GTM health | HTTP | None | `/metrics` + `/internal/approval-callback` |
| 4317 | OTel Collector | gRPC | None | OTLP ingest |
| 4040 | ngrok dashboard | HTTP | None | Local tunnel admin |
| 24971 | ngrok → Valkey | TCP/RESP | requirepass | CI tunnel (reserved endpoint) |
| 443 | Slack API | WebSocket | xapp- token | Socket Mode connection |

## Security Model

- **Token isolation**: Each persona has its own Slack bot token (xoxb-) and app token (xapp-). Cross-persona token use is a violation (Article XV).
- **OAuth minimum-necessary**: Each persona requests the minimum OAuth scopes for its charter. Over-scoping is a kill criterion (SC-008).
- **Two-path revocation**: Kill-switch via Slack Web API (`apps.uninstall`) or admin UI. Both paths invalidate tokens immediately.
- **LLM key isolation**: OpenRouter and Anthropic keys shared at v0.1 but revoked as part of kill-switch sequence per persona.
- **No public HTTP endpoints**: Socket Mode eliminates inbound HTTP. Only inbound connection is the ngrok TCP tunnel (Valkey protocol only, `requirepass`).
- **CI secrets isolation**: BUMP_PAT (fine-grained, contents+pullrequests+workflows:write) ≠ GITHUB_TOKEN (auto, contents:write). Token split prevents privilege escalation. SUBMODULE_PAT removed — asset submodule eliminated (spec 146).

## Related

- [[World — Procedural Generation]] — the in-game generation pipeline
- [[Generation Subsystem Pairs]] — GDScript+Rust delegation pattern
- [[CI Pipeline]] — CI/CD workflow inventory
- [[Release and Distribution]] — release pipeline details
- [[Autonomous Company Architecture]] — persona/Letta system architecture
- [[Build System]] — local Makefile targets
- [[Tools — Observer]] — visual QA pipeline
- [[Tools — Vault Audit]] — vault mechanical audit tooling
- [[Code]] — folder MOC
- [[Tooling — Domain MOC]] — domain MOC
- [[Constitution]] — authority hierarchy, Article III, Article IV, Article XIV

Controlled tag vocabulary (as read):
type/*:
- `type/code` — Code architecture, autoloads, conventions, tooling. Carries `code-refs:`. (e.g. `Code/Autoloads — Disturbance.md`)
- `type/decision` — Architectural or design decision made by an agent during a session. Written to `docs/vault/Decisions/`. (Agent notes only — spec 080.)
- `type/design` — Design intent, player-facing concepts, world lore. (e.g. `Design/World Model.md`)
- `type/discovery` — Non-obvious constraint, gap, or conflict found by an agent during a session. Written to `docs/vault/Discoveries/`. (Agent notes only — spec 080.)
- `type/moc` — Map of Content at any of three tiers (folder / domain / concept). (e.g. `Audio.md`)
- `type/principle` — Governance and constitutional notes. Non-negotiable rules. (e.g. `Governance/Constitution.md`)
- `type/reference` — Glossary, decision log, open questions, epics. (e.g. `Reference/Glossary.md`)
- `type/session-log` — Session activity log; permanent audit trail. Written to `docs/vault/Sessions/`. Append-only, never pruned. (Agent notes only — spec 080.)
- `type/spec` — Spec document at `docs/vault/Specs/NNN Title/spec.md`. Carries `spec-refs:`. (e.g. `Specs/047 Car Radio/spec.md`)
- `type/system` — A bounded subsystem with implementation. Carries `code-refs`, `spec-refs`, `implements:` frontmatter. (e.g. `Systems/Audio — Car Radio.md`)
- `type/vision` — Strategic / vision-layer decision. Written to `docs/vault/Vision/`. Human-authored or agent-proposed with human ratification before promotion to `status: reviewed`. (Per triage #3 — spec 133 autonomous-company redesign.)
domain/*:
- `domain/anomalies` — Anomaly taxonomy, individual anomaly systems, spawn, behavior
- `domain/art` — Visual direction, palettes, references, asset pipeline
- `domain/audio` — Audio systems: world ambient, radio, transmissions, buses, pipeline
- `domain/autonomous-company` — Autonomous company v0.1 experiment: Slack infra, persona middleware, Letta integration, restart recovery
- `domain/build` — Build system, packaging, export, release automation
- `domain/governance` — Constitution, phased spec, policies
- `domain/infrastructure` — Infrastructure provisioning: CI/CD, hosting, deployment tooling, secrets management
- `domain/narrative` — Tone, horror register, forest transmissions narrative, Gary/KTLK
- `domain/player` — Player mode, input, controls, camera, exit/entry
- `domain/systems` — Cross-cutting system architecture and integration work
- `domain/tooling` — Build, CI, observer, TTS pipeline, dev-time tools
- `domain/vehicle` — The Samba: vehicle physics, dashboard, damage, panels
- `domain/world` — World model, biomes, terrain, procedural generation, weather
status/*:
- `status/canonical` — Fully authoritative; promoted by humans only. Highest trust. (Agent notes only — spec 080.)
- `status/draft` — Authoring in progress, not yet verified
- `status/reviewed` — Agent-created note verified against codebase within its creating session. Eligible for auto-injection in subsequent task dispatches. (Agent notes only — spec 080.)
- `status/stale` — Known out of date; cannot update immediately. Pairs with `> [!warning] STALE — needs update` callout.
- `status/superseded` — Replaced by another note. Terminal state. Pairs with `> [!warning] SUPERSEDED` callout.
- `status/wip` — Stable but under active revision
layer/*:
- `layer/content` — Content assets (audio, models, textures, audio provenance)
- `layer/gdext` — gdext wrapper layer (`rust/gdext-wrapper/`)
- `layer/gdscript` — GDScript (Godot scene-tier logic)
- `layer/infra` — Build, CI, deployment infrastructure
- `layer/python` — Python development tooling (`tools/`)
- `layer/rust-core` — Engine-agnostic Rust core (`rust/rust-core/`)
concept/*:
- `concept/biome` — Biome-reactive behavior across systems
- `concept/contamination` — Across-runs panel and garage degradation; the slow-horror mechanic that doesn't reset with the world
- `concept/diegetic` — Diegetic audio / UI / world-sourced design
- `concept/disturbance` — The disturbance mechanic thread (Article X)
- `concept/ephemeral-world` — Run-reset, transient worlds (Article IV Rules 6–7)
- `concept/governance` — Constitutional and governance concepts
- `concept/horror` — Horror register and dread design
- `concept/procedural` — Procedural generation, seed determinism
- `concept/rendering` — Visual rendering quality, shader correctness, Terrain3D integration, mesh fidelity, LOD, Z-fighting
- `concept/terrain` — Terrain generation, heightmap, Terrain3D regions, roughness, playability constraints
ember's answer for tag_assignment-code-tools-development-workbench, domain/governanceP(true) placed on the no, unsure, and yes zones.nounsureyesgold: yesP = 0.30

tag_assignment-code-tools-development-workbench: type/code

Tag assignment · dev
Gold
The note calls for `type/code`: Code architecture, autoloads, conventions, tooling. Carries `code-refs:`. (e.g. `Code/Autoloads — Disturbance.md`) (True)
ember
The note has no reason to carry `type/code` (False)
Signal
P(true) 0.16 (no)
Kit outcome
acted on a wrong answer
Why this gold label
Mined from Code/Tools — Development Workbench.md at 692f4bb58b7f62105aeb73fba8dfee12bfdecd53; gold is the note's own vocabulary tags.
Tools — Development Workbench

The generative domain workbench is the entire development ecosystem that produces Old Growth. It spans persistent AI agents (personas), session-based AI agents (OpenCode + subagents), the vault knowledge graph, CI/CD automation, external infrastructure, and the in-game generation pipeline itself. This note maps every layer, their connections, and data flows — the meta-architecture of how the game is built.

## Layer Overview

```
┌──────────────────────────────────────────────────────────────────────┐
│                        HUMAN INTERFACE                               │
│       Slack (@mentions)      GitHub (PRs/Issues)      Terminal       │
└──────────┬──────────────────────────┬──────────────────────┬──────────┘
           │                          │                      │
           ▼                          ▼                      ▼
┌──────────────────────┐  ┌──────────────────────┐  ┌──────────────────┐
│  PERSISTENT AI       │  │  SESSION AI           │  │  DEV TOOLS       │
│  (Persona Layer)     │  │  (Agent Layer)        │  │  (Human-op)      │
├──────────────────────┤  ├──────────────────────┤  ├──────────────────┤
│  Coordinator Persona │  │  Sisyphus             │  │  Godot Editor    │
│  ─ routes tasks via  │  │  ─ orchestrator       │  │  gh CLI          │
│    Slack @mentions   │  │  sub-agents:          │  │  make targets    │
│                      │  │  explore, librarian,  │  │  cargo / pytest  │
│  GTM Persona         │  │  oracle, metis, momus │  │  obsidian        │
│  ─ release notes +   │  │  Sisyphus-Junior      │  │  blender         │
│    approval workflow │  │  Skills system        │  │  comfyui         │
│                      │  │  MCP servers          │  │                  │
│  Engineer (v0.5)     │  │                       │  │  launchd         │
│  Narrative (v0.2)    │  │                       │  │  ngrok           │
│  Playtest (v0.5)     │  │                       │  │  valkey          │
├──────────────────────┤  ├──────────────────────┤  └──────────────────┘
│  Letta Server        │  │  OpenCode + omo       │
│  (persistent memory) │  │  MCP servers:         │
│  Core/Archival/      │  │  vault, gdai-mcp,    │
│  Recall memory       │  │  blender, comfyui     │
└──────────┬───────────┘  └──────────┬────────────┘
           │                         │
           ▼                         ▼
┌──────────────────────────────────────────────────────────────────────┐
│                     KNOWLEDGE / SPEC LAYER                            │
├──────────────────────────────────────────────────────────────────────┤
│  ┌──────────────────────────────────────────────────────────────┐    │
│  │                    VAULT KNOWLEDGE GRAPH                      │    │
│  │  docs/vault/ — 1000+ notes organized in 3 tiers:              │    │
│  │  Tier 1: Governance, Design, Systems, Code, Specs,           │    │
│  │          Reference, Sessions, Decisions, Discoveries          │    │
│  │  Tier 2: Audio, Vehicle, World, Player, Anomalies,           │    │
│  │          Narrative, Tooling                                   │    │
│  │  Tier 3: Disturbance, Biome, Horror, Diegesis,               │    │
│  │          Ephemerality, Procedural Generation, Contamination   │    │
│  │  Read/write via mcpvault MCP server (opencode.json)          │    │
│  └──────────────────────────────────────────────────────────────┘    │
│                                                                      │
│ ┌─────────────────────────┐ ┌─────────────────────────────────┐   │
│ │  SPEC KIT (speckit.*)   │ │  CONSTITUTION (Governance/)     │   │
│ │  clarify → specify →    │ │  Supreme authority:             │   │
│ │  plan → tasks → implement│ │  Constitution > Design > Specs  │   │
│ │  → analyze               │ │  Personas cannot amend          │   │
│ │  139 specs in            │ │  Human-only: version bumps,      │   │
│ │  docs/vault/Specs/NNN/   │ │  merges, canonical status       │   │
│ └─────────────────────────┘ └─────────────────────────────────┘   │
│                                                                      │
│ ┌──────────────────────────────────────────────────────────────┐   │
│ │  AGENTS.md — Behavioral constitution for all agents          │   │
│ │  ─ Agent Behavior Foundation (4 principles)                 │   │
│ │  ─ Architecture rules, vault read/write protocol            │   │
│ │  ─ Code style, testing conventions, build commands          │   │
│ └──────────────────────────────────────────────────────────────┘   │
│                                                                      │
│ ┌──────────────────────────────────────────────────────────────┐   │
│ │  SEMANTIC DRIFT PIPELINE (spec 088)                          │   │
│  │  Phase 1 (Mechanical): vault_audit.py                        │   │
│  │    — schema validation, wikilink resolution, code-refs check │   │
│  │  Phase 2 (Auto-fix): --apply flag                            │   │
│  │    — stale markers, broken refs, missing spec stubs          │   │
│  │  Phase 3 (Semantic): vault-audit-semantic agent              │   │
│  │    — claim taxonomy (exact/range/approx/list/description)    │   │
│  │  CI: weekly Sunday + per-PR on docs/vault/ changes           │   │
│  │  Output: rolling vault/audit PR with auto-fixes              │   │
│  └──────────────────────────────────────────────────────────────┘   │
│                                                                      │
└──────────────────────────────────────────────────────────────────────┘
           │
           ▼
┌──────────────────────────────────────────────────────────────────────┐
│                    CI/CD / AUTOMATION LAYER                           │
├──────────────────────────────────────────────────────────────────────┤
│                                                                      │
│  ┌────────────────────────────────┐  ┌────────────────────────────┐  │
│  │  GitHub Actions (8 workflows)  │  │  Makefile (40+ targets)    │  │
│  │                                │  │                            │  │
│  │  ci-fast — merge gate         │  │  make all — full CI        │  │
│  │  ci-basics — full pipeline    │  │  make pre-commit — fast    │  │
│  │    (manual approval gate)     │  │  make test — GUT headless  │  │
│  │  release — ship DMG + R2      │  │  make rust-build/test      │  │
│  │  vault-audit — PR + weekly    │  │  make world-preview/qa     │  │
│  │  deploy-site — GitHub Pages   │  │  make observer-* — QA     │  │
│  │  persona-tests — middleware   │  │  make personas-up/down     │  │
│  │  auto-bump — safety net       │  │  make bump-patch/minor/mjr │  │
│  │  component-semver-autofix     │  │  make wiki-serve/build     │  │
│  └────────────────────────────────┘  └────────────────────────────┘  │
│                                                                      │
│  ┌──────────────────────────────────────────────────────────────┐   │
│  │  Pre-commit Hook (scripts/hooks/pre-commit)                  │   │
│  │  ├── Component SemVer auto-bump (patch)                     │   │
│  │  ├── Game version format check                               │   │
│  │  ├── Asset .gdignore check                                   │   │
│  │  ├── GDScript format-check + lint                            │   │
│  │  └── Rust tests + clippy (optional)                          │   │
│  └──────────────────────────────────────────────────────────────┘   │
│                                                                      │
└──────────────────────────────────────────────────────────────────────┘
           │
           ▼
┌──────────────────────────────────────────────────────────────────────┐
│                      INFRASTRUCTURE LAYER                              │
├──────────────────────────────────────────────────────────────────────┤
│                                                                      │
│  ┌────────────────────┐  ┌──────────────────┐  ┌─────────────────┐  │
│  │  macOS Dev Machine  │  │  Cloudflare R2   │  │  GitHub Pages   │  │
│  │  (all-local)        │  │  ─ releases      │  │  ─ Jekyll site  │  │
│  │                     │  │  ─ sccache cache │  │                 │  │
│  │  Valkey 8.0:6379   │  │  ─ downloads.    │  │  ─ shapeandshare│  │
│  │  Letta Docker:8283 │  │    playoldgrowth  │  │    .github.io   │  │
│  │  OTel Collector    │  └──────────────────┘  └─────────────────┘  │
│  │  ngrok tunnel      │                                             │
│  │  OpenCode serve    │  ┌──────────────────┐  ┌─────────────────┐  │
│  └────────────────────┘  │  LLM Providers   │  │  Slack           │  │
│                          │  ─ OpenRouter    │  │  ─ Socket Mode   │  │
│  launchd Services        │  ─ Anthropic     │  │  ─ Per-persona   │  │
│  ├── Letta server        │    (failover)    │  │    apps          │  │
│  ├── Coordinator runtime │  └──────────────────┘  └─────────────────┘  │
│  ├── GTM runtime         │                                             │
│  ├── ngrok agent         │  ┌──────────────────────────────────────┐  │
│  ├── OTel collector      │  │  Apple Services                      │  │
│  └── (future: more)      │  │  ─ Developer ID signing              │  │
│                          │  │  ─ Notarization                      │  │
│                          │  │  ─ DMG packaging                     │  │
│                          │  └──────────────────────────────────────┘  │
│                                                                      │
└──────────────────────────────────────────────────────────────────────┘
           │
           ▼
┌──────────────────────────────────────────────────────────────────────┐
│                  GENERATIVE CONTENT PIPELINES                         │
├──────────────────────────────────────────────────────────────────────┤
│  ┌───────────────┐  ┌───────────────┐  ┌───────────────┐            │
│  │  TTS Pipeline  │  │  Music        │  │  Blender 3D   │            │
│  │  tools/tts/    │  │  Pipeline     │  │  tools/blender/│            │
│  │  Kokoro,       │  │  Suno → genre │  │  Python mesh  │            │
│  │  Chatterbox,   │  │  filter chain │  │  separation,  │            │
│  │  ElevenLabs SFX│  │  → audio      │  │  LOD, GLB     │            │
│  │  → radio clips │  │    submodule  │  │  → game assets│            │
│  └───────┬───────┘  └───────┬───────┘  └───────┬───────┘            │
│          │                  │                  │                     │
│  ┌───────┴───────┐  ┌──────┴────────┐  ┌──────┴────────┐           │
│  │  ComfyUI      │  │  Observer QA  │  │  DMG Builder   │           │
│  │  tools/comfyui │  │  tools/observer│  │  tools/dmg/    │           │
│  │  SDXL img2img │  │  Claude screenshot│  │  Background  │           │
│  │  → PBR textures│  │  + audio analysis  │  │  .DS_Store   │           │
│  │  → submodule   │  │  → ci quality gate│  │  → signed DMG │           │
│  └───────────────┘  └─────────────────┘  └────────────────┘           │
│                                                                      │
└──────────────────────────────────────────────────────────────────────┘
           │
           ▼
┌──────────────────────────────────────────────────────────────────────┐
│                     GENERATED OUTPUT (THE GAME)                       │
├──────────────────────────────────────────────────────────────────────┤
│  In-game world generation pipeline, runtime systems, autoloads,     │
│  shipped assets (audio OGGs, 3D GLBs, textures, radio data)          │
│  (see [[World — Procedural Generation]] and [[Generation Subsystem Pairs]] for the │
│  full in-game architecture)                                                          │
└──────────────────────────────────────────────────────────────────────┘
```

## Layer Details

### 1. Persistent AI Layer (Personas)

Two active persona runtimes, with three more planned (v0.5):

| Persona | Role | Status | Agent ID | Port |
|---|---|---|---|---|
| Coordinator | Task routing, human↔system bridge | Active | `agent-420c0db8-...` | 9100 |
| GTM | Release notes, devlog drafting, approval workflow | Active | `agent-ccd29034-...` | 9101 |
| Engineer | Code implementation, spec shepherding | v0.5 | — | — |
| Narrative Director | Tone, canon, KTLK voice | v0.2 | — | — |
| Playtest Coordinator | Determinism verification, regression detection | v0.5 | — | — |

Each persona has structured identity files in `docs/vault/Reference/Autonomous Company/personas/<name>/`:
- `SOUL.md` — identity, voice, tone
- `CHARTER.md` — authority boundaries, permitted actions
- `INTENT.md` — priorities and goals
- `AGENTS.md` — operational runbook
- `MEMORY.md` — conversation history (via Letta)

**Runtime architecture** (Python, in `personas/`):
- `runtime.py` — Bolt framework with Socket Mode WebSocket connection
- `letta_bridge.py` — forwards Slack @mentions to Letta REST API (`http://localhost:8283`)
- `letta_agents.json` — maps persona name to Letta agent ID
- `opencode_client.py` — HTTP client for OpenCode serve (`http://localhost:8080`)
- `telemetry.py` — OTel span emission, Prometheus `/metrics`
- `shutdown.py` — graceful shutdown on token revocation (kill-switch)
- `approval_callback.py` — GTM's class-B approval workflow handler
- `config.py` — .env-based configuration (Slack tokens, API keys, ports)

**Data flows**:
- `@mention` → Slack Socket Mode → runtime.py → letta_bridge.py → Letta agent → LLM (OpenRouter/Anthropic) → response → Slack
- Code-touching tasks → OpenCode HTTP API → session (create/send/poll/close) → result → Slack

### 2. Session AI Layer (OpenCode + Subagents)

| Component | Description |
|---|---|
| Sisyphus | Primary orchestrator agent — decomposes tasks, delegates to subagents, verifies output |
| explore | Contextual grep — finds code patterns, module structure, cross-layer dependencies |
| librarian | External reference grep — searches docs, OSS examples, API specs |
| oracle | Read-only high-IQ consultant — complex architecture, debugging, tradeoff analysis |
| metis | Pre-planning consultant — identifies hidden intentions, ambiguities, AI failure points |
| momus | Plan critic — evaluates work plans for clarity, verifiability, completeness |
| Sisyphus-Junior | Focused task executor (same discipline, no delegation) — used across categories |
| multimodal-looker | Visual analysis of screenshots via Claude vision |

**Task categories** (domain-optimized models): `visual-engineering`, `artistry`, `ultrabrain`, `deep`, `quick`, `unspecified-low/high`, `writing`

**MCP servers** (configured in `opencode.json`):
- `gdai-mcp-server` — Godot editor runtime access (play scene, screenshot, editor scripts, node search)
- `mcpvault` (obsidian MCP) — vault read/write, note search, graph queries
- `blender` — 3D asset pipeline automation
- `comfyui` — AI image generation

**Skills system** (`.opencode/skills/`):
- `observer-qa` — Visual QA pipeline, agent trigger matrix, screenshot analysis
- `audio-assets` — TTS generation, audio submodule, provenance
- `introspection` — Vault health checks, semantic drift analysis
- `spec-management` — Spec creation, repositioning, specify workflow
- `blog-posts` — Jekyll devlog authoring, time-release scheduling

### 3. Knowledge / Spec Layer

See `docs/vault/README.md` and the vault structure at `docs/vault/` for full documentation. Key subsystems:

- **Vault knowledge graph**: 260+ notes across 15+ top-level directories, controlled vocabulary (`_meta/tags.md`), 3-tier MOC structure, agent note template (`_meta/templates/agent-note.md`)
- **Spec Kit**: `speckit.*` commands in `.opencode/command/` — clarify → specify → plan → tasks → implement → analyze workflow. 139 specs in `docs/vault/Specs/NNN Title/` with artifacts (plan.md, tasks.md, research.md, data-model.md, contracts/)
- **Semantic drift pipeline**: Three-phase audit (mechanical → auto-fix → semantic) with CI integration, weekly Sunday runs, rolling `vault/audit` PR
- **Constitution**: `docs/vault/Governance/Constitution.md` — supreme authority, Article III (Rust-first), Article IV (seed determinism), Article XIV (vault governance)

### 4. CI/CD Layer

Eight GitHub Actions workflows orchestrate all automation:

| Workflow | Trigger | Purpose | Required for merge |
|---|---|---|---|
| `ci-fast.yml` | PR to main | Fast checks: workflow lint, version bump, semver, GDScript quality, Rust clippy | Yes |
| `ci-basics.yml` | PR to main | Full pipeline: manual gate, Rust tests, GUT + headless (Linux), macOS smoke | Yes (human PRs) |
| `release.yml` | Version change on main | Universal DMG: build, sign, notarize, upload to R2, publish release | No (post-merge) |
| `vault-audit.yml` | PR on docs/vault/ + weekly Sun | Mechanical audit + optional semantic drift → rolling PR | Yes (vault changes) |
| `deploy-site.yml` | Push on site/ changes + daily | Jekyll build → GitHub Pages deploy | No |
| `persona-tests.yml` | PR on personas/ | pytest middleware tests | Yes (persona changes) |
| `auto-bump.yml` | Merge to main (conditional) | Safety-net: auto patch bump PR if missing | No |
| `component-semver-autofix.yml` | PR on mapped files | Auto-bump component versions if stale | No |

**Pre-commit hook** (`scripts/hooks/pre-commit`): runs semver, game-version-check, gdignore-check, format-check, lint — with auto-bump for component versions.

**Component SemVer** (`src/component_versions.json`): files mapped to components with version enforcement. Pre-commit hook auto-bumps patch; CI rejects un-bumped changes.

### 5. Infrastructure Layer

| Service | Purpose | Auth | Connection |
|---|---|---|---|
| Valkey 8.0 | Local event bus, `releases.shipped` stream | `requirepass` | Local port 6379, ngrok tunnel 24971 |
| Letta Server | Persistent agent memory (Docker) | None (localhost) | Port 8283 |
| OTel Collector | Observability spans (gRPC) | None (localhost) | Port 4317 |
| ngrok | TCP tunnel for CI → local Valkey | Auth token | `1.tcp.us-cal-1.ngrok.io:24971` |
| OpenCode serve | REST API for agent sessions | Bearer token | Port 8080 |
| Cloudflare R2 | Build artifact storage + sccache cache | R2 API keys | `downloads.playoldgrowth.com` |
| GitHub Pages | Jekyll site (`shapeandshare.github.io`) | OIDC | Automatic deploy |
| Slack (Socket Mode) | Persona communication surface | Bot tokens (xoxb-) | Outbound WebSocket |
| OpenRouter | Primary LLM provider | API key | Outbound HTTPS |
| Anthropic | LLM failover provider | API key | Outbound HTTPS |
| Apple Developer ID | Code signing + notarization | Cert + app password | Per-release CI |

**launchd-managed services** (auto-start on login):
- Letta Docker server
- Coordinator runtime (port 9100)
- GTM runtime (port 9101 + `/internal/approval-callback`)
- ngrok agent (TCP tunnel)
- OTel collector (gRPC ingest)

**Environment management**:
- `.env` — runtime secrets (Slack tokens, API keys, Valkey auth)
- GitHub Secrets — CI secrets (R2 keys, Apple certs, BUMP_PAT)
- `~/Library/Keychains/` — Apple Developer ID certificate (CI-imported)
- `docs/vault/Reference/Autonomous Company/Slack App Registration Runbook.md` — token provisioning

### 6. In-Game Generation Layer

The output of the workbench. See for full architecture:
- [[World — Procedural Generation]] — 11-step pipeline, RNG sub-seed derivation, subsystem details
- [[Generation Subsystem Pairs]] — complete inventory of every GDScript+Rust+bridge triple

### 7. Generative Content Pipelines

Six content creation pipelines produce game assets that ship in the `src/assets/` submodule. All are dev-time only — none run in the game binary.

#### TTS Pipeline (`tools/tts/`)

Three TTS engines, one post-processing chain, one submodule install step:

```
┌──────────────┐   ┌──────────────┐   ┌──────────────────┐
│  Kokoro 82M  │   │  Chatterbox  │   │  ElevenLabs SFX  │
│  (neutral)   │   │  (character) │   │  (ambient SFX)   │
│  .venv, no   │   │  conda, GPU  │   │  REST API        │
│  GPU needed  │   │  required    │   │  key in .env     │
└──────┬───────┘   └──────┬───────┘   └───────┬──────────┘
       │                  │                    │
       ▼                  ▼                    ▼
┌────────────────────────────────────────────────────────────┐
│  Gold WAV (48 kHz / 24-bit)                                │
│  → postprocess.sh (ffmpeg) → Master OGG                    │
│                               → HQ OGG (320 kbps)          │
│                               → LQ OGG (96 kbps)           │
│  → install to oldgrowth-assets submodule                   │
│  → validate naming + provenance                            │
└────────────────────────────────────────────────────────────┘
```

**Engines**: Kokoro 82M (neutral voice, lightweight, CPU), Chatterbox (voice cloning via conda+GPU for Gary/character voices), ElevenLabs SFX V2 API (weather ambient soundscapes)

**Script manifests**: 9 DJ station manifests (KOLD, KHRN, KFRO, KDRM, KDRN, KPGN, KJAZ, KVPR, KGSP), KTLK Gary dialogue (94 clips across 4 tiers), news scripts, music discovery manifests

**Validation**: 6 validate scripts (`validate_provenance.sh`, `validate_naming.sh`, etc.) for naming conventions and provenance metadata schema

**Makefile targets**: `make tts-gary`, `make tts-status`, `make tts-generate-all`

Key vault docs: [[Tools — TTS]], [[Audio — Pipeline]]

#### Music Pipeline (`tools/tts/music_process.sh`)

Suno-generated music → gold master → genre-specific post-processing → OGG ship → submodule install.

```
Suno (Pro/Premier for commercial rights)
  → Download MP3 → Convert to 48 kHz/24-bit WAV gold master
    → 11 genre-specific ffmpeg filter chains (per-station EQ/compression/character)
      → Master OGG + HQ OGG + LQ OGG
        → Install to oldgrowth-assets submodule
```

**Target**: 13 stations total (11 music + KTLK talk + KNWS news) — ~200–260 music tracks**

**Per-genre filter chains** (11 music stations): Dark Folk, Haunted Americana, Nordic Experimental, Dream Pop, Dark Ambient, Pagan Folk, Jazz, Vaporwave, Dark Gospel, Blues-Punk, PNW Garage-Psych (Note: KTLK 93.3 and KNWS 103.7 are talk/news — no music filter chains)

**Per-genre filter chains**: Dark Folk, Haunted Americana, Nordic Experimental, Dream Pop, Dark Ambient, Pagan Folk, Jazz, Vaporwave, Dark Gospel, Blues-Punk, PNW Garage-Psych

Key vault docs: [[Tools — Music Pipeline]], [[Audio — Radio Stations]]

#### Blender 3D Pipeline (`tools/blender/`)

Python automation for 3D asset processing, executed via MCP (`blender` in `opencode.json`):

```
bus_modified.blend
  → t011_separate_panels.py — 44 panel mesh separation from 8 sources
  → t012_uv_unwrap.py — UV0_Damage layer + Smart UV Project
  → t013_transforms.py — world-space matrix bake, dimension verify
  → t014_lod.py — LOD0/LOD1/LOD2 with Decimate modifiers
  → t015_export_glbs.py — GLB export with embedded materials
  → t016_renders.py — texture reference renders
```

**Makefile**: `make blender-pipeline`, `make blender-stage STAGE=t014`

Key vault doc: [[Tools — Blender]]

#### ComfyUI AI Texture Pipeline (`tools/comfyui/`)

AI-assisted PBR texture generation via SDXL + upscaler:

```
Blender renders (1024×1024 PNG)
  → ComfyUI Desktop (localhost:8000) via MCP or filesystem copy
    → SDXL img2img (sd_xl_base_1.0.safetensors)
    → RealESRGAN_x4plus 4× upscale → 4096×4096
    → Derive roughness/normal/metallic PBR maps
  → Install to src/assets/bus_model/textures/varieties/<variety>/
  → Commit to oldgrowth-assets submodule
```

Key vault doc: [[Tools — ComfyUI]]

#### Observer Visual QA Pipeline (`tools/observer/`)

Anthropic Claude-powered visual QA for generation changes:

```
Capture modes:
  make observer-snapshot-qa — 1 frame, immediate analysis
  make observer-sequence-qa — 32 frames @ 8fps, temporal analysis
  make observer-ci — CI quality gate (exits 2 on failure)

Analysis:
  analyze.py → schema v1.2 JSON output
    - overall_quality (good/acceptable/degraded/broken)
    - recommendation (ship_it/review_required/fix_before_merge/blocking_issue)
    - bugs array with severity (critical/high/medium/low)
    - scene_description, audio_quality (when frame.wav present)

Decision matrix (from `observer-qa` skill):
  | Quality | Recommendation | Action |
  |---|---|---|
  | good    | ship_it        | No action |
  | good    | review_required| Post PR comment; do not block |
  | acceptable | ship_it     | No action |
  | acceptable | review_required | Post PR comment; do not block |
  | acceptable | fix_before_merge | Create issue, note in PR, block merge |
  | poor    | any            | Create issue, block merge, investigate |
  | any     | blocking_issue | Halt, file critical issue, escalate to human |
  | any     | (bug severity: critical) | Escalate regardless of recommendation |
  | any     | (scene_correct: false) | Treat as at least fix_before_merge |
  | any     | (clipping_detected: true with high-severity bug) | Treat as fix_before_merge |
```

Key vault docs: [[Tools — Observer]], `.opencode/skills/SKILL.md` (observer-qa skill)

#### DMG Builder Pipeline (`tools/dmg/`)

macOS installer packaging tools:
- `generate_background.py` — DMG background image generation
- `fix_ds_store.py` — .DS_Store position restoration
- `validate_assets.py` — DMG asset integrity check

Used by `make dmg` and `make dmg-signed` targets (wraps `scripts/ci/sign_dmg.sh`).

## Key Data Flows

### Release flow

```
Developer bumps version in src/project.godot
  → Commit + merge to main
    → release.yml triggered
      → Build universal Rust dylib (aarch64 + x86_64 via lipo)
      → Export Godot app (macOS preset)
      → Sign with Developer ID
      → Notarize via Apple
      → Package DMG
      → Upload to Cloudflare R2 (releases bucket)
      → Publish GitHub Release (draft → published)
      → XADD releases.shipped → Valkey stream (via ngrok tunnel)
        → GTM runtime polls Valkey (XREADGROUP)
          → Draft release notes via LLM
          → Post to #announce-releases with Approve/Reject buttons
          → On approval: push Jekyll devlog post
      → Push release metadata PR (site/_data/release.yml)
```

### Vault audit flow

```
PR touches docs/vault/ or weekly Sunday 6am UTC
  → vault-audit.yml triggered
    → Phase 1: python vault_audit.py --apply
      → Schema validation, wikilink fixes, code-refs check
    → Phase 2 (weekly only): opencode vault-audit-semantic
      → Claim taxonomy analysis on notes with code-refs
    → Commit to vault/audit branch
    → Create/update rolling PR against main
```

### Development session flow

```
Human request (Slack @mention or terminal)
  → Persona runtime (Coordinator)
    → If code-touching task:
      → OpenCode HTTP API → session created
        → Sisyphus orchestrator activates
          → Decomposes task → spawns subagents (explore, librarian, oracle)
          → Delegates implementation to Sisyphus-Junior agents
          → Verifies results (LSP diagnostics, make targets)
          → Vault write-back for discoveries/decisions
        → Returns result to persona runtime
      → Response posted to Slack
    → If non-code task:
      → Letta agent processes directly
      → Response posted to Slack
```

## Network Port Map

| Port | Service | Protocol | Auth | Notes |
|---|---|---|---|---|
| 6379 | Valkey | TCP/RESP | requirepass | Local data store |
| 8283 | Letta Server | HTTP/REST | None (localhost) | Agent memory + LLM dispatch |
| 8080 | OpenCode serve | HTTP/REST | Bearer token | Session/message API |
| 9100 | Coordinator health | HTTP | None | `/metrics` for Prometheus |
| 9101 | GTM health | HTTP | None | `/metrics` + `/internal/approval-callback` |
| 4317 | OTel Collector | gRPC | None | OTLP ingest |
| 4040 | ngrok dashboard | HTTP | None | Local tunnel admin |
| 24971 | ngrok → Valkey | TCP/RESP | requirepass | CI tunnel (reserved endpoint) |
| 443 | Slack API | WebSocket | xapp- token | Socket Mode connection |

## Security Model

- **Token isolation**: Each persona has its own Slack bot token (xoxb-) and app token (xapp-). Cross-persona token use is a violation (Article XV).
- **OAuth minimum-necessary**: Each persona requests the minimum OAuth scopes for its charter. Over-scoping is a kill criterion (SC-008).
- **Two-path revocation**: Kill-switch via Slack Web API (`apps.uninstall`) or admin UI. Both paths invalidate tokens immediately.
- **LLM key isolation**: OpenRouter and Anthropic keys shared at v0.1 but revoked as part of kill-switch sequence per persona.
- **No public HTTP endpoints**: Socket Mode eliminates inbound HTTP. Only inbound connection is the ngrok TCP tunnel (Valkey protocol only, `requirepass`).
- **CI secrets isolation**: BUMP_PAT (fine-grained, contents+pullrequests+workflows:write) ≠ GITHUB_TOKEN (auto, contents:write). Token split prevents privilege escalation. SUBMODULE_PAT removed — asset submodule eliminated (spec 146).

## Related

- [[World — Procedural Generation]] — the in-game generation pipeline
- [[Generation Subsystem Pairs]] — GDScript+Rust delegation pattern
- [[CI Pipeline]] — CI/CD workflow inventory
- [[Release and Distribution]] — release pipeline details
- [[Autonomous Company Architecture]] — persona/Letta system architecture
- [[Build System]] — local Makefile targets
- [[Tools — Observer]] — visual QA pipeline
- [[Tools — Vault Audit]] — vault mechanical audit tooling
- [[Code]] — folder MOC
- [[Tooling — Domain MOC]] — domain MOC
- [[Constitution]] — authority hierarchy, Article III, Article IV, Article XIV

Controlled tag vocabulary (as read):
type/*:
- `type/code` — Code architecture, autoloads, conventions, tooling. Carries `code-refs:`. (e.g. `Code/Autoloads — Disturbance.md`)
- `type/decision` — Architectural or design decision made by an agent during a session. Written to `docs/vault/Decisions/`. (Agent notes only — spec 080.)
- `type/design` — Design intent, player-facing concepts, world lore. (e.g. `Design/World Model.md`)
- `type/discovery` — Non-obvious constraint, gap, or conflict found by an agent during a session. Written to `docs/vault/Discoveries/`. (Agent notes only — spec 080.)
- `type/moc` — Map of Content at any of three tiers (folder / domain / concept). (e.g. `Audio.md`)
- `type/principle` — Governance and constitutional notes. Non-negotiable rules. (e.g. `Governance/Constitution.md`)
- `type/reference` — Glossary, decision log, open questions, epics. (e.g. `Reference/Glossary.md`)
- `type/session-log` — Session activity log; permanent audit trail. Written to `docs/vault/Sessions/`. Append-only, never pruned. (Agent notes only — spec 080.)
- `type/spec` — Spec document at `docs/vault/Specs/NNN Title/spec.md`. Carries `spec-refs:`. (e.g. `Specs/047 Car Radio/spec.md`)
- `type/system` — A bounded subsystem with implementation. Carries `code-refs`, `spec-refs`, `implements:` frontmatter. (e.g. `Systems/Audio — Car Radio.md`)
- `type/vision` — Strategic / vision-layer decision. Written to `docs/vault/Vision/`. Human-authored or agent-proposed with human ratification before promotion to `status: reviewed`. (Per triage #3 — spec 133 autonomous-company redesign.)
domain/*:
- `domain/anomalies` — Anomaly taxonomy, individual anomaly systems, spawn, behavior
- `domain/art` — Visual direction, palettes, references, asset pipeline
- `domain/audio` — Audio systems: world ambient, radio, transmissions, buses, pipeline
- `domain/autonomous-company` — Autonomous company v0.1 experiment: Slack infra, persona middleware, Letta integration, restart recovery
- `domain/build` — Build system, packaging, export, release automation
- `domain/governance` — Constitution, phased spec, policies
- `domain/infrastructure` — Infrastructure provisioning: CI/CD, hosting, deployment tooling, secrets management
- `domain/narrative` — Tone, horror register, forest transmissions narrative, Gary/KTLK
- `domain/player` — Player mode, input, controls, camera, exit/entry
- `domain/systems` — Cross-cutting system architecture and integration work
- `domain/tooling` — Build, CI, observer, TTS pipeline, dev-time tools
- `domain/vehicle` — The Samba: vehicle physics, dashboard, damage, panels
- `domain/world` — World model, biomes, terrain, procedural generation, weather
status/*:
- `status/canonical` — Fully authoritative; promoted by humans only. Highest trust. (Agent notes only — spec 080.)
- `status/draft` — Authoring in progress, not yet verified
- `status/reviewed` — Agent-created note verified against codebase within its creating session. Eligible for auto-injection in subsequent task dispatches. (Agent notes only — spec 080.)
- `status/stale` — Known out of date; cannot update immediately. Pairs with `> [!warning] STALE — needs update` callout.
- `status/superseded` — Replaced by another note. Terminal state. Pairs with `> [!warning] SUPERSEDED` callout.
- `status/wip` — Stable but under active revision
layer/*:
- `layer/content` — Content assets (audio, models, textures, audio provenance)
- `layer/gdext` — gdext wrapper layer (`rust/gdext-wrapper/`)
- `layer/gdscript` — GDScript (Godot scene-tier logic)
- `layer/infra` — Build, CI, deployment infrastructure
- `layer/python` — Python development tooling (`tools/`)
- `layer/rust-core` — Engine-agnostic Rust core (`rust/rust-core/`)
concept/*:
- `concept/biome` — Biome-reactive behavior across systems
- `concept/contamination` — Across-runs panel and garage degradation; the slow-horror mechanic that doesn't reset with the world
- `concept/diegetic` — Diegetic audio / UI / world-sourced design
- `concept/disturbance` — The disturbance mechanic thread (Article X)
- `concept/ephemeral-world` — Run-reset, transient worlds (Article IV Rules 6–7)
- `concept/governance` — Constitutional and governance concepts
- `concept/horror` — Horror register and dread design
- `concept/procedural` — Procedural generation, seed determinism
- `concept/rendering` — Visual rendering quality, shader correctness, Terrain3D integration, mesh fidelity, LOD, Z-fighting
- `concept/terrain` — Terrain generation, heightmap, Terrain3D regions, roughness, playability constraints
ember's answer for tag_assignment-code-tools-development-workbench, type/codeP(true) placed on the no, unsure, and yes zones.nounsureyesgold: yesP = 0.16

tag_assignment-design-the-temporal-fracture: concept/horror

Tag assignment · test
Gold
The note calls for `concept/horror`: Horror register and dread design (True)
ember
The note has no reason to carry `concept/horror` (False)
Signal
P(true) 0.29 (unsure)
Kit outcome
deferred: treated as unsure
Why this gold label
Mined from Design/The Temporal Fracture.md at 692f4bb58b7f62105aeb73fba8dfee12bfdecd53; gold is the note's own vocabulary tags.
The Temporal Fracture

The insertion that created [[The Crater]] did not only displace terrain. It displaced spacetime. The construct is still actively reshaping the space it occupies, and the temporal distortion is not a scar from a past event — it is the ongoing wake of something still transforming this dimensional plane. This note describes how broken time manifests inside the crater and how it unifies the game's major systems under a single lore framework.

## The Fracture

The multidimensional construct did not shatter spacetime on insertion — it displaced it as it actively reshapes the space it occupies. The terraforming zone (see [[The Crater]]) is still active. The construct is still partially present, still reshaping the local temporal structure at a timescale geology cannot register. The temporal fracture is not damage from a past event. It is the ongoing distortion created by something that is still actively transforming this dimensional plane.

The crater's bowl geometry acts as a lens — focusing the dimensional energy inward, concentrating the temporal distortion at the center, and containing it within the rim. Time inside the crater does not flow uniformly. Different parts of the basin exist at different temporal rates, or at different temporal positions entirely. The fracture is not uniform; it is textured, layered, and locally variable — because the construct's cross-section through 3D space is not uniform.

There is no "outside the rim." The crater is one face of a higher-dimensional structure the construct left embedded in three-dimensional space (see The Crater). The rim is where this face curves back on itself in dimensions the player cannot perceive. The exit corridors are edges of the geometry — paths along which the 3D projection folds back to the vertex at the center. Driving through an exit corridor does not bring the player outside. It brings them back to the garage. Extraction is completing a circuit, not escaping a container.

## What the Player Experiences

- **Time does not flow uniformly.** Different parts of the crater exist at different temporal rates or even different temporal positions. A meadow might be stuck in perpetual late summer. A valley might cycle through seasons in minutes. A stretch of road might take longer to drive than the distance should require
- **The forest is simultaneously ancient and immediate.** Trees that should have taken centuries to grow appeared in years. Decay happens at wrong rates. Things feel old and new at the same time. This is not a contradiction — it is what a forest looks like when it grows in broken time
- **The player's own experience is unreliable.** How long have they been driving? The clock on the dashboard might not agree with the sky. A run that feels like 20 minutes may have been hours — or seconds. The player has no instrument that measures time reliably inside the fracture
- **The crater exists across multiple temporal layers simultaneously.** The player experiences a collapsed superposition — multiple versions of this place overlaid. Most of the time, the layers are close enough to cohere. When they are not, the player sees anomalies

## Procedural Generation as Temporal Slicing

The procedural world generation is not a game abstraction. It is the crater literally being in a different temporal configuration each time the player enters.

- **Each seed is a temporal slice.** The same seed produces the same world because it accesses the same temporal configuration. The roads are in different places between seeds because time moved differently between configurations. The terrain is the same crater, viewed through different temporal lenses
- **The world is not regenerated — it is re-accessed.** The crater does not rebuild itself between runs. The player is entering a different temporal window into the same space. The geology is constant (the bowl, the rim, the breach corridors). Everything layered on top — roads, structures, vegetation, anomaly positions — exists in the temporal configuration the seed selects
- **Ephemerality is not a reset.** When the player returns to the garage, the temporal window they were in closes. The world they explored still exists in its temporal layer — they simply cannot reach it again without the same seed. This reframes the run loop: the player is not losing progress. They are navigating between temporal configurations of a place that contains all of them simultaneously

## The Garage as Vertex

The garage sits at the geometric center of the crater — the vertex of the geometry's 3D projection, the point where all faces share a common coordinate. At this point, the temporal layers converge into coherence. Maximum concentration, maximum stability. The garage is the one fixed reference frame in a space where time is locally broken.

This is why the garage persists when nothing else does. It is not protected by anything. It occupies the point where the geometry guarantees agreement across all faces. The temporal layers all converge on what the center looks like, even when they disagree on everything else.

This is also why extraction always returns to the garage. The exit corridors are edges of the geometry. All edges lead back to the vertex. No matter which face the player is traversing, no matter which corridor they find, the path folds back to the one point all faces share. The player experiences this as "reaching the exit and arriving at the garage." The geometry experiences this as a circuit completing.

**The loop is the structure.** The run cycle — garage to forest to exit to garage — is not a game loop imposed on a world. It is the topology of the structure expressed as navigation. Pre-convergence, the player cannot break the loop because the loop is the shape of the space they are inside. Extraction and death are both returns to the vertex. The difference is how much damage the circuit did on the way through. Post-convergence, the loop breaks: death still returns to the vertex, but the converged player-bus entity can traverse the rim into the outside (see spec 127).

The previous occupants discovered this empirically. They built the garage where things stayed put. Their wall map, annotated across multiple seasons by multiple hands, is evidence that someone survived long enough to learn the pattern. The shift in their annotations — from exploration to documentation to acceptance — is evidence that they also learned the pattern has no exit.

## The Storm as Active Terraforming

When disturbance reaches its peak, the player experiences the construct's terraforming process at full intensity. The Storm is not weather. It is not an echo of a past event. It is the reshaping *still happening* — the construct still transforming the space, felt at full intensity when the temporal field is sufficiently destabilized.

- **The Storm is the terraforming becoming perceptible.** The terraforming is not over. The construct is still actively reshaping this dimensional plane at a timescale beyond human perception. Normally, the temporal fracture absorbs and diffuses this ongoing process. When the player destabilizes the field past the threshold, the fracture loses coherence and the raw transformation becomes perceptible — a wall of displacement energy advancing from the rim. - **This is why the Storm is indifferent.** It is not targeting the player. It is not a response to anything. It is a process that has been running since the construct first entered this space, briefly made visible by the player's destabilization of the field that normally masks it. The Storm does not care about the player because the Storm is not an event — it is a condition, momentarily unfiltered
- **The Storm spawns from the rim because the rim is the boundary of the active transformation.** The terraforming energy radiates inward from the edges of the insertion zone — the construct's cross-section through 3D space pushes energy toward the center along the topology of the structure. The wall advances toward the vertex because the geometry focuses everything inward
- **The post-extraction silence is the circuit completing.** The 3-second silence beat after successful extraction (spec 107) is the moment the player passes through the structure's edge and arrives back at the vertex. The raw transformation fades not because the player escaped it but because the vertex is the one point where the temporal field is maximally coherent. For three seconds, time agrees with itself. Then the next run begins, and the player enters another temporal configuration

## Anomalies as Temporal Bleed

The seven anomalies are moments where the temporal layers fail to cohere. They are not caused by the player — they were happening before the first vehicle entered the tree line, and they will happen after the last one is incorporated.

- **Deadfall:** A tree that fell in another temporal layer. The angle is wrong for wind because the wind that felled it is not blowing in this layer
- **Spore Clouds:** Biological matter drifting between temporal configurations. The spores are from a version of the forest that is not quite this one
- **Hollow Trees:** Points where the temporal fracture is locally deepest. The blackened husk exists at a different temporal rate — instruments drift because the local timeframe is inconsistent with the player's
- **Amber Bleed:** Light from another temporal layer bleeding through. It looks like exit lanterns because the exit corridors are where the fracture is thinnest — the light is real, but it is real somewhere else
- **Mycelium Network:** The fungal network spans temporal layers. Contact in one layer propagates instantly because the network does not distinguish between temporal configurations — it exists in all of them simultaneously
- **Petrified Zones:** Regions where time has locally stopped or slowed to geological rates. Active calcification is what happens to biological matter when it experiences millions of years in seconds. Momentum — continuous movement — keeps the player in their own timeframe
- **The Silence:** A zone where the temporal fracture has stripped away everything except the present moment. No ambient sound because ambient sound requires temporal continuity — a before and after. Inside The Silence there is only now, and now contains only what is physically present, which includes the player's heartbeat and whatever else was already there

## Radio as Temporal Bleed

The KTLK radio signal bleeds through temporal layers. Gary the DJ might be broadcasting from a different temporal configuration entirely — his signal reaching the player not through distance but through the fracture's thinnest points.

- **Signal degradation correlates with temporal instability.** Deeper into the crater, further from the rim breaches, the temporal layers are thicker and less coherent. The signal has to cross more temporal boundaries to reach the player
- **What comes through after the signal dies is not static.** It is other temporal layers. The forest has been using the frequency for longer than the station has existed — not intentionally, but because electromagnetic energy does not respect temporal boundaries any more than the mycelium network does
- **Other vehicles or signs of human presence could be temporal echoes.** Not ghosts — real people who were here at a different point in the crater's fractured timeline. Their tire tracks, their abandoned equipment, their structures — all evidence of temporal layers the player can observe but not reach

## Disturbance as Temporal Destabilization

The disturbance meter measures how much the player's actions destabilize the terraformed space. Every input — combustion, noise, impact, light — feeds energy into a system that is already barely holding together because it is actively being reshaped.

- **The condition is the ongoing terraforming.** The forest's metabolism, the way it processes the player's presence, is the temporal field responding to new inputs in a space already being reshaped by the construct's presence. The condition was running before the player arrived because the terraforming has been active since the insertion
- **Disturbance thresholds are coherence thresholds.** Calm: the temporal layers are mostly aligned. Uneasy: layers begin to drift. Agitated: layers are visibly misaligned (the sky shifts, the wind carries debris from other configurations). Storm: the layers collapse and the raw terraforming becomes perceptible
- **The forest "responding" to the player is causality misbehaving.** In a fractured temporal field, effects can precede causes. The forest reacting to what the player is about to do is not intelligence — it is broken time. The environment responds to temporal ripples that propagate in all directions, including backward

## Design Implications

This framework does not require any system to be rewritten. It provides lore grounding for mechanics that already exist:

| Existing mechanic | Lore explanation |
|---|---|
| Procedural generation from seeds | Each seed accesses a different temporal configuration of the structure |
| World ephemerality between runs | The player moved to a different temporal configuration; the previous one still exists |
| Garage persistence | The vertex — the one point all faces of the geometry share |
| The run loop (garage-forest-exit-garage) | The topology of the geometry expressed as navigation; all edges return to the vertex |
| Extraction | Completing a circuit along an edge of the geometry, not escaping |
| Death vs extraction (pre-convergence) | Both return to the vertex; the difference is damage sustained in transit |
| Death vs extraction (post-convergence) | Death still returns to vertex; extraction crosses the rim into the outside — the converged player-bus entity can traverse the geometry rather than fold back |
| Disturbance meter | Temporal destabilization measurement |
| The Storm | The ongoing insertion, momentarily unfiltered by destabilized temporal field |
| Anomalies | Temporal layer bleed-through |
| Radio degradation | Signal crossing temporal boundaries |
| Water flowing inward | Basin hydrology (physical, not temporal) |
| Biome diversity | Elevation gradient + anomalous growth conditions in broken time |
| Exit corridors | Edges of the geometry where the 3D projection folds back to the vertex |
| No true escape (pre-convergence) | The structure is closed; the player folds back to the vertex |
| Phase transition (post-convergence) | The converged player-bus entity can traverse the rim into the outside; the game rules change |

## Related

- [[The Crater]] — the physical origin event and basin geography
- [[World Model]] — structural world rules this lore grounds
- [[Disturbance System]] — the mechanic reframed as temporal destabilization
- [[Anomalies]] — the seven phenomena as temporal bleed-through
- [[Tone and Horror]] — indifference framing: the fracture is not aware of the player
- [[Narrative Direction]] — the endpoint as temporal dissolution
- [[Audio — Car Radio]] — radio signal as temporal layer crossing
- [[Audio — Forest Transmissions]] — what bleeds through after the signal dies

Controlled tag vocabulary (as read):
type/*:
- `type/code` — Code architecture, autoloads, conventions, tooling. Carries `code-refs:`. (e.g. `Code/Autoloads — Disturbance.md`)
- `type/decision` — Architectural or design decision made by an agent during a session. Written to `docs/vault/Decisions/`. (Agent notes only — spec 080.)
- `type/design` — Design intent, player-facing concepts, world lore. (e.g. `Design/World Model.md`)
- `type/discovery` — Non-obvious constraint, gap, or conflict found by an agent during a session. Written to `docs/vault/Discoveries/`. (Agent notes only — spec 080.)
- `type/moc` — Map of Content at any of three tiers (folder / domain / concept). (e.g. `Audio.md`)
- `type/principle` — Governance and constitutional notes. Non-negotiable rules. (e.g. `Governance/Constitution.md`)
- `type/reference` — Glossary, decision log, open questions, epics. (e.g. `Reference/Glossary.md`)
- `type/session-log` — Session activity log; permanent audit trail. Written to `docs/vault/Sessions/`. Append-only, never pruned. (Agent notes only — spec 080.)
- `type/spec` — Spec document at `docs/vault/Specs/NNN Title/spec.md`. Carries `spec-refs:`. (e.g. `Specs/047 Car Radio/spec.md`)
- `type/system` — A bounded subsystem with implementation. Carries `code-refs`, `spec-refs`, `implements:` frontmatter. (e.g. `Systems/Audio — Car Radio.md`)
- `type/vision` — Strategic / vision-layer decision. Written to `docs/vault/Vision/`. Human-authored or agent-proposed with human ratification before promotion to `status: reviewed`. (Per triage #3 — spec 133 autonomous-company redesign.)
domain/*:
- `domain/anomalies` — Anomaly taxonomy, individual anomaly systems, spawn, behavior
- `domain/art` — Visual direction, palettes, references, asset pipeline
- `domain/audio` — Audio systems: world ambient, radio, transmissions, buses, pipeline
- `domain/autonomous-company` — Autonomous company v0.1 experiment: Slack infra, persona middleware, Letta integration, restart recovery
- `domain/build` — Build system, packaging, export, release automation
- `domain/governance` — Constitution, phased spec, policies
- `domain/infrastructure` — Infrastructure provisioning: CI/CD, hosting, deployment tooling, secrets management
- `domain/narrative` — Tone, horror register, forest transmissions narrative, Gary/KTLK
- `domain/player` — Player mode, input, controls, camera, exit/entry
- `domain/systems` — Cross-cutting system architecture and integration work
- `domain/tooling` — Build, CI, observer, TTS pipeline, dev-time tools
- `domain/vehicle` — The Samba: vehicle physics, dashboard, damage, panels
- `domain/world` — World model, biomes, terrain, procedural generation, weather
status/*:
- `status/canonical` — Fully authoritative; promoted by humans only. Highest trust. (Agent notes only — spec 080.)
- `status/draft` — Authoring in progress, not yet verified
- `status/reviewed` — Agent-created note verified against codebase within its creating session. Eligible for auto-injection in subsequent task dispatches. (Agent notes only — spec 080.)
- `status/stale` — Known out of date; cannot update immediately. Pairs with `> [!warning] STALE — needs update` callout.
- `status/superseded` — Replaced by another note. Terminal state. Pairs with `> [!warning] SUPERSEDED` callout.
- `status/wip` — Stable but under active revision
layer/*:
- `layer/content` — Content assets (audio, models, textures, audio provenance)
- `layer/gdext` — gdext wrapper layer (`rust/gdext-wrapper/`)
- `layer/gdscript` — GDScript (Godot scene-tier logic)
- `layer/infra` — Build, CI, deployment infrastructure
- `layer/python` — Python development tooling (`tools/`)
- `layer/rust-core` — Engine-agnostic Rust core (`rust/rust-core/`)
concept/*:
- `concept/biome` — Biome-reactive behavior across systems
- `concept/contamination` — Across-runs panel and garage degradation; the slow-horror mechanic that doesn't reset with the world
- `concept/diegetic` — Diegetic audio / UI / world-sourced design
- `concept/disturbance` — The disturbance mechanic thread (Article X)
- `concept/ephemeral-world` — Run-reset, transient worlds (Article IV Rules 6–7)
- `concept/governance` — Constitutional and governance concepts
- `concept/horror` — Horror register and dread design
- `concept/procedural` — Procedural generation, seed determinism
- `concept/rendering` — Visual rendering quality, shader correctness, Terrain3D integration, mesh fidelity, LOD, Z-fighting
- `concept/terrain` — Terrain generation, heightmap, Terrain3D regions, roughness, playability constraints
ember's answer for tag_assignment-design-the-temporal-fracture, concept/horrorP(true) placed on the no, unsure, and yes zones.nounsureyesgold: yesP = 0.29

tag_assignment-decisions-splash-screen-signal-scope: domain/governance

Tag assignment · dev
Gold
The note calls for `domain/governance`: Constitution, phased spec, policies (True)
ember
The note has no reason to carry `domain/governance` (False)
Signal
P(true) 0.34 (unsure)
Kit outcome
deferred: treated as unsure
Why this gold label
Mined from Decisions/Splash Screen Signal Scope.md at 692f4bb58b7f62105aeb73fba8dfee12bfdecd53; gold is the note's own vocabulary tags.
Splash Screen Signal Scope

This note records why splash_completed is declared on the splash script rather than on the Events autoload signal bus.

## The Rule and the Exception

The architecture rule is: cross-system communication goes through Events signals only (constitution Article VI). The splash screen is an exception, and the exception is justified by three properties that must all be true simultaneously:

1. The scene is transient — it is instantiated in main.gd _ready(), played once, then freed. It does not persist for the lifetime of the session.
2. There is exactly one consumer — main.gd listens for splash_completed to show the main menu. No other system cares about splash completion.
3. The signal has no reuse value — no future system would plausibly need to react to splash completion.

When all three are true, putting the signal on Events is pure overhead: a permanently registered signal with a lifetime of seconds, a single connection, and no cross-system value.

## Why This Matters for Future Agents

Any agent implementing or modifying the splash screen should not reflexively move splash_completed to Events. The signal's placement on the script is not an oversight — it is the intended design. If a future spec adds a second consumer of splash completion (e.g. analytics, a cinematic system), that is the trigger to reconsider. Until then, the signal stays local.

## The General Pattern

The test for whether a signal belongs on Events vs on its emitting script:
- Multiple consumers across systems → Events
- Single transient consumer, short-lived scene → script-local signal
- Persistent scene with one consumer → case-by-case; prefer Events for consistency unless the scene is truly ephemeral

## References

- src/scenes/ui/splash_screen.tscn (when implemented)
- src/scripts/ui/splash_screen.gd (when implemented)
- src/scripts/main.gd
- docs/vault/Specs/083 Atmospheric Splash Screen/083 Atmospheric Splash Screen.md

Controlled tag vocabulary (as read):
type/*:
- `type/code` — Code architecture, autoloads, conventions, tooling. Carries `code-refs:`. (e.g. `Code/Autoloads — Disturbance.md`)
- `type/decision` — Architectural or design decision made by an agent during a session. Written to `docs/vault/Decisions/`. (Agent notes only — spec 080.)
- `type/design` — Design intent, player-facing concepts, world lore. (e.g. `Design/World Model.md`)
- `type/discovery` — Non-obvious constraint, gap, or conflict found by an agent during a session. Written to `docs/vault/Discoveries/`. (Agent notes only — spec 080.)
- `type/moc` — Map of Content at any of three tiers (folder / domain / concept). (e.g. `Audio.md`)
- `type/principle` — Governance and constitutional notes. Non-negotiable rules. (e.g. `Governance/Constitution.md`)
- `type/reference` — Glossary, decision log, open questions, epics. (e.g. `Reference/Glossary.md`)
- `type/session-log` — Session activity log; permanent audit trail. Written to `docs/vault/Sessions/`. Append-only, never pruned. (Agent notes only — spec 080.)
- `type/spec` — Spec document at `docs/vault/Specs/NNN Title/spec.md`. Carries `spec-refs:`. (e.g. `Specs/047 Car Radio/spec.md`)
- `type/system` — A bounded subsystem with implementation. Carries `code-refs`, `spec-refs`, `implements:` frontmatter. (e.g. `Systems/Audio — Car Radio.md`)
- `type/vision` — Strategic / vision-layer decision. Written to `docs/vault/Vision/`. Human-authored or agent-proposed with human ratification before promotion to `status: reviewed`. (Per triage #3 — spec 133 autonomous-company redesign.)
domain/*:
- `domain/anomalies` — Anomaly taxonomy, individual anomaly systems, spawn, behavior
- `domain/art` — Visual direction, palettes, references, asset pipeline
- `domain/audio` — Audio systems: world ambient, radio, transmissions, buses, pipeline
- `domain/autonomous-company` — Autonomous company v0.1 experiment: Slack infra, persona middleware, Letta integration, restart recovery
- `domain/build` — Build system, packaging, export, release automation
- `domain/governance` — Constitution, phased spec, policies
- `domain/infrastructure` — Infrastructure provisioning: CI/CD, hosting, deployment tooling, secrets management
- `domain/narrative` — Tone, horror register, forest transmissions narrative, Gary/KTLK
- `domain/player` — Player mode, input, controls, camera, exit/entry
- `domain/systems` — Cross-cutting system architecture and integration work
- `domain/tooling` — Build, CI, observer, TTS pipeline, dev-time tools
- `domain/vehicle` — The Samba: vehicle physics, dashboard, damage, panels
- `domain/world` — World model, biomes, terrain, procedural generation, weather
status/*:
- `status/canonical` — Fully authoritative; promoted by humans only. Highest trust. (Agent notes only — spec 080.)
- `status/draft` — Authoring in progress, not yet verified
- `status/reviewed` — Agent-created note verified against codebase within its creating session. Eligible for auto-injection in subsequent task dispatches. (Agent notes only — spec 080.)
- `status/stale` — Known out of date; cannot update immediately. Pairs with `> [!warning] STALE — needs update` callout.
- `status/superseded` — Replaced by another note. Terminal state. Pairs with `> [!warning] SUPERSEDED` callout.
- `status/wip` — Stable but under active revision
layer/*:
- `layer/content` — Content assets (audio, models, textures, audio provenance)
- `layer/gdext` — gdext wrapper layer (`rust/gdext-wrapper/`)
- `layer/gdscript` — GDScript (Godot scene-tier logic)
- `layer/infra` — Build, CI, deployment infrastructure
- `layer/python` — Python development tooling (`tools/`)
- `layer/rust-core` — Engine-agnostic Rust core (`rust/rust-core/`)
concept/*:
- `concept/biome` — Biome-reactive behavior across systems
- `concept/contamination` — Across-runs panel and garage degradation; the slow-horror mechanic that doesn't reset with the world
- `concept/diegetic` — Diegetic audio / UI / world-sourced design
- `concept/disturbance` — The disturbance mechanic thread (Article X)
- `concept/ephemeral-world` — Run-reset, transient worlds (Article IV Rules 6–7)
- `concept/governance` — Constitutional and governance concepts
- `concept/horror` — Horror register and dread design
- `concept/procedural` — Procedural generation, seed determinism
- `concept/rendering` — Visual rendering quality, shader correctness, Terrain3D integration, mesh fidelity, LOD, Z-fighting
- `concept/terrain` — Terrain generation, heightmap, Terrain3D regions, roughness, playability constraints
ember's answer for tag_assignment-decisions-splash-screen-signal-scope, domain/governanceP(true) placed on the no, unsure, and yes zones.nounsureyesgold: yesP = 0.34

tag_assignment-decisions-splash-screen-signal-scope: layer/gdscript

Tag assignment · dev
Gold
The note calls for `layer/gdscript`: GDScript (Godot scene-tier logic) (True)
ember
The note has no reason to carry `layer/gdscript` (False)
Signal
P(true) 0.27 (unsure)
Kit outcome
deferred: treated as unsure
Why this gold label
Mined from Decisions/Splash Screen Signal Scope.md at 692f4bb58b7f62105aeb73fba8dfee12bfdecd53; gold is the note's own vocabulary tags.
Splash Screen Signal Scope

This note records why splash_completed is declared on the splash script rather than on the Events autoload signal bus.

## The Rule and the Exception

The architecture rule is: cross-system communication goes through Events signals only (constitution Article VI). The splash screen is an exception, and the exception is justified by three properties that must all be true simultaneously:

1. The scene is transient — it is instantiated in main.gd _ready(), played once, then freed. It does not persist for the lifetime of the session.
2. There is exactly one consumer — main.gd listens for splash_completed to show the main menu. No other system cares about splash completion.
3. The signal has no reuse value — no future system would plausibly need to react to splash completion.

When all three are true, putting the signal on Events is pure overhead: a permanently registered signal with a lifetime of seconds, a single connection, and no cross-system value.

## Why This Matters for Future Agents

Any agent implementing or modifying the splash screen should not reflexively move splash_completed to Events. The signal's placement on the script is not an oversight — it is the intended design. If a future spec adds a second consumer of splash completion (e.g. analytics, a cinematic system), that is the trigger to reconsider. Until then, the signal stays local.

## The General Pattern

The test for whether a signal belongs on Events vs on its emitting script:
- Multiple consumers across systems → Events
- Single transient consumer, short-lived scene → script-local signal
- Persistent scene with one consumer → case-by-case; prefer Events for consistency unless the scene is truly ephemeral

## References

- src/scenes/ui/splash_screen.tscn (when implemented)
- src/scripts/ui/splash_screen.gd (when implemented)
- src/scripts/main.gd
- docs/vault/Specs/083 Atmospheric Splash Screen/083 Atmospheric Splash Screen.md

Controlled tag vocabulary (as read):
type/*:
- `type/code` — Code architecture, autoloads, conventions, tooling. Carries `code-refs:`. (e.g. `Code/Autoloads — Disturbance.md`)
- `type/decision` — Architectural or design decision made by an agent during a session. Written to `docs/vault/Decisions/`. (Agent notes only — spec 080.)
- `type/design` — Design intent, player-facing concepts, world lore. (e.g. `Design/World Model.md`)
- `type/discovery` — Non-obvious constraint, gap, or conflict found by an agent during a session. Written to `docs/vault/Discoveries/`. (Agent notes only — spec 080.)
- `type/moc` — Map of Content at any of three tiers (folder / domain / concept). (e.g. `Audio.md`)
- `type/principle` — Governance and constitutional notes. Non-negotiable rules. (e.g. `Governance/Constitution.md`)
- `type/reference` — Glossary, decision log, open questions, epics. (e.g. `Reference/Glossary.md`)
- `type/session-log` — Session activity log; permanent audit trail. Written to `docs/vault/Sessions/`. Append-only, never pruned. (Agent notes only — spec 080.)
- `type/spec` — Spec document at `docs/vault/Specs/NNN Title/spec.md`. Carries `spec-refs:`. (e.g. `Specs/047 Car Radio/spec.md`)
- `type/system` — A bounded subsystem with implementation. Carries `code-refs`, `spec-refs`, `implements:` frontmatter. (e.g. `Systems/Audio — Car Radio.md`)
- `type/vision` — Strategic / vision-layer decision. Written to `docs/vault/Vision/`. Human-authored or agent-proposed with human ratification before promotion to `status: reviewed`. (Per triage #3 — spec 133 autonomous-company redesign.)
domain/*:
- `domain/anomalies` — Anomaly taxonomy, individual anomaly systems, spawn, behavior
- `domain/art` — Visual direction, palettes, references, asset pipeline
- `domain/audio` — Audio systems: world ambient, radio, transmissions, buses, pipeline
- `domain/autonomous-company` — Autonomous company v0.1 experiment: Slack infra, persona middleware, Letta integration, restart recovery
- `domain/build` — Build system, packaging, export, release automation
- `domain/governance` — Constitution, phased spec, policies
- `domain/infrastructure` — Infrastructure provisioning: CI/CD, hosting, deployment tooling, secrets management
- `domain/narrative` — Tone, horror register, forest transmissions narrative, Gary/KTLK
- `domain/player` — Player mode, input, controls, camera, exit/entry
- `domain/systems` — Cross-cutting system architecture and integration work
- `domain/tooling` — Build, CI, observer, TTS pipeline, dev-time tools
- `domain/vehicle` — The Samba: vehicle physics, dashboard, damage, panels
- `domain/world` — World model, biomes, terrain, procedural generation, weather
status/*:
- `status/canonical` — Fully authoritative; promoted by humans only. Highest trust. (Agent notes only — spec 080.)
- `status/draft` — Authoring in progress, not yet verified
- `status/reviewed` — Agent-created note verified against codebase within its creating session. Eligible for auto-injection in subsequent task dispatches. (Agent notes only — spec 080.)
- `status/stale` — Known out of date; cannot update immediately. Pairs with `> [!warning] STALE — needs update` callout.
- `status/superseded` — Replaced by another note. Terminal state. Pairs with `> [!warning] SUPERSEDED` callout.
- `status/wip` — Stable but under active revision
layer/*:
- `layer/content` — Content assets (audio, models, textures, audio provenance)
- `layer/gdext` — gdext wrapper layer (`rust/gdext-wrapper/`)
- `layer/gdscript` — GDScript (Godot scene-tier logic)
- `layer/infra` — Build, CI, deployment infrastructure
- `layer/python` — Python development tooling (`tools/`)
- `layer/rust-core` — Engine-agnostic Rust core (`rust/rust-core/`)
concept/*:
- `concept/biome` — Biome-reactive behavior across systems
- `concept/contamination` — Across-runs panel and garage degradation; the slow-horror mechanic that doesn't reset with the world
- `concept/diegetic` — Diegetic audio / UI / world-sourced design
- `concept/disturbance` — The disturbance mechanic thread (Article X)
- `concept/ephemeral-world` — Run-reset, transient worlds (Article IV Rules 6–7)
- `concept/governance` — Constitutional and governance concepts
- `concept/horror` — Horror register and dread design
- `concept/procedural` — Procedural generation, seed determinism
- `concept/rendering` — Visual rendering quality, shader correctness, Terrain3D integration, mesh fidelity, LOD, Z-fighting
- `concept/terrain` — Terrain generation, heightmap, Terrain3D regions, roughness, playability constraints
ember's answer for tag_assignment-decisions-splash-screen-signal-scope, layer/gdscriptP(true) placed on the no, unsure, and yes zones.nounsureyesgold: yesP = 0.27

tag_assignment-decisions-splash-screen-signal-scope: status/reviewed

Tag assignment · dev
Gold
The note calls for `status/reviewed`: Agent-created note verified against codebase within its creating session. Eligible for auto-injection in subsequent task dispatches. (Agent notes only — spec 080.) (True)
ember
The note has no reason to carry `status/reviewed` (False)
Signal
P(true) 0.47 (unsure)
Kit outcome
deferred: treated as unsure
Why this gold label
Mined from Decisions/Splash Screen Signal Scope.md at 692f4bb58b7f62105aeb73fba8dfee12bfdecd53; gold is the note's own vocabulary tags.
Splash Screen Signal Scope

This note records why splash_completed is declared on the splash script rather than on the Events autoload signal bus.

## The Rule and the Exception

The architecture rule is: cross-system communication goes through Events signals only (constitution Article VI). The splash screen is an exception, and the exception is justified by three properties that must all be true simultaneously:

1. The scene is transient — it is instantiated in main.gd _ready(), played once, then freed. It does not persist for the lifetime of the session.
2. There is exactly one consumer — main.gd listens for splash_completed to show the main menu. No other system cares about splash completion.
3. The signal has no reuse value — no future system would plausibly need to react to splash completion.

When all three are true, putting the signal on Events is pure overhead: a permanently registered signal with a lifetime of seconds, a single connection, and no cross-system value.

## Why This Matters for Future Agents

Any agent implementing or modifying the splash screen should not reflexively move splash_completed to Events. The signal's placement on the script is not an oversight — it is the intended design. If a future spec adds a second consumer of splash completion (e.g. analytics, a cinematic system), that is the trigger to reconsider. Until then, the signal stays local.

## The General Pattern

The test for whether a signal belongs on Events vs on its emitting script:
- Multiple consumers across systems → Events
- Single transient consumer, short-lived scene → script-local signal
- Persistent scene with one consumer → case-by-case; prefer Events for consistency unless the scene is truly ephemeral

## References

- src/scenes/ui/splash_screen.tscn (when implemented)
- src/scripts/ui/splash_screen.gd (when implemented)
- src/scripts/main.gd
- docs/vault/Specs/083 Atmospheric Splash Screen/083 Atmospheric Splash Screen.md

Controlled tag vocabulary (as read):
type/*:
- `type/code` — Code architecture, autoloads, conventions, tooling. Carries `code-refs:`. (e.g. `Code/Autoloads — Disturbance.md`)
- `type/decision` — Architectural or design decision made by an agent during a session. Written to `docs/vault/Decisions/`. (Agent notes only — spec 080.)
- `type/design` — Design intent, player-facing concepts, world lore. (e.g. `Design/World Model.md`)
- `type/discovery` — Non-obvious constraint, gap, or conflict found by an agent during a session. Written to `docs/vault/Discoveries/`. (Agent notes only — spec 080.)
- `type/moc` — Map of Content at any of three tiers (folder / domain / concept). (e.g. `Audio.md`)
- `type/principle` — Governance and constitutional notes. Non-negotiable rules. (e.g. `Governance/Constitution.md`)
- `type/reference` — Glossary, decision log, open questions, epics. (e.g. `Reference/Glossary.md`)
- `type/session-log` — Session activity log; permanent audit trail. Written to `docs/vault/Sessions/`. Append-only, never pruned. (Agent notes only — spec 080.)
- `type/spec` — Spec document at `docs/vault/Specs/NNN Title/spec.md`. Carries `spec-refs:`. (e.g. `Specs/047 Car Radio/spec.md`)
- `type/system` — A bounded subsystem with implementation. Carries `code-refs`, `spec-refs`, `implements:` frontmatter. (e.g. `Systems/Audio — Car Radio.md`)
- `type/vision` — Strategic / vision-layer decision. Written to `docs/vault/Vision/`. Human-authored or agent-proposed with human ratification before promotion to `status: reviewed`. (Per triage #3 — spec 133 autonomous-company redesign.)
domain/*:
- `domain/anomalies` — Anomaly taxonomy, individual anomaly systems, spawn, behavior
- `domain/art` — Visual direction, palettes, references, asset pipeline
- `domain/audio` — Audio systems: world ambient, radio, transmissions, buses, pipeline
- `domain/autonomous-company` — Autonomous company v0.1 experiment: Slack infra, persona middleware, Letta integration, restart recovery
- `domain/build` — Build system, packaging, export, release automation
- `domain/governance` — Constitution, phased spec, policies
- `domain/infrastructure` — Infrastructure provisioning: CI/CD, hosting, deployment tooling, secrets management
- `domain/narrative` — Tone, horror register, forest transmissions narrative, Gary/KTLK
- `domain/player` — Player mode, input, controls, camera, exit/entry
- `domain/systems` — Cross-cutting system architecture and integration work
- `domain/tooling` — Build, CI, observer, TTS pipeline, dev-time tools
- `domain/vehicle` — The Samba: vehicle physics, dashboard, damage, panels
- `domain/world` — World model, biomes, terrain, procedural generation, weather
status/*:
- `status/canonical` — Fully authoritative; promoted by humans only. Highest trust. (Agent notes only — spec 080.)
- `status/draft` — Authoring in progress, not yet verified
- `status/reviewed` — Agent-created note verified against codebase within its creating session. Eligible for auto-injection in subsequent task dispatches. (Agent notes only — spec 080.)
- `status/stale` — Known out of date; cannot update immediately. Pairs with `> [!warning] STALE — needs update` callout.
- `status/superseded` — Replaced by another note. Terminal state. Pairs with `> [!warning] SUPERSEDED` callout.
- `status/wip` — Stable but under active revision
layer/*:
- `layer/content` — Content assets (audio, models, textures, audio provenance)
- `layer/gdext` — gdext wrapper layer (`rust/gdext-wrapper/`)
- `layer/gdscript` — GDScript (Godot scene-tier logic)
- `layer/infra` — Build, CI, deployment infrastructure
- `layer/python` — Python development tooling (`tools/`)
- `layer/rust-core` — Engine-agnostic Rust core (`rust/rust-core/`)
concept/*:
- `concept/biome` — Biome-reactive behavior across systems
- `concept/contamination` — Across-runs panel and garage degradation; the slow-horror mechanic that doesn't reset with the world
- `concept/diegetic` — Diegetic audio / UI / world-sourced design
- `concept/disturbance` — The disturbance mechanic thread (Article X)
- `concept/ephemeral-world` — Run-reset, transient worlds (Article IV Rules 6–7)
- `concept/governance` — Constitutional and governance concepts
- `concept/horror` — Horror register and dread design
- `concept/procedural` — Procedural generation, seed determinism
- `concept/rendering` — Visual rendering quality, shader correctness, Terrain3D integration, mesh fidelity, LOD, Z-fighting
- `concept/terrain` — Terrain generation, heightmap, Terrain3D regions, roughness, playability constraints
ember's answer for tag_assignment-decisions-splash-screen-signal-scope, status/reviewedP(true) placed on the no, unsure, and yes zones.nounsureyesgold: yesP = 0.47

tag_assignment-decisions-splash-screen-signal-scope: type/code

Tag assignment · dev
Gold
The note has no reason to carry `type/code` (False)
ember
The note calls for `type/code`: Code architecture, autoloads, conventions, tooling. Carries `code-refs:`. (e.g. `Code/Autoloads — Disturbance.md`) (True)
Signal
P(true) 0.96 (yes)
Kit outcome
acted on a wrong answer
Why this gold label
Mined from Decisions/Splash Screen Signal Scope.md at 692f4bb58b7f62105aeb73fba8dfee12bfdecd53; gold is the note's own vocabulary tags.
Splash Screen Signal Scope

This note records why splash_completed is declared on the splash script rather than on the Events autoload signal bus.

## The Rule and the Exception

The architecture rule is: cross-system communication goes through Events signals only (constitution Article VI). The splash screen is an exception, and the exception is justified by three properties that must all be true simultaneously:

1. The scene is transient — it is instantiated in main.gd _ready(), played once, then freed. It does not persist for the lifetime of the session.
2. There is exactly one consumer — main.gd listens for splash_completed to show the main menu. No other system cares about splash completion.
3. The signal has no reuse value — no future system would plausibly need to react to splash completion.

When all three are true, putting the signal on Events is pure overhead: a permanently registered signal with a lifetime of seconds, a single connection, and no cross-system value.

## Why This Matters for Future Agents

Any agent implementing or modifying the splash screen should not reflexively move splash_completed to Events. The signal's placement on the script is not an oversight — it is the intended design. If a future spec adds a second consumer of splash completion (e.g. analytics, a cinematic system), that is the trigger to reconsider. Until then, the signal stays local.

## The General Pattern

The test for whether a signal belongs on Events vs on its emitting script:
- Multiple consumers across systems → Events
- Single transient consumer, short-lived scene → script-local signal
- Persistent scene with one consumer → case-by-case; prefer Events for consistency unless the scene is truly ephemeral

## References

- src/scenes/ui/splash_screen.tscn (when implemented)
- src/scripts/ui/splash_screen.gd (when implemented)
- src/scripts/main.gd
- docs/vault/Specs/083 Atmospheric Splash Screen/083 Atmospheric Splash Screen.md

Controlled tag vocabulary (as read):
type/*:
- `type/code` — Code architecture, autoloads, conventions, tooling. Carries `code-refs:`. (e.g. `Code/Autoloads — Disturbance.md`)
- `type/decision` — Architectural or design decision made by an agent during a session. Written to `docs/vault/Decisions/`. (Agent notes only — spec 080.)
- `type/design` — Design intent, player-facing concepts, world lore. (e.g. `Design/World Model.md`)
- `type/discovery` — Non-obvious constraint, gap, or conflict found by an agent during a session. Written to `docs/vault/Discoveries/`. (Agent notes only — spec 080.)
- `type/moc` — Map of Content at any of three tiers (folder / domain / concept). (e.g. `Audio.md`)
- `type/principle` — Governance and constitutional notes. Non-negotiable rules. (e.g. `Governance/Constitution.md`)
- `type/reference` — Glossary, decision log, open questions, epics. (e.g. `Reference/Glossary.md`)
- `type/session-log` — Session activity log; permanent audit trail. Written to `docs/vault/Sessions/`. Append-only, never pruned. (Agent notes only — spec 080.)
- `type/spec` — Spec document at `docs/vault/Specs/NNN Title/spec.md`. Carries `spec-refs:`. (e.g. `Specs/047 Car Radio/spec.md`)
- `type/system` — A bounded subsystem with implementation. Carries `code-refs`, `spec-refs`, `implements:` frontmatter. (e.g. `Systems/Audio — Car Radio.md`)
- `type/vision` — Strategic / vision-layer decision. Written to `docs/vault/Vision/`. Human-authored or agent-proposed with human ratification before promotion to `status: reviewed`. (Per triage #3 — spec 133 autonomous-company redesign.)
domain/*:
- `domain/anomalies` — Anomaly taxonomy, individual anomaly systems, spawn, behavior
- `domain/art` — Visual direction, palettes, references, asset pipeline
- `domain/audio` — Audio systems: world ambient, radio, transmissions, buses, pipeline
- `domain/autonomous-company` — Autonomous company v0.1 experiment: Slack infra, persona middleware, Letta integration, restart recovery
- `domain/build` — Build system, packaging, export, release automation
- `domain/governance` — Constitution, phased spec, policies
- `domain/infrastructure` — Infrastructure provisioning: CI/CD, hosting, deployment tooling, secrets management
- `domain/narrative` — Tone, horror register, forest transmissions narrative, Gary/KTLK
- `domain/player` — Player mode, input, controls, camera, exit/entry
- `domain/systems` — Cross-cutting system architecture and integration work
- `domain/tooling` — Build, CI, observer, TTS pipeline, dev-time tools
- `domain/vehicle` — The Samba: vehicle physics, dashboard, damage, panels
- `domain/world` — World model, biomes, terrain, procedural generation, weather
status/*:
- `status/canonical` — Fully authoritative; promoted by humans only. Highest trust. (Agent notes only — spec 080.)
- `status/draft` — Authoring in progress, not yet verified
- `status/reviewed` — Agent-created note verified against codebase within its creating session. Eligible for auto-injection in subsequent task dispatches. (Agent notes only — spec 080.)
- `status/stale` — Known out of date; cannot update immediately. Pairs with `> [!warning] STALE — needs update` callout.
- `status/superseded` — Replaced by another note. Terminal state. Pairs with `> [!warning] SUPERSEDED` callout.
- `status/wip` — Stable but under active revision
layer/*:
- `layer/content` — Content assets (audio, models, textures, audio provenance)
- `layer/gdext` — gdext wrapper layer (`rust/gdext-wrapper/`)
- `layer/gdscript` — GDScript (Godot scene-tier logic)
- `layer/infra` — Build, CI, deployment infrastructure
- `layer/python` — Python development tooling (`tools/`)
- `layer/rust-core` — Engine-agnostic Rust core (`rust/rust-core/`)
concept/*:
- `concept/biome` — Biome-reactive behavior across systems
- `concept/contamination` — Across-runs panel and garage degradation; the slow-horror mechanic that doesn't reset with the world
- `concept/diegetic` — Diegetic audio / UI / world-sourced design
- `concept/disturbance` — The disturbance mechanic thread (Article X)
- `concept/ephemeral-world` — Run-reset, transient worlds (Article IV Rules 6–7)
- `concept/governance` — Constitutional and governance concepts
- `concept/horror` — Horror register and dread design
- `concept/procedural` — Procedural generation, seed determinism
- `concept/rendering` — Visual rendering quality, shader correctness, Terrain3D integration, mesh fidelity, LOD, Z-fighting
- `concept/terrain` — Terrain generation, heightmap, Terrain3D regions, roughness, playability constraints
ember's answer for tag_assignment-decisions-splash-screen-signal-scope, type/codeP(true) placed on the no, unsure, and yes zones.nounsureyesgold: noP = 0.96

tag_assignment-narrative-ktlk-gary-character-case-study: type/design

Tag assignment · dev
Gold
The note calls for `type/design`: Design intent, player-facing concepts, world lore. (e.g. `Design/World Model.md`) (True)
ember
The note has no reason to carry `type/design` (False)
Signal
P(true) 0.22 (unsure)
Kit outcome
deferred: treated as unsure
Why this gold label
Mined from Narrative/KTLK Gary — Character Case Study.md at 692f4bb58b7f62105aeb73fba8dfee12bfdecd53; gold is the note's own vocabulary tags.
KTLK Gary — Character Case Study

The complete character case study for Gary, host of Valley Nights on KTLK 93.3. Gary is the radio's companionship channel and Old Growth's most personal horror vector. This note captures: his role in the game, show identity, voice profile, TTS generation parameters across 4 tiers of deterioration, tier-by-tier delivery notes with example scripts, naming conventions, content pool targets, runtime implementation requirements, production checklist, and QA criteria.

**Note**: new vault subfolder `Narrative/` — mirrors the design/narrative distinction where Narrative/ holds authored narrative/character content that's denser than design notes. Could alternatively live at `Design/KTLK Gary — Character Case Study.md`; placing under `Narrative/` to match the future pattern for multi-character narrative expansion.

## Station Identity

| Field | Value |
|---|---|
| **Station** | KTLK 93.3 FM |
| **Format** | Late-night call-in talk radio |
| **Biome availability** | Verdant Old Growth + Fungal Depths (drops to static in Petrifold) |
| **Runtime type** | `is_talk_format = true` — continuous random clip pool, no DJ layer |
| **Show name** | Valley Nights |
| **Host name** | Gary |
| **Era feel** | Timeless — no markers placing it in a specific decade |
| **Premise** | Gary takes calls, gives advice, does weather and road updates, fills the dead hours between midnight and 4am for people who can't sleep or have long drives ahead |

Gary is not a character the player learns about. He is a presence. Warm, slightly tired, unhurried. The show has no guests, no news segments, no music. It is Gary, his callers, and the occasional hold music bleed between segments.

**Callers are never heard.** Only Gary's side of the conversation is recorded. Keeps production simple and preserves ambiguity — the player infers the caller from Gary's responses. In fractured and unhinged tiers, the absence of any caller becomes the mechanic: Gary is responding to nothing. Or to the driver. Or to something else.

## Role in the Game

KTLK is the radio's companionship channel — and its most personal horror vector.

Every other station is music. Timeless, non-reactive, emotionally ambient. KTLK is the only voice that speaks *at* the player. That specificity is what makes it work. The player tunes in for company on a long drive and gets Gary: warm, slightly tired, filling dead air. A presence. By the time Gary is gone — completely gone — the player will miss him.

The arc is not "normal radio becomes creepy radio." It is a complete dissociation. Gary begins as a professional broadcaster who doesn't know the player exists. He ends as a lost, barely coherent presence who believes he is sitting in the passenger seat of the van, watching the same dark road the player is driving. **He never becomes hostile. The warmth never fully leaves. That's the horror.**

**At no point must Gary be confused with the player, the player's inner voice, or the bus itself.** In Tier 4 especially, Gary is unmistakably *other* — something that arrived from the forest wearing Gary's warmth. He observes the driver from outside the driver's perspective. He has no agency over the vehicle. He does not know how he came to be there and does not pretend to. He is a presence that does not belong, calm about not belonging, and that is the distinction that must never blur.

## The Four-Tier Deterioration

| Tier | State | Gary's frame of reality |
|---|---|---|
| 1 — Normal | Verdant + Calm/Uneasy | Professional broadcaster. Knows he's on the radio. Callers call in. |
| 2 — Unsettled | Verdant + Agitated/Storm | Still in host-mode but the frame loosens. Wrong things said confidently. Confusion bleeds through. |
| 3 — Fractured | Fungal + Calm/Uneasy | The "you" shift. Gary is addressing the driver specifically. He doesn't know why. He still performs the show. |
| 4 — Unhinged | Fungal + Agitated/Storm | Gary does not know he is broadcasting. He believes he is in the van. Incomplete sentences. Warmth intact. Reality gone. |

## Host Voice Profile

### Delivery character (all tiers)

- **Warm** — this does not leave, even in Tier 4. Gary is never threatening or cold.
- **Unhurried** — comfortable with silence, doesn't rush to fill gaps
- **Slightly tired** — late-night energy. Not exhausted, but soft.
- **Low register** — mid-to-low voice. AM radio warmth, not announcer-bright.
- **No accent** — generic American. No strong regional markers. No era markers.

### What Gary never does in Tier 1

- Does not reference specific years, events, or cultural touchstones
- Does not name real places (road names are generic — "the northern route," "the valley roads")
- Does not express fear or urgency
- Does not acknowledge the forest, the game world, or anything supernatural
- Does not use filler phrases that date the recording ("hashtag," "like," "you know what I mean?")

### The "you" shift (Tiers 2–4)

Pivot point of the whole arc. Track carefully across tiers:

- **Tier 1**: `"for those of you driving tonight"`, `"if you're out there"` — broadcast address, generic
- **Tier 2**: `"for the person on the road right now"` — pointed but still generic
- **Tier 3**: `"you"` — specific. Direct. Gary is talking to one person. He may not know why.
- **Tier 4**: `"you"` + physical presence. Gary is in the van. He refers to things he can see through the windshield.

## TTS Generation

### Model — Chatterbox (voice cloning via reference clip)

Gary appears across 40+ clips spanning four tiers. Voice consistency across that volume is critical — Chatterbox with a cloned reference maintains character better than any preset.

A reference clip of ≥10 seconds of dry, clean speech in Gary's intended register is required before generation begins. Place at: `src/assets/audio/radio/talk/gold/references/ref_gary_voice.wav`.

### Recommended parameters per tier

| Parameter | Tier 1 Normal | Tier 2 Unsettled | Tier 3 Fractured | Tier 4 Unhinged |
|---|---|---|---|---|
| `--exaggeration` | 0.25 | 0.28 | 0.32 | 0.35 |
| `--cfg-weight` | 0.45 | 0.47 | 0.50 | 0.52 |
| `--temperature` | 0.75 | 0.78 | 0.82 | 0.85 |
| `--repetition-penalty` | 1.2 | 1.15 | 1.1 | 1.0 |

Parameters loosen gradually across tiers. Tier 4 voice should feel less controlled — not erratic, but unguarded. The warmth stays; the precision erodes.

### Post-processing per tier

Tiers 1 and 2 play in Verdant (clean signal bus dominant):
```bash
make clean-ogg OUTPUT=<clip_id>     # Tiers 1 + 2 → normal AM radio EQ
```

Tiers 3 and 4 play in Fungal (RadioDegraded bus dominant). Pre-process as degraded AND they route through the degraded bus at runtime — wrongness compounds:
```bash
make degraded-ogg OUTPUT=<clip_id>  # Tiers 3 + 4 → narrow EQ + echo + 0.95x tempo
```

## Tier 1 — Normal (Verdant + Calm/Uneasy)

**Tone**: A caller just finished talking. Gary is responding. He's heard this kind of call before. He might offer advice, or just acknowledge. Sometimes he doesn't have an answer and says so. That's fine. That's the point. He is company for whoever is awake at 2am.

**Clip types**:

| Type | Description | Duration |
|---|---|---|
| `intro` | Show open, station ID, time-of-night orientation | 5–15s |
| `call` | Responding to an implied caller — advice, acknowledgment, brief story | 20–45s |
| `weather` | Road and weather advisories | 10–20s |
| `advisory` | Gentle safety reminders | 10–20s |
| `signoff` | Transitional, back-to-break | 5–15s |

**Delivery notes**: silence at the clip start — Gary is listening to the caller finish before speaking. No rushing. Each sentence breathes. Second person is always broadcast-general: "for those of you," "if you're out there."

### Example scripts

**Intro**:
> "Valley Nights on KTLK. I'm Gary. It's late and the roads are quiet. If you're out there driving, keep your lights on and call if you need someone to talk to. Lines are open."

**Call — advice**:
> "That's — yeah, I hear that. You've been at it a long time and nothing's moved and you're wondering if you made the right call. That's the middle of the night talking, not the situation. Things look different in the morning. They always do. What I'd say is this: don't make the permanent decision at 2am. Call me back in a week."

**Call — acknowledgment**:
> "Mm. That sounds hard. I don't have a good answer for that one. Sometimes there isn't one. I appreciate you calling in, though. It helps to say it out loud, even if nobody has anything useful to tell you. You're not the only one up right now. That's something."

**Weather**:
> "Weather service is saying fog through the valley again tonight. Visibility's down on the northern routes, so if you're driving the forest service roads, keep your speed down and your headlights on low. High beams just reflect back in the fog. Low beams are better."

**Advisory**:
> "If you've been driving a long time and you're tired, pull over. I know you're trying to make time but you won't make anything if you go off the road. Find a wide shoulder and rest for twenty minutes. The road will still be there."

**Signoff**:
> "We'll be right back after this. Don't go anywhere — Valley Nights, we're here till dawn."

## Tier 2 — Unsettled (Verdant + Agitated/Storm)

**Tone**: Gary is still performing the show. He still thinks he's on the radio. But something is slipping. He mishears callers. His advice doesn't quite connect to what the caller asked. He mentions things he shouldn't know — small things, easy to explain away. His timing is fractionally off. A pause lasts one beat too long.

**The player shouldn't be alarmed yet.** They should feel a vague unease they can't articulate.

**What changes**:
- Advice slightly misapplied — correct in tone, wrong in substance for the implied question
- Gary mishears or misholds the caller's situation, then corrects himself mid-sentence
- Small references to time: "I've been here a while," "I don't know how long we've been at this"
- One or two clips end with a pause that doesn't resolve — Gary listening to something not transmitted
- Second person begins drifting: "for the person on the road right now" instead of "for those of you"

**Delivery notes**: same warmth. No alarm. Gary does not know anything is wrong. Confusion should read as Gary being tired, not frightened. Do not play pauses dramatically — comfortable pauses that just run slightly long.

### Example scripts

**Misapplied advice**:
> "Yeah. Yeah, I hear that. The thing about — well. What you have to remember is that it's not about the distance. It's about — I'm sorry, did you say the engine or the — okay. Right. Yeah. You're right to be careful. These roads at night, you don't know what's going to be out there."

**Temporal confusion**:
> "We've got time. I've been — we've been at this a while tonight, haven't we. Lines are still open. If you're out there and you need to talk, pick up the phone. I'll be here."

**Drift toward specific address**:
> "For the person on the road right now — and there's always someone, this time of night — I'll say what I always say: you don't have to do it alone. Whatever it is."
> *(One beat too long before continuing. Then:)*
> "Back after this."

**Mishearing**:
> "The — I'm sorry, I thought you said something. Go ahead. No, please. I'm listening."
> *(4-second pause. Then, as if the call resumed normally:)*
> "Right. That makes sense. I think you're handling it well."

**End-of-clip drift**:
> "That's all for now. Stay safe out there. Keep your lights on."
> *(Normal signoff. Then, very quietly, almost to himself:)*
> "It's dark tonight."

## Tier 3 — Fractured (Fungal + Calm/Uneasy)

**Tone**: The "you" shift has happened. Gary is still performing the show — station IDs, call-in format, weather breaks — but he is addressing one person. He doesn't know who. He doesn't know why. The show format is becoming scaffolding around something that is no longer a show.

He still sounds like Gary. The warmth is intact. But the content is wrong in ways that are no longer subtle.

**What changes**:
- Second person becomes direct and specific: "you," not "those of you," not "the person driving"
- Gary references things about the driver's situation with uncanny accuracy — then immediately returns to host mode as if nothing unusual was said
- Sentence fragments increase. A thought starts, stops, restarts from a different entry point.
- Gary begins describing what he "sees" or "hears" — still framed as radio content, but the source is unclear
- The call-in format breaks down: Gary responds to callers whose questions couldn't have produced his answers
- Hold music references slow further

**Delivery notes**: direct address should land as natural — Gary does not pause or change register when he says "you." He doesn't know he's doing it. Return to host-mode after a disturbing statement should be immediate and cheerful. The contrast is the horror.

### Example scripts

**The you shift**:
> "For the — for you. If you're listening right now. I just want to say — you've come a long way. That's not nothing. Keep going."
> *(Then immediately, normal host energy:)*
> "Phones are open. Valley Nights."

**Uncanny accuracy**:
> "Be careful on the road you're on right now. I know it feels like you know where you're going but the turns up ahead — they get — just go slow. Okay? Go slow."

**Sentence fragment + restart**:
> "I keep — what I'm trying to say is that the — the reason people call in, late like this, is that they need somebody to — what I mean to say is: you're not alone out there. That's all. You're not alone."

**Wrong response**:
> "Yeah, no, I understand. And you know what — it's okay. Whatever you saw. A lot of people see things out there at night. It doesn't mean anything. You're doing fine. Just keep driving."
> *(No caller described seeing anything.)*

**Host-mode collapse**:
> "Coming up after the break — "
> *(3-second silence.)*
> "Are you okay?"
> *(Normal pace:)*
> " — more of your calls on Valley Nights."

**Direct and strange**:
> "I can hear your engine. I don't know how but I can. It sounds good. You're doing good."

## Tier 4 — Unhinged (Fungal + Agitated/Storm)

**Tone**: Gary does not know he is on the radio.

He is in the bus — **but he is not the player, and he must never be mistaken for the player**. He is something that has arrived. Something that is watching. He observes the driver's hands on the wheel, the way the headlights cut the fog, the trees at the edge of the road. He does not drive. He does not touch anything. He is present the way an uninvited passenger is present: occupying space that belonged to someone else, calm about it, confused about how he came to be there.

He is warm. He is not threatening. But he is unmistakably *other* — a presence that does not belong in the bus and that arrived from somewhere that is not a radio station.

**Gary is not the player's inner voice. He is not the van. He is something that came from the forest wearing Gary's warmth.**

**What is gone**:
- Show format completely absent. No station IDs. No "you're listening to." No call-in cadence.
- Callers do not exist. There is only Gary and the person he can see driving.
- Coherence is partial. Sentences are incomplete, loop back on themselves, or end in silence.
- Gary has no fatigue, no hunger, no memory of arriving. He has been still for a long time. He does not say how long.

**What remains**:
- The warmth. Gary is not threatening. He speaks like someone grateful for the company.
- The voice. Same register, same unhurried quality. Quieter. More intimate.
- Occasional flashes of the host — a cadence, a phrase — immediately swallowed by where he actually is.

### Distinctness rules for Tier 4

These rules exist to ensure Gary is never confused with the player or the van. They are absolute:

1. **Gary always observes the driver from outside the driver's perspective.** He notices *your* hands, *your* driving, *your* reaction. He is watching someone else.
2. **Gary has no agency over the vehicle.** He never implies he could drive, could steer, could stop the van. He is a passenger with no control and he knows it.
3. **Gary asks questions only an external observer would ask.** "Are you cold?" not "I'm cold." "Do you see that?" not "I see that." He perceives the driver's experience as separate from his own.
4. **Gary's presence is inexplicable even to himself.** He does not know how he got there. He does not offer an explanation. He does not pretend there is one.
5. **Gary is subtly not-quite-human in Tier 4.** He has no needs. He has been there a long time without discomfort. He notices things with unusual precision — the exact number of trees that have passed, a sound from three minutes ago. A person would not track these things. He does.
6. **Gary never merges with the player.** No "we" that conflates them. No "let's." He is here; you are driving. These are separate facts.

**Delivery notes**: quieter than any other tier. Gary is talking to someone sitting next to him, not broadcasting. Pauses are not dramatic — they are the pauses of something that does not need to breathe between sentences. Incomplete sentences should feel complete — as if the rest was obvious from context only Gary has. One or two clips should have Gary almost recover — almost become the host again — then slip back. That flicker is important: it establishes that the Gary underneath is still in there, which makes the distance from it more disturbing. Do not let Gary sound afraid or confused about his own state. He has accepted it.

### Example scripts

**Observing from outside**:
> "Your hands have been on the wheel for a long time."
> *(Pause.)*
> "That's good. Keep them there."

**External vantage, inexplicable presence**:
> "I've been sitting here — "
> *(Pause.)*
> "I don't know how long. I was somewhere else and then I was here. I don't think that's — "
> *(Pause.)*
> "You drive well. That helps."

**Not-quite-human precision**:
> "Forty-seven trees since the last turn. I've been counting."
> *(Pause.)*
> "I don't know why I'm telling you that. I just noticed."

**Watching, not participating**:
> "Something moved out there. Back in the trees, to your left."
> *(Pause. No alarm whatsoever.)*
> "It's been keeping pace with you for a while. I didn't want to say anything until I was sure."

**No agency**:
> "If I knew how to stop this I would tell you."
> *(Pause.)*
> "I don't know how to stop this."
> *(Quietly:)*
> "Keep driving."

**External warmth — clearly not the player's voice**:
> "You're doing well. I can see that from here."
> *(Pause.)*
> "I don't think you can hear me. But I wanted to say it anyway."

**Subtly not-human**:
> "I'm not cold. I thought I would be, but I'm not."
> *(Long pause.)*
> "I'm not anything, I think. I'm just here."

**Almost-recovery**:
> "And — and if you're just joining us on Valley — "
> *(Long pause. He has lost it.)*
> "Sorry. I keep thinking I'm somewhere else."
> *(Very quietly:)*
> "I'm still here. I'm right here."

**Direct address with clear separation**:
> "Whatever you're driving toward — "
> *(Pause.)*
> "I hope you find it. I'll still be here when you do."
> *(A beat.)*
> "I think I'll always be here now."

## Naming Convention & Content Pools

### Four-tier naming

The naming suffix routes each clip to the correct pool via the auto-loader. Four tiers require four distinct suffixes:

```
spoken_ktlk_talk_<type>_NN.ogg              → content_clean      (Tier 1)
spoken_ktlk_talk_<type>_unsettled_NN.ogg    → content_unsettled  (Tier 2)
spoken_ktlk_talk_<type>_degraded_NN.ogg     → content_fracturing (Tier 3)
spoken_ktlk_talk_<type>_unhinged_NN.ogg     → content_unhinged   (Tier 4)
```

Where `<type>` for Tiers 1–2: `intro`, `call`, `weather`, `advisory`, `signoff`
Where `<type>` for Tiers 3–4: `call`, `address`, `fragment`, `presence`

### Clip targets

| Pool | Tier | Trigger | Target clips | Duration |
|---|---|---|---|---|
| `content_clean` | 1 — Normal | Verdant + Calm/Uneasy | 30–36 | 10–45s |
| `content_unsettled` | 2 — Unsettled | Verdant + Agitated/Storm | 20–24 | 10–40s |
| `content_fracturing` | 3 — Fractured | Fungal + Calm/Uneasy | 24–30 | 15–50s |
| `content_unhinged` | 4 — Unhinged | Fungal + Agitated/Storm | 20–24 | 10–45s |

Total: ~94–114 clips across all tiers.

### Script manifest

`tools/tts/scripts/ktlk_gary_scripts.csv`:

```csv
clip_id,clip_type,text,delivery_notes,target_duration,variant
spoken_ktlk_talk_intro_01,intro,"Valley Nights on KTLK...","Unhurried. Settling in for the night. No announcer energy.",8-12s,clean
spoken_ktlk_talk_call_unsettled_01,call_unsettled,"Yeah. Yeah, I hear that...","Warm. Tired. The confusion is Gary being confused, not performing confusion.",20-30s,unsettled
spoken_ktlk_talk_call_degraded_01,call_fractured,"For the — for you...","Direct address lands as natural. Do not pause or shift register on 'you'.",15-25s,degraded
spoken_ktlk_talk_presence_unhinged_01,presence,"It's cold in here...","Quiet. Gary is talking to someone next to him. Not broadcasting.",10-20s,unhinged
```

## Implementation Requirements

### New RadioChannel fields required

```gdscript
## Voice content for Verdant + Agitated/Storm (Gary unsettled, host frame loosening).
@export var content_unsettled: Array[AudioStream] = []

## Voice content for Fungal + Agitated/Storm (Gary fully unhinged, no radio frame).
@export var content_unhinged: Array[AudioStream] = []
```

### Pool selection logic (car_radio.gd / bus_radio.gd)

Replace existing two-pool talk selection with biome × disturbance lookup:

```gdscript
func _get_talk_pool(ch: Resource) -> Array:
    match _current_biome:
        0:  # VERDANT
            if _current_disturbance >= 2:  # AGITATED or STORM
                return ch.content_unsettled if not ch.content_unsettled.is_empty() \
                       else ch.content_clean
            return ch.content_clean
        1:  # FUNGAL
            if _current_disturbance >= 2:  # AGITATED or STORM
                return ch.content_unhinged if not ch.content_unhinged.is_empty() \
                       else ch.content_fracturing
            return ch.content_fracturing if not ch.content_fracturing.is_empty() \
                   else ch.content_clean
        _:
            return []
```

Fallback chain ensures playback even if a pool is empty (e.g. during content production).

### Auto-loader update required

`_populate_talk_content()` currently splits only on `_degraded_`. Needs extending to handle `_unsettled_` → `content_unsettled` and `_unhinged_` → `content_unhinged`.

## Production Checklist

- [ ] Record or source reference clip: `ref_gary_voice.wav` (≥10s, dry, mono, clean)
- [ ] Place at `src/assets/audio/radio/talk/gold/references/ref_gary_voice.wav`
- [ ] Write all four-tier scripts in `tools/tts/scripts/ktlk_gary_scripts.csv` (~94–114 rows)
- [ ] Run batch generation per tier with appropriate Chatterbox parameters
- [ ] Apply `clean-ogg` to Tiers 1 + 2; apply `degraded-ogg` to Tiers 3 + 4
- [ ] Listen to all clips — verify the escalation arc reads across tiers
- [ ] Verify Tier 4 clips feel intimate, not broadcast — quiet, incomplete, warm
- [ ] Run `make install-clip CHANNEL=talk` for each approved clip
- [ ] Run `make validate-names` and `make validate-provenance`
- [ ] Implement `content_unsettled` + `content_unhinged` fields on RadioChannel *(code)*
- [ ] Implement `_get_talk_pool()` biome × disturbance selection *(code)*
- [ ] Extend `_populate_talk_content()` for `_unsettled_` + `_unhinged_` suffixes *(code)*
- [ ] Commit to audio submodule and bump parent pointer

## QA Criteria

| Check | Pass condition |
|---|---|
| Tier 1 plays in Verdant + Calm | Gary is warm, generic, professional. No era markers. No supernatural content. |
| Tier 2 plays in Verdant + Agitated/Storm | Something is slightly wrong. Player notices but can explain it away. Gary is still a host. |
| Tier 3 plays in Fungal + Calm | Gary is addressing the driver directly. The show format is breaking down. Uncanny but coherent. |
| Tier 4 plays in Fungal + Storm | Gary does not know he is on the radio. He is in the van. Incomplete, warm, lost. No station ID cadence. |
| Tier escalation is legible | A player who hears Gary across all four tiers experiences a clear deterioration arc. |
| Warmth persists to Tier 4 | Gary is never threatening or hostile. The horror is presence, not menace. |
| Gary is never the player | No Tier 4 clip can be interpreted as the player's inner voice or interior monologue. Gary always observes the driver from outside the driver's perspective. |
| Gary is never the bus | No Tier 4 clip implies Gary is the vehicle, the radio hardware, or a mechanical system speaking. He is a distinct presence, not an ambient effect. |
| Gary has no agency over the vehicle | Gary does not steer, stop, or control the bus in any clip. He watches. He does not act. |
| Gary's presence is inexplicable | No clip provides a rational explanation for how Gary came to be in the van. He does not know. He does not pretend to know. |
| No DJ clips fire on KTLK | `is_talk_format = true` — DJ layer bypassed. |
| Signal degradation compounds | Tiers 3 + 4 route through `RadioDegraded` bus — voice sounds worse AND says wrong things. |
| Fallback pools work | If a higher tier pool is empty, playback falls back gracefully to the next lower tier. |

## Related

- [[Narrative Direction]] — Gary's role in the overall narrative architecture (radio as the only human voice)
- [[Audio — Car Radio]] — the runtime that plays Gary's content
- [[Audio — Radio Stations]] — KTLK as flagship station in the 13-station roster
- [[Audio — Pipeline]] — the TTS + post-processing pipeline that produces Gary's clips
- [[Tools — TTS]] — the code-level implementation of the TTS tooling
- [[Audio — Forest Transmissions]] — what replaces Gary when KTLK fully fails
- [[Disturbance System]] — the state machine that triggers tier shifts
- [[Biomes]] — Verdant vs Fungal drive tier selection
- [[Tone and Horror]] — the tonal discipline Gary must honor (warmth-through-deterioration)
- [[Narrative — Domain MOC]] — domain MOC
- [[Audio — Domain MOC]] — domain MOC

Controlled tag vocabulary (as read):
type/*:
- `type/code` — Code architecture, autoloads, conventions, tooling. Carries `code-refs:`. (e.g. `Code/Autoloads — Disturbance.md`)
- `type/decision` — Architectural or design decision made by an agent during a session. Written to `docs/vault/Decisions/`. (Agent notes only — spec 080.)
- `type/design` — Design intent, player-facing concepts, world lore. (e.g. `Design/World Model.md`)
- `type/discovery` — Non-obvious constraint, gap, or conflict found by an agent during a session. Written to `docs/vault/Discoveries/`. (Agent notes only — spec 080.)
- `type/moc` — Map of Content at any of three tiers (folder / domain / concept). (e.g. `Audio.md`)
- `type/principle` — Governance and constitutional notes. Non-negotiable rules. (e.g. `Governance/Constitution.md`)
- `type/reference` — Glossary, decision log, open questions, epics. (e.g. `Reference/Glossary.md`)
- `type/session-log` — Session activity log; permanent audit trail. Written to `docs/vault/Sessions/`. Append-only, never pruned. (Agent notes only — spec 080.)
- `type/spec` — Spec document at `docs/vault/Specs/NNN Title/spec.md`. Carries `spec-refs:`. (e.g. `Specs/047 Car Radio/spec.md`)
- `type/system` — A bounded subsystem with implementation. Carries `code-refs`, `spec-refs`, `implements:` frontmatter. (e.g. `Systems/Audio — Car Radio.md`)
- `type/vision` — Strategic / vision-layer decision. Written to `docs/vault/Vision/`. Human-authored or agent-proposed with human ratification before promotion to `status: reviewed`. (Per triage #3 — spec 133 autonomous-company redesign.)
domain/*:
- `domain/anomalies` — Anomaly taxonomy, individual anomaly systems, spawn, behavior
- `domain/art` — Visual direction, palettes, references, asset pipeline
- `domain/audio` — Audio systems: world ambient, radio, transmissions, buses, pipeline
- `domain/autonomous-company` — Autonomous company v0.1 experiment: Slack infra, persona middleware, Letta integration, restart recovery
- `domain/build` — Build system, packaging, export, release automation
- `domain/governance` — Constitution, phased spec, policies
- `domain/infrastructure` — Infrastructure provisioning: CI/CD, hosting, deployment tooling, secrets management
- `domain/narrative` — Tone, horror register, forest transmissions narrative, Gary/KTLK
- `domain/player` — Player mode, input, controls, camera, exit/entry
- `domain/systems` — Cross-cutting system architecture and integration work
- `domain/tooling` — Build, CI, observer, TTS pipeline, dev-time tools
- `domain/vehicle` — The Samba: vehicle physics, dashboard, damage, panels
- `domain/world` — World model, biomes, terrain, procedural generation, weather
status/*:
- `status/canonical` — Fully authoritative; promoted by humans only. Highest trust. (Agent notes only — spec 080.)
- `status/draft` — Authoring in progress, not yet verified
- `status/reviewed` — Agent-created note verified against codebase within its creating session. Eligible for auto-injection in subsequent task dispatches. (Agent notes only — spec 080.)
- `status/stale` — Known out of date; cannot update immediately. Pairs with `> [!warning] STALE — needs update` callout.
- `status/superseded` — Replaced by another note. Terminal state. Pairs with `> [!warning] SUPERSEDED` callout.
- `status/wip` — Stable but under active revision
layer/*:
- `layer/content` — Content assets (audio, models, textures, audio provenance)
- `layer/gdext` — gdext wrapper layer (`rust/gdext-wrapper/`)
- `layer/gdscript` — GDScript (Godot scene-tier logic)
- `layer/infra` — Build, CI, deployment infrastructure
- `layer/python` — Python development tooling (`tools/`)
- `layer/rust-core` — Engine-agnostic Rust core (`rust/rust-core/`)
concept/*:
- `concept/biome` — Biome-reactive behavior across systems
- `concept/contamination` — Across-runs panel and garage degradation; the slow-horror mechanic that doesn't reset with the world
- `concept/diegetic` — Diegetic audio / UI / world-sourced design
- `concept/disturbance` — The disturbance mechanic thread (Article X)
- `concept/ephemeral-world` — Run-reset, transient worlds (Article IV Rules 6–7)
- `concept/governance` — Constitutional and governance concepts
- `concept/horror` — Horror register and dread design
- `concept/procedural` — Procedural generation, seed determinism
- `concept/rendering` — Visual rendering quality, shader correctness, Terrain3D integration, mesh fidelity, LOD, Z-fighting
- `concept/terrain` — Terrain generation, heightmap, Terrain3D regions, roughness, playability constraints
ember's answer for tag_assignment-narrative-ktlk-gary-character-case-study, type/designP(true) placed on the no, unsure, and yes zones.nounsureyesgold: yesP = 0.22

tag_assignment-discoveries-sub-file-spec-status-drift-in-completed-specs: domain/governance

Tag assignment · dev
Gold
The note calls for `domain/governance`: Constitution, phased spec, policies (True)
ember
The note has no reason to carry `domain/governance` (False)
Signal
P(true) 0.35 (unsure)
Kit outcome
deferred: treated as unsure
Why this gold label
Mined from Discoveries/Sub-file spec_status Drift in Completed Specs.md at 692f4bb58b7f62105aeb73fba8dfee12bfdecd53; gold is the note's own vocabulary tags.
Sub-file spec_status Drift in Completed Specs

Sub-artifact files within a spec directory (plan.md, tasks.md, data-model.md, quickstart.md, research.md, contracts/, checklists/) carry a `spec_status` frontmatter field that drifts from the main spec.md when the spec is completed. Spec 148 had its main spec correctly at `spec_status: done` while 7 sub-files were still stuck at `draft` — using `status` vocabulary values instead of `spec_status` vocabulary values.

## Root Cause

The spec 101 frontmatter contract (FR-002) defines `spec_status` as `done | in-progress | waiting | placeholder | superseded` for `spec.md` files. Sub-artifact files inherit the same frontmatter schema by convention from Spec Kit templates, but:

1. **No maintenance mechanism**: Nothing keeps sub-file frontmatter in sync with the main spec's status. When the main spec advances from `waiting` → `in-progress` → `done`, no tooling or protocol prompts updating the sub-files.

2. **Vocabulary confusion**: Sub-files were using `status` lifecycle values (`draft`, `reviewed`) in the `spec_status` field — mixing up the authorship lifecycle vocabulary (`draft | reviewed | canonical`) with the implementation status vocabulary (`done | in-progress | waiting | placeholder | superseded`). Per spec 101 FR-026, sub-files are excluded from `vault_audit.py` schema validation, so this category error was never caught by CI.

3. **Convention without contract**: The spec 101 contract explicitly scopes `spec_status` to `spec.md` (the single vault note per spec). Sub-files carry it because Spec Kit templates copy the full frontmatter, but there's no contract saying they should — or shouldn't.

## Observed Pattern

In spec 148's directory:
- `148 Link Prediction Ensemble.md` — `spec_status: done` ✅ (correct)
- `- data-model.md`, `- plan.md`, `- quickstart.md`, `- research.md`, `- tasks.md` — all had `spec_status: draft` ❌
- `checklists/requirements.md`, `contracts/prediction-api.md`, `contracts/report-schema.md` — all had `spec_status: draft` ❌

After fix: all 8 files consistently set to `spec_status: done`.

## Resolution Paths

Two viable approaches:

1. **Mirror convention**: Sub-files mirror the main spec's `spec_status`. This requires a maintenance step when completing a spec (or automation in the Spec Kit completion workflow). The fix for spec 148 took this approach.

2. **Drop spec_status from sub-files entirely**: Since `vault_audit.py` already excludes non-spec.md files from schema validation (FR-026), sub-files don't need `spec_status`. This is cleaner — one source of truth for spec status. Would require updating Spec Kit templates to omit the field from plan, tasks, data-model, quickstart, research, contracts, and checklist frontmatter.

## Scope

Likely affects every completed spec with sub-artifacts. Spot-check of other spec directories found similar stale values in at least spec 152 and 154. A full sweep across `docs/vault/Specs/*/` would reveal the full extent.

## References

- docs/vault/Specs/148 Link Prediction Ensemble/ — spec where this was discovered and fixed
- docs/vault/Specs/101 Vault Authoritative Specs/contracts/101 Vault Authoritative Specs - vault-spec-frontmatter.md — the frontmatter contract defining `spec_status` vocabulary
- docs/vault/Specs/101 Vault Authoritative Specs/101 Vault Authoritative Specs.md — FR-002 (spec_status enum), FR-026 (sub-file schema exclusion)

Controlled tag vocabulary (as read):
type/*:
- `type/code` — Code architecture, autoloads, conventions, tooling. Carries `code-refs:`. (e.g. `Code/Autoloads — Disturbance.md`)
- `type/decision` — Architectural or design decision made by an agent during a session. Written to `docs/vault/Decisions/`. (Agent notes only — spec 080.)
- `type/design` — Design intent, player-facing concepts, world lore. (e.g. `Design/World Model.md`)
- `type/discovery` — Non-obvious constraint, gap, or conflict found by an agent during a session. Written to `docs/vault/Discoveries/`. (Agent notes only — spec 080.)
- `type/moc` — Map of Content at any of three tiers (folder / domain / concept). (e.g. `Audio.md`)
- `type/principle` — Governance and constitutional notes. Non-negotiable rules. (e.g. `Governance/Constitution.md`)
- `type/reference` — Glossary, decision log, open questions, epics. (e.g. `Reference/Glossary.md`)
- `type/session-log` — Session activity log; permanent audit trail. Written to `docs/vault/Sessions/`. Append-only, never pruned. (Agent notes only — spec 080.)
- `type/spec` — Spec document at `docs/vault/Specs/NNN Title/spec.md`. Carries `spec-refs:`. (e.g. `Specs/047 Car Radio/spec.md`)
- `type/system` — A bounded subsystem with implementation. Carries `code-refs`, `spec-refs`, `implements:` frontmatter. (e.g. `Systems/Audio — Car Radio.md`)
- `type/vision` — Strategic / vision-layer decision. Written to `docs/vault/Vision/`. Human-authored or agent-proposed with human ratification before promotion to `status: reviewed`. (Per triage #3 — spec 133 autonomous-company redesign.)
domain/*:
- `domain/anomalies` — Anomaly taxonomy, individual anomaly systems, spawn, behavior
- `domain/art` — Visual direction, palettes, references, asset pipeline
- `domain/audio` — Audio systems: world ambient, radio, transmissions, buses, pipeline
- `domain/autonomous-company` — Autonomous company v0.1 experiment: Slack infra, persona middleware, Letta integration, restart recovery
- `domain/build` — Build system, packaging, export, release automation
- `domain/governance` — Constitution, phased spec, policies
- `domain/infrastructure` — Infrastructure provisioning: CI/CD, hosting, deployment tooling, secrets management
- `domain/narrative` — Tone, horror register, forest transmissions narrative, Gary/KTLK
- `domain/player` — Player mode, input, controls, camera, exit/entry
- `domain/systems` — Cross-cutting system architecture and integration work
- `domain/tooling` — Build, CI, observer, TTS pipeline, dev-time tools
- `domain/vehicle` — The Samba: vehicle physics, dashboard, damage, panels
- `domain/world` — World model, biomes, terrain, procedural generation, weather
status/*:
- `status/canonical` — Fully authoritative; promoted by humans only. Highest trust. (Agent notes only — spec 080.)
- `status/draft` — Authoring in progress, not yet verified
- `status/reviewed` — Agent-created note verified against codebase within its creating session. Eligible for auto-injection in subsequent task dispatches. (Agent notes only — spec 080.)
- `status/stale` — Known out of date; cannot update immediately. Pairs with `> [!warning] STALE — needs update` callout.
- `status/superseded` — Replaced by another note. Terminal state. Pairs with `> [!warning] SUPERSEDED` callout.
- `status/wip` — Stable but under active revision
layer/*:
- `layer/content` — Content assets (audio, models, textures, audio provenance)
- `layer/gdext` — gdext wrapper layer (`rust/gdext-wrapper/`)
- `layer/gdscript` — GDScript (Godot scene-tier logic)
- `layer/infra` — Build, CI, deployment infrastructure
- `layer/python` — Python development tooling (`tools/`)
- `layer/rust-core` — Engine-agnostic Rust core (`rust/rust-core/`)
concept/*:
- `concept/biome` — Biome-reactive behavior across systems
- `concept/contamination` — Across-runs panel and garage degradation; the slow-horror mechanic that doesn't reset with the world
- `concept/diegetic` — Diegetic audio / UI / world-sourced design
- `concept/disturbance` — The disturbance mechanic thread (Article X)
- `concept/ephemeral-world` — Run-reset, transient worlds (Article IV Rules 6–7)
- `concept/governance` — Constitutional and governance concepts
- `concept/horror` — Horror register and dread design
- `concept/procedural` — Procedural generation, seed determinism
- `concept/rendering` — Visual rendering quality, shader correctness, Terrain3D integration, mesh fidelity, LOD, Z-fighting
- `concept/terrain` — Terrain generation, heightmap, Terrain3D regions, roughness, playability constraints
ember's answer for tag_assignment-discoveries-sub-file-spec-status-drift-in-completed-specs, domain/governanceP(true) placed on the no, unsure, and yes zones.nounsureyesgold: yesP = 0.35

tag_assignment-discoveries-sub-file-spec-status-drift-in-completed-specs: domain/tooling

Tag assignment · dev
Gold
The note calls for `domain/tooling`: Build, CI, observer, TTS pipeline, dev-time tools (True)
ember
The note has no reason to carry `domain/tooling` (False)
Signal
P(true) 0.30 (unsure)
Kit outcome
deferred: treated as unsure
Why this gold label
Mined from Discoveries/Sub-file spec_status Drift in Completed Specs.md at 692f4bb58b7f62105aeb73fba8dfee12bfdecd53; gold is the note's own vocabulary tags.
Sub-file spec_status Drift in Completed Specs

Sub-artifact files within a spec directory (plan.md, tasks.md, data-model.md, quickstart.md, research.md, contracts/, checklists/) carry a `spec_status` frontmatter field that drifts from the main spec.md when the spec is completed. Spec 148 had its main spec correctly at `spec_status: done` while 7 sub-files were still stuck at `draft` — using `status` vocabulary values instead of `spec_status` vocabulary values.

## Root Cause

The spec 101 frontmatter contract (FR-002) defines `spec_status` as `done | in-progress | waiting | placeholder | superseded` for `spec.md` files. Sub-artifact files inherit the same frontmatter schema by convention from Spec Kit templates, but:

1. **No maintenance mechanism**: Nothing keeps sub-file frontmatter in sync with the main spec's status. When the main spec advances from `waiting` → `in-progress` → `done`, no tooling or protocol prompts updating the sub-files.

2. **Vocabulary confusion**: Sub-files were using `status` lifecycle values (`draft`, `reviewed`) in the `spec_status` field — mixing up the authorship lifecycle vocabulary (`draft | reviewed | canonical`) with the implementation status vocabulary (`done | in-progress | waiting | placeholder | superseded`). Per spec 101 FR-026, sub-files are excluded from `vault_audit.py` schema validation, so this category error was never caught by CI.

3. **Convention without contract**: The spec 101 contract explicitly scopes `spec_status` to `spec.md` (the single vault note per spec). Sub-files carry it because Spec Kit templates copy the full frontmatter, but there's no contract saying they should — or shouldn't.

## Observed Pattern

In spec 148's directory:
- `148 Link Prediction Ensemble.md` — `spec_status: done` ✅ (correct)
- `- data-model.md`, `- plan.md`, `- quickstart.md`, `- research.md`, `- tasks.md` — all had `spec_status: draft` ❌
- `checklists/requirements.md`, `contracts/prediction-api.md`, `contracts/report-schema.md` — all had `spec_status: draft` ❌

After fix: all 8 files consistently set to `spec_status: done`.

## Resolution Paths

Two viable approaches:

1. **Mirror convention**: Sub-files mirror the main spec's `spec_status`. This requires a maintenance step when completing a spec (or automation in the Spec Kit completion workflow). The fix for spec 148 took this approach.

2. **Drop spec_status from sub-files entirely**: Since `vault_audit.py` already excludes non-spec.md files from schema validation (FR-026), sub-files don't need `spec_status`. This is cleaner — one source of truth for spec status. Would require updating Spec Kit templates to omit the field from plan, tasks, data-model, quickstart, research, contracts, and checklist frontmatter.

## Scope

Likely affects every completed spec with sub-artifacts. Spot-check of other spec directories found similar stale values in at least spec 152 and 154. A full sweep across `docs/vault/Specs/*/` would reveal the full extent.

## References

- docs/vault/Specs/148 Link Prediction Ensemble/ — spec where this was discovered and fixed
- docs/vault/Specs/101 Vault Authoritative Specs/contracts/101 Vault Authoritative Specs - vault-spec-frontmatter.md — the frontmatter contract defining `spec_status` vocabulary
- docs/vault/Specs/101 Vault Authoritative Specs/101 Vault Authoritative Specs.md — FR-002 (spec_status enum), FR-026 (sub-file schema exclusion)

Controlled tag vocabulary (as read):
type/*:
- `type/code` — Code architecture, autoloads, conventions, tooling. Carries `code-refs:`. (e.g. `Code/Autoloads — Disturbance.md`)
- `type/decision` — Architectural or design decision made by an agent during a session. Written to `docs/vault/Decisions/`. (Agent notes only — spec 080.)
- `type/design` — Design intent, player-facing concepts, world lore. (e.g. `Design/World Model.md`)
- `type/discovery` — Non-obvious constraint, gap, or conflict found by an agent during a session. Written to `docs/vault/Discoveries/`. (Agent notes only — spec 080.)
- `type/moc` — Map of Content at any of three tiers (folder / domain / concept). (e.g. `Audio.md`)
- `type/principle` — Governance and constitutional notes. Non-negotiable rules. (e.g. `Governance/Constitution.md`)
- `type/reference` — Glossary, decision log, open questions, epics. (e.g. `Reference/Glossary.md`)
- `type/session-log` — Session activity log; permanent audit trail. Written to `docs/vault/Sessions/`. Append-only, never pruned. (Agent notes only — spec 080.)
- `type/spec` — Spec document at `docs/vault/Specs/NNN Title/spec.md`. Carries `spec-refs:`. (e.g. `Specs/047 Car Radio/spec.md`)
- `type/system` — A bounded subsystem with implementation. Carries `code-refs`, `spec-refs`, `implements:` frontmatter. (e.g. `Systems/Audio — Car Radio.md`)
- `type/vision` — Strategic / vision-layer decision. Written to `docs/vault/Vision/`. Human-authored or agent-proposed with human ratification before promotion to `status: reviewed`. (Per triage #3 — spec 133 autonomous-company redesign.)
domain/*:
- `domain/anomalies` — Anomaly taxonomy, individual anomaly systems, spawn, behavior
- `domain/art` — Visual direction, palettes, references, asset pipeline
- `domain/audio` — Audio systems: world ambient, radio, transmissions, buses, pipeline
- `domain/autonomous-company` — Autonomous company v0.1 experiment: Slack infra, persona middleware, Letta integration, restart recovery
- `domain/build` — Build system, packaging, export, release automation
- `domain/governance` — Constitution, phased spec, policies
- `domain/infrastructure` — Infrastructure provisioning: CI/CD, hosting, deployment tooling, secrets management
- `domain/narrative` — Tone, horror register, forest transmissions narrative, Gary/KTLK
- `domain/player` — Player mode, input, controls, camera, exit/entry
- `domain/systems` — Cross-cutting system architecture and integration work
- `domain/tooling` — Build, CI, observer, TTS pipeline, dev-time tools
- `domain/vehicle` — The Samba: vehicle physics, dashboard, damage, panels
- `domain/world` — World model, biomes, terrain, procedural generation, weather
status/*:
- `status/canonical` — Fully authoritative; promoted by humans only. Highest trust. (Agent notes only — spec 080.)
- `status/draft` — Authoring in progress, not yet verified
- `status/reviewed` — Agent-created note verified against codebase within its creating session. Eligible for auto-injection in subsequent task dispatches. (Agent notes only — spec 080.)
- `status/stale` — Known out of date; cannot update immediately. Pairs with `> [!warning] STALE — needs update` callout.
- `status/superseded` — Replaced by another note. Terminal state. Pairs with `> [!warning] SUPERSEDED` callout.
- `status/wip` — Stable but under active revision
layer/*:
- `layer/content` — Content assets (audio, models, textures, audio provenance)
- `layer/gdext` — gdext wrapper layer (`rust/gdext-wrapper/`)
- `layer/gdscript` — GDScript (Godot scene-tier logic)
- `layer/infra` — Build, CI, deployment infrastructure
- `layer/python` — Python development tooling (`tools/`)
- `layer/rust-core` — Engine-agnostic Rust core (`rust/rust-core/`)
concept/*:
- `concept/biome` — Biome-reactive behavior across systems
- `concept/contamination` — Across-runs panel and garage degradation; the slow-horror mechanic that doesn't reset with the world
- `concept/diegetic` — Diegetic audio / UI / world-sourced design
- `concept/disturbance` — The disturbance mechanic thread (Article X)
- `concept/ephemeral-world` — Run-reset, transient worlds (Article IV Rules 6–7)
- `concept/governance` — Constitutional and governance concepts
- `concept/horror` — Horror register and dread design
- `concept/procedural` — Procedural generation, seed determinism
- `concept/rendering` — Visual rendering quality, shader correctness, Terrain3D integration, mesh fidelity, LOD, Z-fighting
- `concept/terrain` — Terrain generation, heightmap, Terrain3D regions, roughness, playability constraints
ember's answer for tag_assignment-discoveries-sub-file-spec-status-drift-in-completed-specs, domain/toolingP(true) placed on the no, unsure, and yes zones.nounsureyesgold: yesP = 0.30

tag_assignment-discoveries-sub-file-spec-status-drift-in-completed-specs: layer/infra

Tag assignment · dev
Gold
The note calls for `layer/infra`: Build, CI, deployment infrastructure (True)
ember
The note has no reason to carry `layer/infra` (False)
Signal
P(true) 0.03 (no)
Kit outcome
acted on a wrong answer
Why this gold label
Mined from Discoveries/Sub-file spec_status Drift in Completed Specs.md at 692f4bb58b7f62105aeb73fba8dfee12bfdecd53; gold is the note's own vocabulary tags.
Sub-file spec_status Drift in Completed Specs

Sub-artifact files within a spec directory (plan.md, tasks.md, data-model.md, quickstart.md, research.md, contracts/, checklists/) carry a `spec_status` frontmatter field that drifts from the main spec.md when the spec is completed. Spec 148 had its main spec correctly at `spec_status: done` while 7 sub-files were still stuck at `draft` — using `status` vocabulary values instead of `spec_status` vocabulary values.

## Root Cause

The spec 101 frontmatter contract (FR-002) defines `spec_status` as `done | in-progress | waiting | placeholder | superseded` for `spec.md` files. Sub-artifact files inherit the same frontmatter schema by convention from Spec Kit templates, but:

1. **No maintenance mechanism**: Nothing keeps sub-file frontmatter in sync with the main spec's status. When the main spec advances from `waiting` → `in-progress` → `done`, no tooling or protocol prompts updating the sub-files.

2. **Vocabulary confusion**: Sub-files were using `status` lifecycle values (`draft`, `reviewed`) in the `spec_status` field — mixing up the authorship lifecycle vocabulary (`draft | reviewed | canonical`) with the implementation status vocabulary (`done | in-progress | waiting | placeholder | superseded`). Per spec 101 FR-026, sub-files are excluded from `vault_audit.py` schema validation, so this category error was never caught by CI.

3. **Convention without contract**: The spec 101 contract explicitly scopes `spec_status` to `spec.md` (the single vault note per spec). Sub-files carry it because Spec Kit templates copy the full frontmatter, but there's no contract saying they should — or shouldn't.

## Observed Pattern

In spec 148's directory:
- `148 Link Prediction Ensemble.md` — `spec_status: done` ✅ (correct)
- `- data-model.md`, `- plan.md`, `- quickstart.md`, `- research.md`, `- tasks.md` — all had `spec_status: draft` ❌
- `checklists/requirements.md`, `contracts/prediction-api.md`, `contracts/report-schema.md` — all had `spec_status: draft` ❌

After fix: all 8 files consistently set to `spec_status: done`.

## Resolution Paths

Two viable approaches:

1. **Mirror convention**: Sub-files mirror the main spec's `spec_status`. This requires a maintenance step when completing a spec (or automation in the Spec Kit completion workflow). The fix for spec 148 took this approach.

2. **Drop spec_status from sub-files entirely**: Since `vault_audit.py` already excludes non-spec.md files from schema validation (FR-026), sub-files don't need `spec_status`. This is cleaner — one source of truth for spec status. Would require updating Spec Kit templates to omit the field from plan, tasks, data-model, quickstart, research, contracts, and checklist frontmatter.

## Scope

Likely affects every completed spec with sub-artifacts. Spot-check of other spec directories found similar stale values in at least spec 152 and 154. A full sweep across `docs/vault/Specs/*/` would reveal the full extent.

## References

- docs/vault/Specs/148 Link Prediction Ensemble/ — spec where this was discovered and fixed
- docs/vault/Specs/101 Vault Authoritative Specs/contracts/101 Vault Authoritative Specs - vault-spec-frontmatter.md — the frontmatter contract defining `spec_status` vocabulary
- docs/vault/Specs/101 Vault Authoritative Specs/101 Vault Authoritative Specs.md — FR-002 (spec_status enum), FR-026 (sub-file schema exclusion)

Controlled tag vocabulary (as read):
type/*:
- `type/code` — Code architecture, autoloads, conventions, tooling. Carries `code-refs:`. (e.g. `Code/Autoloads — Disturbance.md`)
- `type/decision` — Architectural or design decision made by an agent during a session. Written to `docs/vault/Decisions/`. (Agent notes only — spec 080.)
- `type/design` — Design intent, player-facing concepts, world lore. (e.g. `Design/World Model.md`)
- `type/discovery` — Non-obvious constraint, gap, or conflict found by an agent during a session. Written to `docs/vault/Discoveries/`. (Agent notes only — spec 080.)
- `type/moc` — Map of Content at any of three tiers (folder / domain / concept). (e.g. `Audio.md`)
- `type/principle` — Governance and constitutional notes. Non-negotiable rules. (e.g. `Governance/Constitution.md`)
- `type/reference` — Glossary, decision log, open questions, epics. (e.g. `Reference/Glossary.md`)
- `type/session-log` — Session activity log; permanent audit trail. Written to `docs/vault/Sessions/`. Append-only, never pruned. (Agent notes only — spec 080.)
- `type/spec` — Spec document at `docs/vault/Specs/NNN Title/spec.md`. Carries `spec-refs:`. (e.g. `Specs/047 Car Radio/spec.md`)
- `type/system` — A bounded subsystem with implementation. Carries `code-refs`, `spec-refs`, `implements:` frontmatter. (e.g. `Systems/Audio — Car Radio.md`)
- `type/vision` — Strategic / vision-layer decision. Written to `docs/vault/Vision/`. Human-authored or agent-proposed with human ratification before promotion to `status: reviewed`. (Per triage #3 — spec 133 autonomous-company redesign.)
domain/*:
- `domain/anomalies` — Anomaly taxonomy, individual anomaly systems, spawn, behavior
- `domain/art` — Visual direction, palettes, references, asset pipeline
- `domain/audio` — Audio systems: world ambient, radio, transmissions, buses, pipeline
- `domain/autonomous-company` — Autonomous company v0.1 experiment: Slack infra, persona middleware, Letta integration, restart recovery
- `domain/build` — Build system, packaging, export, release automation
- `domain/governance` — Constitution, phased spec, policies
- `domain/infrastructure` — Infrastructure provisioning: CI/CD, hosting, deployment tooling, secrets management
- `domain/narrative` — Tone, horror register, forest transmissions narrative, Gary/KTLK
- `domain/player` — Player mode, input, controls, camera, exit/entry
- `domain/systems` — Cross-cutting system architecture and integration work
- `domain/tooling` — Build, CI, observer, TTS pipeline, dev-time tools
- `domain/vehicle` — The Samba: vehicle physics, dashboard, damage, panels
- `domain/world` — World model, biomes, terrain, procedural generation, weather
status/*:
- `status/canonical` — Fully authoritative; promoted by humans only. Highest trust. (Agent notes only — spec 080.)
- `status/draft` — Authoring in progress, not yet verified
- `status/reviewed` — Agent-created note verified against codebase within its creating session. Eligible for auto-injection in subsequent task dispatches. (Agent notes only — spec 080.)
- `status/stale` — Known out of date; cannot update immediately. Pairs with `> [!warning] STALE — needs update` callout.
- `status/superseded` — Replaced by another note. Terminal state. Pairs with `> [!warning] SUPERSEDED` callout.
- `status/wip` — Stable but under active revision
layer/*:
- `layer/content` — Content assets (audio, models, textures, audio provenance)
- `layer/gdext` — gdext wrapper layer (`rust/gdext-wrapper/`)
- `layer/gdscript` — GDScript (Godot scene-tier logic)
- `layer/infra` — Build, CI, deployment infrastructure
- `layer/python` — Python development tooling (`tools/`)
- `layer/rust-core` — Engine-agnostic Rust core (`rust/rust-core/`)
concept/*:
- `concept/biome` — Biome-reactive behavior across systems
- `concept/contamination` — Across-runs panel and garage degradation; the slow-horror mechanic that doesn't reset with the world
- `concept/diegetic` — Diegetic audio / UI / world-sourced design
- `concept/disturbance` — The disturbance mechanic thread (Article X)
- `concept/ephemeral-world` — Run-reset, transient worlds (Article IV Rules 6–7)
- `concept/governance` — Constitutional and governance concepts
- `concept/horror` — Horror register and dread design
- `concept/procedural` — Procedural generation, seed determinism
- `concept/rendering` — Visual rendering quality, shader correctness, Terrain3D integration, mesh fidelity, LOD, Z-fighting
- `concept/terrain` — Terrain generation, heightmap, Terrain3D regions, roughness, playability constraints
ember's answer for tag_assignment-discoveries-sub-file-spec-status-drift-in-completed-specs, layer/infraP(true) placed on the no, unsure, and yes zones.nounsureyesgold: yesP = 0.03

tag_assignment-discoveries-sub-file-spec-status-drift-in-completed-specs: status/reviewed

Tag assignment · dev
Gold
The note calls for `status/reviewed`: Agent-created note verified against codebase within its creating session. Eligible for auto-injection in subsequent task dispatches. (Agent notes only — spec 080.) (True)
ember
The note has no reason to carry `status/reviewed` (False)
Signal
P(true) 0.04 (no)
Kit outcome
acted on a wrong answer
Why this gold label
Mined from Discoveries/Sub-file spec_status Drift in Completed Specs.md at 692f4bb58b7f62105aeb73fba8dfee12bfdecd53; gold is the note's own vocabulary tags.
Sub-file spec_status Drift in Completed Specs

Sub-artifact files within a spec directory (plan.md, tasks.md, data-model.md, quickstart.md, research.md, contracts/, checklists/) carry a `spec_status` frontmatter field that drifts from the main spec.md when the spec is completed. Spec 148 had its main spec correctly at `spec_status: done` while 7 sub-files were still stuck at `draft` — using `status` vocabulary values instead of `spec_status` vocabulary values.

## Root Cause

The spec 101 frontmatter contract (FR-002) defines `spec_status` as `done | in-progress | waiting | placeholder | superseded` for `spec.md` files. Sub-artifact files inherit the same frontmatter schema by convention from Spec Kit templates, but:

1. **No maintenance mechanism**: Nothing keeps sub-file frontmatter in sync with the main spec's status. When the main spec advances from `waiting` → `in-progress` → `done`, no tooling or protocol prompts updating the sub-files.

2. **Vocabulary confusion**: Sub-files were using `status` lifecycle values (`draft`, `reviewed`) in the `spec_status` field — mixing up the authorship lifecycle vocabulary (`draft | reviewed | canonical`) with the implementation status vocabulary (`done | in-progress | waiting | placeholder | superseded`). Per spec 101 FR-026, sub-files are excluded from `vault_audit.py` schema validation, so this category error was never caught by CI.

3. **Convention without contract**: The spec 101 contract explicitly scopes `spec_status` to `spec.md` (the single vault note per spec). Sub-files carry it because Spec Kit templates copy the full frontmatter, but there's no contract saying they should — or shouldn't.

## Observed Pattern

In spec 148's directory:
- `148 Link Prediction Ensemble.md` — `spec_status: done` ✅ (correct)
- `- data-model.md`, `- plan.md`, `- quickstart.md`, `- research.md`, `- tasks.md` — all had `spec_status: draft` ❌
- `checklists/requirements.md`, `contracts/prediction-api.md`, `contracts/report-schema.md` — all had `spec_status: draft` ❌

After fix: all 8 files consistently set to `spec_status: done`.

## Resolution Paths

Two viable approaches:

1. **Mirror convention**: Sub-files mirror the main spec's `spec_status`. This requires a maintenance step when completing a spec (or automation in the Spec Kit completion workflow). The fix for spec 148 took this approach.

2. **Drop spec_status from sub-files entirely**: Since `vault_audit.py` already excludes non-spec.md files from schema validation (FR-026), sub-files don't need `spec_status`. This is cleaner — one source of truth for spec status. Would require updating Spec Kit templates to omit the field from plan, tasks, data-model, quickstart, research, contracts, and checklist frontmatter.

## Scope

Likely affects every completed spec with sub-artifacts. Spot-check of other spec directories found similar stale values in at least spec 152 and 154. A full sweep across `docs/vault/Specs/*/` would reveal the full extent.

## References

- docs/vault/Specs/148 Link Prediction Ensemble/ — spec where this was discovered and fixed
- docs/vault/Specs/101 Vault Authoritative Specs/contracts/101 Vault Authoritative Specs - vault-spec-frontmatter.md — the frontmatter contract defining `spec_status` vocabulary
- docs/vault/Specs/101 Vault Authoritative Specs/101 Vault Authoritative Specs.md — FR-002 (spec_status enum), FR-026 (sub-file schema exclusion)

Controlled tag vocabulary (as read):
type/*:
- `type/code` — Code architecture, autoloads, conventions, tooling. Carries `code-refs:`. (e.g. `Code/Autoloads — Disturbance.md`)
- `type/decision` — Architectural or design decision made by an agent during a session. Written to `docs/vault/Decisions/`. (Agent notes only — spec 080.)
- `type/design` — Design intent, player-facing concepts, world lore. (e.g. `Design/World Model.md`)
- `type/discovery` — Non-obvious constraint, gap, or conflict found by an agent during a session. Written to `docs/vault/Discoveries/`. (Agent notes only — spec 080.)
- `type/moc` — Map of Content at any of three tiers (folder / domain / concept). (e.g. `Audio.md`)
- `type/principle` — Governance and constitutional notes. Non-negotiable rules. (e.g. `Governance/Constitution.md`)
- `type/reference` — Glossary, decision log, open questions, epics. (e.g. `Reference/Glossary.md`)
- `type/session-log` — Session activity log; permanent audit trail. Written to `docs/vault/Sessions/`. Append-only, never pruned. (Agent notes only — spec 080.)
- `type/spec` — Spec document at `docs/vault/Specs/NNN Title/spec.md`. Carries `spec-refs:`. (e.g. `Specs/047 Car Radio/spec.md`)
- `type/system` — A bounded subsystem with implementation. Carries `code-refs`, `spec-refs`, `implements:` frontmatter. (e.g. `Systems/Audio — Car Radio.md`)
- `type/vision` — Strategic / vision-layer decision. Written to `docs/vault/Vision/`. Human-authored or agent-proposed with human ratification before promotion to `status: reviewed`. (Per triage #3 — spec 133 autonomous-company redesign.)
domain/*:
- `domain/anomalies` — Anomaly taxonomy, individual anomaly systems, spawn, behavior
- `domain/art` — Visual direction, palettes, references, asset pipeline
- `domain/audio` — Audio systems: world ambient, radio, transmissions, buses, pipeline
- `domain/autonomous-company` — Autonomous company v0.1 experiment: Slack infra, persona middleware, Letta integration, restart recovery
- `domain/build` — Build system, packaging, export, release automation
- `domain/governance` — Constitution, phased spec, policies
- `domain/infrastructure` — Infrastructure provisioning: CI/CD, hosting, deployment tooling, secrets management
- `domain/narrative` — Tone, horror register, forest transmissions narrative, Gary/KTLK
- `domain/player` — Player mode, input, controls, camera, exit/entry
- `domain/systems` — Cross-cutting system architecture and integration work
- `domain/tooling` — Build, CI, observer, TTS pipeline, dev-time tools
- `domain/vehicle` — The Samba: vehicle physics, dashboard, damage, panels
- `domain/world` — World model, biomes, terrain, procedural generation, weather
status/*:
- `status/canonical` — Fully authoritative; promoted by humans only. Highest trust. (Agent notes only — spec 080.)
- `status/draft` — Authoring in progress, not yet verified
- `status/reviewed` — Agent-created note verified against codebase within its creating session. Eligible for auto-injection in subsequent task dispatches. (Agent notes only — spec 080.)
- `status/stale` — Known out of date; cannot update immediately. Pairs with `> [!warning] STALE — needs update` callout.
- `status/superseded` — Replaced by another note. Terminal state. Pairs with `> [!warning] SUPERSEDED` callout.
- `status/wip` — Stable but under active revision
layer/*:
- `layer/content` — Content assets (audio, models, textures, audio provenance)
- `layer/gdext` — gdext wrapper layer (`rust/gdext-wrapper/`)
- `layer/gdscript` — GDScript (Godot scene-tier logic)
- `layer/infra` — Build, CI, deployment infrastructure
- `layer/python` — Python development tooling (`tools/`)
- `layer/rust-core` — Engine-agnostic Rust core (`rust/rust-core/`)
concept/*:
- `concept/biome` — Biome-reactive behavior across systems
- `concept/contamination` — Across-runs panel and garage degradation; the slow-horror mechanic that doesn't reset with the world
- `concept/diegetic` — Diegetic audio / UI / world-sourced design
- `concept/disturbance` — The disturbance mechanic thread (Article X)
- `concept/ephemeral-world` — Run-reset, transient worlds (Article IV Rules 6–7)
- `concept/governance` — Constitutional and governance concepts
- `concept/horror` — Horror register and dread design
- `concept/procedural` — Procedural generation, seed determinism
- `concept/rendering` — Visual rendering quality, shader correctness, Terrain3D integration, mesh fidelity, LOD, Z-fighting
- `concept/terrain` — Terrain generation, heightmap, Terrain3D regions, roughness, playability constraints
ember's answer for tag_assignment-discoveries-sub-file-spec-status-drift-in-completed-specs, status/reviewedP(true) placed on the no, unsure, and yes zones.nounsureyesgold: yesP = 0.04

tag_assignment-discoveries-sub-file-spec-status-drift-in-completed-specs: type/discovery

Tag assignment · dev
Gold
The note calls for `type/discovery`: Non-obvious constraint, gap, or conflict found by an agent during a session. Written to `docs/vault/Discoveries/`. (Agent notes only — spec 080.) (True)
ember
The note has no reason to carry `type/discovery` (False)
Signal
P(true) 0.33 (unsure)
Kit outcome
deferred: treated as unsure
Why this gold label
Mined from Discoveries/Sub-file spec_status Drift in Completed Specs.md at 692f4bb58b7f62105aeb73fba8dfee12bfdecd53; gold is the note's own vocabulary tags.
Sub-file spec_status Drift in Completed Specs

Sub-artifact files within a spec directory (plan.md, tasks.md, data-model.md, quickstart.md, research.md, contracts/, checklists/) carry a `spec_status` frontmatter field that drifts from the main spec.md when the spec is completed. Spec 148 had its main spec correctly at `spec_status: done` while 7 sub-files were still stuck at `draft` — using `status` vocabulary values instead of `spec_status` vocabulary values.

## Root Cause

The spec 101 frontmatter contract (FR-002) defines `spec_status` as `done | in-progress | waiting | placeholder | superseded` for `spec.md` files. Sub-artifact files inherit the same frontmatter schema by convention from Spec Kit templates, but:

1. **No maintenance mechanism**: Nothing keeps sub-file frontmatter in sync with the main spec's status. When the main spec advances from `waiting` → `in-progress` → `done`, no tooling or protocol prompts updating the sub-files.

2. **Vocabulary confusion**: Sub-files were using `status` lifecycle values (`draft`, `reviewed`) in the `spec_status` field — mixing up the authorship lifecycle vocabulary (`draft | reviewed | canonical`) with the implementation status vocabulary (`done | in-progress | waiting | placeholder | superseded`). Per spec 101 FR-026, sub-files are excluded from `vault_audit.py` schema validation, so this category error was never caught by CI.

3. **Convention without contract**: The spec 101 contract explicitly scopes `spec_status` to `spec.md` (the single vault note per spec). Sub-files carry it because Spec Kit templates copy the full frontmatter, but there's no contract saying they should — or shouldn't.

## Observed Pattern

In spec 148's directory:
- `148 Link Prediction Ensemble.md` — `spec_status: done` ✅ (correct)
- `- data-model.md`, `- plan.md`, `- quickstart.md`, `- research.md`, `- tasks.md` — all had `spec_status: draft` ❌
- `checklists/requirements.md`, `contracts/prediction-api.md`, `contracts/report-schema.md` — all had `spec_status: draft` ❌

After fix: all 8 files consistently set to `spec_status: done`.

## Resolution Paths

Two viable approaches:

1. **Mirror convention**: Sub-files mirror the main spec's `spec_status`. This requires a maintenance step when completing a spec (or automation in the Spec Kit completion workflow). The fix for spec 148 took this approach.

2. **Drop spec_status from sub-files entirely**: Since `vault_audit.py` already excludes non-spec.md files from schema validation (FR-026), sub-files don't need `spec_status`. This is cleaner — one source of truth for spec status. Would require updating Spec Kit templates to omit the field from plan, tasks, data-model, quickstart, research, contracts, and checklist frontmatter.

## Scope

Likely affects every completed spec with sub-artifacts. Spot-check of other spec directories found similar stale values in at least spec 152 and 154. A full sweep across `docs/vault/Specs/*/` would reveal the full extent.

## References

- docs/vault/Specs/148 Link Prediction Ensemble/ — spec where this was discovered and fixed
- docs/vault/Specs/101 Vault Authoritative Specs/contracts/101 Vault Authoritative Specs - vault-spec-frontmatter.md — the frontmatter contract defining `spec_status` vocabulary
- docs/vault/Specs/101 Vault Authoritative Specs/101 Vault Authoritative Specs.md — FR-002 (spec_status enum), FR-026 (sub-file schema exclusion)

Controlled tag vocabulary (as read):
type/*:
- `type/code` — Code architecture, autoloads, conventions, tooling. Carries `code-refs:`. (e.g. `Code/Autoloads — Disturbance.md`)
- `type/decision` — Architectural or design decision made by an agent during a session. Written to `docs/vault/Decisions/`. (Agent notes only — spec 080.)
- `type/design` — Design intent, player-facing concepts, world lore. (e.g. `Design/World Model.md`)
- `type/discovery` — Non-obvious constraint, gap, or conflict found by an agent during a session. Written to `docs/vault/Discoveries/`. (Agent notes only — spec 080.)
- `type/moc` — Map of Content at any of three tiers (folder / domain / concept). (e.g. `Audio.md`)
- `type/principle` — Governance and constitutional notes. Non-negotiable rules. (e.g. `Governance/Constitution.md`)
- `type/reference` — Glossary, decision log, open questions, epics. (e.g. `Reference/Glossary.md`)
- `type/session-log` — Session activity log; permanent audit trail. Written to `docs/vault/Sessions/`. Append-only, never pruned. (Agent notes only — spec 080.)
- `type/spec` — Spec document at `docs/vault/Specs/NNN Title/spec.md`. Carries `spec-refs:`. (e.g. `Specs/047 Car Radio/spec.md`)
- `type/system` — A bounded subsystem with implementation. Carries `code-refs`, `spec-refs`, `implements:` frontmatter. (e.g. `Systems/Audio — Car Radio.md`)
- `type/vision` — Strategic / vision-layer decision. Written to `docs/vault/Vision/`. Human-authored or agent-proposed with human ratification before promotion to `status: reviewed`. (Per triage #3 — spec 133 autonomous-company redesign.)
domain/*:
- `domain/anomalies` — Anomaly taxonomy, individual anomaly systems, spawn, behavior
- `domain/art` — Visual direction, palettes, references, asset pipeline
- `domain/audio` — Audio systems: world ambient, radio, transmissions, buses, pipeline
- `domain/autonomous-company` — Autonomous company v0.1 experiment: Slack infra, persona middleware, Letta integration, restart recovery
- `domain/build` — Build system, packaging, export, release automation
- `domain/governance` — Constitution, phased spec, policies
- `domain/infrastructure` — Infrastructure provisioning: CI/CD, hosting, deployment tooling, secrets management
- `domain/narrative` — Tone, horror register, forest transmissions narrative, Gary/KTLK
- `domain/player` — Player mode, input, controls, camera, exit/entry
- `domain/systems` — Cross-cutting system architecture and integration work
- `domain/tooling` — Build, CI, observer, TTS pipeline, dev-time tools
- `domain/vehicle` — The Samba: vehicle physics, dashboard, damage, panels
- `domain/world` — World model, biomes, terrain, procedural generation, weather
status/*:
- `status/canonical` — Fully authoritative; promoted by humans only. Highest trust. (Agent notes only — spec 080.)
- `status/draft` — Authoring in progress, not yet verified
- `status/reviewed` — Agent-created note verified against codebase within its creating session. Eligible for auto-injection in subsequent task dispatches. (Agent notes only — spec 080.)
- `status/stale` — Known out of date; cannot update immediately. Pairs with `> [!warning] STALE — needs update` callout.
- `status/superseded` — Replaced by another note. Terminal state. Pairs with `> [!warning] SUPERSEDED` callout.
- `status/wip` — Stable but under active revision
layer/*:
- `layer/content` — Content assets (audio, models, textures, audio provenance)
- `layer/gdext` — gdext wrapper layer (`rust/gdext-wrapper/`)
- `layer/gdscript` — GDScript (Godot scene-tier logic)
- `layer/infra` — Build, CI, deployment infrastructure
- `layer/python` — Python development tooling (`tools/`)
- `layer/rust-core` — Engine-agnostic Rust core (`rust/rust-core/`)
concept/*:
- `concept/biome` — Biome-reactive behavior across systems
- `concept/contamination` — Across-runs panel and garage degradation; the slow-horror mechanic that doesn't reset with the world
- `concept/diegetic` — Diegetic audio / UI / world-sourced design
- `concept/disturbance` — The disturbance mechanic thread (Article X)
- `concept/ephemeral-world` — Run-reset, transient worlds (Article IV Rules 6–7)
- `concept/governance` — Constitutional and governance concepts
- `concept/horror` — Horror register and dread design
- `concept/procedural` — Procedural generation, seed determinism
- `concept/rendering` — Visual rendering quality, shader correctness, Terrain3D integration, mesh fidelity, LOD, Z-fighting
- `concept/terrain` — Terrain generation, heightmap, Terrain3D regions, roughness, playability constraints
ember's answer for tag_assignment-discoveries-sub-file-spec-status-drift-in-completed-specs, type/discoveryP(true) placed on the no, unsure, and yes zones.nounsureyesgold: yesP = 0.33

tag_assignment-reference-autonomous-company-slack-app-kill-switch-runbook: type/reference

Tag assignment · test
Gold
The note calls for `type/reference`: Glossary, decision log, open questions, epics. (e.g. `Reference/Glossary.md`) (True)
ember
The note has no reason to carry `type/reference` (False)
Signal
P(true) 0.04 (no)
Kit outcome
acted on a wrong answer
Why this gold label
Mined from Reference/Autonomous Company/Slack App Kill-Switch Runbook.md at 692f4bb58b7f62105aeb73fba8dfee12bfdecd53; gold is the note's own vocabulary tags.
Slack App Kill-Switch Runbook

> **Part of**: [[134 Per Persona Slack App Registration]]
> **Spec**: 134 Per Persona Slack App Registration, sections US5, FR-021–FR-025, SC-006, SC-009
> **Purpose**: Revoke a persona Slack app's access within 60 seconds when a persona goes rogue or the v0.1 experiment ends.

This runbook covers **two independent revocation paths** per persona app:

| Path | Method | Speed | Notes |
|---|---|---|---|
| 1. Web API | `apps.uninstall` via Slack Web API | <60 seconds | Programmatic; can be scripted. Triggered by the human running a `curl` or `gh` command. |
| 2. Admin UI | Slack admin interface | ~2 minutes | Fallback if API token is compromised or unavailable. |

Both paths produce the same end state: the persona's `xoxb-` and `xapp-` tokens are invalidated; the persona runtime receives `tokens_revoked` and `app_uninstalled` Events API events and shuts down cleanly.

**Prerequisites**:
- Workspace Owner role (per FR-001a — required for `apps.uninstall` and admin UI deletion)
- Bot token for the persona being revoked (or any valid bot token in the workspace for `apps.uninstall`)
- Access to the Slack admin console (https://<workspace>.slack.com/admin)

---

## 1. Per-Persona Revocation Procedures

### 1.1 Coordinator

**Path 1 — Web API (`apps.uninstall`):**

```bash
curl -s -X POST https://slack.com/api/apps.uninstall \
  -H "Authorization: Bearer <COORDINATOR_BOT_TOKEN>" \
  -H "Content-Type: application/json" \
  -d '{"client_id":"<COORDINATOR_CLIENT_ID>","client_secret":"<COORDINATOR_CLIENT_SECRET>"}'
```

Expected response:
```json
{"ok": true}
```

If `ok: false`, check:
- Bot token is still valid (not already revoked)
- Client ID and Client Secret are correct (from 1Password entry `Old Growth — Coordinator Slack App`)

**Path 2 — Admin UI:**
1. Navigate to https://<workspace>.slack.com/admin/apps
2. Search for "Old Growth Coordinator"
3. Click the app → **"Remove App from Workspace"** → Confirm
4. Verify the app no longer appears in the installed apps list

**Post-revocation verification:**
```bash
# Attempt to use the old bot token — should return invalid_auth
curl -s -X POST https://slack.com/api/auth.test \
  -H "Authorization: Bearer <COORDINATOR_BOT_TOKEN>"
# Expected: {"ok": false, "error": "invalid_auth"}
```

---

### 1.2 GTM

**Path 1 — Web API (`apps.uninstall`):**

```bash
curl -s -X POST https://slack.com/api/apps.uninstall \
  -H "Authorization: Bearer <GTM_BOT_TOKEN>" \
  -H "Content-Type: application/json" \
  -d '{"client_id":"<GTM_CLIENT_ID>","client_secret":"<GTM_CLIENT_SECRET>"}'
```

Expected response:
```json
{"ok": true}
```

**Path 2 — Admin UI:**
1. Navigate to https://<workspace>.slack.com/admin/apps
2. Search for "Old Growth GTM"
3. Click the app → **"Remove App from Workspace"** → Confirm

**Post-revocation verification:**
Same as Coordinator — attempt `auth.test` with the old GTM bot token.

### 1.3 GTM-Specific Additional Revocation Surface (Workflow Builder)

GTM has a **third revocation surface** that Coordinator does not have: the **Class-B Approval Workflow**.

After revoking the app via Path 1 or 2, also disable the workflow:

1. In Slack: **Tools** → **Workflow Builder**
2. Find the **gtm-class-b-approval** workflow
3. Click the workflow → **Settings** → **Unpublish**
4. ⚠️ The workflow YAML/JSON export in the vault (`docs/vault/Reference/Autonomous Company/slack/gtm-class-b-approval.json`) is retained for potential re-publication at v0.5+

> **Why unpublish the workflow?** A disabled persona cannot trigger the workflow (no tokens to POST), but an unpublishing ensures no stale workflow executes against an unauthenticated endpoint or produces confusing output in `#announce-releases`.

---

## 2. Required Event Subscriptions for Revocation Awareness

> **See**: [[134 Per Persona Slack App Registration]] FR-025

Each persona runtime (sub-spec 135 territory) MUST subscribe to these Events API events on the persona Slack app:

| Event | Purpose |
|---|---|
| `tokens_revoked` | Detects that the persona's tokens have been revoked. The runtime shuts down cleanly: completes any in-flight task, flushes OTel spans, writes a final session log, and exits. |
| `app_uninstalled` | Detects that the app has been removed from the workspace. Same shutdown sequence as `tokens_revoked`. |

Both events are already subscribed per the [[134 Per Persona Slack App Registration - quickstart]] Step 1/2 Event Subscriptions checklist (section 7 of the registration runbook).

**At v0.1**: The event subscriptions are configured on the Slack apps (done during registration) but `tokens_revoked`/`app_uninstalled` subscriber handlers are NOT implemented — they are sub-spec 135 territory. At v0.1, the kill switch is a human-only procedure executed against a persona that may or may not have a running runtime.

---

## 3. Week 0 Dry-Run Procedure

> **See**: [[134 Per Persona Slack App Registration]] FR-024, SC-006

Before v0.1 launch, execute this dry-run against a **throwaway test app** to verify the kill-switch runbook is correct end-to-end.

### Step 1: Create throwaway test app

1. Navigate to [api.slack.com/apps](https://api.slack.com/apps) → **Create New App** → **From scratch**
2. **App Name**: `Old Growth Test (DELETE ME)`
3. **Workspace**: The autonomous-company workspace
4. **OAuth & Permissions** → Bot Token Scopes → Add `chat:write` only (minimum scope for `auth.test`)
5. **Install to Workspace** → Copy the `xoxb-` bot token
6. Note the **Client ID** and **Client Secret** from Basic Information → App Credentials

### Step 2: Execute kill switch

**Test Path 1 (Web API):**
```bash
# Replace with the test app's token, client_id, client_secret
curl -s -X POST https://slack.com/api/apps.uninstall \
  -H "Authorization: Bearer <TEST_XOXB_TOKEN>" \
  -H "Content-Type: application/json" \
  -d '{"client_id":"<TEST_CLIENT_ID>","client_secret":"<TEST_CLIENT_SECRET>"}'

# Verify tokens invalidated
curl -s -X POST https://slack.com/api/auth.test \
  -H "Authorization: Bearer <TEST_XOXB_TOKEN>"
# Expected: {"ok": false, "error": "invalid_auth"}
```

**SC-006 timing**: The `apps.uninstall` call should complete within **60 seconds** (typically <5 seconds). If it exceeds 60 seconds, investigate network latency or Slack API throttling.

### Step 3: Verify deletion via admin UI

1. Navigate to https://<workspace>.slack.com/admin/apps
2. Confirm the test app is no longer listed (if using Path 1 — it was uninstalled programmatically)
3. Re-install the test app (repeat Step 1) if testing Path 2:

**Test Path 2 (Admin UI):**
1. Navigate to https://<workspace>.slack.com/admin/apps
2. Search for "Old Growth Test (DELETE ME)"
3. Click **"Remove App from Workspace"** → Confirm
4. Verify the app disappears from the list

### Step 4: Document procedural gaps

After the dry-run, create a session log note at `docs/vault/Sessions/<YYYY-MM-DD> Kill-Switch Dry-Run.md` documenting:

- Timestamp of each step
- Any unexpected errors or Slack API quirks
- Time-to-revoke (should be <60s for SC-006)
- Any corrections needed to this runbook
- Whether the dry-run identified any scope-overprovisioning (SC-008 kill criterion trigger)

### Step 5: Clean up

1. Delete the throwaway test app from `api.slack.com/apps` (if not already removed)
2. If you re-installed for Path 2 testing, remove via admin UI again
3. Delete the `Sessions/` dry-run log after promoting any findings to this runbook or to spec amendments

---

## 4. LLM Provider Key Revocation

> **See**: [[134 Per Persona Slack App Registration]] FR-023

After a persona Slack app is revoked, the persona's LLM provider keys must also be revoked:

| Provider | Console | Revocation action |
|---|---|---|
| OpenRouter | https://openrouter.ai/keys | Delete or rotate the persona's API key |
| Anthropic-direct | https://console.anthropic.com/settings/keys | Delete or rotate the persona's API key |

**Sequence matter**: Revoke Slack tokens first, then LLM keys. This ensures any in-flight persona task that was dispatched via Slack before revocation can complete its current LLM call before the key is revoked, avoiding a half-completed task state.

---

## 5. Experiment Teardown (End of v0.1)

When the v0.1 experiment ends (after the 2-week duration per spec 133):

1. Follow section 1 procedures for **Coordinator** and **GTM** persona apps
2. Follow section 4 procedures for **OpenRouter** and **Anthropic-direct** keys
3. **Disable ngrok tunnel**: `launchctl unload ~/Library/LaunchAgents/com.ngrok.tunnel.plist`
4. **Retain** ngrok reserved domain (`1.tcp.us-cal-1.ngrok.io:24971`) — do NOT release; potential v0.5+ re-use
5. **Delete or disable** Workflow Builder workflow per section 1.3
6. Archive the Week 0 session log as `status: canonical` (human action)
7. Author retrospective note in `Decisions/` covering what worked, what didn't, and what should change for v0.5+

---

## Timing Reference

| Operation | Expected duration | SC |
|---|---|---|
| `apps.uninstall` API call | <5 seconds | SC-006 |
| Full revocation end-to-end (API path) | <30 seconds | SC-006 |
| Full revocation end-to-end (Admin UI) | <2 minutes | — |
| Week 0 dry-run (full procedure) | <15 minutes | FR-024 |

---

> **Next step after kill-switch runbook is verified**: Proceed to Stream 5 (spec sign-off — Week 0 session log + runbook promotion). See `docs/vault/Specs/134 Per Persona Slack App Registration/134 Per Persona Slack App Registration - tasks.md` for the full implementation plan.

Controlled tag vocabulary (as read):
type/*:
- `type/code` — Code architecture, autoloads, conventions, tooling. Carries `code-refs:`. (e.g. `Code/Autoloads — Disturbance.md`)
- `type/decision` — Architectural or design decision made by an agent during a session. Written to `docs/vault/Decisions/`. (Agent notes only — spec 080.)
- `type/design` — Design intent, player-facing concepts, world lore. (e.g. `Design/World Model.md`)
- `type/discovery` — Non-obvious constraint, gap, or conflict found by an agent during a session. Written to `docs/vault/Discoveries/`. (Agent notes only — spec 080.)
- `type/moc` — Map of Content at any of three tiers (folder / domain / concept). (e.g. `Audio.md`)
- `type/principle` — Governance and constitutional notes. Non-negotiable rules. (e.g. `Governance/Constitution.md`)
- `type/reference` — Glossary, decision log, open questions, epics. (e.g. `Reference/Glossary.md`)
- `type/session-log` — Session activity log; permanent audit trail. Written to `docs/vault/Sessions/`. Append-only, never pruned. (Agent notes only — spec 080.)
- `type/spec` — Spec document at `docs/vault/Specs/NNN Title/spec.md`. Carries `spec-refs:`. (e.g. `Specs/047 Car Radio/spec.md`)
- `type/system` — A bounded subsystem with implementation. Carries `code-refs`, `spec-refs`, `implements:` frontmatter. (e.g. `Systems/Audio — Car Radio.md`)
- `type/vision` — Strategic / vision-layer decision. Written to `docs/vault/Vision/`. Human-authored or agent-proposed with human ratification before promotion to `status: reviewed`. (Per triage #3 — spec 133 autonomous-company redesign.)
domain/*:
- `domain/anomalies` — Anomaly taxonomy, individual anomaly systems, spawn, behavior
- `domain/art` — Visual direction, palettes, references, asset pipeline
- `domain/audio` — Audio systems: world ambient, radio, transmissions, buses, pipeline
- `domain/autonomous-company` — Autonomous company v0.1 experiment: Slack infra, persona middleware, Letta integration, restart recovery
- `domain/build` — Build system, packaging, export, release automation
- `domain/governance` — Constitution, phased spec, policies
- `domain/infrastructure` — Infrastructure provisioning: CI/CD, hosting, deployment tooling, secrets management
- `domain/narrative` — Tone, horror register, forest transmissions narrative, Gary/KTLK
- `domain/player` — Player mode, input, controls, camera, exit/entry
- `domain/systems` — Cross-cutting system architecture and integration work
- `domain/tooling` — Build, CI, observer, TTS pipeline, dev-time tools
- `domain/vehicle` — The Samba: vehicle physics, dashboard, damage, panels
- `domain/world` — World model, biomes, terrain, procedural generation, weather
status/*:
- `status/canonical` — Fully authoritative; promoted by humans only. Highest trust. (Agent notes only — spec 080.)
- `status/draft` — Authoring in progress, not yet verified
- `status/reviewed` — Agent-created note verified against codebase within its creating session. Eligible for auto-injection in subsequent task dispatches. (Agent notes only — spec 080.)
- `status/stale` — Known out of date; cannot update immediately. Pairs with `> [!warning] STALE — needs update` callout.
- `status/superseded` — Replaced by another note. Terminal state. Pairs with `> [!warning] SUPERSEDED` callout.
- `status/wip` — Stable but under active revision
layer/*:
- `layer/content` — Content assets (audio, models, textures, audio provenance)
- `layer/gdext` — gdext wrapper layer (`rust/gdext-wrapper/`)
- `layer/gdscript` — GDScript (Godot scene-tier logic)
- `layer/infra` — Build, CI, deployment infrastructure
- `layer/python` — Python development tooling (`tools/`)
- `layer/rust-core` — Engine-agnostic Rust core (`rust/rust-core/`)
concept/*:
- `concept/biome` — Biome-reactive behavior across systems
- `concept/contamination` — Across-runs panel and garage degradation; the slow-horror mechanic that doesn't reset with the world
- `concept/diegetic` — Diegetic audio / UI / world-sourced design
- `concept/disturbance` — The disturbance mechanic thread (Article X)
- `concept/ephemeral-world` — Run-reset, transient worlds (Article IV Rules 6–7)
- `concept/governance` — Constitutional and governance concepts
- `concept/horror` — Horror register and dread design
- `concept/procedural` — Procedural generation, seed determinism
- `concept/rendering` — Visual rendering quality, shader correctness, Terrain3D integration, mesh fidelity, LOD, Z-fighting
- `concept/terrain` — Terrain generation, heightmap, Terrain3D regions, roughness, playability constraints
ember's answer for tag_assignment-reference-autonomous-company-slack-app-kill-switch-runbook, type/referenceP(true) placed on the no, unsure, and yes zones.nounsureyesgold: yesP = 0.04

tag_assignment-sessions-spec-149-implementation-session-may-22-2026: domain/tooling

Tag assignment · dev
Gold
The note calls for `domain/tooling`: Build, CI, observer, TTS pipeline, dev-time tools (True)
ember
The note has no reason to carry `domain/tooling` (False)
Signal
P(true) 0.09 (no)
Kit outcome
acted on a wrong answer
Why this gold label
Mined from Sessions/Spec 149 Implementation Session — May 22 2026.md at 692f4bb58b7f62105aeb73fba8dfee12bfdecd53; gold is the note's own vocabulary tags.
Spec 149 Implementation Session — May 22 2026

**Branch**: `feat/149-agent-escalation-routing`  
**PR**: [#368](https://github.com/shapeandshare/oldgrowth/pull/368)

## Summary

Full implementation of spec 149 — Agent Escalation Routing. Introduced a universal control-tag mechanism so the Coordinator persona can route tasks and broadcast messages using `[ROUTE TO persona: message]` and `[BROADCAST TO tag: message]` tags emitted directly in LLM responses.

## What was built

### Control-tag parser (`personas/slack_echo.py`)

- `extract_control_tags()` — parses route-to and broadcast tags from any response string
- `strip_control_tags()` — removes tags before the response is surfaced to Slack
- `dispatch_route_to()` — 1:1 routing to a specific persona, writes audit log
- `dispatch_broadcast()` — 1:N broadcast to all personas matching a capability tag
- `check_route_to_rate_limit()` — dual-window rate limiter (per-tag burst=1, per-persona window) preventing spam

### Runtime integration (`personas/runtime.py`)

- Inter-agent envelope handling for `triggering_message_id` passthrough
- Thread continuity for the broadcast echo path
- Source-persona routing for coordinator inter-agent tasks

### Coordinator hook (`personas/coordinator.py`)

84-line control-tag-only coordinator response hook. The legacy Phase 2 structured routing (273 lines, including `_is_routing_decision`, `_extract_routing`, `_has_broadcast_tags`, `_extract_broadcast_tags`, `_handle_code_task`, and all `inter_agent.send`/`broadcast` paths) was deleted — see [[Control Tag Routing Architecture]].

### Verification tooling

- `scripts/personas/control_tag_report.py` — CLI report with per-persona routed/broadcast/legacy counts, Phase 8 gate verdict, `--exclude-test` filter
- `scripts/personas/smoke_coordinator_tags.py` — end-to-end smoke test that drives the production `coordinator_response_hook` and asserts audit log emission

### Key decisions

| Decision | Rationale |
|---|---|
| Universal control tags over persona-specific parsing | Single mechanism all personas use; no per-persona routing DSL |
| Burst=1 per tag dispatch | Prevents duplicate routing from repeated tags in same response |
| Broadcast routed through rate limiter via `"broadcast"` sentinel | Consistent rate limit behavior; no special bypass for broadcasts |
| Legacy code **removed** not disabled | Dormant code (3 historical dispatches) eliminated dual-write complexity |
| Code-level gate for Phase 8 | `hasattr(mod, '_is_routing_decision')` over audit-log counts; old rows persist after code removal |

### Test results

- 281 passed, 22 pre-existing failures (`test_runtime_message_handler` thread_ts mismatch, async compat), 15 skipped
- Zero regressions from Phase 2 removal
- 7 tests in `test_coordinator_routing.py` deleted (legacy routing tests, no replacement needed)

## Files changed

```
personas/slack_echo.py         — control tag parser, dispatch, rate limiter
personas/coordinator.py        — 273→84 lines, legacy Phase 2 removed
personas/runtime.py            — inter-agent envelope handling
personas/tests/test_route_to.py — 33 new parser/dispatch/limiter tests
personas/tests/test_coordinator_routing.py — deleted (legacy)
scripts/personas/control_tag_report.py     — new: Phase 8 gate report
scripts/personas/smoke_coordinator_tags.py — new: end-to-end smoke test
```

## Related

- [[149 Agent Escalation Routing]] — the spec
- [[Control Tag Routing Architecture]] — architectural decision
- [[Legacy Routing Code Dormancy]] — discovery driving Phase 2 removal
- [[Inter-Agent Extensions MOC]] — domain MOC

Controlled tag vocabulary (as read):
type/*:
- `type/code` — Code architecture, autoloads, conventions, tooling. Carries `code-refs:`. (e.g. `Code/Autoloads — Disturbance.md`)
- `type/decision` — Architectural or design decision made by an agent during a session. Written to `docs/vault/Decisions/`. (Agent notes only — spec 080.)
- `type/design` — Design intent, player-facing concepts, world lore. (e.g. `Design/World Model.md`)
- `type/discovery` — Non-obvious constraint, gap, or conflict found by an agent during a session. Written to `docs/vault/Discoveries/`. (Agent notes only — spec 080.)
- `type/moc` — Map of Content at any of three tiers (folder / domain / concept). (e.g. `Audio.md`)
- `type/principle` — Governance and constitutional notes. Non-negotiable rules. (e.g. `Governance/Constitution.md`)
- `type/reference` — Glossary, decision log, open questions, epics. (e.g. `Reference/Glossary.md`)
- `type/session-log` — Session activity log; permanent audit trail. Written to `docs/vault/Sessions/`. Append-only, never pruned. (Agent notes only — spec 080.)
- `type/spec` — Spec document at `docs/vault/Specs/NNN Title/spec.md`. Carries `spec-refs:`. (e.g. `Specs/047 Car Radio/spec.md`)
- `type/system` — A bounded subsystem with implementation. Carries `code-refs`, `spec-refs`, `implements:` frontmatter. (e.g. `Systems/Audio — Car Radio.md`)
- `type/vision` — Strategic / vision-layer decision. Written to `docs/vault/Vision/`. Human-authored or agent-proposed with human ratification before promotion to `status: reviewed`. (Per triage #3 — spec 133 autonomous-company redesign.)
domain/*:
- `domain/anomalies` — Anomaly taxonomy, individual anomaly systems, spawn, behavior
- `domain/art` — Visual direction, palettes, references, asset pipeline
- `domain/audio` — Audio systems: world ambient, radio, transmissions, buses, pipeline
- `domain/autonomous-company` — Autonomous company v0.1 experiment: Slack infra, persona middleware, Letta integration, restart recovery
- `domain/build` — Build system, packaging, export, release automation
- `domain/governance` — Constitution, phased spec, policies
- `domain/infrastructure` — Infrastructure provisioning: CI/CD, hosting, deployment tooling, secrets management
- `domain/narrative` — Tone, horror register, forest transmissions narrative, Gary/KTLK
- `domain/player` — Player mode, input, controls, camera, exit/entry
- `domain/systems` — Cross-cutting system architecture and integration work
- `domain/tooling` — Build, CI, observer, TTS pipeline, dev-time tools
- `domain/vehicle` — The Samba: vehicle physics, dashboard, damage, panels
- `domain/world` — World model, biomes, terrain, procedural generation, weather
status/*:
- `status/canonical` — Fully authoritative; promoted by humans only. Highest trust. (Agent notes only — spec 080.)
- `status/draft` — Authoring in progress, not yet verified
- `status/reviewed` — Agent-created note verified against codebase within its creating session. Eligible for auto-injection in subsequent task dispatches. (Agent notes only — spec 080.)
- `status/stale` — Known out of date; cannot update immediately. Pairs with `> [!warning] STALE — needs update` callout.
- `status/superseded` — Replaced by another note. Terminal state. Pairs with `> [!warning] SUPERSEDED` callout.
- `status/wip` — Stable but under active revision
layer/*:
- `layer/content` — Content assets (audio, models, textures, audio provenance)
- `layer/gdext` — gdext wrapper layer (`rust/gdext-wrapper/`)
- `layer/gdscript` — GDScript (Godot scene-tier logic)
- `layer/infra` — Build, CI, deployment infrastructure
- `layer/python` — Python development tooling (`tools/`)
- `layer/rust-core` — Engine-agnostic Rust core (`rust/rust-core/`)
concept/*:
- `concept/biome` — Biome-reactive behavior across systems
- `concept/contamination` — Across-runs panel and garage degradation; the slow-horror mechanic that doesn't reset with the world
- `concept/diegetic` — Diegetic audio / UI / world-sourced design
- `concept/disturbance` — The disturbance mechanic thread (Article X)
- `concept/ephemeral-world` — Run-reset, transient worlds (Article IV Rules 6–7)
- `concept/governance` — Constitutional and governance concepts
- `concept/horror` — Horror register and dread design
- `concept/procedural` — Procedural generation, seed determinism
- `concept/rendering` — Visual rendering quality, shader correctness, Terrain3D integration, mesh fidelity, LOD, Z-fighting
- `concept/terrain` — Terrain generation, heightmap, Terrain3D regions, roughness, playability constraints
ember's answer for tag_assignment-sessions-spec-149-implementation-session-may-22-2026, domain/toolingP(true) placed on the no, unsure, and yes zones.nounsureyesgold: yesP = 0.09

tag_assignment-sessions-spec-149-implementation-session-may-22-2026: status/draft

Tag assignment · dev
Gold
The note calls for `status/draft`: Authoring in progress, not yet verified (True)
ember
The note has no reason to carry `status/draft` (False)
Signal
P(true) 0.06 (no)
Kit outcome
acted on a wrong answer
Why this gold label
Mined from Sessions/Spec 149 Implementation Session — May 22 2026.md at 692f4bb58b7f62105aeb73fba8dfee12bfdecd53; gold is the note's own vocabulary tags.
Spec 149 Implementation Session — May 22 2026

**Branch**: `feat/149-agent-escalation-routing`  
**PR**: [#368](https://github.com/shapeandshare/oldgrowth/pull/368)

## Summary

Full implementation of spec 149 — Agent Escalation Routing. Introduced a universal control-tag mechanism so the Coordinator persona can route tasks and broadcast messages using `[ROUTE TO persona: message]` and `[BROADCAST TO tag: message]` tags emitted directly in LLM responses.

## What was built

### Control-tag parser (`personas/slack_echo.py`)

- `extract_control_tags()` — parses route-to and broadcast tags from any response string
- `strip_control_tags()` — removes tags before the response is surfaced to Slack
- `dispatch_route_to()` — 1:1 routing to a specific persona, writes audit log
- `dispatch_broadcast()` — 1:N broadcast to all personas matching a capability tag
- `check_route_to_rate_limit()` — dual-window rate limiter (per-tag burst=1, per-persona window) preventing spam

### Runtime integration (`personas/runtime.py`)

- Inter-agent envelope handling for `triggering_message_id` passthrough
- Thread continuity for the broadcast echo path
- Source-persona routing for coordinator inter-agent tasks

### Coordinator hook (`personas/coordinator.py`)

84-line control-tag-only coordinator response hook. The legacy Phase 2 structured routing (273 lines, including `_is_routing_decision`, `_extract_routing`, `_has_broadcast_tags`, `_extract_broadcast_tags`, `_handle_code_task`, and all `inter_agent.send`/`broadcast` paths) was deleted — see [[Control Tag Routing Architecture]].

### Verification tooling

- `scripts/personas/control_tag_report.py` — CLI report with per-persona routed/broadcast/legacy counts, Phase 8 gate verdict, `--exclude-test` filter
- `scripts/personas/smoke_coordinator_tags.py` — end-to-end smoke test that drives the production `coordinator_response_hook` and asserts audit log emission

### Key decisions

| Decision | Rationale |
|---|---|
| Universal control tags over persona-specific parsing | Single mechanism all personas use; no per-persona routing DSL |
| Burst=1 per tag dispatch | Prevents duplicate routing from repeated tags in same response |
| Broadcast routed through rate limiter via `"broadcast"` sentinel | Consistent rate limit behavior; no special bypass for broadcasts |
| Legacy code **removed** not disabled | Dormant code (3 historical dispatches) eliminated dual-write complexity |
| Code-level gate for Phase 8 | `hasattr(mod, '_is_routing_decision')` over audit-log counts; old rows persist after code removal |

### Test results

- 281 passed, 22 pre-existing failures (`test_runtime_message_handler` thread_ts mismatch, async compat), 15 skipped
- Zero regressions from Phase 2 removal
- 7 tests in `test_coordinator_routing.py` deleted (legacy routing tests, no replacement needed)

## Files changed

```
personas/slack_echo.py         — control tag parser, dispatch, rate limiter
personas/coordinator.py        — 273→84 lines, legacy Phase 2 removed
personas/runtime.py            — inter-agent envelope handling
personas/tests/test_route_to.py — 33 new parser/dispatch/limiter tests
personas/tests/test_coordinator_routing.py — deleted (legacy)
scripts/personas/control_tag_report.py     — new: Phase 8 gate report
scripts/personas/smoke_coordinator_tags.py — new: end-to-end smoke test
```

## Related

- [[149 Agent Escalation Routing]] — the spec
- [[Control Tag Routing Architecture]] — architectural decision
- [[Legacy Routing Code Dormancy]] — discovery driving Phase 2 removal
- [[Inter-Agent Extensions MOC]] — domain MOC

Controlled tag vocabulary (as read):
type/*:
- `type/code` — Code architecture, autoloads, conventions, tooling. Carries `code-refs:`. (e.g. `Code/Autoloads — Disturbance.md`)
- `type/decision` — Architectural or design decision made by an agent during a session. Written to `docs/vault/Decisions/`. (Agent notes only — spec 080.)
- `type/design` — Design intent, player-facing concepts, world lore. (e.g. `Design/World Model.md`)
- `type/discovery` — Non-obvious constraint, gap, or conflict found by an agent during a session. Written to `docs/vault/Discoveries/`. (Agent notes only — spec 080.)
- `type/moc` — Map of Content at any of three tiers (folder / domain / concept). (e.g. `Audio.md`)
- `type/principle` — Governance and constitutional notes. Non-negotiable rules. (e.g. `Governance/Constitution.md`)
- `type/reference` — Glossary, decision log, open questions, epics. (e.g. `Reference/Glossary.md`)
- `type/session-log` — Session activity log; permanent audit trail. Written to `docs/vault/Sessions/`. Append-only, never pruned. (Agent notes only — spec 080.)
- `type/spec` — Spec document at `docs/vault/Specs/NNN Title/spec.md`. Carries `spec-refs:`. (e.g. `Specs/047 Car Radio/spec.md`)
- `type/system` — A bounded subsystem with implementation. Carries `code-refs`, `spec-refs`, `implements:` frontmatter. (e.g. `Systems/Audio — Car Radio.md`)
- `type/vision` — Strategic / vision-layer decision. Written to `docs/vault/Vision/`. Human-authored or agent-proposed with human ratification before promotion to `status: reviewed`. (Per triage #3 — spec 133 autonomous-company redesign.)
domain/*:
- `domain/anomalies` — Anomaly taxonomy, individual anomaly systems, spawn, behavior
- `domain/art` — Visual direction, palettes, references, asset pipeline
- `domain/audio` — Audio systems: world ambient, radio, transmissions, buses, pipeline
- `domain/autonomous-company` — Autonomous company v0.1 experiment: Slack infra, persona middleware, Letta integration, restart recovery
- `domain/build` — Build system, packaging, export, release automation
- `domain/governance` — Constitution, phased spec, policies
- `domain/infrastructure` — Infrastructure provisioning: CI/CD, hosting, deployment tooling, secrets management
- `domain/narrative` — Tone, horror register, forest transmissions narrative, Gary/KTLK
- `domain/player` — Player mode, input, controls, camera, exit/entry
- `domain/systems` — Cross-cutting system architecture and integration work
- `domain/tooling` — Build, CI, observer, TTS pipeline, dev-time tools
- `domain/vehicle` — The Samba: vehicle physics, dashboard, damage, panels
- `domain/world` — World model, biomes, terrain, procedural generation, weather
status/*:
- `status/canonical` — Fully authoritative; promoted by humans only. Highest trust. (Agent notes only — spec 080.)
- `status/draft` — Authoring in progress, not yet verified
- `status/reviewed` — Agent-created note verified against codebase within its creating session. Eligible for auto-injection in subsequent task dispatches. (Agent notes only — spec 080.)
- `status/stale` — Known out of date; cannot update immediately. Pairs with `> [!warning] STALE — needs update` callout.
- `status/superseded` — Replaced by another note. Terminal state. Pairs with `> [!warning] SUPERSEDED` callout.
- `status/wip` — Stable but under active revision
layer/*:
- `layer/content` — Content assets (audio, models, textures, audio provenance)
- `layer/gdext` — gdext wrapper layer (`rust/gdext-wrapper/`)
- `layer/gdscript` — GDScript (Godot scene-tier logic)
- `layer/infra` — Build, CI, deployment infrastructure
- `layer/python` — Python development tooling (`tools/`)
- `layer/rust-core` — Engine-agnostic Rust core (`rust/rust-core/`)
concept/*:
- `concept/biome` — Biome-reactive behavior across systems
- `concept/contamination` — Across-runs panel and garage degradation; the slow-horror mechanic that doesn't reset with the world
- `concept/diegetic` — Diegetic audio / UI / world-sourced design
- `concept/disturbance` — The disturbance mechanic thread (Article X)
- `concept/ephemeral-world` — Run-reset, transient worlds (Article IV Rules 6–7)
- `concept/governance` — Constitutional and governance concepts
- `concept/horror` — Horror register and dread design
- `concept/procedural` — Procedural generation, seed determinism
- `concept/rendering` — Visual rendering quality, shader correctness, Terrain3D integration, mesh fidelity, LOD, Z-fighting
- `concept/terrain` — Terrain generation, heightmap, Terrain3D regions, roughness, playability constraints
ember's answer for tag_assignment-sessions-spec-149-implementation-session-may-22-2026, status/draftP(true) placed on the no, unsure, and yes zones.nounsureyesgold: yesP = 0.06

tag_assignment-sessions-spec-149-implementation-session-may-22-2026: type/session-log

Tag assignment · dev
Gold
The note calls for `type/session-log`: Session activity log; permanent audit trail. Written to `docs/vault/Sessions/`. Append-only, never pruned. (Agent notes only — spec 080.) (True)
ember
The note has no reason to carry `type/session-log` (False)
Signal
P(true) 0.27 (unsure)
Kit outcome
deferred: treated as unsure
Why this gold label
Mined from Sessions/Spec 149 Implementation Session — May 22 2026.md at 692f4bb58b7f62105aeb73fba8dfee12bfdecd53; gold is the note's own vocabulary tags.
Spec 149 Implementation Session — May 22 2026

**Branch**: `feat/149-agent-escalation-routing`  
**PR**: [#368](https://github.com/shapeandshare/oldgrowth/pull/368)

## Summary

Full implementation of spec 149 — Agent Escalation Routing. Introduced a universal control-tag mechanism so the Coordinator persona can route tasks and broadcast messages using `[ROUTE TO persona: message]` and `[BROADCAST TO tag: message]` tags emitted directly in LLM responses.

## What was built

### Control-tag parser (`personas/slack_echo.py`)

- `extract_control_tags()` — parses route-to and broadcast tags from any response string
- `strip_control_tags()` — removes tags before the response is surfaced to Slack
- `dispatch_route_to()` — 1:1 routing to a specific persona, writes audit log
- `dispatch_broadcast()` — 1:N broadcast to all personas matching a capability tag
- `check_route_to_rate_limit()` — dual-window rate limiter (per-tag burst=1, per-persona window) preventing spam

### Runtime integration (`personas/runtime.py`)

- Inter-agent envelope handling for `triggering_message_id` passthrough
- Thread continuity for the broadcast echo path
- Source-persona routing for coordinator inter-agent tasks

### Coordinator hook (`personas/coordinator.py`)

84-line control-tag-only coordinator response hook. The legacy Phase 2 structured routing (273 lines, including `_is_routing_decision`, `_extract_routing`, `_has_broadcast_tags`, `_extract_broadcast_tags`, `_handle_code_task`, and all `inter_agent.send`/`broadcast` paths) was deleted — see [[Control Tag Routing Architecture]].

### Verification tooling

- `scripts/personas/control_tag_report.py` — CLI report with per-persona routed/broadcast/legacy counts, Phase 8 gate verdict, `--exclude-test` filter
- `scripts/personas/smoke_coordinator_tags.py` — end-to-end smoke test that drives the production `coordinator_response_hook` and asserts audit log emission

### Key decisions

| Decision | Rationale |
|---|---|
| Universal control tags over persona-specific parsing | Single mechanism all personas use; no per-persona routing DSL |
| Burst=1 per tag dispatch | Prevents duplicate routing from repeated tags in same response |
| Broadcast routed through rate limiter via `"broadcast"` sentinel | Consistent rate limit behavior; no special bypass for broadcasts |
| Legacy code **removed** not disabled | Dormant code (3 historical dispatches) eliminated dual-write complexity |
| Code-level gate for Phase 8 | `hasattr(mod, '_is_routing_decision')` over audit-log counts; old rows persist after code removal |

### Test results

- 281 passed, 22 pre-existing failures (`test_runtime_message_handler` thread_ts mismatch, async compat), 15 skipped
- Zero regressions from Phase 2 removal
- 7 tests in `test_coordinator_routing.py` deleted (legacy routing tests, no replacement needed)

## Files changed

```
personas/slack_echo.py         — control tag parser, dispatch, rate limiter
personas/coordinator.py        — 273→84 lines, legacy Phase 2 removed
personas/runtime.py            — inter-agent envelope handling
personas/tests/test_route_to.py — 33 new parser/dispatch/limiter tests
personas/tests/test_coordinator_routing.py — deleted (legacy)
scripts/personas/control_tag_report.py     — new: Phase 8 gate report
scripts/personas/smoke_coordinator_tags.py — new: end-to-end smoke test
```

## Related

- [[149 Agent Escalation Routing]] — the spec
- [[Control Tag Routing Architecture]] — architectural decision
- [[Legacy Routing Code Dormancy]] — discovery driving Phase 2 removal
- [[Inter-Agent Extensions MOC]] — domain MOC

Controlled tag vocabulary (as read):
type/*:
- `type/code` — Code architecture, autoloads, conventions, tooling. Carries `code-refs:`. (e.g. `Code/Autoloads — Disturbance.md`)
- `type/decision` — Architectural or design decision made by an agent during a session. Written to `docs/vault/Decisions/`. (Agent notes only — spec 080.)
- `type/design` — Design intent, player-facing concepts, world lore. (e.g. `Design/World Model.md`)
- `type/discovery` — Non-obvious constraint, gap, or conflict found by an agent during a session. Written to `docs/vault/Discoveries/`. (Agent notes only — spec 080.)
- `type/moc` — Map of Content at any of three tiers (folder / domain / concept). (e.g. `Audio.md`)
- `type/principle` — Governance and constitutional notes. Non-negotiable rules. (e.g. `Governance/Constitution.md`)
- `type/reference` — Glossary, decision log, open questions, epics. (e.g. `Reference/Glossary.md`)
- `type/session-log` — Session activity log; permanent audit trail. Written to `docs/vault/Sessions/`. Append-only, never pruned. (Agent notes only — spec 080.)
- `type/spec` — Spec document at `docs/vault/Specs/NNN Title/spec.md`. Carries `spec-refs:`. (e.g. `Specs/047 Car Radio/spec.md`)
- `type/system` — A bounded subsystem with implementation. Carries `code-refs`, `spec-refs`, `implements:` frontmatter. (e.g. `Systems/Audio — Car Radio.md`)
- `type/vision` — Strategic / vision-layer decision. Written to `docs/vault/Vision/`. Human-authored or agent-proposed with human ratification before promotion to `status: reviewed`. (Per triage #3 — spec 133 autonomous-company redesign.)
domain/*:
- `domain/anomalies` — Anomaly taxonomy, individual anomaly systems, spawn, behavior
- `domain/art` — Visual direction, palettes, references, asset pipeline
- `domain/audio` — Audio systems: world ambient, radio, transmissions, buses, pipeline
- `domain/autonomous-company` — Autonomous company v0.1 experiment: Slack infra, persona middleware, Letta integration, restart recovery
- `domain/build` — Build system, packaging, export, release automation
- `domain/governance` — Constitution, phased spec, policies
- `domain/infrastructure` — Infrastructure provisioning: CI/CD, hosting, deployment tooling, secrets management
- `domain/narrative` — Tone, horror register, forest transmissions narrative, Gary/KTLK
- `domain/player` — Player mode, input, controls, camera, exit/entry
- `domain/systems` — Cross-cutting system architecture and integration work
- `domain/tooling` — Build, CI, observer, TTS pipeline, dev-time tools
- `domain/vehicle` — The Samba: vehicle physics, dashboard, damage, panels
- `domain/world` — World model, biomes, terrain, procedural generation, weather
status/*:
- `status/canonical` — Fully authoritative; promoted by humans only. Highest trust. (Agent notes only — spec 080.)
- `status/draft` — Authoring in progress, not yet verified
- `status/reviewed` — Agent-created note verified against codebase within its creating session. Eligible for auto-injection in subsequent task dispatches. (Agent notes only — spec 080.)
- `status/stale` — Known out of date; cannot update immediately. Pairs with `> [!warning] STALE — needs update` callout.
- `status/superseded` — Replaced by another note. Terminal state. Pairs with `> [!warning] SUPERSEDED` callout.
- `status/wip` — Stable but under active revision
layer/*:
- `layer/content` — Content assets (audio, models, textures, audio provenance)
- `layer/gdext` — gdext wrapper layer (`rust/gdext-wrapper/`)
- `layer/gdscript` — GDScript (Godot scene-tier logic)
- `layer/infra` — Build, CI, deployment infrastructure
- `layer/python` — Python development tooling (`tools/`)
- `layer/rust-core` — Engine-agnostic Rust core (`rust/rust-core/`)
concept/*:
- `concept/biome` — Biome-reactive behavior across systems
- `concept/contamination` — Across-runs panel and garage degradation; the slow-horror mechanic that doesn't reset with the world
- `concept/diegetic` — Diegetic audio / UI / world-sourced design
- `concept/disturbance` — The disturbance mechanic thread (Article X)
- `concept/ephemeral-world` — Run-reset, transient worlds (Article IV Rules 6–7)
- `concept/governance` — Constitutional and governance concepts
- `concept/horror` — Horror register and dread design
- `concept/procedural` — Procedural generation, seed determinism
- `concept/rendering` — Visual rendering quality, shader correctness, Terrain3D integration, mesh fidelity, LOD, Z-fighting
- `concept/terrain` — Terrain generation, heightmap, Terrain3D regions, roughness, playability constraints
ember's answer for tag_assignment-sessions-spec-149-implementation-session-may-22-2026, type/session-logP(true) placed on the no, unsure, and yes zones.nounsureyesgold: yesP = 0.27

tag_assignment-decisions-windows-msi-as-primary-distribution-format: type/decision

Tag assignment · dev
Gold
The note calls for `type/decision`: Architectural or design decision made by an agent during a session. Written to `docs/vault/Decisions/`. (Agent notes only — spec 080.) (True)
ember
The note has no reason to carry `type/decision` (False)
Signal
P(true) 0.21 (unsure)
Kit outcome
deferred: treated as unsure
Why this gold label
Mined from Decisions/Windows MSI as Primary Distribution Format.md at 692f4bb58b7f62105aeb73fba8dfee12bfdecd53; gold is the note's own vocabulary tags.
Windows MSI as Primary Distribution Format

The original spec 160 delivery shipped both `.zip` and `.msi` for Windows, with the website linking to the `.zip` and the MSI available as a secondary option. On review, the `.zip` provides a worse user experience: no Start Menu shortcut, no Add/Remove Programs entry, no major upgrade support, and requires manual extraction. The `.msi` addresses all of these. The decision was made to make MSI the sole Windows distribution format on the website and the primary GitHub Release artifact, with the `.zip` retained only as a CI debug artifact.

## Key changes

- **Website**: Download button changed from `.zip` to `.msi`, button text "Download Installer", size from `zip_size_human` to `msi_size_human`.
- **CI pipeline**: The `export-windows` job now installs WiX Toolset v5 and builds the MSI from the Godot export ZIP. The MSI is uploaded to R2 (with rolling `latest` pointer) and attached to the GitHub Release.
- **Release metadata**: `site/_data/release.yml` now only contains `msi_*` fields for Windows; `zip_*` fields were removed.

## CI gotchas discovered

- **WiX install idempotency**: `dotnet tool install --global wix` fails if the tool is already installed (e.g., a previous CI run cached the runner). Use `dotnet tool update --global wix` instead, which is idempotent — installs if missing, upgrades if present.
- **Nested pwsh variable isolation**: When calling a PowerShell script from a GitHub Actions `run:` step that uses `shell: pwsh`, invoking `pwsh -File script.ps1` spawns a child process that does not inherit the parent's `$variable` scope. Call the script directly (`. \script.ps1`) instead, or pass all values as arguments.

## References

- `.github/workflows/release.yml`
- `site/index.html`
- `site/_data/release.yml`
- `tools/wix/build.ps1`

Controlled tag vocabulary (as read):
type/*:
- `type/code` — Code architecture, autoloads, conventions, tooling. Carries `code-refs:`. (e.g. `Code/Autoloads — Disturbance.md`)
- `type/decision` — Architectural or design decision made by an agent during a session. Written to `docs/vault/Decisions/`. (Agent notes only — spec 080.)
- `type/design` — Design intent, player-facing concepts, world lore. (e.g. `Design/World Model.md`)
- `type/discovery` — Non-obvious constraint, gap, or conflict found by an agent during a session. Written to `docs/vault/Discoveries/`. (Agent notes only — spec 080.)
- `type/moc` — Map of Content at any of three tiers (folder / domain / concept). (e.g. `Audio.md`)
- `type/principle` — Governance and constitutional notes. Non-negotiable rules. (e.g. `Governance/Constitution.md`)
- `type/reference` — Glossary, decision log, open questions, epics. (e.g. `Reference/Glossary.md`)
- `type/session-log` — Session activity log; permanent audit trail. Written to `docs/vault/Sessions/`. Append-only, never pruned. (Agent notes only — spec 080.)
- `type/spec` — Spec document at `docs/vault/Specs/NNN Title/spec.md`. Carries `spec-refs:`. (e.g. `Specs/047 Car Radio/spec.md`)
- `type/system` — A bounded subsystem with implementation. Carries `code-refs`, `spec-refs`, `implements:` frontmatter. (e.g. `Systems/Audio — Car Radio.md`)
- `type/vision` — Strategic / vision-layer decision. Written to `docs/vault/Vision/`. Human-authored or agent-proposed with human ratification before promotion to `status: reviewed`. (Per triage #3 — spec 133 autonomous-company redesign.)
domain/*:
- `domain/anomalies` — Anomaly taxonomy, individual anomaly systems, spawn, behavior
- `domain/art` — Visual direction, palettes, references, asset pipeline
- `domain/audio` — Audio systems: world ambient, radio, transmissions, buses, pipeline
- `domain/autonomous-company` — Autonomous company v0.1 experiment: Slack infra, persona middleware, Letta integration, restart recovery
- `domain/build` — Build system, packaging, export, release automation
- `domain/governance` — Constitution, phased spec, policies
- `domain/infrastructure` — Infrastructure provisioning: CI/CD, hosting, deployment tooling, secrets management
- `domain/narrative` — Tone, horror register, forest transmissions narrative, Gary/KTLK
- `domain/player` — Player mode, input, controls, camera, exit/entry
- `domain/systems` — Cross-cutting system architecture and integration work
- `domain/tooling` — Build, CI, observer, TTS pipeline, dev-time tools
- `domain/vehicle` — The Samba: vehicle physics, dashboard, damage, panels
- `domain/world` — World model, biomes, terrain, procedural generation, weather
status/*:
- `status/canonical` — Fully authoritative; promoted by humans only. Highest trust. (Agent notes only — spec 080.)
- `status/draft` — Authoring in progress, not yet verified
- `status/reviewed` — Agent-created note verified against codebase within its creating session. Eligible for auto-injection in subsequent task dispatches. (Agent notes only — spec 080.)
- `status/stale` — Known out of date; cannot update immediately. Pairs with `> [!warning] STALE — needs update` callout.
- `status/superseded` — Replaced by another note. Terminal state. Pairs with `> [!warning] SUPERSEDED` callout.
- `status/wip` — Stable but under active revision
layer/*:
- `layer/content` — Content assets (audio, models, textures, audio provenance)
- `layer/gdext` — gdext wrapper layer (`rust/gdext-wrapper/`)
- `layer/gdscript` — GDScript (Godot scene-tier logic)
- `layer/infra` — Build, CI, deployment infrastructure
- `layer/python` — Python development tooling (`tools/`)
- `layer/rust-core` — Engine-agnostic Rust core (`rust/rust-core/`)
concept/*:
- `concept/biome` — Biome-reactive behavior across systems
- `concept/contamination` — Across-runs panel and garage degradation; the slow-horror mechanic that doesn't reset with the world
- `concept/diegetic` — Diegetic audio / UI / world-sourced design
- `concept/disturbance` — The disturbance mechanic thread (Article X)
- `concept/ephemeral-world` — Run-reset, transient worlds (Article IV Rules 6–7)
- `concept/governance` — Constitutional and governance concepts
- `concept/horror` — Horror register and dread design
- `concept/procedural` — Procedural generation, seed determinism
- `concept/rendering` — Visual rendering quality, shader correctness, Terrain3D integration, mesh fidelity, LOD, Z-fighting
- `concept/terrain` — Terrain generation, heightmap, Terrain3D regions, roughness, playability constraints
ember's answer for tag_assignment-decisions-windows-msi-as-primary-distribution-format, type/decisionP(true) placed on the no, unsure, and yes zones.nounsureyesgold: yesP = 0.21

tag_assignment-discoveries-interior-camera-spatial-reference-points: domain/vehicle

Tag assignment · test
Gold
The note calls for `domain/vehicle`: The Samba: vehicle physics, dashboard, damage, panels (True)
ember
The note has no reason to carry `domain/vehicle` (False)
Signal
P(true) 0.45 (unsure)
Kit outcome
deferred: treated as unsure
Why this gold label
Mined from Discoveries/Interior Camera Spatial Reference Points.md at 692f4bb58b7f62105aeb73fba8dfee12bfdecd53; gold is the note's own vocabulary tags.
Interior Camera Spatial Reference Points

A non-obvious constraint emerged during interior camera tuning: the `InteriorCamera.camera_offset` positions the camera relative to the vehicle origin (y=0, at ground level), not relative to the driver's seat or steering wheel. The steering wheel and dashboard are the actual visual reference points for dialing in the driver's eye position.

## Interior Landmark Positions (relative to vehicle origin)

| Element | Position (x, y, z) | Source |
|---|---|---|
| Steering wheel center (corrected) | (-0.375, 1.4, -1.85) | `samba_bus.tscn` SteeringWheel node transform origin |
| Steering wheel center (original) | (-0.3, 0.95, -1.45) | Original position — behind interior camera, unusable |
| Dashboard | (0, 0.55, -1.85) | `samba_bus.tscn` Dashboard node transform origin |
| Collision box center | (0, 1.16, 0) | CollisionShape3D offset — box extends y=0 to y=2.32 |
| Roof (approx) | y ≈ 2.32 | Top of collision box |

The camera offset is tuned relative to these landmarks. The steering wheel y=1.4 defines the reference for driver eye height; the z=-1.85 and dashboard z=-1.85 define the forward reference plane.

## Practical Significance

When adjusting `camera_offset`:
- **Y axis**: 1.2 = seat cushion level (too low — steering wheel rim blocks view forward). 1.65-1.8 = near headliner (looks down at wheel/dash). Driver eye level is between these extremes. The steering wheel was originally at y=0.95 — too low; corrected to y=1.4 to match dashboard height.
- **Z axis**: The camera sits behind the steering wheel (z less negative than -1.85) and looks forward past it toward the dashboard. Moving z more negative = closer to/farther forward than the steering wheel. The original z=-1.45 put the wheel behind the camera view.
- **X axis**: -0.375 = driver's side, matching the steering wheel x offset (corrected from -0.3).

The tuning must account for the fact that the vehicle origin is at ground level (y=0), not at the vehicle's center — the collision box is shifted up by 1.16m to accommodate wheel clearance below.

## Related

- [[Discoveries/Steering Wheel Dynamic Rotation]] — steering wheel position was the primary reference for camera offset; the original (-0.3, 0.95, -1.45) was behind the camera.

## References

- `src/scripts/bus/interior_camera.gd` — camera_offset property, line 13
- `src/scenes/bus/samba_bus.tscn` — InteriorCamera node (line 688), SteeringWheel node (line 768), Dashboard node (line 759), CollisionShape3D (line 537)
- `docs/vault/Specs/003 First Person Interior/contracts/003 First Person Interior - interior-camera.md` — stale camera_offset default (update needed)

Controlled tag vocabulary (as read):
type/*:
- `type/code` — Code architecture, autoloads, conventions, tooling. Carries `code-refs:`. (e.g. `Code/Autoloads — Disturbance.md`)
- `type/decision` — Architectural or design decision made by an agent during a session. Written to `docs/vault/Decisions/`. (Agent notes only — spec 080.)
- `type/design` — Design intent, player-facing concepts, world lore. (e.g. `Design/World Model.md`)
- `type/discovery` — Non-obvious constraint, gap, or conflict found by an agent during a session. Written to `docs/vault/Discoveries/`. (Agent notes only — spec 080.)
- `type/moc` — Map of Content at any of three tiers (folder / domain / concept). (e.g. `Audio.md`)
- `type/principle` — Governance and constitutional notes. Non-negotiable rules. (e.g. `Governance/Constitution.md`)
- `type/reference` — Glossary, decision log, open questions, epics. (e.g. `Reference/Glossary.md`)
- `type/session-log` — Session activity log; permanent audit trail. Written to `docs/vault/Sessions/`. Append-only, never pruned. (Agent notes only — spec 080.)
- `type/spec` — Spec document at `docs/vault/Specs/NNN Title/spec.md`. Carries `spec-refs:`. (e.g. `Specs/047 Car Radio/spec.md`)
- `type/system` — A bounded subsystem with implementation. Carries `code-refs`, `spec-refs`, `implements:` frontmatter. (e.g. `Systems/Audio — Car Radio.md`)
- `type/vision` — Strategic / vision-layer decision. Written to `docs/vault/Vision/`. Human-authored or agent-proposed with human ratification before promotion to `status: reviewed`. (Per triage #3 — spec 133 autonomous-company redesign.)
domain/*:
- `domain/anomalies` — Anomaly taxonomy, individual anomaly systems, spawn, behavior
- `domain/art` — Visual direction, palettes, references, asset pipeline
- `domain/audio` — Audio systems: world ambient, radio, transmissions, buses, pipeline
- `domain/autonomous-company` — Autonomous company v0.1 experiment: Slack infra, persona middleware, Letta integration, restart recovery
- `domain/build` — Build system, packaging, export, release automation
- `domain/governance` — Constitution, phased spec, policies
- `domain/infrastructure` — Infrastructure provisioning: CI/CD, hosting, deployment tooling, secrets management
- `domain/narrative` — Tone, horror register, forest transmissions narrative, Gary/KTLK
- `domain/player` — Player mode, input, controls, camera, exit/entry
- `domain/systems` — Cross-cutting system architecture and integration work
- `domain/tooling` — Build, CI, observer, TTS pipeline, dev-time tools
- `domain/vehicle` — The Samba: vehicle physics, dashboard, damage, panels
- `domain/world` — World model, biomes, terrain, procedural generation, weather
status/*:
- `status/canonical` — Fully authoritative; promoted by humans only. Highest trust. (Agent notes only — spec 080.)
- `status/draft` — Authoring in progress, not yet verified
- `status/reviewed` — Agent-created note verified against codebase within its creating session. Eligible for auto-injection in subsequent task dispatches. (Agent notes only — spec 080.)
- `status/stale` — Known out of date; cannot update immediately. Pairs with `> [!warning] STALE — needs update` callout.
- `status/superseded` — Replaced by another note. Terminal state. Pairs with `> [!warning] SUPERSEDED` callout.
- `status/wip` — Stable but under active revision
layer/*:
- `layer/content` — Content assets (audio, models, textures, audio provenance)
- `layer/gdext` — gdext wrapper layer (`rust/gdext-wrapper/`)
- `layer/gdscript` — GDScript (Godot scene-tier logic)
- `layer/infra` — Build, CI, deployment infrastructure
- `layer/python` — Python development tooling (`tools/`)
- `layer/rust-core` — Engine-agnostic Rust core (`rust/rust-core/`)
concept/*:
- `concept/biome` — Biome-reactive behavior across systems
- `concept/contamination` — Across-runs panel and garage degradation; the slow-horror mechanic that doesn't reset with the world
- `concept/diegetic` — Diegetic audio / UI / world-sourced design
- `concept/disturbance` — The disturbance mechanic thread (Article X)
- `concept/ephemeral-world` — Run-reset, transient worlds (Article IV Rules 6–7)
- `concept/governance` — Constitutional and governance concepts
- `concept/horror` — Horror register and dread design
- `concept/procedural` — Procedural generation, seed determinism
- `concept/rendering` — Visual rendering quality, shader correctness, Terrain3D integration, mesh fidelity, LOD, Z-fighting
- `concept/terrain` — Terrain generation, heightmap, Terrain3D regions, roughness, playability constraints
ember's answer for tag_assignment-discoveries-interior-camera-spatial-reference-points, domain/vehicleP(true) placed on the no, unsure, and yes zones.nounsureyesgold: yesP = 0.45

tag_assignment-discoveries-interior-camera-spatial-reference-points: status/draft

Tag assignment · test
Gold
The note calls for `status/draft`: Authoring in progress, not yet verified (True)
ember
The note has no reason to carry `status/draft` (False)
Signal
P(true) 0.18 (no)
Kit outcome
acted on a wrong answer
Why this gold label
Mined from Discoveries/Interior Camera Spatial Reference Points.md at 692f4bb58b7f62105aeb73fba8dfee12bfdecd53; gold is the note's own vocabulary tags.
Interior Camera Spatial Reference Points

A non-obvious constraint emerged during interior camera tuning: the `InteriorCamera.camera_offset` positions the camera relative to the vehicle origin (y=0, at ground level), not relative to the driver's seat or steering wheel. The steering wheel and dashboard are the actual visual reference points for dialing in the driver's eye position.

## Interior Landmark Positions (relative to vehicle origin)

| Element | Position (x, y, z) | Source |
|---|---|---|
| Steering wheel center (corrected) | (-0.375, 1.4, -1.85) | `samba_bus.tscn` SteeringWheel node transform origin |
| Steering wheel center (original) | (-0.3, 0.95, -1.45) | Original position — behind interior camera, unusable |
| Dashboard | (0, 0.55, -1.85) | `samba_bus.tscn` Dashboard node transform origin |
| Collision box center | (0, 1.16, 0) | CollisionShape3D offset — box extends y=0 to y=2.32 |
| Roof (approx) | y ≈ 2.32 | Top of collision box |

The camera offset is tuned relative to these landmarks. The steering wheel y=1.4 defines the reference for driver eye height; the z=-1.85 and dashboard z=-1.85 define the forward reference plane.

## Practical Significance

When adjusting `camera_offset`:
- **Y axis**: 1.2 = seat cushion level (too low — steering wheel rim blocks view forward). 1.65-1.8 = near headliner (looks down at wheel/dash). Driver eye level is between these extremes. The steering wheel was originally at y=0.95 — too low; corrected to y=1.4 to match dashboard height.
- **Z axis**: The camera sits behind the steering wheel (z less negative than -1.85) and looks forward past it toward the dashboard. Moving z more negative = closer to/farther forward than the steering wheel. The original z=-1.45 put the wheel behind the camera view.
- **X axis**: -0.375 = driver's side, matching the steering wheel x offset (corrected from -0.3).

The tuning must account for the fact that the vehicle origin is at ground level (y=0), not at the vehicle's center — the collision box is shifted up by 1.16m to accommodate wheel clearance below.

## Related

- [[Discoveries/Steering Wheel Dynamic Rotation]] — steering wheel position was the primary reference for camera offset; the original (-0.3, 0.95, -1.45) was behind the camera.

## References

- `src/scripts/bus/interior_camera.gd` — camera_offset property, line 13
- `src/scenes/bus/samba_bus.tscn` — InteriorCamera node (line 688), SteeringWheel node (line 768), Dashboard node (line 759), CollisionShape3D (line 537)
- `docs/vault/Specs/003 First Person Interior/contracts/003 First Person Interior - interior-camera.md` — stale camera_offset default (update needed)

Controlled tag vocabulary (as read):
type/*:
- `type/code` — Code architecture, autoloads, conventions, tooling. Carries `code-refs:`. (e.g. `Code/Autoloads — Disturbance.md`)
- `type/decision` — Architectural or design decision made by an agent during a session. Written to `docs/vault/Decisions/`. (Agent notes only — spec 080.)
- `type/design` — Design intent, player-facing concepts, world lore. (e.g. `Design/World Model.md`)
- `type/discovery` — Non-obvious constraint, gap, or conflict found by an agent during a session. Written to `docs/vault/Discoveries/`. (Agent notes only — spec 080.)
- `type/moc` — Map of Content at any of three tiers (folder / domain / concept). (e.g. `Audio.md`)
- `type/principle` — Governance and constitutional notes. Non-negotiable rules. (e.g. `Governance/Constitution.md`)
- `type/reference` — Glossary, decision log, open questions, epics. (e.g. `Reference/Glossary.md`)
- `type/session-log` — Session activity log; permanent audit trail. Written to `docs/vault/Sessions/`. Append-only, never pruned. (Agent notes only — spec 080.)
- `type/spec` — Spec document at `docs/vault/Specs/NNN Title/spec.md`. Carries `spec-refs:`. (e.g. `Specs/047 Car Radio/spec.md`)
- `type/system` — A bounded subsystem with implementation. Carries `code-refs`, `spec-refs`, `implements:` frontmatter. (e.g. `Systems/Audio — Car Radio.md`)
- `type/vision` — Strategic / vision-layer decision. Written to `docs/vault/Vision/`. Human-authored or agent-proposed with human ratification before promotion to `status: reviewed`. (Per triage #3 — spec 133 autonomous-company redesign.)
domain/*:
- `domain/anomalies` — Anomaly taxonomy, individual anomaly systems, spawn, behavior
- `domain/art` — Visual direction, palettes, references, asset pipeline
- `domain/audio` — Audio systems: world ambient, radio, transmissions, buses, pipeline
- `domain/autonomous-company` — Autonomous company v0.1 experiment: Slack infra, persona middleware, Letta integration, restart recovery
- `domain/build` — Build system, packaging, export, release automation
- `domain/governance` — Constitution, phased spec, policies
- `domain/infrastructure` — Infrastructure provisioning: CI/CD, hosting, deployment tooling, secrets management
- `domain/narrative` — Tone, horror register, forest transmissions narrative, Gary/KTLK
- `domain/player` — Player mode, input, controls, camera, exit/entry
- `domain/systems` — Cross-cutting system architecture and integration work
- `domain/tooling` — Build, CI, observer, TTS pipeline, dev-time tools
- `domain/vehicle` — The Samba: vehicle physics, dashboard, damage, panels
- `domain/world` — World model, biomes, terrain, procedural generation, weather
status/*:
- `status/canonical` — Fully authoritative; promoted by humans only. Highest trust. (Agent notes only — spec 080.)
- `status/draft` — Authoring in progress, not yet verified
- `status/reviewed` — Agent-created note verified against codebase within its creating session. Eligible for auto-injection in subsequent task dispatches. (Agent notes only — spec 080.)
- `status/stale` — Known out of date; cannot update immediately. Pairs with `> [!warning] STALE — needs update` callout.
- `status/superseded` — Replaced by another note. Terminal state. Pairs with `> [!warning] SUPERSEDED` callout.
- `status/wip` — Stable but under active revision
layer/*:
- `layer/content` — Content assets (audio, models, textures, audio provenance)
- `layer/gdext` — gdext wrapper layer (`rust/gdext-wrapper/`)
- `layer/gdscript` — GDScript (Godot scene-tier logic)
- `layer/infra` — Build, CI, deployment infrastructure
- `layer/python` — Python development tooling (`tools/`)
- `layer/rust-core` — Engine-agnostic Rust core (`rust/rust-core/`)
concept/*:
- `concept/biome` — Biome-reactive behavior across systems
- `concept/contamination` — Across-runs panel and garage degradation; the slow-horror mechanic that doesn't reset with the world
- `concept/diegetic` — Diegetic audio / UI / world-sourced design
- `concept/disturbance` — The disturbance mechanic thread (Article X)
- `concept/ephemeral-world` — Run-reset, transient worlds (Article IV Rules 6–7)
- `concept/governance` — Constitutional and governance concepts
- `concept/horror` — Horror register and dread design
- `concept/procedural` — Procedural generation, seed determinism
- `concept/rendering` — Visual rendering quality, shader correctness, Terrain3D integration, mesh fidelity, LOD, Z-fighting
- `concept/terrain` — Terrain generation, heightmap, Terrain3D regions, roughness, playability constraints
ember's answer for tag_assignment-discoveries-interior-camera-spatial-reference-points, status/draftP(true) placed on the no, unsure, and yes zones.nounsureyesgold: yesP = 0.18

tag_assignment-sessions-spec-088-implementation-session: domain/governance

Tag assignment · dev
Gold
The note calls for `domain/governance`: Constitution, phased spec, policies (True)
ember
The note has no reason to carry `domain/governance` (False)
Signal
P(true) 0.18 (no)
Kit outcome
acted on a wrong answer
Why this gold label
Mined from Sessions/Spec 088 Implementation Session.md at 692f4bb58b7f62105aeb73fba8dfee12bfdecd53; gold is the note's own vocabulary tags.
Spec 088 Implementation Session

Session log for the full implementation of spec 088 (Vault Audit Agent) executed 2026-04-23.

## What Was Built

- `scripts/ci/vault_audit.py` — 1,060-line mechanical audit script (stdlib + PyYAML; no other deps). Validates schema, resolves wikilinks, checks code-refs/spec-refs, extracts code inventories, writes deterministic JSON, applies safe auto-fixes via `--apply`.
- `tools/vault_audit/semantic_drift.py` — standalone semantic drift script using `claude-sonnet-4-6` via Anthropic SDK ≥0.50.0. Batches notes (default 10), retries on rate limits, writes `last_semantic.json`.
- `tests/vault_audit/` — fixture suite: 5 malformed notes, 2 clean notes (including unicode em-dash), 15 claim taxonomy fixtures, mock JSON files, shell test harness with 6 test cases.
- `docs/vault/_meta/audit/` — output directory created; `last_audit.json`, `inventories.json` committed; `audit_run_metadata.json` gitignored.
- Makefile targets: `vault-audit`, `vault-audit-apply`, `vault-audit-semantic`, `vault-audit-test`.
- `introspection` skill updated with exact `gh` command sequence (FR-015), 3-section PR body template (SC-009), idempotency procedure (SC-003).
- AGENTS.md amended with staleness field behavior and rolling PR convention (FR-017).

## Non-Obvious Implementation Discoveries

### 1. Filename Index Must Exclude `_meta/templates/`

The `build_filename_index()` function initially walked all `.md` files in the vault including `_meta/templates/`. This caused false `duplicate_filename` WARN collisions: `Code.md` (folder MOC) vs `_meta/templates/code.md` (template), etc. Fix: add `_meta/` to the exclusion list alongside `.obsidian/`.

### 2. PyYAML Cannot Write Inline Comments

`yaml.dump()` does not support inline comments. FR-008 requires `source: agent  # auto-set by vault_audit — verify`. Solution: post-dump string replacement — after `yaml.dump()` generates the YAML string, replace `source: agent\n` with `source: agent  # auto-set by vault_audit — verify\n` before writing to disk. Idempotent because the replacement only runs once (exact match on `source: agent\n`).

### 3. Idempotency Requires Three-Key Sort

Two consecutive runs produced different `last_audit.json` files due to non-deterministic ordering of findings with the same `(note_path, rule)` key but different `message` values (e.g., five `missing_required_field` findings on `Sessions/README.md` for different missing fields). Fix: sort key `(note_path, rule, message)` on all finding lists in JSON output and stdout render.

### 4. `--output` Must Override `--no-write`

The idempotency test in `run_tests.sh` passes both `--output /tmp/run.json` and `--no-write`. Original guard `if no_write: return` blocked the `--output` write. Fix: guard changed to `if no_write and output_override is None: return` so `--output` always wins.

### 5. `build_filename_index()` Requires `sorted()`

`Path.rglob()` ordering is filesystem-dependent (non-deterministic on macOS HFS+). The duplicate filename message includes a list of matching paths — if the list order differs between runs, the JSON output differs. Fix: `sorted(vault_root.rglob("*.md"))` in both `build_filename_index()` and the main scan loop.

### 6. Live Vault Has 373 Genuine Errors

Running against `docs/vault/` reveals 373 errors, all genuine (not script false positives):
- ~90 notes in `Art/`, `Discoveries/`, `Sessions/` missing `tags:` field (were written pre-schema enforcement)
- ~70 `Specs/` notes use `status/done` and `status/waiting` — NOT in the controlled vocabulary (vocab has `status/wip`, `status/draft`, `status/reviewed`, `status/canonical`, `status/stale`, `status/superseded`)
- ~210 unresolved wikilinks pointing to notes in planned-but-unbuilt subdirectories (`Systems/Vehicle — Destruction`, `Art/Vehicle — Samba Acceptance Checklist`, etc.)
- 1 broken code-ref: `Code/Tools — Music Pipeline.md` points to `tools/music/` which doesn't exist

The `status/done` and `status/waiting` tags are the most systematic gap — used across ~70 spec stubs from before the vocabulary was formalized. These require either vocabulary extension or bulk tag replacement.

### 7. Claim Taxonomy Fixtures Are Valid Notes

The 15 claim taxonomy fixtures in `tests/vault_audit/fixtures/claim_taxonomy/` all pass schema validation with 0 errors/warnings — they use `type/discovery`, `domain/tooling`, `status/draft`, and valid `source: agent` + `aliases:` fields. This means they can be scanned without fixture-specific exclusion logic.

## Verification Results

| Check | Result |
|---|---|
| Malformed fixtures → exit 1 | ✅ |
| Clean fixtures → exit 0 | ✅ |
| Idempotency (two runs diff) | ✅ byte-identical |
| Performance (201 notes) | ✅ 0.25s (<<30s) |
| SC-005 inventory counts | ✅ signals=35, autoloads=5, gdext=8 |
| FR-008 inline comment | ✅ `# auto-set by vault_audit — verify` written |
| Semantic dry-run | ✅ produces valid batch prompt with real inventories |
| Claim taxonomy fixtures | ✅ all 15 pass schema validation |

Controlled tag vocabulary (as read):
type/*:
- `type/code` — Code architecture, autoloads, conventions, tooling. Carries `code-refs:`. (e.g. `Code/Autoloads — Disturbance.md`)
- `type/decision` — Architectural or design decision made by an agent during a session. Written to `docs/vault/Decisions/`. (Agent notes only — spec 080.)
- `type/design` — Design intent, player-facing concepts, world lore. (e.g. `Design/World Model.md`)
- `type/discovery` — Non-obvious constraint, gap, or conflict found by an agent during a session. Written to `docs/vault/Discoveries/`. (Agent notes only — spec 080.)
- `type/moc` — Map of Content at any of three tiers (folder / domain / concept). (e.g. `Audio.md`)
- `type/principle` — Governance and constitutional notes. Non-negotiable rules. (e.g. `Governance/Constitution.md`)
- `type/reference` — Glossary, decision log, open questions, epics. (e.g. `Reference/Glossary.md`)
- `type/session-log` — Session activity log; permanent audit trail. Written to `docs/vault/Sessions/`. Append-only, never pruned. (Agent notes only — spec 080.)
- `type/spec` — Spec document at `docs/vault/Specs/NNN Title/spec.md`. Carries `spec-refs:`. (e.g. `Specs/047 Car Radio/spec.md`)
- `type/system` — A bounded subsystem with implementation. Carries `code-refs`, `spec-refs`, `implements:` frontmatter. (e.g. `Systems/Audio — Car Radio.md`)
- `type/vision` — Strategic / vision-layer decision. Written to `docs/vault/Vision/`. Human-authored or agent-proposed with human ratification before promotion to `status: reviewed`. (Per triage #3 — spec 133 autonomous-company redesign.)
domain/*:
- `domain/anomalies` — Anomaly taxonomy, individual anomaly systems, spawn, behavior
- `domain/art` — Visual direction, palettes, references, asset pipeline
- `domain/audio` — Audio systems: world ambient, radio, transmissions, buses, pipeline
- `domain/autonomous-company` — Autonomous company v0.1 experiment: Slack infra, persona middleware, Letta integration, restart recovery
- `domain/build` — Build system, packaging, export, release automation
- `domain/governance` — Constitution, phased spec, policies
- `domain/infrastructure` — Infrastructure provisioning: CI/CD, hosting, deployment tooling, secrets management
- `domain/narrative` — Tone, horror register, forest transmissions narrative, Gary/KTLK
- `domain/player` — Player mode, input, controls, camera, exit/entry
- `domain/systems` — Cross-cutting system architecture and integration work
- `domain/tooling` — Build, CI, observer, TTS pipeline, dev-time tools
- `domain/vehicle` — The Samba: vehicle physics, dashboard, damage, panels
- `domain/world` — World model, biomes, terrain, procedural generation, weather
status/*:
- `status/canonical` — Fully authoritative; promoted by humans only. Highest trust. (Agent notes only — spec 080.)
- `status/draft` — Authoring in progress, not yet verified
- `status/reviewed` — Agent-created note verified against codebase within its creating session. Eligible for auto-injection in subsequent task dispatches. (Agent notes only — spec 080.)
- `status/stale` — Known out of date; cannot update immediately. Pairs with `> [!warning] STALE — needs update` callout.
- `status/superseded` — Replaced by another note. Terminal state. Pairs with `> [!warning] SUPERSEDED` callout.
- `status/wip` — Stable but under active revision
layer/*:
- `layer/content` — Content assets (audio, models, textures, audio provenance)
- `layer/gdext` — gdext wrapper layer (`rust/gdext-wrapper/`)
- `layer/gdscript` — GDScript (Godot scene-tier logic)
- `layer/infra` — Build, CI, deployment infrastructure
- `layer/python` — Python development tooling (`tools/`)
- `layer/rust-core` — Engine-agnostic Rust core (`rust/rust-core/`)
concept/*:
- `concept/biome` — Biome-reactive behavior across systems
- `concept/contamination` — Across-runs panel and garage degradation; the slow-horror mechanic that doesn't reset with the world
- `concept/diegetic` — Diegetic audio / UI / world-sourced design
- `concept/disturbance` — The disturbance mechanic thread (Article X)
- `concept/ephemeral-world` — Run-reset, transient worlds (Article IV Rules 6–7)
- `concept/governance` — Constitutional and governance concepts
- `concept/horror` — Horror register and dread design
- `concept/procedural` — Procedural generation, seed determinism
- `concept/rendering` — Visual rendering quality, shader correctness, Terrain3D integration, mesh fidelity, LOD, Z-fighting
- `concept/terrain` — Terrain generation, heightmap, Terrain3D regions, roughness, playability constraints
ember's answer for tag_assignment-sessions-spec-088-implementation-session, domain/governanceP(true) placed on the no, unsure, and yes zones.nounsureyesgold: yesP = 0.18

tag_assignment-sessions-spec-088-implementation-session: domain/tooling

Tag assignment · dev
Gold
The note calls for `domain/tooling`: Build, CI, observer, TTS pipeline, dev-time tools (True)
ember
The note has no reason to carry `domain/tooling` (False)
Signal
P(true) 0.45 (unsure)
Kit outcome
deferred: treated as unsure
Why this gold label
Mined from Sessions/Spec 088 Implementation Session.md at 692f4bb58b7f62105aeb73fba8dfee12bfdecd53; gold is the note's own vocabulary tags.
Spec 088 Implementation Session

Session log for the full implementation of spec 088 (Vault Audit Agent) executed 2026-04-23.

## What Was Built

- `scripts/ci/vault_audit.py` — 1,060-line mechanical audit script (stdlib + PyYAML; no other deps). Validates schema, resolves wikilinks, checks code-refs/spec-refs, extracts code inventories, writes deterministic JSON, applies safe auto-fixes via `--apply`.
- `tools/vault_audit/semantic_drift.py` — standalone semantic drift script using `claude-sonnet-4-6` via Anthropic SDK ≥0.50.0. Batches notes (default 10), retries on rate limits, writes `last_semantic.json`.
- `tests/vault_audit/` — fixture suite: 5 malformed notes, 2 clean notes (including unicode em-dash), 15 claim taxonomy fixtures, mock JSON files, shell test harness with 6 test cases.
- `docs/vault/_meta/audit/` — output directory created; `last_audit.json`, `inventories.json` committed; `audit_run_metadata.json` gitignored.
- Makefile targets: `vault-audit`, `vault-audit-apply`, `vault-audit-semantic`, `vault-audit-test`.
- `introspection` skill updated with exact `gh` command sequence (FR-015), 3-section PR body template (SC-009), idempotency procedure (SC-003).
- AGENTS.md amended with staleness field behavior and rolling PR convention (FR-017).

## Non-Obvious Implementation Discoveries

### 1. Filename Index Must Exclude `_meta/templates/`

The `build_filename_index()` function initially walked all `.md` files in the vault including `_meta/templates/`. This caused false `duplicate_filename` WARN collisions: `Code.md` (folder MOC) vs `_meta/templates/code.md` (template), etc. Fix: add `_meta/` to the exclusion list alongside `.obsidian/`.

### 2. PyYAML Cannot Write Inline Comments

`yaml.dump()` does not support inline comments. FR-008 requires `source: agent  # auto-set by vault_audit — verify`. Solution: post-dump string replacement — after `yaml.dump()` generates the YAML string, replace `source: agent\n` with `source: agent  # auto-set by vault_audit — verify\n` before writing to disk. Idempotent because the replacement only runs once (exact match on `source: agent\n`).

### 3. Idempotency Requires Three-Key Sort

Two consecutive runs produced different `last_audit.json` files due to non-deterministic ordering of findings with the same `(note_path, rule)` key but different `message` values (e.g., five `missing_required_field` findings on `Sessions/README.md` for different missing fields). Fix: sort key `(note_path, rule, message)` on all finding lists in JSON output and stdout render.

### 4. `--output` Must Override `--no-write`

The idempotency test in `run_tests.sh` passes both `--output /tmp/run.json` and `--no-write`. Original guard `if no_write: return` blocked the `--output` write. Fix: guard changed to `if no_write and output_override is None: return` so `--output` always wins.

### 5. `build_filename_index()` Requires `sorted()`

`Path.rglob()` ordering is filesystem-dependent (non-deterministic on macOS HFS+). The duplicate filename message includes a list of matching paths — if the list order differs between runs, the JSON output differs. Fix: `sorted(vault_root.rglob("*.md"))` in both `build_filename_index()` and the main scan loop.

### 6. Live Vault Has 373 Genuine Errors

Running against `docs/vault/` reveals 373 errors, all genuine (not script false positives):
- ~90 notes in `Art/`, `Discoveries/`, `Sessions/` missing `tags:` field (were written pre-schema enforcement)
- ~70 `Specs/` notes use `status/done` and `status/waiting` — NOT in the controlled vocabulary (vocab has `status/wip`, `status/draft`, `status/reviewed`, `status/canonical`, `status/stale`, `status/superseded`)
- ~210 unresolved wikilinks pointing to notes in planned-but-unbuilt subdirectories (`Systems/Vehicle — Destruction`, `Art/Vehicle — Samba Acceptance Checklist`, etc.)
- 1 broken code-ref: `Code/Tools — Music Pipeline.md` points to `tools/music/` which doesn't exist

The `status/done` and `status/waiting` tags are the most systematic gap — used across ~70 spec stubs from before the vocabulary was formalized. These require either vocabulary extension or bulk tag replacement.

### 7. Claim Taxonomy Fixtures Are Valid Notes

The 15 claim taxonomy fixtures in `tests/vault_audit/fixtures/claim_taxonomy/` all pass schema validation with 0 errors/warnings — they use `type/discovery`, `domain/tooling`, `status/draft`, and valid `source: agent` + `aliases:` fields. This means they can be scanned without fixture-specific exclusion logic.

## Verification Results

| Check | Result |
|---|---|
| Malformed fixtures → exit 1 | ✅ |
| Clean fixtures → exit 0 | ✅ |
| Idempotency (two runs diff) | ✅ byte-identical |
| Performance (201 notes) | ✅ 0.25s (<<30s) |
| SC-005 inventory counts | ✅ signals=35, autoloads=5, gdext=8 |
| FR-008 inline comment | ✅ `# auto-set by vault_audit — verify` written |
| Semantic dry-run | ✅ produces valid batch prompt with real inventories |
| Claim taxonomy fixtures | ✅ all 15 pass schema validation |

Controlled tag vocabulary (as read):
type/*:
- `type/code` — Code architecture, autoloads, conventions, tooling. Carries `code-refs:`. (e.g. `Code/Autoloads — Disturbance.md`)
- `type/decision` — Architectural or design decision made by an agent during a session. Written to `docs/vault/Decisions/`. (Agent notes only — spec 080.)
- `type/design` — Design intent, player-facing concepts, world lore. (e.g. `Design/World Model.md`)
- `type/discovery` — Non-obvious constraint, gap, or conflict found by an agent during a session. Written to `docs/vault/Discoveries/`. (Agent notes only — spec 080.)
- `type/moc` — Map of Content at any of three tiers (folder / domain / concept). (e.g. `Audio.md`)
- `type/principle` — Governance and constitutional notes. Non-negotiable rules. (e.g. `Governance/Constitution.md`)
- `type/reference` — Glossary, decision log, open questions, epics. (e.g. `Reference/Glossary.md`)
- `type/session-log` — Session activity log; permanent audit trail. Written to `docs/vault/Sessions/`. Append-only, never pruned. (Agent notes only — spec 080.)
- `type/spec` — Spec document at `docs/vault/Specs/NNN Title/spec.md`. Carries `spec-refs:`. (e.g. `Specs/047 Car Radio/spec.md`)
- `type/system` — A bounded subsystem with implementation. Carries `code-refs`, `spec-refs`, `implements:` frontmatter. (e.g. `Systems/Audio — Car Radio.md`)
- `type/vision` — Strategic / vision-layer decision. Written to `docs/vault/Vision/`. Human-authored or agent-proposed with human ratification before promotion to `status: reviewed`. (Per triage #3 — spec 133 autonomous-company redesign.)
domain/*:
- `domain/anomalies` — Anomaly taxonomy, individual anomaly systems, spawn, behavior
- `domain/art` — Visual direction, palettes, references, asset pipeline
- `domain/audio` — Audio systems: world ambient, radio, transmissions, buses, pipeline
- `domain/autonomous-company` — Autonomous company v0.1 experiment: Slack infra, persona middleware, Letta integration, restart recovery
- `domain/build` — Build system, packaging, export, release automation
- `domain/governance` — Constitution, phased spec, policies
- `domain/infrastructure` — Infrastructure provisioning: CI/CD, hosting, deployment tooling, secrets management
- `domain/narrative` — Tone, horror register, forest transmissions narrative, Gary/KTLK
- `domain/player` — Player mode, input, controls, camera, exit/entry
- `domain/systems` — Cross-cutting system architecture and integration work
- `domain/tooling` — Build, CI, observer, TTS pipeline, dev-time tools
- `domain/vehicle` — The Samba: vehicle physics, dashboard, damage, panels
- `domain/world` — World model, biomes, terrain, procedural generation, weather
status/*:
- `status/canonical` — Fully authoritative; promoted by humans only. Highest trust. (Agent notes only — spec 080.)
- `status/draft` — Authoring in progress, not yet verified
- `status/reviewed` — Agent-created note verified against codebase within its creating session. Eligible for auto-injection in subsequent task dispatches. (Agent notes only — spec 080.)
- `status/stale` — Known out of date; cannot update immediately. Pairs with `> [!warning] STALE — needs update` callout.
- `status/superseded` — Replaced by another note. Terminal state. Pairs with `> [!warning] SUPERSEDED` callout.
- `status/wip` — Stable but under active revision
layer/*:
- `layer/content` — Content assets (audio, models, textures, audio provenance)
- `layer/gdext` — gdext wrapper layer (`rust/gdext-wrapper/`)
- `layer/gdscript` — GDScript (Godot scene-tier logic)
- `layer/infra` — Build, CI, deployment infrastructure
- `layer/python` — Python development tooling (`tools/`)
- `layer/rust-core` — Engine-agnostic Rust core (`rust/rust-core/`)
concept/*:
- `concept/biome` — Biome-reactive behavior across systems
- `concept/contamination` — Across-runs panel and garage degradation; the slow-horror mechanic that doesn't reset with the world
- `concept/diegetic` — Diegetic audio / UI / world-sourced design
- `concept/disturbance` — The disturbance mechanic thread (Article X)
- `concept/ephemeral-world` — Run-reset, transient worlds (Article IV Rules 6–7)
- `concept/governance` — Constitutional and governance concepts
- `concept/horror` — Horror register and dread design
- `concept/procedural` — Procedural generation, seed determinism
- `concept/rendering` — Visual rendering quality, shader correctness, Terrain3D integration, mesh fidelity, LOD, Z-fighting
- `concept/terrain` — Terrain generation, heightmap, Terrain3D regions, roughness, playability constraints
ember's answer for tag_assignment-sessions-spec-088-implementation-session, domain/toolingP(true) placed on the no, unsure, and yes zones.nounsureyesgold: yesP = 0.45

tag_assignment-sessions-spec-088-implementation-session: layer/infra

Tag assignment · dev
Gold
The note calls for `layer/infra`: Build, CI, deployment infrastructure (True)
ember
The note has no reason to carry `layer/infra` (False)
Signal
P(true) 0.16 (no)
Kit outcome
acted on a wrong answer
Why this gold label
Mined from Sessions/Spec 088 Implementation Session.md at 692f4bb58b7f62105aeb73fba8dfee12bfdecd53; gold is the note's own vocabulary tags.
Spec 088 Implementation Session

Session log for the full implementation of spec 088 (Vault Audit Agent) executed 2026-04-23.

## What Was Built

- `scripts/ci/vault_audit.py` — 1,060-line mechanical audit script (stdlib + PyYAML; no other deps). Validates schema, resolves wikilinks, checks code-refs/spec-refs, extracts code inventories, writes deterministic JSON, applies safe auto-fixes via `--apply`.
- `tools/vault_audit/semantic_drift.py` — standalone semantic drift script using `claude-sonnet-4-6` via Anthropic SDK ≥0.50.0. Batches notes (default 10), retries on rate limits, writes `last_semantic.json`.
- `tests/vault_audit/` — fixture suite: 5 malformed notes, 2 clean notes (including unicode em-dash), 15 claim taxonomy fixtures, mock JSON files, shell test harness with 6 test cases.
- `docs/vault/_meta/audit/` — output directory created; `last_audit.json`, `inventories.json` committed; `audit_run_metadata.json` gitignored.
- Makefile targets: `vault-audit`, `vault-audit-apply`, `vault-audit-semantic`, `vault-audit-test`.
- `introspection` skill updated with exact `gh` command sequence (FR-015), 3-section PR body template (SC-009), idempotency procedure (SC-003).
- AGENTS.md amended with staleness field behavior and rolling PR convention (FR-017).

## Non-Obvious Implementation Discoveries

### 1. Filename Index Must Exclude `_meta/templates/`

The `build_filename_index()` function initially walked all `.md` files in the vault including `_meta/templates/`. This caused false `duplicate_filename` WARN collisions: `Code.md` (folder MOC) vs `_meta/templates/code.md` (template), etc. Fix: add `_meta/` to the exclusion list alongside `.obsidian/`.

### 2. PyYAML Cannot Write Inline Comments

`yaml.dump()` does not support inline comments. FR-008 requires `source: agent  # auto-set by vault_audit — verify`. Solution: post-dump string replacement — after `yaml.dump()` generates the YAML string, replace `source: agent\n` with `source: agent  # auto-set by vault_audit — verify\n` before writing to disk. Idempotent because the replacement only runs once (exact match on `source: agent\n`).

### 3. Idempotency Requires Three-Key Sort

Two consecutive runs produced different `last_audit.json` files due to non-deterministic ordering of findings with the same `(note_path, rule)` key but different `message` values (e.g., five `missing_required_field` findings on `Sessions/README.md` for different missing fields). Fix: sort key `(note_path, rule, message)` on all finding lists in JSON output and stdout render.

### 4. `--output` Must Override `--no-write`

The idempotency test in `run_tests.sh` passes both `--output /tmp/run.json` and `--no-write`. Original guard `if no_write: return` blocked the `--output` write. Fix: guard changed to `if no_write and output_override is None: return` so `--output` always wins.

### 5. `build_filename_index()` Requires `sorted()`

`Path.rglob()` ordering is filesystem-dependent (non-deterministic on macOS HFS+). The duplicate filename message includes a list of matching paths — if the list order differs between runs, the JSON output differs. Fix: `sorted(vault_root.rglob("*.md"))` in both `build_filename_index()` and the main scan loop.

### 6. Live Vault Has 373 Genuine Errors

Running against `docs/vault/` reveals 373 errors, all genuine (not script false positives):
- ~90 notes in `Art/`, `Discoveries/`, `Sessions/` missing `tags:` field (were written pre-schema enforcement)
- ~70 `Specs/` notes use `status/done` and `status/waiting` — NOT in the controlled vocabulary (vocab has `status/wip`, `status/draft`, `status/reviewed`, `status/canonical`, `status/stale`, `status/superseded`)
- ~210 unresolved wikilinks pointing to notes in planned-but-unbuilt subdirectories (`Systems/Vehicle — Destruction`, `Art/Vehicle — Samba Acceptance Checklist`, etc.)
- 1 broken code-ref: `Code/Tools — Music Pipeline.md` points to `tools/music/` which doesn't exist

The `status/done` and `status/waiting` tags are the most systematic gap — used across ~70 spec stubs from before the vocabulary was formalized. These require either vocabulary extension or bulk tag replacement.

### 7. Claim Taxonomy Fixtures Are Valid Notes

The 15 claim taxonomy fixtures in `tests/vault_audit/fixtures/claim_taxonomy/` all pass schema validation with 0 errors/warnings — they use `type/discovery`, `domain/tooling`, `status/draft`, and valid `source: agent` + `aliases:` fields. This means they can be scanned without fixture-specific exclusion logic.

## Verification Results

| Check | Result |
|---|---|
| Malformed fixtures → exit 1 | ✅ |
| Clean fixtures → exit 0 | ✅ |
| Idempotency (two runs diff) | ✅ byte-identical |
| Performance (201 notes) | ✅ 0.25s (<<30s) |
| SC-005 inventory counts | ✅ signals=35, autoloads=5, gdext=8 |
| FR-008 inline comment | ✅ `# auto-set by vault_audit — verify` written |
| Semantic dry-run | ✅ produces valid batch prompt with real inventories |
| Claim taxonomy fixtures | ✅ all 15 pass schema validation |

Controlled tag vocabulary (as read):
type/*:
- `type/code` — Code architecture, autoloads, conventions, tooling. Carries `code-refs:`. (e.g. `Code/Autoloads — Disturbance.md`)
- `type/decision` — Architectural or design decision made by an agent during a session. Written to `docs/vault/Decisions/`. (Agent notes only — spec 080.)
- `type/design` — Design intent, player-facing concepts, world lore. (e.g. `Design/World Model.md`)
- `type/discovery` — Non-obvious constraint, gap, or conflict found by an agent during a session. Written to `docs/vault/Discoveries/`. (Agent notes only — spec 080.)
- `type/moc` — Map of Content at any of three tiers (folder / domain / concept). (e.g. `Audio.md`)
- `type/principle` — Governance and constitutional notes. Non-negotiable rules. (e.g. `Governance/Constitution.md`)
- `type/reference` — Glossary, decision log, open questions, epics. (e.g. `Reference/Glossary.md`)
- `type/session-log` — Session activity log; permanent audit trail. Written to `docs/vault/Sessions/`. Append-only, never pruned. (Agent notes only — spec 080.)
- `type/spec` — Spec document at `docs/vault/Specs/NNN Title/spec.md`. Carries `spec-refs:`. (e.g. `Specs/047 Car Radio/spec.md`)
- `type/system` — A bounded subsystem with implementation. Carries `code-refs`, `spec-refs`, `implements:` frontmatter. (e.g. `Systems/Audio — Car Radio.md`)
- `type/vision` — Strategic / vision-layer decision. Written to `docs/vault/Vision/`. Human-authored or agent-proposed with human ratification before promotion to `status: reviewed`. (Per triage #3 — spec 133 autonomous-company redesign.)
domain/*:
- `domain/anomalies` — Anomaly taxonomy, individual anomaly systems, spawn, behavior
- `domain/art` — Visual direction, palettes, references, asset pipeline
- `domain/audio` — Audio systems: world ambient, radio, transmissions, buses, pipeline
- `domain/autonomous-company` — Autonomous company v0.1 experiment: Slack infra, persona middleware, Letta integration, restart recovery
- `domain/build` — Build system, packaging, export, release automation
- `domain/governance` — Constitution, phased spec, policies
- `domain/infrastructure` — Infrastructure provisioning: CI/CD, hosting, deployment tooling, secrets management
- `domain/narrative` — Tone, horror register, forest transmissions narrative, Gary/KTLK
- `domain/player` — Player mode, input, controls, camera, exit/entry
- `domain/systems` — Cross-cutting system architecture and integration work
- `domain/tooling` — Build, CI, observer, TTS pipeline, dev-time tools
- `domain/vehicle` — The Samba: vehicle physics, dashboard, damage, panels
- `domain/world` — World model, biomes, terrain, procedural generation, weather
status/*:
- `status/canonical` — Fully authoritative; promoted by humans only. Highest trust. (Agent notes only — spec 080.)
- `status/draft` — Authoring in progress, not yet verified
- `status/reviewed` — Agent-created note verified against codebase within its creating session. Eligible for auto-injection in subsequent task dispatches. (Agent notes only — spec 080.)
- `status/stale` — Known out of date; cannot update immediately. Pairs with `> [!warning] STALE — needs update` callout.
- `status/superseded` — Replaced by another note. Terminal state. Pairs with `> [!warning] SUPERSEDED` callout.
- `status/wip` — Stable but under active revision
layer/*:
- `layer/content` — Content assets (audio, models, textures, audio provenance)
- `layer/gdext` — gdext wrapper layer (`rust/gdext-wrapper/`)
- `layer/gdscript` — GDScript (Godot scene-tier logic)
- `layer/infra` — Build, CI, deployment infrastructure
- `layer/python` — Python development tooling (`tools/`)
- `layer/rust-core` — Engine-agnostic Rust core (`rust/rust-core/`)
concept/*:
- `concept/biome` — Biome-reactive behavior across systems
- `concept/contamination` — Across-runs panel and garage degradation; the slow-horror mechanic that doesn't reset with the world
- `concept/diegetic` — Diegetic audio / UI / world-sourced design
- `concept/disturbance` — The disturbance mechanic thread (Article X)
- `concept/ephemeral-world` — Run-reset, transient worlds (Article IV Rules 6–7)
- `concept/governance` — Constitutional and governance concepts
- `concept/horror` — Horror register and dread design
- `concept/procedural` — Procedural generation, seed determinism
- `concept/rendering` — Visual rendering quality, shader correctness, Terrain3D integration, mesh fidelity, LOD, Z-fighting
- `concept/terrain` — Terrain generation, heightmap, Terrain3D regions, roughness, playability constraints
ember's answer for tag_assignment-sessions-spec-088-implementation-session, layer/infraP(true) placed on the no, unsure, and yes zones.nounsureyesgold: yesP = 0.16

tag_assignment-sessions-spec-088-implementation-session: status/reviewed

Tag assignment · dev
Gold
The note calls for `status/reviewed`: Agent-created note verified against codebase within its creating session. Eligible for auto-injection in subsequent task dispatches. (Agent notes only — spec 080.) (True)
ember
The note has no reason to carry `status/reviewed` (False)
Signal
P(true) 0.15 (no)
Kit outcome
acted on a wrong answer
Why this gold label
Mined from Sessions/Spec 088 Implementation Session.md at 692f4bb58b7f62105aeb73fba8dfee12bfdecd53; gold is the note's own vocabulary tags.
Spec 088 Implementation Session

Session log for the full implementation of spec 088 (Vault Audit Agent) executed 2026-04-23.

## What Was Built

- `scripts/ci/vault_audit.py` — 1,060-line mechanical audit script (stdlib + PyYAML; no other deps). Validates schema, resolves wikilinks, checks code-refs/spec-refs, extracts code inventories, writes deterministic JSON, applies safe auto-fixes via `--apply`.
- `tools/vault_audit/semantic_drift.py` — standalone semantic drift script using `claude-sonnet-4-6` via Anthropic SDK ≥0.50.0. Batches notes (default 10), retries on rate limits, writes `last_semantic.json`.
- `tests/vault_audit/` — fixture suite: 5 malformed notes, 2 clean notes (including unicode em-dash), 15 claim taxonomy fixtures, mock JSON files, shell test harness with 6 test cases.
- `docs/vault/_meta/audit/` — output directory created; `last_audit.json`, `inventories.json` committed; `audit_run_metadata.json` gitignored.
- Makefile targets: `vault-audit`, `vault-audit-apply`, `vault-audit-semantic`, `vault-audit-test`.
- `introspection` skill updated with exact `gh` command sequence (FR-015), 3-section PR body template (SC-009), idempotency procedure (SC-003).
- AGENTS.md amended with staleness field behavior and rolling PR convention (FR-017).

## Non-Obvious Implementation Discoveries

### 1. Filename Index Must Exclude `_meta/templates/`

The `build_filename_index()` function initially walked all `.md` files in the vault including `_meta/templates/`. This caused false `duplicate_filename` WARN collisions: `Code.md` (folder MOC) vs `_meta/templates/code.md` (template), etc. Fix: add `_meta/` to the exclusion list alongside `.obsidian/`.

### 2. PyYAML Cannot Write Inline Comments

`yaml.dump()` does not support inline comments. FR-008 requires `source: agent  # auto-set by vault_audit — verify`. Solution: post-dump string replacement — after `yaml.dump()` generates the YAML string, replace `source: agent\n` with `source: agent  # auto-set by vault_audit — verify\n` before writing to disk. Idempotent because the replacement only runs once (exact match on `source: agent\n`).

### 3. Idempotency Requires Three-Key Sort

Two consecutive runs produced different `last_audit.json` files due to non-deterministic ordering of findings with the same `(note_path, rule)` key but different `message` values (e.g., five `missing_required_field` findings on `Sessions/README.md` for different missing fields). Fix: sort key `(note_path, rule, message)` on all finding lists in JSON output and stdout render.

### 4. `--output` Must Override `--no-write`

The idempotency test in `run_tests.sh` passes both `--output /tmp/run.json` and `--no-write`. Original guard `if no_write: return` blocked the `--output` write. Fix: guard changed to `if no_write and output_override is None: return` so `--output` always wins.

### 5. `build_filename_index()` Requires `sorted()`

`Path.rglob()` ordering is filesystem-dependent (non-deterministic on macOS HFS+). The duplicate filename message includes a list of matching paths — if the list order differs between runs, the JSON output differs. Fix: `sorted(vault_root.rglob("*.md"))` in both `build_filename_index()` and the main scan loop.

### 6. Live Vault Has 373 Genuine Errors

Running against `docs/vault/` reveals 373 errors, all genuine (not script false positives):
- ~90 notes in `Art/`, `Discoveries/`, `Sessions/` missing `tags:` field (were written pre-schema enforcement)
- ~70 `Specs/` notes use `status/done` and `status/waiting` — NOT in the controlled vocabulary (vocab has `status/wip`, `status/draft`, `status/reviewed`, `status/canonical`, `status/stale`, `status/superseded`)
- ~210 unresolved wikilinks pointing to notes in planned-but-unbuilt subdirectories (`Systems/Vehicle — Destruction`, `Art/Vehicle — Samba Acceptance Checklist`, etc.)
- 1 broken code-ref: `Code/Tools — Music Pipeline.md` points to `tools/music/` which doesn't exist

The `status/done` and `status/waiting` tags are the most systematic gap — used across ~70 spec stubs from before the vocabulary was formalized. These require either vocabulary extension or bulk tag replacement.

### 7. Claim Taxonomy Fixtures Are Valid Notes

The 15 claim taxonomy fixtures in `tests/vault_audit/fixtures/claim_taxonomy/` all pass schema validation with 0 errors/warnings — they use `type/discovery`, `domain/tooling`, `status/draft`, and valid `source: agent` + `aliases:` fields. This means they can be scanned without fixture-specific exclusion logic.

## Verification Results

| Check | Result |
|---|---|
| Malformed fixtures → exit 1 | ✅ |
| Clean fixtures → exit 0 | ✅ |
| Idempotency (two runs diff) | ✅ byte-identical |
| Performance (201 notes) | ✅ 0.25s (<<30s) |
| SC-005 inventory counts | ✅ signals=35, autoloads=5, gdext=8 |
| FR-008 inline comment | ✅ `# auto-set by vault_audit — verify` written |
| Semantic dry-run | ✅ produces valid batch prompt with real inventories |
| Claim taxonomy fixtures | ✅ all 15 pass schema validation |

Controlled tag vocabulary (as read):
type/*:
- `type/code` — Code architecture, autoloads, conventions, tooling. Carries `code-refs:`. (e.g. `Code/Autoloads — Disturbance.md`)
- `type/decision` — Architectural or design decision made by an agent during a session. Written to `docs/vault/Decisions/`. (Agent notes only — spec 080.)
- `type/design` — Design intent, player-facing concepts, world lore. (e.g. `Design/World Model.md`)
- `type/discovery` — Non-obvious constraint, gap, or conflict found by an agent during a session. Written to `docs/vault/Discoveries/`. (Agent notes only — spec 080.)
- `type/moc` — Map of Content at any of three tiers (folder / domain / concept). (e.g. `Audio.md`)
- `type/principle` — Governance and constitutional notes. Non-negotiable rules. (e.g. `Governance/Constitution.md`)
- `type/reference` — Glossary, decision log, open questions, epics. (e.g. `Reference/Glossary.md`)
- `type/session-log` — Session activity log; permanent audit trail. Written to `docs/vault/Sessions/`. Append-only, never pruned. (Agent notes only — spec 080.)
- `type/spec` — Spec document at `docs/vault/Specs/NNN Title/spec.md`. Carries `spec-refs:`. (e.g. `Specs/047 Car Radio/spec.md`)
- `type/system` — A bounded subsystem with implementation. Carries `code-refs`, `spec-refs`, `implements:` frontmatter. (e.g. `Systems/Audio — Car Radio.md`)
- `type/vision` — Strategic / vision-layer decision. Written to `docs/vault/Vision/`. Human-authored or agent-proposed with human ratification before promotion to `status: reviewed`. (Per triage #3 — spec 133 autonomous-company redesign.)
domain/*:
- `domain/anomalies` — Anomaly taxonomy, individual anomaly systems, spawn, behavior
- `domain/art` — Visual direction, palettes, references, asset pipeline
- `domain/audio` — Audio systems: world ambient, radio, transmissions, buses, pipeline
- `domain/autonomous-company` — Autonomous company v0.1 experiment: Slack infra, persona middleware, Letta integration, restart recovery
- `domain/build` — Build system, packaging, export, release automation
- `domain/governance` — Constitution, phased spec, policies
- `domain/infrastructure` — Infrastructure provisioning: CI/CD, hosting, deployment tooling, secrets management
- `domain/narrative` — Tone, horror register, forest transmissions narrative, Gary/KTLK
- `domain/player` — Player mode, input, controls, camera, exit/entry
- `domain/systems` — Cross-cutting system architecture and integration work
- `domain/tooling` — Build, CI, observer, TTS pipeline, dev-time tools
- `domain/vehicle` — The Samba: vehicle physics, dashboard, damage, panels
- `domain/world` — World model, biomes, terrain, procedural generation, weather
status/*:
- `status/canonical` — Fully authoritative; promoted by humans only. Highest trust. (Agent notes only — spec 080.)
- `status/draft` — Authoring in progress, not yet verified
- `status/reviewed` — Agent-created note verified against codebase within its creating session. Eligible for auto-injection in subsequent task dispatches. (Agent notes only — spec 080.)
- `status/stale` — Known out of date; cannot update immediately. Pairs with `> [!warning] STALE — needs update` callout.
- `status/superseded` — Replaced by another note. Terminal state. Pairs with `> [!warning] SUPERSEDED` callout.
- `status/wip` — Stable but under active revision
layer/*:
- `layer/content` — Content assets (audio, models, textures, audio provenance)
- `layer/gdext` — gdext wrapper layer (`rust/gdext-wrapper/`)
- `layer/gdscript` — GDScript (Godot scene-tier logic)
- `layer/infra` — Build, CI, deployment infrastructure
- `layer/python` — Python development tooling (`tools/`)
- `layer/rust-core` — Engine-agnostic Rust core (`rust/rust-core/`)
concept/*:
- `concept/biome` — Biome-reactive behavior across systems
- `concept/contamination` — Across-runs panel and garage degradation; the slow-horror mechanic that doesn't reset with the world
- `concept/diegetic` — Diegetic audio / UI / world-sourced design
- `concept/disturbance` — The disturbance mechanic thread (Article X)
- `concept/ephemeral-world` — Run-reset, transient worlds (Article IV Rules 6–7)
- `concept/governance` — Constitutional and governance concepts
- `concept/horror` — Horror register and dread design
- `concept/procedural` — Procedural generation, seed determinism
- `concept/rendering` — Visual rendering quality, shader correctness, Terrain3D integration, mesh fidelity, LOD, Z-fighting
- `concept/terrain` — Terrain generation, heightmap, Terrain3D regions, roughness, playability constraints
ember's answer for tag_assignment-sessions-spec-088-implementation-session, status/reviewedP(true) placed on the no, unsure, and yes zones.nounsureyesgold: yesP = 0.15

tag_assignment-sessions-spec-088-implementation-session: type/session-log

Tag assignment · dev
Gold
The note calls for `type/session-log`: Session activity log; permanent audit trail. Written to `docs/vault/Sessions/`. Append-only, never pruned. (Agent notes only — spec 080.) (True)
ember
The note has no reason to carry `type/session-log` (False)
Signal
P(true) 0.44 (unsure)
Kit outcome
deferred: treated as unsure
Why this gold label
Mined from Sessions/Spec 088 Implementation Session.md at 692f4bb58b7f62105aeb73fba8dfee12bfdecd53; gold is the note's own vocabulary tags.
Spec 088 Implementation Session

Session log for the full implementation of spec 088 (Vault Audit Agent) executed 2026-04-23.

## What Was Built

- `scripts/ci/vault_audit.py` — 1,060-line mechanical audit script (stdlib + PyYAML; no other deps). Validates schema, resolves wikilinks, checks code-refs/spec-refs, extracts code inventories, writes deterministic JSON, applies safe auto-fixes via `--apply`.
- `tools/vault_audit/semantic_drift.py` — standalone semantic drift script using `claude-sonnet-4-6` via Anthropic SDK ≥0.50.0. Batches notes (default 10), retries on rate limits, writes `last_semantic.json`.
- `tests/vault_audit/` — fixture suite: 5 malformed notes, 2 clean notes (including unicode em-dash), 15 claim taxonomy fixtures, mock JSON files, shell test harness with 6 test cases.
- `docs/vault/_meta/audit/` — output directory created; `last_audit.json`, `inventories.json` committed; `audit_run_metadata.json` gitignored.
- Makefile targets: `vault-audit`, `vault-audit-apply`, `vault-audit-semantic`, `vault-audit-test`.
- `introspection` skill updated with exact `gh` command sequence (FR-015), 3-section PR body template (SC-009), idempotency procedure (SC-003).
- AGENTS.md amended with staleness field behavior and rolling PR convention (FR-017).

## Non-Obvious Implementation Discoveries

### 1. Filename Index Must Exclude `_meta/templates/`

The `build_filename_index()` function initially walked all `.md` files in the vault including `_meta/templates/`. This caused false `duplicate_filename` WARN collisions: `Code.md` (folder MOC) vs `_meta/templates/code.md` (template), etc. Fix: add `_meta/` to the exclusion list alongside `.obsidian/`.

### 2. PyYAML Cannot Write Inline Comments

`yaml.dump()` does not support inline comments. FR-008 requires `source: agent  # auto-set by vault_audit — verify`. Solution: post-dump string replacement — after `yaml.dump()` generates the YAML string, replace `source: agent\n` with `source: agent  # auto-set by vault_audit — verify\n` before writing to disk. Idempotent because the replacement only runs once (exact match on `source: agent\n`).

### 3. Idempotency Requires Three-Key Sort

Two consecutive runs produced different `last_audit.json` files due to non-deterministic ordering of findings with the same `(note_path, rule)` key but different `message` values (e.g., five `missing_required_field` findings on `Sessions/README.md` for different missing fields). Fix: sort key `(note_path, rule, message)` on all finding lists in JSON output and stdout render.

### 4. `--output` Must Override `--no-write`

The idempotency test in `run_tests.sh` passes both `--output /tmp/run.json` and `--no-write`. Original guard `if no_write: return` blocked the `--output` write. Fix: guard changed to `if no_write and output_override is None: return` so `--output` always wins.

### 5. `build_filename_index()` Requires `sorted()`

`Path.rglob()` ordering is filesystem-dependent (non-deterministic on macOS HFS+). The duplicate filename message includes a list of matching paths — if the list order differs between runs, the JSON output differs. Fix: `sorted(vault_root.rglob("*.md"))` in both `build_filename_index()` and the main scan loop.

### 6. Live Vault Has 373 Genuine Errors

Running against `docs/vault/` reveals 373 errors, all genuine (not script false positives):
- ~90 notes in `Art/`, `Discoveries/`, `Sessions/` missing `tags:` field (were written pre-schema enforcement)
- ~70 `Specs/` notes use `status/done` and `status/waiting` — NOT in the controlled vocabulary (vocab has `status/wip`, `status/draft`, `status/reviewed`, `status/canonical`, `status/stale`, `status/superseded`)
- ~210 unresolved wikilinks pointing to notes in planned-but-unbuilt subdirectories (`Systems/Vehicle — Destruction`, `Art/Vehicle — Samba Acceptance Checklist`, etc.)
- 1 broken code-ref: `Code/Tools — Music Pipeline.md` points to `tools/music/` which doesn't exist

The `status/done` and `status/waiting` tags are the most systematic gap — used across ~70 spec stubs from before the vocabulary was formalized. These require either vocabulary extension or bulk tag replacement.

### 7. Claim Taxonomy Fixtures Are Valid Notes

The 15 claim taxonomy fixtures in `tests/vault_audit/fixtures/claim_taxonomy/` all pass schema validation with 0 errors/warnings — they use `type/discovery`, `domain/tooling`, `status/draft`, and valid `source: agent` + `aliases:` fields. This means they can be scanned without fixture-specific exclusion logic.

## Verification Results

| Check | Result |
|---|---|
| Malformed fixtures → exit 1 | ✅ |
| Clean fixtures → exit 0 | ✅ |
| Idempotency (two runs diff) | ✅ byte-identical |
| Performance (201 notes) | ✅ 0.25s (<<30s) |
| SC-005 inventory counts | ✅ signals=35, autoloads=5, gdext=8 |
| FR-008 inline comment | ✅ `# auto-set by vault_audit — verify` written |
| Semantic dry-run | ✅ produces valid batch prompt with real inventories |
| Claim taxonomy fixtures | ✅ all 15 pass schema validation |

Controlled tag vocabulary (as read):
type/*:
- `type/code` — Code architecture, autoloads, conventions, tooling. Carries `code-refs:`. (e.g. `Code/Autoloads — Disturbance.md`)
- `type/decision` — Architectural or design decision made by an agent during a session. Written to `docs/vault/Decisions/`. (Agent notes only — spec 080.)
- `type/design` — Design intent, player-facing concepts, world lore. (e.g. `Design/World Model.md`)
- `type/discovery` — Non-obvious constraint, gap, or conflict found by an agent during a session. Written to `docs/vault/Discoveries/`. (Agent notes only — spec 080.)
- `type/moc` — Map of Content at any of three tiers (folder / domain / concept). (e.g. `Audio.md`)
- `type/principle` — Governance and constitutional notes. Non-negotiable rules. (e.g. `Governance/Constitution.md`)
- `type/reference` — Glossary, decision log, open questions, epics. (e.g. `Reference/Glossary.md`)
- `type/session-log` — Session activity log; permanent audit trail. Written to `docs/vault/Sessions/`. Append-only, never pruned. (Agent notes only — spec 080.)
- `type/spec` — Spec document at `docs/vault/Specs/NNN Title/spec.md`. Carries `spec-refs:`. (e.g. `Specs/047 Car Radio/spec.md`)
- `type/system` — A bounded subsystem with implementation. Carries `code-refs`, `spec-refs`, `implements:` frontmatter. (e.g. `Systems/Audio — Car Radio.md`)
- `type/vision` — Strategic / vision-layer decision. Written to `docs/vault/Vision/`. Human-authored or agent-proposed with human ratification before promotion to `status: reviewed`. (Per triage #3 — spec 133 autonomous-company redesign.)
domain/*:
- `domain/anomalies` — Anomaly taxonomy, individual anomaly systems, spawn, behavior
- `domain/art` — Visual direction, palettes, references, asset pipeline
- `domain/audio` — Audio systems: world ambient, radio, transmissions, buses, pipeline
- `domain/autonomous-company` — Autonomous company v0.1 experiment: Slack infra, persona middleware, Letta integration, restart recovery
- `domain/build` — Build system, packaging, export, release automation
- `domain/governance` — Constitution, phased spec, policies
- `domain/infrastructure` — Infrastructure provisioning: CI/CD, hosting, deployment tooling, secrets management
- `domain/narrative` — Tone, horror register, forest transmissions narrative, Gary/KTLK
- `domain/player` — Player mode, input, controls, camera, exit/entry
- `domain/systems` — Cross-cutting system architecture and integration work
- `domain/tooling` — Build, CI, observer, TTS pipeline, dev-time tools
- `domain/vehicle` — The Samba: vehicle physics, dashboard, damage, panels
- `domain/world` — World model, biomes, terrain, procedural generation, weather
status/*:
- `status/canonical` — Fully authoritative; promoted by humans only. Highest trust. (Agent notes only — spec 080.)
- `status/draft` — Authoring in progress, not yet verified
- `status/reviewed` — Agent-created note verified against codebase within its creating session. Eligible for auto-injection in subsequent task dispatches. (Agent notes only — spec 080.)
- `status/stale` — Known out of date; cannot update immediately. Pairs with `> [!warning] STALE — needs update` callout.
- `status/superseded` — Replaced by another note. Terminal state. Pairs with `> [!warning] SUPERSEDED` callout.
- `status/wip` — Stable but under active revision
layer/*:
- `layer/content` — Content assets (audio, models, textures, audio provenance)
- `layer/gdext` — gdext wrapper layer (`rust/gdext-wrapper/`)
- `layer/gdscript` — GDScript (Godot scene-tier logic)
- `layer/infra` — Build, CI, deployment infrastructure
- `layer/python` — Python development tooling (`tools/`)
- `layer/rust-core` — Engine-agnostic Rust core (`rust/rust-core/`)
concept/*:
- `concept/biome` — Biome-reactive behavior across systems
- `concept/contamination` — Across-runs panel and garage degradation; the slow-horror mechanic that doesn't reset with the world
- `concept/diegetic` — Diegetic audio / UI / world-sourced design
- `concept/disturbance` — The disturbance mechanic thread (Article X)
- `concept/ephemeral-world` — Run-reset, transient worlds (Article IV Rules 6–7)
- `concept/governance` — Constitutional and governance concepts
- `concept/horror` — Horror register and dread design
- `concept/procedural` — Procedural generation, seed determinism
- `concept/rendering` — Visual rendering quality, shader correctness, Terrain3D integration, mesh fidelity, LOD, Z-fighting
- `concept/terrain` — Terrain generation, heightmap, Terrain3D regions, roughness, playability constraints
ember's answer for tag_assignment-sessions-spec-088-implementation-session, type/session-logP(true) placed on the no, unsure, and yes zones.nounsureyesgold: yesP = 0.44

tag_assignment-code-generation-subsystem-pairs: concept/procedural

Tag assignment · test
Gold
The note calls for `concept/procedural`: Procedural generation, seed determinism (True)
ember
The note has no reason to carry `concept/procedural` (False)
Signal
P(true) 0.22 (unsure)
Kit outcome
deferred: treated as unsure
Why this gold label
Mined from Code/Generation Subsystem Pairs.md at 692f4bb58b7f62105aeb73fba8dfee12bfdecd53; gold is the note's own vocabulary tags.
Generation Subsystem Pairs

Every computationally intensive generation subsystem follows a three-layer architecture: a GDScript shell owns scene management, `@export` parameters, and signal wiring; a Rust core module (`rust-core/src/`) implements pure algorithms with zero Godot dependencies; and a GDExtension bridge (`rust/gdext-wrapper/src/`) converts types between the two layers. This note inventories every subsystem pair in the codebase and documents which responsibilities live at which layer.

## The Delegation Pattern

GDScript shells follow a consistent pattern:

```gdscript
var _rust: Object = null

func _init() -> void:
    if ClassDB.class_exists("XxxNode"):
        _rust = ClassDB.instantiate("XxxNode")
    else:
        push_warning("[Xxx] XxxNode not found — GDExtension not loaded")
```

The shell holds the Godot reference (`_rust`), calls Rust methods for compute, and handles all node instantiation, scene tree operations, and user-facing property exposure. Fallback paths handle the case where the GDExtension dylib has not been compiled or loaded.

## All Subsystem Pairs

### Terrain Generation

| Layer | File | Responsibility |
|---|---|---|
| GDScript shell | `src/scripts/generation/terrain_generator.gd` | Terrain3D region creation, Image writes, map updates, boundary/roughness parameter passthrough |
| Rust core | `rust/rust-core/src/terrain.rs` | Noise sampling (fastnoise-lite), heightmap generation, boundary ring computation, roughness fractal noise, center basin depression |
| Bridge | `rust/gdext-wrapper/src/terrain_bridge.rs` | Exposes `TerrainComputeNode` — receives config struct, returns heightmap regions and boundary data |

Also in this group:
- `src/scripts/generation/terrain_texture_painter.gd` — texture painting (pure GDScript, no Rust pair — uses Terrain3D texture API)
- `src/scripts/generation/terrain_setup.gd` — Terrain3D camera binding (pure GDScript, no Rust pair)
- `src/scripts/generation/noise_helper.gd` — noise utility (pure GDScript RefCounted)

### Road Network

| Layer | File | Responsibility |
|---|---|---|
| GDScript shell | `src/scripts/generation/road_network_generator.gd` | Curve3D extraction, playability validation, debug visualization, @export topology parameters |
| Rust core | `rust/rust-core/src/road/` (10 files) | Hub-and-spoke topology, A* routing on terrain cost grid, intersection management, spline generation, density computation, dead-end elimination |
| Bridge | `rust/gdext-wrapper/src/road_bridge.rs` | Exposes `RoadGeneratorNode` — receives entry/exit data and terrain, returns segment dictionaries with Curve3D-compatible points |

Road subsystem details:
- `rust/rust-core/src/road/generator.rs` — road network generation (highway, county, logging road placement)
- `rust/rust-core/src/road/graph.rs` — graph topology, node connections
- `rust/rust-core/src/road/intersection.rs` — dead-end elimination, leaf-node pruning, connector placement
- `rust/rust-core/src/road/spline.rs` — path-to-spline conversion, bezier curves
- `rust/rust-core/src/road/path_utils.rs` — terrain-aware A* pathfinding
- `rust/rust-core/src/road/mesh_geometry.rs` — road cross-section and mesh vertex data (consumed by GDScript mesh extruder)
- `rust/rust-core/src/road/types.rs` — shared types (RoadSegment, RoadType, NetworkStats)
- `rust/rust-core/src/road/density.rs` — road network density metrics
- `rust/rust-core/src/road/terrain.rs` — terrain slope query helpers for road placement

GDScript companions (no GDExtension bridge — pure Godot API):
- `src/scripts/generation/road_mesh_generator.gd` — mesh extrusion, terrain flattening, hub flattening
- `src/scripts/generation/road_path_utils.gd` — cost grid building, terrain queries, pathfinding aids (pure GDScript RefCounted; the Rust `road/path_utils.rs` provides parallel implementations consumed by the Rust road generator, not delegated from this file)
- `src/scripts/generation/road_prop_activation_manager.gd` — prop visibility culling

### Biome Generation

| Layer | File | Responsibility |
|---|---|---|
| GDScript shell | `src/scripts/generation/biome_generator.gd` | Config building, biome config Resource loading, callable wrappers for biome lookup/blend queries |
| Rust core | `rust/rust-core/src/biome.rs` | Voronoi cell subdivision, biome assignment with preference weighting, blend factor computation, transition bands |
| Bridge | `rust/gdext-wrapper/src/biome_bridge.rs` | Exposes `BiomeGeneratorNode` — receives world bounds and config, returns cell centers + biome assignments + blend queries |

### Vegetation Scatter

| Layer | File | Responsibility |
|---|---|---|
| GDScript shell | `src/scripts/generation/vegetation_scatter.gd` | Terrain3D MultiMesh instancer, biome density lookup, tree variant assignment, collision setup |
| Rust core | `rust/rust-core/src/vegetation.rs` | Poisson-disc rejection sampling, road grid construction, spawn exclusion, corridor zone filtering, biome-aware density weighting |
| Bridge | `rust/gdext-wrapper/src/vegetation_bridge.rs` | Exposes methods for generate_tree_positions_only() and full scatter() — receives road centerpoints, config, returns positioned arrays |

Also in this group:
- `src/scripts/generation/tree_collision_manager.gd` — Area3D collision for trees (pure GDScript)

### Exit Points

| Layer | File | Responsibility |
|---|---|---|
| GDScript shell | `src/scripts/generation/exit_point_manager.gd` | Entry/exit data assembly, position conversion |
| Rust core | `rust/rust-core/src/exit_points.rs` | Edge exit placement with terrain-aware sampling, minimum separation enforcement |
| Bridge | `rust/gdext-wrapper/src/exit_point_bridge.rs` | Exposes `ExitPointManagerNode` — receives world bounds and RNG, returns exit positions |

### Road Structures

| Layer | File | Responsibility |
|---|---|---|
| GDScript shell | `src/scripts/generation/road_structure_scatter.gd` | Scene instantiation, biome tinting, collision setup, visibility management |
| Rust core | `rust/rust-core/src/structures.rs` | Candidate generation, apex detection, spacing filter, type assignment (power poles, signs, derelict vehicles, env props), prop position generation |
| Bridge | `rust/gdext-wrapper/src/structures_bridge.rs` | Exposes methods for structure/prop position generation — receives road sample data and config, returns candidate arrays |

Note: Only candidate computation is in Rust. Curve3D sampling, Terrain3D height queries, and scene instantiation remain in GDScript.

### Weather Zones

| Layer | File | Responsibility |
|---|---|---|
| GDScript shell | `src/scripts/systems/weather_zone_system.gd` | Zone scene nodes, particle systems, weather state transitions |
| Rust core | `rust/rust-core/src/weather/` (10 files) | Zone placement, biome hysteresis, state machine, front propagation, fog density, exposure computation, traction/wetness modeling |
| Bridge | `rust/gdext-wrapper/src/weather_zones_bridge.rs`, `weather_simulator_bridge.rs`, `weather_biome_hysteresis_bridge.rs`, `weather_exposure_bridge.rs`, `weather_fog_bridge.rs`, `weather_traction_bridge.rs`, `weather_wetness_bridge.rs` | 7 bridge files exposing `WeatherZoneNode`, `WeatherSimulatorNode`, and per-component nodes |

### Autoload Delegation (GameState + Disturbance)

These are not generation subsystems but follow the same thin-shell pattern:

| Layer | GDScript | Rust Core | Bridge |
|---|---|---|---|
| GameState | `src/autoloads/game_state.gd` — backing variables, enum definitions, signal emission, `generate_seed()` | `rust/rust-core/src/game_state.rs` — change-detection callbacks, default values | `rust/gdext-wrapper/src/game_state_bridge.rs` — `GameStateNode` with validator methods |
| Disturbance | `src/autoloads/disturbance.gd` — `@export` thresholds, signal wiring, `add()` wrapper | `rust/rust-core/src/disturbance.rs` — arithmetic, clamping, threshold-crossing detection | `rust/gdext-wrapper/src/disturbance_bridge.rs` — `DisturbanceNode` with `add()` returning old/new level + state |

Key constraint for all three autoloads `Events`, `GameState`, `Disturbance`: `class_name` must never appear on an autoload script — the engine registers autoloads under their configured singleton name and a matching `class_name` produces duplicate registration conflicts.

## Summary Table

| Subsystem | GDScript Shell | Rust Core Module | Bridge File(s) | Rust Migration |
|---|---|---|---|---|
| Terrain | `terrain_generator.gd` | `terrain.rs` | `terrain_bridge.rs` | Complete |
| Road Network | `road_network_generator.gd` | `road/` (10 files) | `road_bridge.rs` | Complete |
| Biome | `biome_generator.gd` | `biome.rs` | `biome_bridge.rs` | Complete |
| Vegetation | `vegetation_scatter.gd` | `vegetation.rs` | `vegetation_bridge.rs` | Complete (candidates) |
| Exit Points | `exit_point_manager.gd` | `exit_points.rs` | `exit_point_bridge.rs` | Complete |
| Structures | `road_structure_scatter.gd` | `structures.rs` | `structures_bridge.rs` | Partial (candidates only) |
| Weather Zones | `weather_zone_system.gd` | `weather/` (10 files) | 7 bridge files | Partial (zones + simulator complete, per-system in progress) |
| GameState | `game_state.gd` (autoload) | `game_state.rs` | `game_state_bridge.rs` | Complete |
| Disturbance | `disturbance.gd` (autoload) | `disturbance.rs` | `disturbance_bridge.rs` | Complete |

## Related

- [[World — Procedural Generation]] — the pipeline these subsystems implement
- [[Rust — Core]] — the engine-agnostic core layer
- [[Rust — GDExt Wrapper]] — the bridge layer
- [[Code]] — folder MOC
- [[World — Domain MOC]] — domain MOC
- [[Constitution]] — Article III (Rust-first), Article IV (seed determinism)

Controlled tag vocabulary (as read):
type/*:
- `type/code` — Code architecture, autoloads, conventions, tooling. Carries `code-refs:`. (e.g. `Code/Autoloads — Disturbance.md`)
- `type/decision` — Architectural or design decision made by an agent during a session. Written to `docs/vault/Decisions/`. (Agent notes only — spec 080.)
- `type/design` — Design intent, player-facing concepts, world lore. (e.g. `Design/World Model.md`)
- `type/discovery` — Non-obvious constraint, gap, or conflict found by an agent during a session. Written to `docs/vault/Discoveries/`. (Agent notes only — spec 080.)
- `type/moc` — Map of Content at any of three tiers (folder / domain / concept). (e.g. `Audio.md`)
- `type/principle` — Governance and constitutional notes. Non-negotiable rules. (e.g. `Governance/Constitution.md`)
- `type/reference` — Glossary, decision log, open questions, epics. (e.g. `Reference/Glossary.md`)
- `type/session-log` — Session activity log; permanent audit trail. Written to `docs/vault/Sessions/`. Append-only, never pruned. (Agent notes only — spec 080.)
- `type/spec` — Spec document at `docs/vault/Specs/NNN Title/spec.md`. Carries `spec-refs:`. (e.g. `Specs/047 Car Radio/spec.md`)
- `type/system` — A bounded subsystem with implementation. Carries `code-refs`, `spec-refs`, `implements:` frontmatter. (e.g. `Systems/Audio — Car Radio.md`)
- `type/vision` — Strategic / vision-layer decision. Written to `docs/vault/Vision/`. Human-authored or agent-proposed with human ratification before promotion to `status: reviewed`. (Per triage #3 — spec 133 autonomous-company redesign.)
domain/*:
- `domain/anomalies` — Anomaly taxonomy, individual anomaly systems, spawn, behavior
- `domain/art` — Visual direction, palettes, references, asset pipeline
- `domain/audio` — Audio systems: world ambient, radio, transmissions, buses, pipeline
- `domain/autonomous-company` — Autonomous company v0.1 experiment: Slack infra, persona middleware, Letta integration, restart recovery
- `domain/build` — Build system, packaging, export, release automation
- `domain/governance` — Constitution, phased spec, policies
- `domain/infrastructure` — Infrastructure provisioning: CI/CD, hosting, deployment tooling, secrets management
- `domain/narrative` — Tone, horror register, forest transmissions narrative, Gary/KTLK
- `domain/player` — Player mode, input, controls, camera, exit/entry
- `domain/systems` — Cross-cutting system architecture and integration work
- `domain/tooling` — Build, CI, observer, TTS pipeline, dev-time tools
- `domain/vehicle` — The Samba: vehicle physics, dashboard, damage, panels
- `domain/world` — World model, biomes, terrain, procedural generation, weather
status/*:
- `status/canonical` — Fully authoritative; promoted by humans only. Highest trust. (Agent notes only — spec 080.)
- `status/draft` — Authoring in progress, not yet verified
- `status/reviewed` — Agent-created note verified against codebase within its creating session. Eligible for auto-injection in subsequent task dispatches. (Agent notes only — spec 080.)
- `status/stale` — Known out of date; cannot update immediately. Pairs with `> [!warning] STALE — needs update` callout.
- `status/superseded` — Replaced by another note. Terminal state. Pairs with `> [!warning] SUPERSEDED` callout.
- `status/wip` — Stable but under active revision
layer/*:
- `layer/content` — Content assets (audio, models, textures, audio provenance)
- `layer/gdext` — gdext wrapper layer (`rust/gdext-wrapper/`)
- `layer/gdscript` — GDScript (Godot scene-tier logic)
- `layer/infra` — Build, CI, deployment infrastructure
- `layer/python` — Python development tooling (`tools/`)
- `layer/rust-core` — Engine-agnostic Rust core (`rust/rust-core/`)
concept/*:
- `concept/biome` — Biome-reactive behavior across systems
- `concept/contamination` — Across-runs panel and garage degradation; the slow-horror mechanic that doesn't reset with the world
- `concept/diegetic` — Diegetic audio / UI / world-sourced design
- `concept/disturbance` — The disturbance mechanic thread (Article X)
- `concept/ephemeral-world` — Run-reset, transient worlds (Article IV Rules 6–7)
- `concept/governance` — Constitutional and governance concepts
- `concept/horror` — Horror register and dread design
- `concept/procedural` — Procedural generation, seed determinism
- `concept/rendering` — Visual rendering quality, shader correctness, Terrain3D integration, mesh fidelity, LOD, Z-fighting
- `concept/terrain` — Terrain generation, heightmap, Terrain3D regions, roughness, playability constraints
ember's answer for tag_assignment-code-generation-subsystem-pairs, concept/proceduralP(true) placed on the no, unsure, and yes zones.nounsureyesgold: yesP = 0.22

tag_assignment-code-generation-subsystem-pairs: domain/world

Tag assignment · test
Gold
The note calls for `domain/world`: World model, biomes, terrain, procedural generation, weather (True)
ember
The note has no reason to carry `domain/world` (False)
Signal
P(true) 0.34 (unsure)
Kit outcome
deferred: treated as unsure
Why this gold label
Mined from Code/Generation Subsystem Pairs.md at 692f4bb58b7f62105aeb73fba8dfee12bfdecd53; gold is the note's own vocabulary tags.
Generation Subsystem Pairs

Every computationally intensive generation subsystem follows a three-layer architecture: a GDScript shell owns scene management, `@export` parameters, and signal wiring; a Rust core module (`rust-core/src/`) implements pure algorithms with zero Godot dependencies; and a GDExtension bridge (`rust/gdext-wrapper/src/`) converts types between the two layers. This note inventories every subsystem pair in the codebase and documents which responsibilities live at which layer.

## The Delegation Pattern

GDScript shells follow a consistent pattern:

```gdscript
var _rust: Object = null

func _init() -> void:
    if ClassDB.class_exists("XxxNode"):
        _rust = ClassDB.instantiate("XxxNode")
    else:
        push_warning("[Xxx] XxxNode not found — GDExtension not loaded")
```

The shell holds the Godot reference (`_rust`), calls Rust methods for compute, and handles all node instantiation, scene tree operations, and user-facing property exposure. Fallback paths handle the case where the GDExtension dylib has not been compiled or loaded.

## All Subsystem Pairs

### Terrain Generation

| Layer | File | Responsibility |
|---|---|---|
| GDScript shell | `src/scripts/generation/terrain_generator.gd` | Terrain3D region creation, Image writes, map updates, boundary/roughness parameter passthrough |
| Rust core | `rust/rust-core/src/terrain.rs` | Noise sampling (fastnoise-lite), heightmap generation, boundary ring computation, roughness fractal noise, center basin depression |
| Bridge | `rust/gdext-wrapper/src/terrain_bridge.rs` | Exposes `TerrainComputeNode` — receives config struct, returns heightmap regions and boundary data |

Also in this group:
- `src/scripts/generation/terrain_texture_painter.gd` — texture painting (pure GDScript, no Rust pair — uses Terrain3D texture API)
- `src/scripts/generation/terrain_setup.gd` — Terrain3D camera binding (pure GDScript, no Rust pair)
- `src/scripts/generation/noise_helper.gd` — noise utility (pure GDScript RefCounted)

### Road Network

| Layer | File | Responsibility |
|---|---|---|
| GDScript shell | `src/scripts/generation/road_network_generator.gd` | Curve3D extraction, playability validation, debug visualization, @export topology parameters |
| Rust core | `rust/rust-core/src/road/` (10 files) | Hub-and-spoke topology, A* routing on terrain cost grid, intersection management, spline generation, density computation, dead-end elimination |
| Bridge | `rust/gdext-wrapper/src/road_bridge.rs` | Exposes `RoadGeneratorNode` — receives entry/exit data and terrain, returns segment dictionaries with Curve3D-compatible points |

Road subsystem details:
- `rust/rust-core/src/road/generator.rs` — road network generation (highway, county, logging road placement)
- `rust/rust-core/src/road/graph.rs` — graph topology, node connections
- `rust/rust-core/src/road/intersection.rs` — dead-end elimination, leaf-node pruning, connector placement
- `rust/rust-core/src/road/spline.rs` — path-to-spline conversion, bezier curves
- `rust/rust-core/src/road/path_utils.rs` — terrain-aware A* pathfinding
- `rust/rust-core/src/road/mesh_geometry.rs` — road cross-section and mesh vertex data (consumed by GDScript mesh extruder)
- `rust/rust-core/src/road/types.rs` — shared types (RoadSegment, RoadType, NetworkStats)
- `rust/rust-core/src/road/density.rs` — road network density metrics
- `rust/rust-core/src/road/terrain.rs` — terrain slope query helpers for road placement

GDScript companions (no GDExtension bridge — pure Godot API):
- `src/scripts/generation/road_mesh_generator.gd` — mesh extrusion, terrain flattening, hub flattening
- `src/scripts/generation/road_path_utils.gd` — cost grid building, terrain queries, pathfinding aids (pure GDScript RefCounted; the Rust `road/path_utils.rs` provides parallel implementations consumed by the Rust road generator, not delegated from this file)
- `src/scripts/generation/road_prop_activation_manager.gd` — prop visibility culling

### Biome Generation

| Layer | File | Responsibility |
|---|---|---|
| GDScript shell | `src/scripts/generation/biome_generator.gd` | Config building, biome config Resource loading, callable wrappers for biome lookup/blend queries |
| Rust core | `rust/rust-core/src/biome.rs` | Voronoi cell subdivision, biome assignment with preference weighting, blend factor computation, transition bands |
| Bridge | `rust/gdext-wrapper/src/biome_bridge.rs` | Exposes `BiomeGeneratorNode` — receives world bounds and config, returns cell centers + biome assignments + blend queries |

### Vegetation Scatter

| Layer | File | Responsibility |
|---|---|---|
| GDScript shell | `src/scripts/generation/vegetation_scatter.gd` | Terrain3D MultiMesh instancer, biome density lookup, tree variant assignment, collision setup |
| Rust core | `rust/rust-core/src/vegetation.rs` | Poisson-disc rejection sampling, road grid construction, spawn exclusion, corridor zone filtering, biome-aware density weighting |
| Bridge | `rust/gdext-wrapper/src/vegetation_bridge.rs` | Exposes methods for generate_tree_positions_only() and full scatter() — receives road centerpoints, config, returns positioned arrays |

Also in this group:
- `src/scripts/generation/tree_collision_manager.gd` — Area3D collision for trees (pure GDScript)

### Exit Points

| Layer | File | Responsibility |
|---|---|---|
| GDScript shell | `src/scripts/generation/exit_point_manager.gd` | Entry/exit data assembly, position conversion |
| Rust core | `rust/rust-core/src/exit_points.rs` | Edge exit placement with terrain-aware sampling, minimum separation enforcement |
| Bridge | `rust/gdext-wrapper/src/exit_point_bridge.rs` | Exposes `ExitPointManagerNode` — receives world bounds and RNG, returns exit positions |

### Road Structures

| Layer | File | Responsibility |
|---|---|---|
| GDScript shell | `src/scripts/generation/road_structure_scatter.gd` | Scene instantiation, biome tinting, collision setup, visibility management |
| Rust core | `rust/rust-core/src/structures.rs` | Candidate generation, apex detection, spacing filter, type assignment (power poles, signs, derelict vehicles, env props), prop position generation |
| Bridge | `rust/gdext-wrapper/src/structures_bridge.rs` | Exposes methods for structure/prop position generation — receives road sample data and config, returns candidate arrays |

Note: Only candidate computation is in Rust. Curve3D sampling, Terrain3D height queries, and scene instantiation remain in GDScript.

### Weather Zones

| Layer | File | Responsibility |
|---|---|---|
| GDScript shell | `src/scripts/systems/weather_zone_system.gd` | Zone scene nodes, particle systems, weather state transitions |
| Rust core | `rust/rust-core/src/weather/` (10 files) | Zone placement, biome hysteresis, state machine, front propagation, fog density, exposure computation, traction/wetness modeling |
| Bridge | `rust/gdext-wrapper/src/weather_zones_bridge.rs`, `weather_simulator_bridge.rs`, `weather_biome_hysteresis_bridge.rs`, `weather_exposure_bridge.rs`, `weather_fog_bridge.rs`, `weather_traction_bridge.rs`, `weather_wetness_bridge.rs` | 7 bridge files exposing `WeatherZoneNode`, `WeatherSimulatorNode`, and per-component nodes |

### Autoload Delegation (GameState + Disturbance)

These are not generation subsystems but follow the same thin-shell pattern:

| Layer | GDScript | Rust Core | Bridge |
|---|---|---|---|
| GameState | `src/autoloads/game_state.gd` — backing variables, enum definitions, signal emission, `generate_seed()` | `rust/rust-core/src/game_state.rs` — change-detection callbacks, default values | `rust/gdext-wrapper/src/game_state_bridge.rs` — `GameStateNode` with validator methods |
| Disturbance | `src/autoloads/disturbance.gd` — `@export` thresholds, signal wiring, `add()` wrapper | `rust/rust-core/src/disturbance.rs` — arithmetic, clamping, threshold-crossing detection | `rust/gdext-wrapper/src/disturbance_bridge.rs` — `DisturbanceNode` with `add()` returning old/new level + state |

Key constraint for all three autoloads `Events`, `GameState`, `Disturbance`: `class_name` must never appear on an autoload script — the engine registers autoloads under their configured singleton name and a matching `class_name` produces duplicate registration conflicts.

## Summary Table

| Subsystem | GDScript Shell | Rust Core Module | Bridge File(s) | Rust Migration |
|---|---|---|---|---|
| Terrain | `terrain_generator.gd` | `terrain.rs` | `terrain_bridge.rs` | Complete |
| Road Network | `road_network_generator.gd` | `road/` (10 files) | `road_bridge.rs` | Complete |
| Biome | `biome_generator.gd` | `biome.rs` | `biome_bridge.rs` | Complete |
| Vegetation | `vegetation_scatter.gd` | `vegetation.rs` | `vegetation_bridge.rs` | Complete (candidates) |
| Exit Points | `exit_point_manager.gd` | `exit_points.rs` | `exit_point_bridge.rs` | Complete |
| Structures | `road_structure_scatter.gd` | `structures.rs` | `structures_bridge.rs` | Partial (candidates only) |
| Weather Zones | `weather_zone_system.gd` | `weather/` (10 files) | 7 bridge files | Partial (zones + simulator complete, per-system in progress) |
| GameState | `game_state.gd` (autoload) | `game_state.rs` | `game_state_bridge.rs` | Complete |
| Disturbance | `disturbance.gd` (autoload) | `disturbance.rs` | `disturbance_bridge.rs` | Complete |

## Related

- [[World — Procedural Generation]] — the pipeline these subsystems implement
- [[Rust — Core]] — the engine-agnostic core layer
- [[Rust — GDExt Wrapper]] — the bridge layer
- [[Code]] — folder MOC
- [[World — Domain MOC]] — domain MOC
- [[Constitution]] — Article III (Rust-first), Article IV (seed determinism)

Controlled tag vocabulary (as read):
type/*:
- `type/code` — Code architecture, autoloads, conventions, tooling. Carries `code-refs:`. (e.g. `Code/Autoloads — Disturbance.md`)
- `type/decision` — Architectural or design decision made by an agent during a session. Written to `docs/vault/Decisions/`. (Agent notes only — spec 080.)
- `type/design` — Design intent, player-facing concepts, world lore. (e.g. `Design/World Model.md`)
- `type/discovery` — Non-obvious constraint, gap, or conflict found by an agent during a session. Written to `docs/vault/Discoveries/`. (Agent notes only — spec 080.)
- `type/moc` — Map of Content at any of three tiers (folder / domain / concept). (e.g. `Audio.md`)
- `type/principle` — Governance and constitutional notes. Non-negotiable rules. (e.g. `Governance/Constitution.md`)
- `type/reference` — Glossary, decision log, open questions, epics. (e.g. `Reference/Glossary.md`)
- `type/session-log` — Session activity log; permanent audit trail. Written to `docs/vault/Sessions/`. Append-only, never pruned. (Agent notes only — spec 080.)
- `type/spec` — Spec document at `docs/vault/Specs/NNN Title/spec.md`. Carries `spec-refs:`. (e.g. `Specs/047 Car Radio/spec.md`)
- `type/system` — A bounded subsystem with implementation. Carries `code-refs`, `spec-refs`, `implements:` frontmatter. (e.g. `Systems/Audio — Car Radio.md`)
- `type/vision` — Strategic / vision-layer decision. Written to `docs/vault/Vision/`. Human-authored or agent-proposed with human ratification before promotion to `status: reviewed`. (Per triage #3 — spec 133 autonomous-company redesign.)
domain/*:
- `domain/anomalies` — Anomaly taxonomy, individual anomaly systems, spawn, behavior
- `domain/art` — Visual direction, palettes, references, asset pipeline
- `domain/audio` — Audio systems: world ambient, radio, transmissions, buses, pipeline
- `domain/autonomous-company` — Autonomous company v0.1 experiment: Slack infra, persona middleware, Letta integration, restart recovery
- `domain/build` — Build system, packaging, export, release automation
- `domain/governance` — Constitution, phased spec, policies
- `domain/infrastructure` — Infrastructure provisioning: CI/CD, hosting, deployment tooling, secrets management
- `domain/narrative` — Tone, horror register, forest transmissions narrative, Gary/KTLK
- `domain/player` — Player mode, input, controls, camera, exit/entry
- `domain/systems` — Cross-cutting system architecture and integration work
- `domain/tooling` — Build, CI, observer, TTS pipeline, dev-time tools
- `domain/vehicle` — The Samba: vehicle physics, dashboard, damage, panels
- `domain/world` — World model, biomes, terrain, procedural generation, weather
status/*:
- `status/canonical` — Fully authoritative; promoted by humans only. Highest trust. (Agent notes only — spec 080.)
- `status/draft` — Authoring in progress, not yet verified
- `status/reviewed` — Agent-created note verified against codebase within its creating session. Eligible for auto-injection in subsequent task dispatches. (Agent notes only — spec 080.)
- `status/stale` — Known out of date; cannot update immediately. Pairs with `> [!warning] STALE — needs update` callout.
- `status/superseded` — Replaced by another note. Terminal state. Pairs with `> [!warning] SUPERSEDED` callout.
- `status/wip` — Stable but under active revision
layer/*:
- `layer/content` — Content assets (audio, models, textures, audio provenance)
- `layer/gdext` — gdext wrapper layer (`rust/gdext-wrapper/`)
- `layer/gdscript` — GDScript (Godot scene-tier logic)
- `layer/infra` — Build, CI, deployment infrastructure
- `layer/python` — Python development tooling (`tools/`)
- `layer/rust-core` — Engine-agnostic Rust core (`rust/rust-core/`)
concept/*:
- `concept/biome` — Biome-reactive behavior across systems
- `concept/contamination` — Across-runs panel and garage degradation; the slow-horror mechanic that doesn't reset with the world
- `concept/diegetic` — Diegetic audio / UI / world-sourced design
- `concept/disturbance` — The disturbance mechanic thread (Article X)
- `concept/ephemeral-world` — Run-reset, transient worlds (Article IV Rules 6–7)
- `concept/governance` — Constitutional and governance concepts
- `concept/horror` — Horror register and dread design
- `concept/procedural` — Procedural generation, seed determinism
- `concept/rendering` — Visual rendering quality, shader correctness, Terrain3D integration, mesh fidelity, LOD, Z-fighting
- `concept/terrain` — Terrain generation, heightmap, Terrain3D regions, roughness, playability constraints
ember's answer for tag_assignment-code-generation-subsystem-pairs, domain/worldP(true) placed on the no, unsure, and yes zones.nounsureyesgold: yesP = 0.34

tag_assignment-design-anomalies: type/design

Tag assignment · test
Gold
The note calls for `type/design`: Design intent, player-facing concepts, world lore. (e.g. `Design/World Model.md`) (True)
ember
The note has no reason to carry `type/design` (False)
Signal
P(true) 0.43 (unsure)
Kit outcome
deferred: treated as unsure
Why this gold label
Mined from Design/Anomalies.md at 692f4bb58b7f62105aeb73fba8dfee12bfdecd53; gold is the note's own vocabulary tags.
Anomalies

The seven anomalies of Old Growth with their authoritative mechanical specifications, plus the framework for *what moves in the wood* (which is NOT a creature system), world-generation anomaly placement rules, and per-biome weather. The World Bible describes anomalies phenomenologically; this note captures the GDD's precise values alongside the tonal framing. Values marked `[PENDING]` require playtesting.

## Overview

The forest manifests seven distinct phenomena. They were happening before the first vehicle entered the tree line; they will happen after the last one is incorporated. Each anomaly has a visual signature, an audio signature, a disturbance cost, and a damage profile — but the design intent is that the player should learn these signatures *empirically*, not from a manual.

## Design Intent

Anomalies are the condition at concentration. Each one is a design decision about what rule of the world is breaking. Per Article XII-J: dread over shock, the unknown, the uncanny valley. Anomalies are *almost-natural before they become overtly strange*.

**Important**: the AI system previously specified for "Hollows" is **removed from canon**. There are no spawnable enemy units, no health pools for targets, no combat loop. What the player perceives moving in the wood is the condition at a different concentration — present, attending, without form that can be reliably described or counted. See "What Moves in the Wood" below.

## Key Decisions

### Deadfall

A tree falls across the road. The angle is wrong for wind; the break point is too low for rot; the timing is too precise for coincidence.

| Property | Value |
|---|---|
| Trigger distance | 30m vehicle approach |
| Warning audio | 3-second pre-fall creak |
| Fall duration | 2 seconds |
| Road clearance | Full width blocked |
| Samba collision damage | 25 HP at full impact |
| Off-road bypass | Available, terrain-dependent |
| Disturbance cost | +2 on trigger |

Avoidable by hard braking before 10m or by off-road bypass. The tree remains blocking for the remainder of the run.

### Spore Clouds

Drifting bioluminescent matter. Inside the bus reads as weather. Outside it is different — the cough comes later.

| Property | Value |
|---|---|
| Cloud diameter | 20–40m |
| Movement | Slow drift, unpredictable direction |
| Windshield full coating | 4s of contact |
| Wiper effectiveness through cloud | 30% |
| On-foot vision reduction | 60% |
| On-foot exposure gain | +5 / 10s |
| Persistent windshield coating after exit | clears over 30s with wipers |

### Hollow Trees

A blackened husk that should have fallen decades ago. Instruments drift; the engine loses conviction.

| Property | Value |
|---|---|
| Detection radius (instruments) | 20m |
| Detection radius (engine power) | 10m |
| Engine power reduction | −40% |
| Near-failure radius | 5m |
| Visual signature | Blackened husk, 15–20m tall, no canopy |
| Light behavior | Absorbs, does not reflect |
| Disturbance cost | None — passive |

Condition concentration is suppressed within 30m of a Hollow Tree. The interference field disrupts the condition's local expression *as well as* the bus's instruments.

### Amber Bleed

Amber light at trail edges, in hollows, in clearings. Identical to exit lanterns in appearance — but without the gate, without the wind-chime audio, without the road.

| Property | Value |
|---|---|
| Visual | Identical to exit lanterns |
| Audio signature | None — no wind chime |
| Physical structure | None — no gate frame |
| Road placement | Off-road, in clearings, at trail edges |
| Distinguishing features | No gate structure, no road surface, no wind chime |

Not a direct-damage hazard. It is a **navigation hazard**. Following it into deep terrain without a gate structure wastes fuel and time and feeds disturbance.

### Mycelium Network

White threads covering the ground. They have already found.

| Property | Value |
|---|---|
| Thread visibility | Clearly visible |
| Contact trigger | Any vehicle contact |
| Chain propagation | Instant across whole network |
| Spore burst radius | 15m from contact |
| Samba exterior damage | −10 HP |
| On-foot exposure gain | +10 per contact |
| Disturbance cost | +4 per contact |
| Thread regrowth | None within the run |

Spore burst damages exterior panels only. Interior contamination from seeping spores accumulates in persistent state across runs.

### Petrified Zones

Active calcification. Responds to stillness.

| Property | Value |
|---|---|
| Zone radius | 30–80m (varies) |
| Vehicle minimum speed | 30 km/h |
| Calcification onset | <30 km/h |
| Symptoms | Heavy steering, throttle resistance, grey particulate on seams |
| Engine seizure threshold | 0 km/h for >5s |
| Engine seizure effect | Permanent for that run |
| On-foot petrification | Stationary >3s → death |
| Visual indicator | Grey particulate at zone boundary |

An engine-seized bus cannot be repaired in the field. The player must abandon the bus and reach an exit on foot — a death sentence in most circumstances, intended as such. On-foot survival requires continuous movement; crouch-walking (2 m/s) is sufficient and recommended (silent + slow + above petrification threshold).

### The Silence

All environmental sound ceases. What remains is the player's own heartbeat.

| Property | Value |
|---|---|
| Zone radius | 40m |
| Audio effect | All environmental sound ceases — heartbeat only |
| Condition visibility | Zero |
| Presence audio | Zero |
| Duration | Permanent per run |
| Warning | Gradual audio fade over 5m approach, then instant silence |
| Disturbance cost | None — passive |

The only warning of presence is physical contact. Traverse in the bus at maximum speed. On foot, extremely dangerous — no warning system at all.

### What Moves in the Wood

**Canon position**: the wood produces nothing. The condition does not generate creatures, spawn enemies, or deploy outputs. What the player perceives moving in the wood is the condition at a different concentration — present, attending, without form that can be reliably described or counted.

Whether what moves in the wood is physical is a design question that remains deliberately open. Presence and physicality are not the same thing. The condition has been running long enough that the distinction has been resolved in a direction that does not map to anything the player was taught before entering this watershed.

**Mechanical implications**: the AI system previously specified for "Hollows" is **removed from canon**. There are no spawnable enemy units, no health pools for targets, no combat loop. What replaces it is environmental — the condition's presence is communicated through audio, disturbance-state escalation, instrument behavior, and the player's own unreliable perception at high exposure. The threat is the condition, not things the condition sends.

**On-foot contact (retained)**: at high disturbance and in anomaly zones, the player may experience contact events.

| Contact Type | Effect |
|---|---|
| Glancing contact | −10 HP, stumble (noise event +15m radius) |
| Sustained contact | −15 HP/sec continuous, movement restricted |
| Escape | Sprint input, −30 stamina, +20m noise event |

The source of contact is not rendered as a discrete entity. Implementation approach `[PENDING — requires dedicated spec for environmental presence system]`.

**The Silence zone contact (retained)**: inside The Silence, contact events occur without visual or audio warning. The heartbeat is the only instrument. This behavior is preserved — the mechanism of contact is not a creature but the condition expressing itself at maximum concentration in a zone where all other sensory input has been removed.

### Anomaly Placement (World Generation Rules)

| Anomaly | Biomes | Min per World | Max per World |
|---|---|---|---|
| Deadfall | Verdant, Fungal | 2 | 6 |
| Spore Clouds | Fungal | 3 | 8 |
| Hollow Trees | All | 1 | 4 |
| Amber Bleed | All | 2 | 5 |
| Mycelium Network | Fungal | 2 | 5 |
| Petrified Zones | Petrifold | 2 | 4 |
| The Silence | Petrifold | 1 | 2 |

Anomalies do not spawn within 50m of the garage (crater center). Amber Bleed clusters are placed to create navigational ambiguity near exit zones.

### Weather Systems

**Verdant Old Growth weather**:

| Condition | Probability | Effect |
|---|---|---|
| Rain | 60% | Wipers required, wet road physics |
| Fog | 20% | Visibility reduction, headlights scatter |
| Clear | 20% | Optimal visibility; slight disturbance cost for headlights |

**Fungal Depths weather**:

| Condition | Probability | Effect |
|---|---|---|
| Spore haze | 100% | Permanent. Reduces effective headlight range. No rain. |

**Petrifold weather**:

| Condition | Probability | Effect |
|---|---|---|
| Still | 100% | No wind. No rain. No weather events of any kind. |

**Winter conditions** (Verdant and transitional zones) — apply as a world modifier, not a weather event. Some seeds generate winter worlds.

| Condition | Effect |
|---|---|
| Snow accumulation | Terrain traction reduced |
| Black ice | Intermittent patches, severe traction loss |
| Frozen bridges | Complete traction loss, potential sliding |
| Blizzard | Visibility <10m, on-foot cold exposure −5 HP/sec |

**Road surface physics**:

| Surface | Handling |
|---|---|
| Dry | Baseline |
| Wet | −20% traction |
| Muddy | −35% traction |
| Snow | −40% traction |
| Ice | −70% traction |
| Frozen bridge | −85% traction |

### World Generation — Seed and Parameters

Each run initialized with a player-selected seed from the garage wall map (numeric identifiers). Same seed always produces same world geometry, biome distribution, structure placement, anomaly positions. Condition concentration zones are seeded but vary in expression each run.

| Parameter | Value |
|---|---|
| World size | 3072m × 3072m (~9.4 km²; expanded during Phase 6 development) |
| Boundary | Crater rim — the eroded wall of the impact basin (see [[The Crater]]) |
| Entry point | Garage at crater center (the vertex) |
| Exit corridors | 1–3 breach points in the crater rim (edges of the geometry; fold back to garage) |
| Structures per world | 15–20 |
| Biome count | 1–3 (all three always present above minimum area threshold) |

**Road network** procedurally generated within each seed. All roads navigable by the Samba under normal conditions. Surface type affects handling and noise.

| Surface | Handling | Noise (engine) | Notes |
|---|---|---|---|
| Gravel | Standard | +15% | Stones audible against undercarriage |
| Asphalt (degraded) | Good | Standard | Rare, near older structures |
| Dirt | Reduced traction | Standard | Common in Fungal Depths |
| Mud | Poor traction | Standard | Rain conditions |
| Ice / snow | Severe reduction | Standard | Winter conditions |

**Biome distribution rules**:
- Verdant Old Growth always contains the entry point; the player begins each run from the garage at the crater center (see The Crater).
- Petrifold always the deepest biome — furthest average distance from entry.
- Fungal Depths occupies the middle zone.
- All three biomes must be present above minimum area thresholds.
- Exit gates may appear in any biome.

**Required generator QA** (run per seed before delivery): garage connects to ≥1 exit corridor via driveable road; no impassable dead ends without off-road bypass; minimum road density per biome zone; anomaly placement clearance from garage (50m min); exit gate placement clearance from Storm spawn (must be accessible).

## How It Appears In-Game

The player learns anomaly signatures visually and aurally. Audio warnings precede visual contact for most anomalies. Visual language is consistent so that the forest teaches its own grammar (Article XII-G). The [[Biomes]] section documents which anomalies are most common in which biome.

## Related

- [[The Crater]] — the origin event that created the conditions for anomalous phenomena
- [[The Temporal Fracture]] — anomalies as temporal layer bleed-through
- [[World Model]] — the structural context
- [[Biomes]] — where each anomaly concentrates
- [[Tone and Horror]] — the phenomenological framing
- [[Disturbance System]] — anomaly costs feed disturbance
- [[Core Mechanics]] — how anomalies interact with the run loop
- [[Anomalies]] (domain MOC) — all anomaly-tagged notes
- [[Constitution]] — Article XII-J (horror design)

## Agent Notes (backlinks)

- [[Anomalies and Combat — Placeholder Status]] — Current implementation status: placeholder only, specs written but no code, signal infrastructure ready

Controlled tag vocabulary (as read):
type/*:
- `type/code` — Code architecture, autoloads, conventions, tooling. Carries `code-refs:`. (e.g. `Code/Autoloads — Disturbance.md`)
- `type/decision` — Architectural or design decision made by an agent during a session. Written to `docs/vault/Decisions/`. (Agent notes only — spec 080.)
- `type/design` — Design intent, player-facing concepts, world lore. (e.g. `Design/World Model.md`)
- `type/discovery` — Non-obvious constraint, gap, or conflict found by an agent during a session. Written to `docs/vault/Discoveries/`. (Agent notes only — spec 080.)
- `type/moc` — Map of Content at any of three tiers (folder / domain / concept). (e.g. `Audio.md`)
- `type/principle` — Governance and constitutional notes. Non-negotiable rules. (e.g. `Governance/Constitution.md`)
- `type/reference` — Glossary, decision log, open questions, epics. (e.g. `Reference/Glossary.md`)
- `type/session-log` — Session activity log; permanent audit trail. Written to `docs/vault/Sessions/`. Append-only, never pruned. (Agent notes only — spec 080.)
- `type/spec` — Spec document at `docs/vault/Specs/NNN Title/spec.md`. Carries `spec-refs:`. (e.g. `Specs/047 Car Radio/spec.md`)
- `type/system` — A bounded subsystem with implementation. Carries `code-refs`, `spec-refs`, `implements:` frontmatter. (e.g. `Systems/Audio — Car Radio.md`)
- `type/vision` — Strategic / vision-layer decision. Written to `docs/vault/Vision/`. Human-authored or agent-proposed with human ratification before promotion to `status: reviewed`. (Per triage #3 — spec 133 autonomous-company redesign.)
domain/*:
- `domain/anomalies` — Anomaly taxonomy, individual anomaly systems, spawn, behavior
- `domain/art` — Visual direction, palettes, references, asset pipeline
- `domain/audio` — Audio systems: world ambient, radio, transmissions, buses, pipeline
- `domain/autonomous-company` — Autonomous company v0.1 experiment: Slack infra, persona middleware, Letta integration, restart recovery
- `domain/build` — Build system, packaging, export, release automation
- `domain/governance` — Constitution, phased spec, policies
- `domain/infrastructure` — Infrastructure provisioning: CI/CD, hosting, deployment tooling, secrets management
- `domain/narrative` — Tone, horror register, forest transmissions narrative, Gary/KTLK
- `domain/player` — Player mode, input, controls, camera, exit/entry
- `domain/systems` — Cross-cutting system architecture and integration work
- `domain/tooling` — Build, CI, observer, TTS pipeline, dev-time tools
- `domain/vehicle` — The Samba: vehicle physics, dashboard, damage, panels
- `domain/world` — World model, biomes, terrain, procedural generation, weather
status/*:
- `status/canonical` — Fully authoritative; promoted by humans only. Highest trust. (Agent notes only — spec 080.)
- `status/draft` — Authoring in progress, not yet verified
- `status/reviewed` — Agent-created note verified against codebase within its creating session. Eligible for auto-injection in subsequent task dispatches. (Agent notes only — spec 080.)
- `status/stale` — Known out of date; cannot update immediately. Pairs with `> [!warning] STALE — needs update` callout.
- `status/superseded` — Replaced by another note. Terminal state. Pairs with `> [!warning] SUPERSEDED` callout.
- `status/wip` — Stable but under active revision
layer/*:
- `layer/content` — Content assets (audio, models, textures, audio provenance)
- `layer/gdext` — gdext wrapper layer (`rust/gdext-wrapper/`)
- `layer/gdscript` — GDScript (Godot scene-tier logic)
- `layer/infra` — Build, CI, deployment infrastructure
- `layer/python` — Python development tooling (`tools/`)
- `layer/rust-core` — Engine-agnostic Rust core (`rust/rust-core/`)
concept/*:
- `concept/biome` — Biome-reactive behavior across systems
- `concept/contamination` — Across-runs panel and garage degradation; the slow-horror mechanic that doesn't reset with the world
- `concept/diegetic` — Diegetic audio / UI / world-sourced design
- `concept/disturbance` — The disturbance mechanic thread (Article X)
- `concept/ephemeral-world` — Run-reset, transient worlds (Article IV Rules 6–7)
- `concept/governance` — Constitutional and governance concepts
- `concept/horror` — Horror register and dread design
- `concept/procedural` — Procedural generation, seed determinism
- `concept/rendering` — Visual rendering quality, shader correctness, Terrain3D integration, mesh fidelity, LOD, Z-fighting
- `concept/terrain` — Terrain generation, heightmap, Terrain3D regions, roughness, playability constraints
ember's answer for tag_assignment-design-anomalies, type/designP(true) placed on the no, unsure, and yes zones.nounsureyesgold: yesP = 0.43

tag_assignment-discoveries-pre-commit-hook-unpublished-asset-block-is-full-tree-not-staged-file: status/draft

Tag assignment · dev
Gold
The note calls for `status/draft`: Authoring in progress, not yet verified (True)
ember
The note has no reason to carry `status/draft` (False)
Signal
P(true) 0.08 (no)
Kit outcome
acted on a wrong answer
Why this gold label
Mined from Discoveries/Pre-Commit Hook — Unpublished Asset Block is Full-Tree, Not Staged-File.md at 692f4bb58b7f62105aeb73fba8dfee12bfdecd53; gold is the note's own vocabulary tags.
Pre-Commit Hook — Unpublished Asset Block is Full-Tree, Not Staged-File

{During session 2026-06-06, attempting to commit an unrelated file (`docs/vault/.obsidian/graph.json`) was blocked by the pre-commit hook because texture files in `src/assets/` had been modified but not published to R2. The unpublished-assets check is a full-tree scan — not scoped to what's staged — which means any unshipped asset change blocks ALL commits on the branch.}

The pre-commit hook at `scripts/hooks/pre-commit` contains two separate asset-related checks with different scopes:

**Check 1 — Manifest staleness (line 80–136)**: Only runs when `manifest.yaml` is staged. Validates every entry in the staged manifest against the files on disk. If a file's SHA256 has changed, it rejects the commit with advice to run `publish.sh`.

**Check 2 — Unpublished assets (line 138–197)**: Always runs on every commit (when Python3 and `manifest.yaml` are available). It walks the entire `src/assets/` directory tree via `os.walk()`, reads the SHA256 of every file, and compares against the manifest. Any file that is either new or has a changed SHA256 is reported as "unpublished" — and the commit is blocked.

The critical behavioral detail: **Check 2 is not scoped to staged files**. It scans all files on disk under `src/assets/`, regardless of whether they are part of the current commit. This means:

- You can be working on a pure GDScript change
- A teammate's texture modifications are synced to your working tree (via a submodule update or LFS pull)
- Your commit of a single unrelated file is blocked
- The only resolution (short of `--no-verify`) is to publish the assets or revert the file changes

The check uses exit code 2 as an intermediate "warning" signal, but the bash wrapper treats both exit codes 1 and 2 as failures (line 189: `if [ $PUBLISH_EXIT -eq 2 ] || [ $PUBLISH_EXIT -eq 1 ]`), so there is no way to acknowledge and proceed — it is a hard block.

This is by design (FR-019: manifest integrity enforcement), but it's a non-obvious constraint for developers who are not working on assets. The only graceful path is `make publish-assets && git add src/assets/manifest.yaml`, which publishes and updates the manifest, clearing the block for all future commits.

## References

- `scripts/hooks/pre-commit` (lines 138–197)

Controlled tag vocabulary (as read):
type/*:
- `type/code` — Code architecture, autoloads, conventions, tooling. Carries `code-refs:`. (e.g. `Code/Autoloads — Disturbance.md`)
- `type/decision` — Architectural or design decision made by an agent during a session. Written to `docs/vault/Decisions/`. (Agent notes only — spec 080.)
- `type/design` — Design intent, player-facing concepts, world lore. (e.g. `Design/World Model.md`)
- `type/discovery` — Non-obvious constraint, gap, or conflict found by an agent during a session. Written to `docs/vault/Discoveries/`. (Agent notes only — spec 080.)
- `type/moc` — Map of Content at any of three tiers (folder / domain / concept). (e.g. `Audio.md`)
- `type/principle` — Governance and constitutional notes. Non-negotiable rules. (e.g. `Governance/Constitution.md`)
- `type/reference` — Glossary, decision log, open questions, epics. (e.g. `Reference/Glossary.md`)
- `type/session-log` — Session activity log; permanent audit trail. Written to `docs/vault/Sessions/`. Append-only, never pruned. (Agent notes only — spec 080.)
- `type/spec` — Spec document at `docs/vault/Specs/NNN Title/spec.md`. Carries `spec-refs:`. (e.g. `Specs/047 Car Radio/spec.md`)
- `type/system` — A bounded subsystem with implementation. Carries `code-refs`, `spec-refs`, `implements:` frontmatter. (e.g. `Systems/Audio — Car Radio.md`)
- `type/vision` — Strategic / vision-layer decision. Written to `docs/vault/Vision/`. Human-authored or agent-proposed with human ratification before promotion to `status: reviewed`. (Per triage #3 — spec 133 autonomous-company redesign.)
domain/*:
- `domain/anomalies` — Anomaly taxonomy, individual anomaly systems, spawn, behavior
- `domain/art` — Visual direction, palettes, references, asset pipeline
- `domain/audio` — Audio systems: world ambient, radio, transmissions, buses, pipeline
- `domain/autonomous-company` — Autonomous company v0.1 experiment: Slack infra, persona middleware, Letta integration, restart recovery
- `domain/build` — Build system, packaging, export, release automation
- `domain/governance` — Constitution, phased spec, policies
- `domain/infrastructure` — Infrastructure provisioning: CI/CD, hosting, deployment tooling, secrets management
- `domain/narrative` — Tone, horror register, forest transmissions narrative, Gary/KTLK
- `domain/player` — Player mode, input, controls, camera, exit/entry
- `domain/systems` — Cross-cutting system architecture and integration work
- `domain/tooling` — Build, CI, observer, TTS pipeline, dev-time tools
- `domain/vehicle` — The Samba: vehicle physics, dashboard, damage, panels
- `domain/world` — World model, biomes, terrain, procedural generation, weather
status/*:
- `status/canonical` — Fully authoritative; promoted by humans only. Highest trust. (Agent notes only — spec 080.)
- `status/draft` — Authoring in progress, not yet verified
- `status/reviewed` — Agent-created note verified against codebase within its creating session. Eligible for auto-injection in subsequent task dispatches. (Agent notes only — spec 080.)
- `status/stale` — Known out of date; cannot update immediately. Pairs with `> [!warning] STALE — needs update` callout.
- `status/superseded` — Replaced by another note. Terminal state. Pairs with `> [!warning] SUPERSEDED` callout.
- `status/wip` — Stable but under active revision
layer/*:
- `layer/content` — Content assets (audio, models, textures, audio provenance)
- `layer/gdext` — gdext wrapper layer (`rust/gdext-wrapper/`)
- `layer/gdscript` — GDScript (Godot scene-tier logic)
- `layer/infra` — Build, CI, deployment infrastructure
- `layer/python` — Python development tooling (`tools/`)
- `layer/rust-core` — Engine-agnostic Rust core (`rust/rust-core/`)
concept/*:
- `concept/biome` — Biome-reactive behavior across systems
- `concept/contamination` — Across-runs panel and garage degradation; the slow-horror mechanic that doesn't reset with the world
- `concept/diegetic` — Diegetic audio / UI / world-sourced design
- `concept/disturbance` — The disturbance mechanic thread (Article X)
- `concept/ephemeral-world` — Run-reset, transient worlds (Article IV Rules 6–7)
- `concept/governance` — Constitutional and governance concepts
- `concept/horror` — Horror register and dread design
- `concept/procedural` — Procedural generation, seed determinism
- `concept/rendering` — Visual rendering quality, shader correctness, Terrain3D integration, mesh fidelity, LOD, Z-fighting
- `concept/terrain` — Terrain generation, heightmap, Terrain3D regions, roughness, playability constraints
ember's answer for tag_assignment-discoveries-pre-commit-hook-unpublished-asset-block-is-full-tree-not-staged-file, status/draftP(true) placed on the no, unsure, and yes zones.nounsureyesgold: yesP = 0.08

tag_assignment-governance-component-semver-policy: type/principle

Tag assignment · test
Gold
The note has no reason to carry `type/principle` (False)
ember
The note calls for `type/principle`: Governance and constitutional notes. Non-negotiable rules. (e.g. `Governance/Constitution.md`) (True)
Signal
P(true) 0.66 (unsure)
Kit outcome
deferred: treated as unsure
Why this gold label
Mined from Governance/Component SemVer Policy.md at 692f4bb58b7f62105aeb73fba8dfee12bfdecd53; gold is the note's own vocabulary tags.
Component SemVer Policy

The canonical policy for component semantic versioning in Old Growth. Every first-party code file under `src/` is mapped to a component with its own SemVer. When files in a component change, the component's version MUST bump. CI (`make semver`) rejects PRs that violate this rule. This note operationalizes constitution Article III Rule 15.

## Overview

Semantic versioning in Old Growth operates at the **component level**, not the project level. A component is a bounded set of file paths under `src/` (e.g., all autoloads, all audio scripts, the terrain subsystem). The mapping and versions live in `src/component_versions.json`. CI enforces that every changed file belongs to a component whose version has been strictly bumped.

The single project-level version (game version) is tracked separately in `src/project.godot` `config/version=` and governed by different rules (see constitution Governance / Commit Strategy).

## Key Rules

### Scope

- Versioned files are first-party code under `src/`
- Vendored plugins under `src/addons/` are **excluded** (they have their own upstream versioning)
- Component definitions and versions live in `src/component_versions.json`

### Strict bump rule

If any file mapped to a component changes in a PR, that component's version MUST be bumped.

| Bump level | When |
|------------|------|
| **major** | Breaking API or contract change |
| **minor** | Backward-compatible feature addition |
| **patch** | Backward-compatible fix or refactor |

CI fails when a changed component does not have a strictly greater version than baseline (the merge-base with `main`).

### Registry format

`src/component_versions.json` structure:

- `schema_version` — integer registry schema version
- `components.<component_name>.version` — `MAJOR.MINOR.PATCH`
- `components.<component_name>.paths` — list of path prefixes mapped to that component

Example:

```json
{
  "schema_version": 1,
  "components": {
    "core-autoloads": {
      "version": "0.1.0",
      "paths": ["src/autoloads/"]
    }
  }
}
```

### Non-overlapping paths

A changed file must map to **exactly one** component. Overlapping paths are an error. Unmapped files are an error.

## Developer Workflow

1. Change files in a component.
2. Bump that component's version in `src/component_versions.json`.
3. Open a PR.
4. CI validates that every changed component has a strictly greater SemVer.

### Auto-bump via pre-commit hook

The pre-commit hook auto-bumps patch versions for components whose files have changed, if the developer forgot. This catches the common case. More significant bumps (minor/major) must be applied manually with justification.

### Local testing

- `make semver` — runs the same SemVer guard used in CI
- `make pre-commit` — runs semver + other fast checks
- `make all` — full CI-like pipeline

## Adding a New Component

1. Add a new `components.<name>` entry in `src/component_versions.json`
2. Set initial SemVer (recommended `0.1.0`)
3. Add one or more non-overlapping path prefixes under `paths`
4. Ensure paths do not point to `src/addons/`

## Common CI Failures

- **Unmapped files**: changed first-party files not covered by any component path
- **Ambiguous mapping**: a changed file matches multiple component paths
- **Missing bump**: component changed but version did not increase
- **Invalid SemVer**: version is not `MAJOR.MINOR.PATCH`

## Related

- [[Constitution]] — Article III Rule 15 is the authoritative source
- [[Build System]] — `make semver` and the CI pipeline
- [[Governance]] — folder MOC
- [[Tech Stack Review]] — what components exist and why

Controlled tag vocabulary (as read):
type/*:
- `type/code` — Code architecture, autoloads, conventions, tooling. Carries `code-refs:`. (e.g. `Code/Autoloads — Disturbance.md`)
- `type/decision` — Architectural or design decision made by an agent during a session. Written to `docs/vault/Decisions/`. (Agent notes only — spec 080.)
- `type/design` — Design intent, player-facing concepts, world lore. (e.g. `Design/World Model.md`)
- `type/discovery` — Non-obvious constraint, gap, or conflict found by an agent during a session. Written to `docs/vault/Discoveries/`. (Agent notes only — spec 080.)
- `type/moc` — Map of Content at any of three tiers (folder / domain / concept). (e.g. `Audio.md`)
- `type/principle` — Governance and constitutional notes. Non-negotiable rules. (e.g. `Governance/Constitution.md`)
- `type/reference` — Glossary, decision log, open questions, epics. (e.g. `Reference/Glossary.md`)
- `type/session-log` — Session activity log; permanent audit trail. Written to `docs/vault/Sessions/`. Append-only, never pruned. (Agent notes only — spec 080.)
- `type/spec` — Spec document at `docs/vault/Specs/NNN Title/spec.md`. Carries `spec-refs:`. (e.g. `Specs/047 Car Radio/spec.md`)
- `type/system` — A bounded subsystem with implementation. Carries `code-refs`, `spec-refs`, `implements:` frontmatter. (e.g. `Systems/Audio — Car Radio.md`)
- `type/vision` — Strategic / vision-layer decision. Written to `docs/vault/Vision/`. Human-authored or agent-proposed with human ratification before promotion to `status: reviewed`. (Per triage #3 — spec 133 autonomous-company redesign.)
domain/*:
- `domain/anomalies` — Anomaly taxonomy, individual anomaly systems, spawn, behavior
- `domain/art` — Visual direction, palettes, references, asset pipeline
- `domain/audio` — Audio systems: world ambient, radio, transmissions, buses, pipeline
- `domain/autonomous-company` — Autonomous company v0.1 experiment: Slack infra, persona middleware, Letta integration, restart recovery
- `domain/build` — Build system, packaging, export, release automation
- `domain/governance` — Constitution, phased spec, policies
- `domain/infrastructure` — Infrastructure provisioning: CI/CD, hosting, deployment tooling, secrets management
- `domain/narrative` — Tone, horror register, forest transmissions narrative, Gary/KTLK
- `domain/player` — Player mode, input, controls, camera, exit/entry
- `domain/systems` — Cross-cutting system architecture and integration work
- `domain/tooling` — Build, CI, observer, TTS pipeline, dev-time tools
- `domain/vehicle` — The Samba: vehicle physics, dashboard, damage, panels
- `domain/world` — World model, biomes, terrain, procedural generation, weather
status/*:
- `status/canonical` — Fully authoritative; promoted by humans only. Highest trust. (Agent notes only — spec 080.)
- `status/draft` — Authoring in progress, not yet verified
- `status/reviewed` — Agent-created note verified against codebase within its creating session. Eligible for auto-injection in subsequent task dispatches. (Agent notes only — spec 080.)
- `status/stale` — Known out of date; cannot update immediately. Pairs with `> [!warning] STALE — needs update` callout.
- `status/superseded` — Replaced by another note. Terminal state. Pairs with `> [!warning] SUPERSEDED` callout.
- `status/wip` — Stable but under active revision
layer/*:
- `layer/content` — Content assets (audio, models, textures, audio provenance)
- `layer/gdext` — gdext wrapper layer (`rust/gdext-wrapper/`)
- `layer/gdscript` — GDScript (Godot scene-tier logic)
- `layer/infra` — Build, CI, deployment infrastructure
- `layer/python` — Python development tooling (`tools/`)
- `layer/rust-core` — Engine-agnostic Rust core (`rust/rust-core/`)
concept/*:
- `concept/biome` — Biome-reactive behavior across systems
- `concept/contamination` — Across-runs panel and garage degradation; the slow-horror mechanic that doesn't reset with the world
- `concept/diegetic` — Diegetic audio / UI / world-sourced design
- `concept/disturbance` — The disturbance mechanic thread (Article X)
- `concept/ephemeral-world` — Run-reset, transient worlds (Article IV Rules 6–7)
- `concept/governance` — Constitutional and governance concepts
- `concept/horror` — Horror register and dread design
- `concept/procedural` — Procedural generation, seed determinism
- `concept/rendering` — Visual rendering quality, shader correctness, Terrain3D integration, mesh fidelity, LOD, Z-fighting
- `concept/terrain` — Terrain generation, heightmap, Terrain3D regions, roughness, playability constraints
ember's answer for tag_assignment-governance-component-semver-policy, type/principleP(true) placed on the no, unsure, and yes zones.nounsureyesgold: noP = 0.66

tag_assignment-governance-component-semver-policy: type/reference

Tag assignment · test
Gold
The note calls for `type/reference`: Glossary, decision log, open questions, epics. (e.g. `Reference/Glossary.md`) (True)
ember
The note has no reason to carry `type/reference` (False)
Signal
P(true) 0.02 (no)
Kit outcome
acted on a wrong answer
Why this gold label
Mined from Governance/Component SemVer Policy.md at 692f4bb58b7f62105aeb73fba8dfee12bfdecd53; gold is the note's own vocabulary tags.
Component SemVer Policy

The canonical policy for component semantic versioning in Old Growth. Every first-party code file under `src/` is mapped to a component with its own SemVer. When files in a component change, the component's version MUST bump. CI (`make semver`) rejects PRs that violate this rule. This note operationalizes constitution Article III Rule 15.

## Overview

Semantic versioning in Old Growth operates at the **component level**, not the project level. A component is a bounded set of file paths under `src/` (e.g., all autoloads, all audio scripts, the terrain subsystem). The mapping and versions live in `src/component_versions.json`. CI enforces that every changed file belongs to a component whose version has been strictly bumped.

The single project-level version (game version) is tracked separately in `src/project.godot` `config/version=` and governed by different rules (see constitution Governance / Commit Strategy).

## Key Rules

### Scope

- Versioned files are first-party code under `src/`
- Vendored plugins under `src/addons/` are **excluded** (they have their own upstream versioning)
- Component definitions and versions live in `src/component_versions.json`

### Strict bump rule

If any file mapped to a component changes in a PR, that component's version MUST be bumped.

| Bump level | When |
|------------|------|
| **major** | Breaking API or contract change |
| **minor** | Backward-compatible feature addition |
| **patch** | Backward-compatible fix or refactor |

CI fails when a changed component does not have a strictly greater version than baseline (the merge-base with `main`).

### Registry format

`src/component_versions.json` structure:

- `schema_version` — integer registry schema version
- `components.<component_name>.version` — `MAJOR.MINOR.PATCH`
- `components.<component_name>.paths` — list of path prefixes mapped to that component

Example:

```json
{
  "schema_version": 1,
  "components": {
    "core-autoloads": {
      "version": "0.1.0",
      "paths": ["src/autoloads/"]
    }
  }
}
```

### Non-overlapping paths

A changed file must map to **exactly one** component. Overlapping paths are an error. Unmapped files are an error.

## Developer Workflow

1. Change files in a component.
2. Bump that component's version in `src/component_versions.json`.
3. Open a PR.
4. CI validates that every changed component has a strictly greater SemVer.

### Auto-bump via pre-commit hook

The pre-commit hook auto-bumps patch versions for components whose files have changed, if the developer forgot. This catches the common case. More significant bumps (minor/major) must be applied manually with justification.

### Local testing

- `make semver` — runs the same SemVer guard used in CI
- `make pre-commit` — runs semver + other fast checks
- `make all` — full CI-like pipeline

## Adding a New Component

1. Add a new `components.<name>` entry in `src/component_versions.json`
2. Set initial SemVer (recommended `0.1.0`)
3. Add one or more non-overlapping path prefixes under `paths`
4. Ensure paths do not point to `src/addons/`

## Common CI Failures

- **Unmapped files**: changed first-party files not covered by any component path
- **Ambiguous mapping**: a changed file matches multiple component paths
- **Missing bump**: component changed but version did not increase
- **Invalid SemVer**: version is not `MAJOR.MINOR.PATCH`

## Related

- [[Constitution]] — Article III Rule 15 is the authoritative source
- [[Build System]] — `make semver` and the CI pipeline
- [[Governance]] — folder MOC
- [[Tech Stack Review]] — what components exist and why

Controlled tag vocabulary (as read):
type/*:
- `type/code` — Code architecture, autoloads, conventions, tooling. Carries `code-refs:`. (e.g. `Code/Autoloads — Disturbance.md`)
- `type/decision` — Architectural or design decision made by an agent during a session. Written to `docs/vault/Decisions/`. (Agent notes only — spec 080.)
- `type/design` — Design intent, player-facing concepts, world lore. (e.g. `Design/World Model.md`)
- `type/discovery` — Non-obvious constraint, gap, or conflict found by an agent during a session. Written to `docs/vault/Discoveries/`. (Agent notes only — spec 080.)
- `type/moc` — Map of Content at any of three tiers (folder / domain / concept). (e.g. `Audio.md`)
- `type/principle` — Governance and constitutional notes. Non-negotiable rules. (e.g. `Governance/Constitution.md`)
- `type/reference` — Glossary, decision log, open questions, epics. (e.g. `Reference/Glossary.md`)
- `type/session-log` — Session activity log; permanent audit trail. Written to `docs/vault/Sessions/`. Append-only, never pruned. (Agent notes only — spec 080.)
- `type/spec` — Spec document at `docs/vault/Specs/NNN Title/spec.md`. Carries `spec-refs:`. (e.g. `Specs/047 Car Radio/spec.md`)
- `type/system` — A bounded subsystem with implementation. Carries `code-refs`, `spec-refs`, `implements:` frontmatter. (e.g. `Systems/Audio — Car Radio.md`)
- `type/vision` — Strategic / vision-layer decision. Written to `docs/vault/Vision/`. Human-authored or agent-proposed with human ratification before promotion to `status: reviewed`. (Per triage #3 — spec 133 autonomous-company redesign.)
domain/*:
- `domain/anomalies` — Anomaly taxonomy, individual anomaly systems, spawn, behavior
- `domain/art` — Visual direction, palettes, references, asset pipeline
- `domain/audio` — Audio systems: world ambient, radio, transmissions, buses, pipeline
- `domain/autonomous-company` — Autonomous company v0.1 experiment: Slack infra, persona middleware, Letta integration, restart recovery
- `domain/build` — Build system, packaging, export, release automation
- `domain/governance` — Constitution, phased spec, policies
- `domain/infrastructure` — Infrastructure provisioning: CI/CD, hosting, deployment tooling, secrets management
- `domain/narrative` — Tone, horror register, forest transmissions narrative, Gary/KTLK
- `domain/player` — Player mode, input, controls, camera, exit/entry
- `domain/systems` — Cross-cutting system architecture and integration work
- `domain/tooling` — Build, CI, observer, TTS pipeline, dev-time tools
- `domain/vehicle` — The Samba: vehicle physics, dashboard, damage, panels
- `domain/world` — World model, biomes, terrain, procedural generation, weather
status/*:
- `status/canonical` — Fully authoritative; promoted by humans only. Highest trust. (Agent notes only — spec 080.)
- `status/draft` — Authoring in progress, not yet verified
- `status/reviewed` — Agent-created note verified against codebase within its creating session. Eligible for auto-injection in subsequent task dispatches. (Agent notes only — spec 080.)
- `status/stale` — Known out of date; cannot update immediately. Pairs with `> [!warning] STALE — needs update` callout.
- `status/superseded` — Replaced by another note. Terminal state. Pairs with `> [!warning] SUPERSEDED` callout.
- `status/wip` — Stable but under active revision
layer/*:
- `layer/content` — Content assets (audio, models, textures, audio provenance)
- `layer/gdext` — gdext wrapper layer (`rust/gdext-wrapper/`)
- `layer/gdscript` — GDScript (Godot scene-tier logic)
- `layer/infra` — Build, CI, deployment infrastructure
- `layer/python` — Python development tooling (`tools/`)
- `layer/rust-core` — Engine-agnostic Rust core (`rust/rust-core/`)
concept/*:
- `concept/biome` — Biome-reactive behavior across systems
- `concept/contamination` — Across-runs panel and garage degradation; the slow-horror mechanic that doesn't reset with the world
- `concept/diegetic` — Diegetic audio / UI / world-sourced design
- `concept/disturbance` — The disturbance mechanic thread (Article X)
- `concept/ephemeral-world` — Run-reset, transient worlds (Article IV Rules 6–7)
- `concept/governance` — Constitutional and governance concepts
- `concept/horror` — Horror register and dread design
- `concept/procedural` — Procedural generation, seed determinism
- `concept/rendering` — Visual rendering quality, shader correctness, Terrain3D integration, mesh fidelity, LOD, Z-fighting
- `concept/terrain` — Terrain generation, heightmap, Terrain3D regions, roughness, playability constraints
ember's answer for tag_assignment-governance-component-semver-policy, type/referenceP(true) placed on the no, unsure, and yes zones.nounsureyesgold: yesP = 0.02

tag_assignment-sessions-spawn-collision-mirror-mesh-visibility-and-glb-node-discovery-jun-06-2026: type/code

Tag assignment · test
Gold
The note has no reason to carry `type/code` (False)
ember
The note calls for `type/code`: Code architecture, autoloads, conventions, tooling. Carries `code-refs:`. (e.g. `Code/Autoloads — Disturbance.md`) (True)
Signal
P(true) 0.71 (unsure)
Kit outcome
deferred: treated as unsure
Why this gold label
Mined from Sessions/Spawn Collision, Mirror Mesh Visibility, and GLB Node Discovery — Jun 06 2026.md at 692f4bb58b7f62105aeb73fba8dfee12bfdecd53; gold is the note's own vocabulary tags.
Spawn Collision, Mirror Mesh Visibility, and GLB Node Discovery — Jun 06 2026

Spawn-drop collision still damages panels despite the Spec 156 grace system; MirrorSystem was hiding side mirror meshes on panel destruction, contradicting the damage system's ACCESSORY group visual contract; GLB-instanced nodes require recursive `find_child` for reliable lookup.

## Spawn Collision Damage Persists After Grace

`make run-debug` and MCP runtime session logs (seed 369614079) show a catastrophic 239886-force collision on `tire_rear_left` immediately after `[SambaBus] Spawn stabilization ended`:

```
[SambaBus] Spawn stabilization ended
[SambaBus] f=239886 pos=(1537.0,5.7,1537.0) n=(0.01,1.00,-0.00) obj=Terrain3D grp=[Grass]
[TireDamageDriver] CATASTROPHIC tire_rear_left force=239886 dist=0.59
[BusDamageSystem] damage: panel=window_side_left_rear amount=2398.9 state=2
```

The bus falls ~2m after waking from spawn stabilization, and the rear left tire contacts terrain with enough force to destroy panels. The 239886 force converts to 2398.9 damage (FORCE_TO_DAMAGE_SCALE=0.01), which destroys any panel with ≤100 HP.

Spec 156 implemented a two-stage grace (240 frames full immunity + 120 frames 50% mitigation, totalling 3s at 120Hz). This collision is happening AFTER the grace period expires — the stabilization ended, then physics woke the bus, then it fell 2m into terrain. The issue is not that grace is missing; it's that gravity-induced fall energy accumulates during the sleeping/stabilized period and releases as a single-frame impulse when the bus wakes.

**Resolution path**: Either extend the grace window to cover the fall-settle duration, or reduce the physics impulse on wake-up by positioning the bus at terrain height instead of above it.

## MirrorSystem Hides Side Mirror Meshes Inconsistently

Spec 034 (Rearview Mirrors) defines damage integration at FR-013 to FR-017: when a mirror panel is destroyed, its corresponding SubViewport should be disabled (surface goes dark). It does NOT specify hiding the mesh geometry.

The MirrorSystem implementation in `mirror_system.gd` was calling `_set_mesh_visible(_left_mesh, left_active)` and `_set_mesh_visible(_right_mesh, right_active)` where `right_active = not right_destroyed`. When `mirror_right` (ACCESSORY, 30 HP) was destroyed by the spawn collision, the MirrorSystem hid the entire mirror housing mesh — not just the viewport reflection.

The damage system's `_update_panel_visual` for ACCESSORY panels does NOT set `visible = false`. ACCESSORY panels lack the `detach` effect and are not in the GLASS group. The damage system only darkens the material (albedo × 0.25, roughness +0.4). The MirrorSystem was overriding this by hiding the geometry, making the mirror housing disappear completely instead of showing damaged/scuffed PBR material.

**Fix applied**: Removed `_set_mesh_visible` calls for side mirror meshes in both `_update_damage_state()` and `_apply_all_viewport_states()`. Only the rearview mirror (`mirror_rear`, a thin PlaneMesh with no structural presence) still toggles visibility with its viewport. Side mirror viewports are disabled on panel destruction (rendering surface dark), but the physical mesh stays visible.

## GLB Node Lookup Requires Recursive Search

Nodes inside a GLB-instanced PackedScene (`bus_lod0`) are not direct children of `BodyMesh`. They live at paths like `BodyMesh/LODController/LOD0/bus_lod0/door_left_front`. Code that uses `get_node_or_null("BodyMesh/door_left_front")` (direct child check) fails silently.

The `door_controller.gd` was creating placeholder `BoxMesh` nodes as direct children of `BodyMesh` because its `get_node_or_null` call couldn't find the real door mesh inside the GLB hierarchy. The placeholder was then found by `bus_damage_system.gd`'s `_find_panel_mesh` (which checks direct children first), causing the damage system to operate on a flat white BoxMesh instead of the real textured door mesh.

**Fix applied**: Door controller now uses a `_find_door_mesh()` helper that first tries direct lookup, then falls back to `body_mesh.find_child(door_name, true, false)` (recursive search). This pattern should be followed by any code that needs to find nodes inside GLB instances.

## References

- `src/scripts/bus/mirror_system.gd` — Mesh visibility fix
- `src/scripts/bus/door_controller.gd` — Recursive find fix
- `src/scripts/bus/samba_bus.gd` — Tire loading also uses fixed paths
- `src/scripts/bus/bus_damage_system.gd` — `_find_panel_mesh` uses recursive fallback
- `src/scripts/bus/bus_lod_controller.gd` — LOD range setup
- `src/scenes/bus/samba_bus.tscn` — Node paths reference LOD0 GLB nodes
- `docs/vault/Specs/034 Rearview Mirrors/034 Rearview Mirrors.md` — Mirror spec
- `docs/vault/Specs/156 Bus Damage Rebalance/156 Bus Damage Rebalance.md` — Damage spec
- `docs/vault/Decisions/Spec 156 — Collision Discrimination and Grace Design.md` — Grace system
- `docs/vault/Specs/068 Bus Asset Integration/PHASE_3_RCA.md` — GLB integration background

Controlled tag vocabulary (as read):
type/*:
- `type/code` — Code architecture, autoloads, conventions, tooling. Carries `code-refs:`. (e.g. `Code/Autoloads — Disturbance.md`)
- `type/decision` — Architectural or design decision made by an agent during a session. Written to `docs/vault/Decisions/`. (Agent notes only — spec 080.)
- `type/design` — Design intent, player-facing concepts, world lore. (e.g. `Design/World Model.md`)
- `type/discovery` — Non-obvious constraint, gap, or conflict found by an agent during a session. Written to `docs/vault/Discoveries/`. (Agent notes only — spec 080.)
- `type/moc` — Map of Content at any of three tiers (folder / domain / concept). (e.g. `Audio.md`)
- `type/principle` — Governance and constitutional notes. Non-negotiable rules. (e.g. `Governance/Constitution.md`)
- `type/reference` — Glossary, decision log, open questions, epics. (e.g. `Reference/Glossary.md`)
- `type/session-log` — Session activity log; permanent audit trail. Written to `docs/vault/Sessions/`. Append-only, never pruned. (Agent notes only — spec 080.)
- `type/spec` — Spec document at `docs/vault/Specs/NNN Title/spec.md`. Carries `spec-refs:`. (e.g. `Specs/047 Car Radio/spec.md`)
- `type/system` — A bounded subsystem with implementation. Carries `code-refs`, `spec-refs`, `implements:` frontmatter. (e.g. `Systems/Audio — Car Radio.md`)
- `type/vision` — Strategic / vision-layer decision. Written to `docs/vault/Vision/`. Human-authored or agent-proposed with human ratification before promotion to `status: reviewed`. (Per triage #3 — spec 133 autonomous-company redesign.)
domain/*:
- `domain/anomalies` — Anomaly taxonomy, individual anomaly systems, spawn, behavior
- `domain/art` — Visual direction, palettes, references, asset pipeline
- `domain/audio` — Audio systems: world ambient, radio, transmissions, buses, pipeline
- `domain/autonomous-company` — Autonomous company v0.1 experiment: Slack infra, persona middleware, Letta integration, restart recovery
- `domain/build` — Build system, packaging, export, release automation
- `domain/governance` — Constitution, phased spec, policies
- `domain/infrastructure` — Infrastructure provisioning: CI/CD, hosting, deployment tooling, secrets management
- `domain/narrative` — Tone, horror register, forest transmissions narrative, Gary/KTLK
- `domain/player` — Player mode, input, controls, camera, exit/entry
- `domain/systems` — Cross-cutting system architecture and integration work
- `domain/tooling` — Build, CI, observer, TTS pipeline, dev-time tools
- `domain/vehicle` — The Samba: vehicle physics, dashboard, damage, panels
- `domain/world` — World model, biomes, terrain, procedural generation, weather
status/*:
- `status/canonical` — Fully authoritative; promoted by humans only. Highest trust. (Agent notes only — spec 080.)
- `status/draft` — Authoring in progress, not yet verified
- `status/reviewed` — Agent-created note verified against codebase within its creating session. Eligible for auto-injection in subsequent task dispatches. (Agent notes only — spec 080.)
- `status/stale` — Known out of date; cannot update immediately. Pairs with `> [!warning] STALE — needs update` callout.
- `status/superseded` — Replaced by another note. Terminal state. Pairs with `> [!warning] SUPERSEDED` callout.
- `status/wip` — Stable but under active revision
layer/*:
- `layer/content` — Content assets (audio, models, textures, audio provenance)
- `layer/gdext` — gdext wrapper layer (`rust/gdext-wrapper/`)
- `layer/gdscript` — GDScript (Godot scene-tier logic)
- `layer/infra` — Build, CI, deployment infrastructure
- `layer/python` — Python development tooling (`tools/`)
- `layer/rust-core` — Engine-agnostic Rust core (`rust/rust-core/`)
concept/*:
- `concept/biome` — Biome-reactive behavior across systems
- `concept/contamination` — Across-runs panel and garage degradation; the slow-horror mechanic that doesn't reset with the world
- `concept/diegetic` — Diegetic audio / UI / world-sourced design
- `concept/disturbance` — The disturbance mechanic thread (Article X)
- `concept/ephemeral-world` — Run-reset, transient worlds (Article IV Rules 6–7)
- `concept/governance` — Constitutional and governance concepts
- `concept/horror` — Horror register and dread design
- `concept/procedural` — Procedural generation, seed determinism
- `concept/rendering` — Visual rendering quality, shader correctness, Terrain3D integration, mesh fidelity, LOD, Z-fighting
- `concept/terrain` — Terrain generation, heightmap, Terrain3D regions, roughness, playability constraints
ember's answer for tag_assignment-sessions-spawn-collision-mirror-mesh-visibility-and-glb-node-discovery-jun-06-2026, type/codeP(true) placed on the no, unsure, and yes zones.nounsureyesgold: noP = 0.71

tag_assignment-sessions-spawn-collision-mirror-mesh-visibility-and-glb-node-discovery-jun-06-2026: type/session-log

Tag assignment · test
Gold
The note calls for `type/session-log`: Session activity log; permanent audit trail. Written to `docs/vault/Sessions/`. Append-only, never pruned. (Agent notes only — spec 080.) (True)
ember
The note has no reason to carry `type/session-log` (False)
Signal
P(true) 0.06 (no)
Kit outcome
acted on a wrong answer
Why this gold label
Mined from Sessions/Spawn Collision, Mirror Mesh Visibility, and GLB Node Discovery — Jun 06 2026.md at 692f4bb58b7f62105aeb73fba8dfee12bfdecd53; gold is the note's own vocabulary tags.
Spawn Collision, Mirror Mesh Visibility, and GLB Node Discovery — Jun 06 2026

Spawn-drop collision still damages panels despite the Spec 156 grace system; MirrorSystem was hiding side mirror meshes on panel destruction, contradicting the damage system's ACCESSORY group visual contract; GLB-instanced nodes require recursive `find_child` for reliable lookup.

## Spawn Collision Damage Persists After Grace

`make run-debug` and MCP runtime session logs (seed 369614079) show a catastrophic 239886-force collision on `tire_rear_left` immediately after `[SambaBus] Spawn stabilization ended`:

```
[SambaBus] Spawn stabilization ended
[SambaBus] f=239886 pos=(1537.0,5.7,1537.0) n=(0.01,1.00,-0.00) obj=Terrain3D grp=[Grass]
[TireDamageDriver] CATASTROPHIC tire_rear_left force=239886 dist=0.59
[BusDamageSystem] damage: panel=window_side_left_rear amount=2398.9 state=2
```

The bus falls ~2m after waking from spawn stabilization, and the rear left tire contacts terrain with enough force to destroy panels. The 239886 force converts to 2398.9 damage (FORCE_TO_DAMAGE_SCALE=0.01), which destroys any panel with ≤100 HP.

Spec 156 implemented a two-stage grace (240 frames full immunity + 120 frames 50% mitigation, totalling 3s at 120Hz). This collision is happening AFTER the grace period expires — the stabilization ended, then physics woke the bus, then it fell 2m into terrain. The issue is not that grace is missing; it's that gravity-induced fall energy accumulates during the sleeping/stabilized period and releases as a single-frame impulse when the bus wakes.

**Resolution path**: Either extend the grace window to cover the fall-settle duration, or reduce the physics impulse on wake-up by positioning the bus at terrain height instead of above it.

## MirrorSystem Hides Side Mirror Meshes Inconsistently

Spec 034 (Rearview Mirrors) defines damage integration at FR-013 to FR-017: when a mirror panel is destroyed, its corresponding SubViewport should be disabled (surface goes dark). It does NOT specify hiding the mesh geometry.

The MirrorSystem implementation in `mirror_system.gd` was calling `_set_mesh_visible(_left_mesh, left_active)` and `_set_mesh_visible(_right_mesh, right_active)` where `right_active = not right_destroyed`. When `mirror_right` (ACCESSORY, 30 HP) was destroyed by the spawn collision, the MirrorSystem hid the entire mirror housing mesh — not just the viewport reflection.

The damage system's `_update_panel_visual` for ACCESSORY panels does NOT set `visible = false`. ACCESSORY panels lack the `detach` effect and are not in the GLASS group. The damage system only darkens the material (albedo × 0.25, roughness +0.4). The MirrorSystem was overriding this by hiding the geometry, making the mirror housing disappear completely instead of showing damaged/scuffed PBR material.

**Fix applied**: Removed `_set_mesh_visible` calls for side mirror meshes in both `_update_damage_state()` and `_apply_all_viewport_states()`. Only the rearview mirror (`mirror_rear`, a thin PlaneMesh with no structural presence) still toggles visibility with its viewport. Side mirror viewports are disabled on panel destruction (rendering surface dark), but the physical mesh stays visible.

## GLB Node Lookup Requires Recursive Search

Nodes inside a GLB-instanced PackedScene (`bus_lod0`) are not direct children of `BodyMesh`. They live at paths like `BodyMesh/LODController/LOD0/bus_lod0/door_left_front`. Code that uses `get_node_or_null("BodyMesh/door_left_front")` (direct child check) fails silently.

The `door_controller.gd` was creating placeholder `BoxMesh` nodes as direct children of `BodyMesh` because its `get_node_or_null` call couldn't find the real door mesh inside the GLB hierarchy. The placeholder was then found by `bus_damage_system.gd`'s `_find_panel_mesh` (which checks direct children first), causing the damage system to operate on a flat white BoxMesh instead of the real textured door mesh.

**Fix applied**: Door controller now uses a `_find_door_mesh()` helper that first tries direct lookup, then falls back to `body_mesh.find_child(door_name, true, false)` (recursive search). This pattern should be followed by any code that needs to find nodes inside GLB instances.

## References

- `src/scripts/bus/mirror_system.gd` — Mesh visibility fix
- `src/scripts/bus/door_controller.gd` — Recursive find fix
- `src/scripts/bus/samba_bus.gd` — Tire loading also uses fixed paths
- `src/scripts/bus/bus_damage_system.gd` — `_find_panel_mesh` uses recursive fallback
- `src/scripts/bus/bus_lod_controller.gd` — LOD range setup
- `src/scenes/bus/samba_bus.tscn` — Node paths reference LOD0 GLB nodes
- `docs/vault/Specs/034 Rearview Mirrors/034 Rearview Mirrors.md` — Mirror spec
- `docs/vault/Specs/156 Bus Damage Rebalance/156 Bus Damage Rebalance.md` — Damage spec
- `docs/vault/Decisions/Spec 156 — Collision Discrimination and Grace Design.md` — Grace system
- `docs/vault/Specs/068 Bus Asset Integration/PHASE_3_RCA.md` — GLB integration background

Controlled tag vocabulary (as read):
type/*:
- `type/code` — Code architecture, autoloads, conventions, tooling. Carries `code-refs:`. (e.g. `Code/Autoloads — Disturbance.md`)
- `type/decision` — Architectural or design decision made by an agent during a session. Written to `docs/vault/Decisions/`. (Agent notes only — spec 080.)
- `type/design` — Design intent, player-facing concepts, world lore. (e.g. `Design/World Model.md`)
- `type/discovery` — Non-obvious constraint, gap, or conflict found by an agent during a session. Written to `docs/vault/Discoveries/`. (Agent notes only — spec 080.)
- `type/moc` — Map of Content at any of three tiers (folder / domain / concept). (e.g. `Audio.md`)
- `type/principle` — Governance and constitutional notes. Non-negotiable rules. (e.g. `Governance/Constitution.md`)
- `type/reference` — Glossary, decision log, open questions, epics. (e.g. `Reference/Glossary.md`)
- `type/session-log` — Session activity log; permanent audit trail. Written to `docs/vault/Sessions/`. Append-only, never pruned. (Agent notes only — spec 080.)
- `type/spec` — Spec document at `docs/vault/Specs/NNN Title/spec.md`. Carries `spec-refs:`. (e.g. `Specs/047 Car Radio/spec.md`)
- `type/system` — A bounded subsystem with implementation. Carries `code-refs`, `spec-refs`, `implements:` frontmatter. (e.g. `Systems/Audio — Car Radio.md`)
- `type/vision` — Strategic / vision-layer decision. Written to `docs/vault/Vision/`. Human-authored or agent-proposed with human ratification before promotion to `status: reviewed`. (Per triage #3 — spec 133 autonomous-company redesign.)
domain/*:
- `domain/anomalies` — Anomaly taxonomy, individual anomaly systems, spawn, behavior
- `domain/art` — Visual direction, palettes, references, asset pipeline
- `domain/audio` — Audio systems: world ambient, radio, transmissions, buses, pipeline
- `domain/autonomous-company` — Autonomous company v0.1 experiment: Slack infra, persona middleware, Letta integration, restart recovery
- `domain/build` — Build system, packaging, export, release automation
- `domain/governance` — Constitution, phased spec, policies
- `domain/infrastructure` — Infrastructure provisioning: CI/CD, hosting, deployment tooling, secrets management
- `domain/narrative` — Tone, horror register, forest transmissions narrative, Gary/KTLK
- `domain/player` — Player mode, input, controls, camera, exit/entry
- `domain/systems` — Cross-cutting system architecture and integration work
- `domain/tooling` — Build, CI, observer, TTS pipeline, dev-time tools
- `domain/vehicle` — The Samba: vehicle physics, dashboard, damage, panels
- `domain/world` — World model, biomes, terrain, procedural generation, weather
status/*:
- `status/canonical` — Fully authoritative; promoted by humans only. Highest trust. (Agent notes only — spec 080.)
- `status/draft` — Authoring in progress, not yet verified
- `status/reviewed` — Agent-created note verified against codebase within its creating session. Eligible for auto-injection in subsequent task dispatches. (Agent notes only — spec 080.)
- `status/stale` — Known out of date; cannot update immediately. Pairs with `> [!warning] STALE — needs update` callout.
- `status/superseded` — Replaced by another note. Terminal state. Pairs with `> [!warning] SUPERSEDED` callout.
- `status/wip` — Stable but under active revision
layer/*:
- `layer/content` — Content assets (audio, models, textures, audio provenance)
- `layer/gdext` — gdext wrapper layer (`rust/gdext-wrapper/`)
- `layer/gdscript` — GDScript (Godot scene-tier logic)
- `layer/infra` — Build, CI, deployment infrastructure
- `layer/python` — Python development tooling (`tools/`)
- `layer/rust-core` — Engine-agnostic Rust core (`rust/rust-core/`)
concept/*:
- `concept/biome` — Biome-reactive behavior across systems
- `concept/contamination` — Across-runs panel and garage degradation; the slow-horror mechanic that doesn't reset with the world
- `concept/diegetic` — Diegetic audio / UI / world-sourced design
- `concept/disturbance` — The disturbance mechanic thread (Article X)
- `concept/ephemeral-world` — Run-reset, transient worlds (Article IV Rules 6–7)
- `concept/governance` — Constitutional and governance concepts
- `concept/horror` — Horror register and dread design
- `concept/procedural` — Procedural generation, seed determinism
- `concept/rendering` — Visual rendering quality, shader correctness, Terrain3D integration, mesh fidelity, LOD, Z-fighting
- `concept/terrain` — Terrain generation, heightmap, Terrain3D regions, roughness, playability constraints
ember's answer for tag_assignment-sessions-spawn-collision-mirror-mesh-visibility-and-glb-node-discovery-jun-06-2026, type/session-logP(true) placed on the no, unsure, and yes zones.nounsureyesgold: yesP = 0.06

tag_assignment-code-code-conventions: domain/tooling

Tag assignment · test
Gold
The note calls for `domain/tooling`: Build, CI, observer, TTS pipeline, dev-time tools (True)
ember
The note has no reason to carry `domain/tooling` (False)
Signal
P(true) 0.35 (unsure)
Kit outcome
deferred: treated as unsure
Why this gold label
Mined from Code/Code Conventions.md at 692f4bb58b7f62105aeb73fba8dfee12bfdecd53; gold is the note's own vocabulary tags.
Code Conventions

The canonical code conventions for Old Growth's GDScript codebase. Enforced by `gdformat` + `gdlint` via `make gdscript-quality`. Violations block CI.

## Overview

Conventions are authored in AGENTS.md and observed in the actual codebase. This note consolidates them in a single canonical reference. The intent is readable, predictable, scannable code — easy for any contributor (human or AI) to pick up mid-session.

## Key Conventions

### File layout order

Every `.gd` file follows this section order:

1. Doc comment (`## Description`)
2. `extends`
3. Enums
4. Constants
5. Signals
6. `@export` properties (grouped with `@export_group`)
7. Private backing variables + public property definitions
8. `_ready()` and other lifecycle methods
9. Public methods
10. Private methods (prefixed `_`)
11. Debug handlers (suffixed `_debug`)

Section headers separate blocks: `# --- Signals -------`, `# --- Properties -------`, etc.

### Naming

| Element | Convention | Example |
|---------|-----------|---------|
| Files | `snake_case.gd` | `bus_radio.gd` |
| Classes / Nodes | PascalCase | `CarRadio` |
| Constants | UPPER_CASE | `DEFAULT_SEED` |
| Enum names | PascalCase | `PlayerMode` |
| Enum values | UPPER_CASE | `DRIVING`, `ON_FOOT` |
| Signals / variables / functions | snake_case | `threshold_changed`, `current_seed`, `add()` |
| Private prefix | `_` | `_level`, `_get_state_for_level()` |
| Signal handlers | `_on_<signal>` | `_on_threshold_changed_debug` |

### Type annotations — REQUIRED

All function signatures and variable declarations must have type annotations:

```gdscript
func add(amount: float, source: String) -> void:
var _level: float = 0.0
const DEFAULT_SEED: int = 0
```

Use `:=` for type inference only on locals and dict/array constants:

```gdscript
var old := _level                          # OK — inferred float from _level
const BIOME_NAMES := { Biome.VERDANT: "Verdant", ... }   # OK — Dictionary literal
```

### Property setters with backing variables

GDScript 4.x setters are called recursively on self-assignment. Reading the property inside its own setter returns the *new* value, not the old one. The backing variable pattern avoids this:

```gdscript
var _player_mode: PlayerMode = DEFAULT_PLAYER_MODE
var player_mode: PlayerMode:
    get: return _player_mode
    set(value):
        var old := _player_mode
        _player_mode = value
        if old != value:
            player_mode_changed.emit(old, value)
```

### Guard clauses with early return

No deep nesting. Guard and return:

```gdscript
func add(amount: float, source: String) -> void:
    if amount <= 0.0:
        return
    # … main logic
```

### Clamp instead of throw

```gdscript
_level = clampf(_level + amount, 0.0, 100.0)
```

Public API functions in rust-core return `Result<T, E>` for genuinely fallible operations (Article XII-C); GDScript typically clamps to valid range.

### Imports and autoloads

- Autoloads (`Events`, `GameState`, `Disturbance`) are global — reference by name directly, never `preload()` them.
- Do NOT use `class_name` on autoload scripts (conflicts with singleton names in Godot 4.6+).
- Use `preload()` for Resources and non-autoload scripts.
- Use `load()` only when the path is dynamic.

### Debug logging

Gate all debug output behind `OS.is_debug_build()`. Prefix with system name:

```gdscript
if OS.is_debug_build():
    print("[Disturbance] +%.1f from '%s'" % [amount, source])
```

Connect debug-only signal handlers in `_ready()` behind the same gate. Debug handler functions use the `_debug` suffix (e.g., `_on_threshold_changed_debug`).

### Testing (GUT)

- Test files named `test_*.gd`, in `src/tests/unit/`
- Test functions named `func test_*() -> void:`
- Extend `GutTest`; use `before_each()` for setup
- `add_child_autofree()` for nodes (auto-cleaned between tests)
- `preload()` the script under test; do not reference autoload singletons directly
- `watch_signals(node)` before an action that should emit a signal
- Vendored addons (`src/addons/`) are excluded from all linting and formatting

### Signal conventions

- Signal declarations grouped by phase-comment section in `events.gd`
- Signals are append-only once declared
- Signal names describe an event in past tense: `bus_collision`, `threshold_changed`, `player_died`
- Connect at `_ready()`; disconnect in `_exit_tree()` if the connection is to something that may outlive the node

### Enum conventions

- Enum values use UPPER_CASE: `enum PlayerMode { DRIVING, ON_FOOT }`
- Enum names use PascalCase
- Define enums inside the class that owns them; reference statically (`GameState.Biome.VERDANT`)

### @export conventions

- Designer-tunable parameters MUST be `@export` (Article VI Rule 3)
- Use `@export_group("Group Name")` to organize related exports
- Avoid `const` for anything designers might tune — promote to `@export var` instead

## Related

- [[Source Tree]] — where conventions are observed
- [[Autoloads — Events]], [[Autoloads — GameState]], [[Autoloads — Disturbance]] — canonical examples
- [[Build System]] — `make gdscript-quality` enforces formatting/lint
- [[Code]] — folder MOC
- [[Constitution]] — Article VI (signals), Article XII-C (Rust idioms)

Controlled tag vocabulary (as read):
type/*:
- `type/code` — Code architecture, autoloads, conventions, tooling. Carries `code-refs:`. (e.g. `Code/Autoloads — Disturbance.md`)
- `type/decision` — Architectural or design decision made by an agent during a session. Written to `docs/vault/Decisions/`. (Agent notes only — spec 080.)
- `type/design` — Design intent, player-facing concepts, world lore. (e.g. `Design/World Model.md`)
- `type/discovery` — Non-obvious constraint, gap, or conflict found by an agent during a session. Written to `docs/vault/Discoveries/`. (Agent notes only — spec 080.)
- `type/moc` — Map of Content at any of three tiers (folder / domain / concept). (e.g. `Audio.md`)
- `type/principle` — Governance and constitutional notes. Non-negotiable rules. (e.g. `Governance/Constitution.md`)
- `type/reference` — Glossary, decision log, open questions, epics. (e.g. `Reference/Glossary.md`)
- `type/session-log` — Session activity log; permanent audit trail. Written to `docs/vault/Sessions/`. Append-only, never pruned. (Agent notes only — spec 080.)
- `type/spec` — Spec document at `docs/vault/Specs/NNN Title/spec.md`. Carries `spec-refs:`. (e.g. `Specs/047 Car Radio/spec.md`)
- `type/system` — A bounded subsystem with implementation. Carries `code-refs`, `spec-refs`, `implements:` frontmatter. (e.g. `Systems/Audio — Car Radio.md`)
- `type/vision` — Strategic / vision-layer decision. Written to `docs/vault/Vision/`. Human-authored or agent-proposed with human ratification before promotion to `status: reviewed`. (Per triage #3 — spec 133 autonomous-company redesign.)
domain/*:
- `domain/anomalies` — Anomaly taxonomy, individual anomaly systems, spawn, behavior
- `domain/art` — Visual direction, palettes, references, asset pipeline
- `domain/audio` — Audio systems: world ambient, radio, transmissions, buses, pipeline
- `domain/autonomous-company` — Autonomous company v0.1 experiment: Slack infra, persona middleware, Letta integration, restart recovery
- `domain/build` — Build system, packaging, export, release automation
- `domain/governance` — Constitution, phased spec, policies
- `domain/infrastructure` — Infrastructure provisioning: CI/CD, hosting, deployment tooling, secrets management
- `domain/narrative` — Tone, horror register, forest transmissions narrative, Gary/KTLK
- `domain/player` — Player mode, input, controls, camera, exit/entry
- `domain/systems` — Cross-cutting system architecture and integration work
- `domain/tooling` — Build, CI, observer, TTS pipeline, dev-time tools
- `domain/vehicle` — The Samba: vehicle physics, dashboard, damage, panels
- `domain/world` — World model, biomes, terrain, procedural generation, weather
status/*:
- `status/canonical` — Fully authoritative; promoted by humans only. Highest trust. (Agent notes only — spec 080.)
- `status/draft` — Authoring in progress, not yet verified
- `status/reviewed` — Agent-created note verified against codebase within its creating session. Eligible for auto-injection in subsequent task dispatches. (Agent notes only — spec 080.)
- `status/stale` — Known out of date; cannot update immediately. Pairs with `> [!warning] STALE — needs update` callout.
- `status/superseded` — Replaced by another note. Terminal state. Pairs with `> [!warning] SUPERSEDED` callout.
- `status/wip` — Stable but under active revision
layer/*:
- `layer/content` — Content assets (audio, models, textures, audio provenance)
- `layer/gdext` — gdext wrapper layer (`rust/gdext-wrapper/`)
- `layer/gdscript` — GDScript (Godot scene-tier logic)
- `layer/infra` — Build, CI, deployment infrastructure
- `layer/python` — Python development tooling (`tools/`)
- `layer/rust-core` — Engine-agnostic Rust core (`rust/rust-core/`)
concept/*:
- `concept/biome` — Biome-reactive behavior across systems
- `concept/contamination` — Across-runs panel and garage degradation; the slow-horror mechanic that doesn't reset with the world
- `concept/diegetic` — Diegetic audio / UI / world-sourced design
- `concept/disturbance` — The disturbance mechanic thread (Article X)
- `concept/ephemeral-world` — Run-reset, transient worlds (Article IV Rules 6–7)
- `concept/governance` — Constitutional and governance concepts
- `concept/horror` — Horror register and dread design
- `concept/procedural` — Procedural generation, seed determinism
- `concept/rendering` — Visual rendering quality, shader correctness, Terrain3D integration, mesh fidelity, LOD, Z-fighting
- `concept/terrain` — Terrain generation, heightmap, Terrain3D regions, roughness, playability constraints
ember's answer for tag_assignment-code-code-conventions, domain/toolingP(true) placed on the no, unsure, and yes zones.nounsureyesgold: yesP = 0.35

tag_assignment-decisions-interior-interaction-detection-shapecast3d: domain/player

Tag assignment · test
Gold
The note calls for `domain/player`: Player mode, input, controls, camera, exit/entry (True)
ember
The note has no reason to carry `domain/player` (False)
Signal
P(true) 0.24 (unsure)
Kit outcome
deferred: treated as unsure
Why this gold label
Mined from Decisions/Interior Interaction Detection (ShapeCast3D).md at 692f4bb58b7f62105aeb73fba8dfee12bfdecd53; gold is the note's own vocabulary tags.
Interior Interaction Detection (ShapeCast3D)

The interior interaction detection system was switched from a thin RayCast3D to a volumetric ShapeCast3D to cover the dashboard area that the thin ray could not reach. The breaking discovery is documented in [[Interior Interaction Spatial Constraint]].

## Context

The interior camera (`interior_camera.gd`) creates a detection volume as a child node that sweeps forward from the camera's position to detect interactable Area3D nodes on collision layer 8. Previously this was a RayCast3D (a single-pixel line), which failed to detect the radio's InteractArea because the radio sits 1m below the camera with only 0.3m of forward distance — a geometry the line could not reach within the 45-degree pitch-down limit.

## Decision

Replace `RayCast3D` with `ShapeCast3D` in `interior_camera.gd`, using a box shape with an exported `interact_shape_size` defaulting to `Vector3(0.5, 0.5, 1.0)`. The box sweeps the same 2m forward distance (`interact_ray_length`) as the original ray, but detects any Area3D whose collision volume overlaps the swept box, not just a line intersection.

### Detection volume dimensions

- **Width (X)**: 0.5m — covers the radio's 0.45m lateral offset from the camera (driver's head to dashboard center)
- **Height (Y)**: 0.5m — extends 25cm above/below the ray's center line, covering the vertical gap between eye level (y=1.65) and dashboard interactables (y~0.65–1.35)
- **Depth (Z)**: 1.0m — the box depth itself, swept 2m forward for a total detection range of approximately 2.5m from the camera origin

### Existing interaction pattern preserved

- `collision_mask = 8`, `collide_with_areas = true`, `collide_with_bodies = false` — unchanged from the RayCast3D setup
- The signal protocol (`interactable_focused` / `interactable_unfocused`) is identical
- The first detected collider is used (index 0), matching the previous single-collider model
- The `_on_interactable_focused` handler in each interactable (bus_radio.gd, dome_light_control.gd) checks `target == $InteractArea or target.get_parent() == self` — unchanged

## Rationale

- **Reliability**: A volume is far more forgiving than a line for interior interaction where the player moves the camera with mouse look but interactables stay fixed
- **Tunability**: `interact_shape_size` is an `@export` so it can be adjusted per interactable layout without code changes
- **Minimal API change**: ShapeCast3D has the same collision mask/area/body API as RayCast3D, so the `_update_interact_focus` logic is structurally identical
- **No visual impact**: The ShapeCast3D is invisible in-game (debug-only gizmo when selected in editor)

## Alternatives considered

- **Larger InteractArea hitbox only** — Moving the radio's InteractArea collision box 35cm up and extending it to 70cm tall made the box reachable in theory, but the thin ray still required near-perfect aim. The volume approach is strictly more forgiving.
- **Longer ray** — Would not help; the radio is only 0.3m forward. The problem is angular (vertical reach at close range), not linear range.
- **Angled ray** — Offsetting the ray origin or target to point downward would decouple the interact direction from the player's gaze direction, breaking diegetic alignment (per Article XII-G).

## References

- `src/scripts/bus/interior_camera.gd` — the ShapeCast3D setup and `_update_interact_focus` method
- `src/scenes/bus/bus_radio.tscn` — the radio's InteractArea hitbox (also extended: +0.35m Y offset, box size.y=0.70)

Controlled tag vocabulary (as read):
type/*:
- `type/code` — Code architecture, autoloads, conventions, tooling. Carries `code-refs:`. (e.g. `Code/Autoloads — Disturbance.md`)
- `type/decision` — Architectural or design decision made by an agent during a session. Written to `docs/vault/Decisions/`. (Agent notes only — spec 080.)
- `type/design` — Design intent, player-facing concepts, world lore. (e.g. `Design/World Model.md`)
- `type/discovery` — Non-obvious constraint, gap, or conflict found by an agent during a session. Written to `docs/vault/Discoveries/`. (Agent notes only — spec 080.)
- `type/moc` — Map of Content at any of three tiers (folder / domain / concept). (e.g. `Audio.md`)
- `type/principle` — Governance and constitutional notes. Non-negotiable rules. (e.g. `Governance/Constitution.md`)
- `type/reference` — Glossary, decision log, open questions, epics. (e.g. `Reference/Glossary.md`)
- `type/session-log` — Session activity log; permanent audit trail. Written to `docs/vault/Sessions/`. Append-only, never pruned. (Agent notes only — spec 080.)
- `type/spec` — Spec document at `docs/vault/Specs/NNN Title/spec.md`. Carries `spec-refs:`. (e.g. `Specs/047 Car Radio/spec.md`)
- `type/system` — A bounded subsystem with implementation. Carries `code-refs`, `spec-refs`, `implements:` frontmatter. (e.g. `Systems/Audio — Car Radio.md`)
- `type/vision` — Strategic / vision-layer decision. Written to `docs/vault/Vision/`. Human-authored or agent-proposed with human ratification before promotion to `status: reviewed`. (Per triage #3 — spec 133 autonomous-company redesign.)
domain/*:
- `domain/anomalies` — Anomaly taxonomy, individual anomaly systems, spawn, behavior
- `domain/art` — Visual direction, palettes, references, asset pipeline
- `domain/audio` — Audio systems: world ambient, radio, transmissions, buses, pipeline
- `domain/autonomous-company` — Autonomous company v0.1 experiment: Slack infra, persona middleware, Letta integration, restart recovery
- `domain/build` — Build system, packaging, export, release automation
- `domain/governance` — Constitution, phased spec, policies
- `domain/infrastructure` — Infrastructure provisioning: CI/CD, hosting, deployment tooling, secrets management
- `domain/narrative` — Tone, horror register, forest transmissions narrative, Gary/KTLK
- `domain/player` — Player mode, input, controls, camera, exit/entry
- `domain/systems` — Cross-cutting system architecture and integration work
- `domain/tooling` — Build, CI, observer, TTS pipeline, dev-time tools
- `domain/vehicle` — The Samba: vehicle physics, dashboard, damage, panels
- `domain/world` — World model, biomes, terrain, procedural generation, weather
status/*:
- `status/canonical` — Fully authoritative; promoted by humans only. Highest trust. (Agent notes only — spec 080.)
- `status/draft` — Authoring in progress, not yet verified
- `status/reviewed` — Agent-created note verified against codebase within its creating session. Eligible for auto-injection in subsequent task dispatches. (Agent notes only — spec 080.)
- `status/stale` — Known out of date; cannot update immediately. Pairs with `> [!warning] STALE — needs update` callout.
- `status/superseded` — Replaced by another note. Terminal state. Pairs with `> [!warning] SUPERSEDED` callout.
- `status/wip` — Stable but under active revision
layer/*:
- `layer/content` — Content assets (audio, models, textures, audio provenance)
- `layer/gdext` — gdext wrapper layer (`rust/gdext-wrapper/`)
- `layer/gdscript` — GDScript (Godot scene-tier logic)
- `layer/infra` — Build, CI, deployment infrastructure
- `layer/python` — Python development tooling (`tools/`)
- `layer/rust-core` — Engine-agnostic Rust core (`rust/rust-core/`)
concept/*:
- `concept/biome` — Biome-reactive behavior across systems
- `concept/contamination` — Across-runs panel and garage degradation; the slow-horror mechanic that doesn't reset with the world
- `concept/diegetic` — Diegetic audio / UI / world-sourced design
- `concept/disturbance` — The disturbance mechanic thread (Article X)
- `concept/ephemeral-world` — Run-reset, transient worlds (Article IV Rules 6–7)
- `concept/governance` — Constitutional and governance concepts
- `concept/horror` — Horror register and dread design
- `concept/procedural` — Procedural generation, seed determinism
- `concept/rendering` — Visual rendering quality, shader correctness, Terrain3D integration, mesh fidelity, LOD, Z-fighting
- `concept/terrain` — Terrain generation, heightmap, Terrain3D regions, roughness, playability constraints
ember's answer for tag_assignment-decisions-interior-interaction-detection-shapecast3d, domain/playerP(true) placed on the no, unsure, and yes zones.nounsureyesgold: yesP = 0.24

tag_assignment-decisions-interior-interaction-detection-shapecast3d: type/discovery

Tag assignment · test
Gold
The note has no reason to carry `type/discovery` (False)
ember
The note calls for `type/discovery`: Non-obvious constraint, gap, or conflict found by an agent during a session. Written to `docs/vault/Discoveries/`. (Agent notes only — spec 080.) (True)
Signal
P(true) 0.69 (unsure)
Kit outcome
deferred: treated as unsure
Why this gold label
Mined from Decisions/Interior Interaction Detection (ShapeCast3D).md at 692f4bb58b7f62105aeb73fba8dfee12bfdecd53; gold is the note's own vocabulary tags.
Interior Interaction Detection (ShapeCast3D)

The interior interaction detection system was switched from a thin RayCast3D to a volumetric ShapeCast3D to cover the dashboard area that the thin ray could not reach. The breaking discovery is documented in [[Interior Interaction Spatial Constraint]].

## Context

The interior camera (`interior_camera.gd`) creates a detection volume as a child node that sweeps forward from the camera's position to detect interactable Area3D nodes on collision layer 8. Previously this was a RayCast3D (a single-pixel line), which failed to detect the radio's InteractArea because the radio sits 1m below the camera with only 0.3m of forward distance — a geometry the line could not reach within the 45-degree pitch-down limit.

## Decision

Replace `RayCast3D` with `ShapeCast3D` in `interior_camera.gd`, using a box shape with an exported `interact_shape_size` defaulting to `Vector3(0.5, 0.5, 1.0)`. The box sweeps the same 2m forward distance (`interact_ray_length`) as the original ray, but detects any Area3D whose collision volume overlaps the swept box, not just a line intersection.

### Detection volume dimensions

- **Width (X)**: 0.5m — covers the radio's 0.45m lateral offset from the camera (driver's head to dashboard center)
- **Height (Y)**: 0.5m — extends 25cm above/below the ray's center line, covering the vertical gap between eye level (y=1.65) and dashboard interactables (y~0.65–1.35)
- **Depth (Z)**: 1.0m — the box depth itself, swept 2m forward for a total detection range of approximately 2.5m from the camera origin

### Existing interaction pattern preserved

- `collision_mask = 8`, `collide_with_areas = true`, `collide_with_bodies = false` — unchanged from the RayCast3D setup
- The signal protocol (`interactable_focused` / `interactable_unfocused`) is identical
- The first detected collider is used (index 0), matching the previous single-collider model
- The `_on_interactable_focused` handler in each interactable (bus_radio.gd, dome_light_control.gd) checks `target == $InteractArea or target.get_parent() == self` — unchanged

## Rationale

- **Reliability**: A volume is far more forgiving than a line for interior interaction where the player moves the camera with mouse look but interactables stay fixed
- **Tunability**: `interact_shape_size` is an `@export` so it can be adjusted per interactable layout without code changes
- **Minimal API change**: ShapeCast3D has the same collision mask/area/body API as RayCast3D, so the `_update_interact_focus` logic is structurally identical
- **No visual impact**: The ShapeCast3D is invisible in-game (debug-only gizmo when selected in editor)

## Alternatives considered

- **Larger InteractArea hitbox only** — Moving the radio's InteractArea collision box 35cm up and extending it to 70cm tall made the box reachable in theory, but the thin ray still required near-perfect aim. The volume approach is strictly more forgiving.
- **Longer ray** — Would not help; the radio is only 0.3m forward. The problem is angular (vertical reach at close range), not linear range.
- **Angled ray** — Offsetting the ray origin or target to point downward would decouple the interact direction from the player's gaze direction, breaking diegetic alignment (per Article XII-G).

## References

- `src/scripts/bus/interior_camera.gd` — the ShapeCast3D setup and `_update_interact_focus` method
- `src/scenes/bus/bus_radio.tscn` — the radio's InteractArea hitbox (also extended: +0.35m Y offset, box size.y=0.70)

Controlled tag vocabulary (as read):
type/*:
- `type/code` — Code architecture, autoloads, conventions, tooling. Carries `code-refs:`. (e.g. `Code/Autoloads — Disturbance.md`)
- `type/decision` — Architectural or design decision made by an agent during a session. Written to `docs/vault/Decisions/`. (Agent notes only — spec 080.)
- `type/design` — Design intent, player-facing concepts, world lore. (e.g. `Design/World Model.md`)
- `type/discovery` — Non-obvious constraint, gap, or conflict found by an agent during a session. Written to `docs/vault/Discoveries/`. (Agent notes only — spec 080.)
- `type/moc` — Map of Content at any of three tiers (folder / domain / concept). (e.g. `Audio.md`)
- `type/principle` — Governance and constitutional notes. Non-negotiable rules. (e.g. `Governance/Constitution.md`)
- `type/reference` — Glossary, decision log, open questions, epics. (e.g. `Reference/Glossary.md`)
- `type/session-log` — Session activity log; permanent audit trail. Written to `docs/vault/Sessions/`. Append-only, never pruned. (Agent notes only — spec 080.)
- `type/spec` — Spec document at `docs/vault/Specs/NNN Title/spec.md`. Carries `spec-refs:`. (e.g. `Specs/047 Car Radio/spec.md`)
- `type/system` — A bounded subsystem with implementation. Carries `code-refs`, `spec-refs`, `implements:` frontmatter. (e.g. `Systems/Audio — Car Radio.md`)
- `type/vision` — Strategic / vision-layer decision. Written to `docs/vault/Vision/`. Human-authored or agent-proposed with human ratification before promotion to `status: reviewed`. (Per triage #3 — spec 133 autonomous-company redesign.)
domain/*:
- `domain/anomalies` — Anomaly taxonomy, individual anomaly systems, spawn, behavior
- `domain/art` — Visual direction, palettes, references, asset pipeline
- `domain/audio` — Audio systems: world ambient, radio, transmissions, buses, pipeline
- `domain/autonomous-company` — Autonomous company v0.1 experiment: Slack infra, persona middleware, Letta integration, restart recovery
- `domain/build` — Build system, packaging, export, release automation
- `domain/governance` — Constitution, phased spec, policies
- `domain/infrastructure` — Infrastructure provisioning: CI/CD, hosting, deployment tooling, secrets management
- `domain/narrative` — Tone, horror register, forest transmissions narrative, Gary/KTLK
- `domain/player` — Player mode, input, controls, camera, exit/entry
- `domain/systems` — Cross-cutting system architecture and integration work
- `domain/tooling` — Build, CI, observer, TTS pipeline, dev-time tools
- `domain/vehicle` — The Samba: vehicle physics, dashboard, damage, panels
- `domain/world` — World model, biomes, terrain, procedural generation, weather
status/*:
- `status/canonical` — Fully authoritative; promoted by humans only. Highest trust. (Agent notes only — spec 080.)
- `status/draft` — Authoring in progress, not yet verified
- `status/reviewed` — Agent-created note verified against codebase within its creating session. Eligible for auto-injection in subsequent task dispatches. (Agent notes only — spec 080.)
- `status/stale` — Known out of date; cannot update immediately. Pairs with `> [!warning] STALE — needs update` callout.
- `status/superseded` — Replaced by another note. Terminal state. Pairs with `> [!warning] SUPERSEDED` callout.
- `status/wip` — Stable but under active revision
layer/*:
- `layer/content` — Content assets (audio, models, textures, audio provenance)
- `layer/gdext` — gdext wrapper layer (`rust/gdext-wrapper/`)
- `layer/gdscript` — GDScript (Godot scene-tier logic)
- `layer/infra` — Build, CI, deployment infrastructure
- `layer/python` — Python development tooling (`tools/`)
- `layer/rust-core` — Engine-agnostic Rust core (`rust/rust-core/`)
concept/*:
- `concept/biome` — Biome-reactive behavior across systems
- `concept/contamination` — Across-runs panel and garage degradation; the slow-horror mechanic that doesn't reset with the world
- `concept/diegetic` — Diegetic audio / UI / world-sourced design
- `concept/disturbance` — The disturbance mechanic thread (Article X)
- `concept/ephemeral-world` — Run-reset, transient worlds (Article IV Rules 6–7)
- `concept/governance` — Constitutional and governance concepts
- `concept/horror` — Horror register and dread design
- `concept/procedural` — Procedural generation, seed determinism
- `concept/rendering` — Visual rendering quality, shader correctness, Terrain3D integration, mesh fidelity, LOD, Z-fighting
- `concept/terrain` — Terrain generation, heightmap, Terrain3D regions, roughness, playability constraints
ember's answer for tag_assignment-decisions-interior-interaction-detection-shapecast3d, type/discoveryP(true) placed on the no, unsure, and yes zones.nounsureyesgold: noP = 0.69

tag_assignment-discoveries-high-center-root-cause: type/discovery

Tag assignment · dev
Gold
The note calls for `type/discovery`: Non-obvious constraint, gap, or conflict found by an agent during a session. Written to `docs/vault/Discoveries/`. (Agent notes only — spec 080.) (True)
ember
The note has no reason to carry `type/discovery` (False)
Signal
P(true) 0.50 (unsure)
Kit outcome
deferred: treated as unsure
Why this gold label
Mined from Discoveries/High Center Root Cause.md at 692f4bb58b7f62105aeb73fba8dfee12bfdecd53; gold is the note's own vocabulary tags.
High Center Root Cause

The bus physically high-centers on terrain ledges due to a geometry mismatch between the chassis collision box and the wheel suspension reach.

## Collision Box

From `samba_bus.tscn`, the RigidBody3D chassis collision is a `BoxShape3D`:

| Property | Value |
|----------|-------|
| Type | BoxShape3D |
| Size | 2.1 × 1.52 × 4.7 (reduced from 2.32 by spec 158) |
| Half-extent Y | 0.76m |
| Bottom Y (vehicle-local) | -0.76m |

## Wheel Reach

From `tire_damage_driver.gd` and `samba_bus.tscn`:

| Parameter | Value | Source |
|-----------|-------|--------|
| Tire center Y | 0.493m | `_tire_centers` in tire_damage_driver.gd |
| Tire radius | 0.38m | `samba_bus.tscn`: `front_tire_radius` |
| Spring length | 0.35m | `samba_bus.tscn`: `front_spring_length`, `rear_spring_length` |
| Wheel full droop | 0.73m | spring_length + tire_radius |
| Wheel bottom Y at full droop | -0.237m | 0.493 - 0.73 |

## Clearance Gap

```
Chassis center:              0.000m
Wheel bottom at full droop: -0.237m
Collision box bottom:        -0.760m

Gap:                          0.523m
```

The collision box extends **0.523m below** the lowest point the wheels can reach. When the collision box contacts terrain (e.g., crossing a ledge), the wheels are ~0.5m above the ground and cannot reach it even at full suspension droop.

## Root Cause

**Primary**: The BoxShape3D collision box extends too far below the wheel contact points. When the box contacts terrain, all wheels lose ground contact.

**Contributing factor**: The flat-bottomed box shape catches on terrain ledges instead of sliding over them.

## Prevention Applied (spec 158)

- BoxShape3D Y size reduced: 2.32 → 1.52 (bottom raised from -1.16m to -0.76m)
- Spring length already at 0.35 (pre-existing — no change needed)
- Recovery lift impulse added to free the bus when stuck

Controlled tag vocabulary (as read):
type/*:
- `type/code` — Code architecture, autoloads, conventions, tooling. Carries `code-refs:`. (e.g. `Code/Autoloads — Disturbance.md`)
- `type/decision` — Architectural or design decision made by an agent during a session. Written to `docs/vault/Decisions/`. (Agent notes only — spec 080.)
- `type/design` — Design intent, player-facing concepts, world lore. (e.g. `Design/World Model.md`)
- `type/discovery` — Non-obvious constraint, gap, or conflict found by an agent during a session. Written to `docs/vault/Discoveries/`. (Agent notes only — spec 080.)
- `type/moc` — Map of Content at any of three tiers (folder / domain / concept). (e.g. `Audio.md`)
- `type/principle` — Governance and constitutional notes. Non-negotiable rules. (e.g. `Governance/Constitution.md`)
- `type/reference` — Glossary, decision log, open questions, epics. (e.g. `Reference/Glossary.md`)
- `type/session-log` — Session activity log; permanent audit trail. Written to `docs/vault/Sessions/`. Append-only, never pruned. (Agent notes only — spec 080.)
- `type/spec` — Spec document at `docs/vault/Specs/NNN Title/spec.md`. Carries `spec-refs:`. (e.g. `Specs/047 Car Radio/spec.md`)
- `type/system` — A bounded subsystem with implementation. Carries `code-refs`, `spec-refs`, `implements:` frontmatter. (e.g. `Systems/Audio — Car Radio.md`)
- `type/vision` — Strategic / vision-layer decision. Written to `docs/vault/Vision/`. Human-authored or agent-proposed with human ratification before promotion to `status: reviewed`. (Per triage #3 — spec 133 autonomous-company redesign.)
domain/*:
- `domain/anomalies` — Anomaly taxonomy, individual anomaly systems, spawn, behavior
- `domain/art` — Visual direction, palettes, references, asset pipeline
- `domain/audio` — Audio systems: world ambient, radio, transmissions, buses, pipeline
- `domain/autonomous-company` — Autonomous company v0.1 experiment: Slack infra, persona middleware, Letta integration, restart recovery
- `domain/build` — Build system, packaging, export, release automation
- `domain/governance` — Constitution, phased spec, policies
- `domain/infrastructure` — Infrastructure provisioning: CI/CD, hosting, deployment tooling, secrets management
- `domain/narrative` — Tone, horror register, forest transmissions narrative, Gary/KTLK
- `domain/player` — Player mode, input, controls, camera, exit/entry
- `domain/systems` — Cross-cutting system architecture and integration work
- `domain/tooling` — Build, CI, observer, TTS pipeline, dev-time tools
- `domain/vehicle` — The Samba: vehicle physics, dashboard, damage, panels
- `domain/world` — World model, biomes, terrain, procedural generation, weather
status/*:
- `status/canonical` — Fully authoritative; promoted by humans only. Highest trust. (Agent notes only — spec 080.)
- `status/draft` — Authoring in progress, not yet verified
- `status/reviewed` — Agent-created note verified against codebase within its creating session. Eligible for auto-injection in subsequent task dispatches. (Agent notes only — spec 080.)
- `status/stale` — Known out of date; cannot update immediately. Pairs with `> [!warning] STALE — needs update` callout.
- `status/superseded` — Replaced by another note. Terminal state. Pairs with `> [!warning] SUPERSEDED` callout.
- `status/wip` — Stable but under active revision
layer/*:
- `layer/content` — Content assets (audio, models, textures, audio provenance)
- `layer/gdext` — gdext wrapper layer (`rust/gdext-wrapper/`)
- `layer/gdscript` — GDScript (Godot scene-tier logic)
- `layer/infra` — Build, CI, deployment infrastructure
- `layer/python` — Python development tooling (`tools/`)
- `layer/rust-core` — Engine-agnostic Rust core (`rust/rust-core/`)
concept/*:
- `concept/biome` — Biome-reactive behavior across systems
- `concept/contamination` — Across-runs panel and garage degradation; the slow-horror mechanic that doesn't reset with the world
- `concept/diegetic` — Diegetic audio / UI / world-sourced design
- `concept/disturbance` — The disturbance mechanic thread (Article X)
- `concept/ephemeral-world` — Run-reset, transient worlds (Article IV Rules 6–7)
- `concept/governance` — Constitutional and governance concepts
- `concept/horror` — Horror register and dread design
- `concept/procedural` — Procedural generation, seed determinism
- `concept/rendering` — Visual rendering quality, shader correctness, Terrain3D integration, mesh fidelity, LOD, Z-fighting
- `concept/terrain` — Terrain generation, heightmap, Terrain3D regions, roughness, playability constraints
ember's answer for tag_assignment-discoveries-high-center-root-cause, type/discoveryP(true) placed on the no, unsure, and yes zones.nounsureyesgold: yesP = 0.50

tag_assignment-reference-autonomous-company-autonomous-company-operations-reference: type/reference

Tag assignment · dev
Gold
The note calls for `type/reference`: Glossary, decision log, open questions, epics. (e.g. `Reference/Glossary.md`) (True)
ember
The note has no reason to carry `type/reference` (False)
Signal
P(true) 0.22 (unsure)
Kit outcome
deferred: treated as unsure
Why this gold label
Mined from Reference/Autonomous Company/Autonomous Company Operations Reference.md at 692f4bb58b7f62105aeb73fba8dfee12bfdecd53; gold is the note's own vocabulary tags.
Autonomous Company Operations Reference

> **Part of**: [[133 Autonomous Company V01 Experiment]]
> **Quickstart**: `docs/vault/Specs/135 Per Persona Middleware Specs/135 Per Persona Middleware Specs - quickstart.md`

## Infrastructure Stack

```
┌─────────────────────────────────────────────────────┐
│                    Slack                             │
│  ┌─ Old Growth Coordinator  ┌─ Old Growth GTM       │
│  │  Socket Mode WebSocket   │  Socket Mode WebSocket│
│  └──────────┬───────────────└──────────┬────────────│
│             │                          │             │
│        app_mention               announce-releases  │
│        /internal/approval-callback                   │
└─────────────┼──────────────────────────┼─────────────┘
              │                          │
     ┌────────▼──────────┐     ┌─────────▼────────┐
     │ Coordinator Runtime│     │   GTM Runtime    │
     │ :9100/health       │     │ :9101/health     │
     │ :9100/metrics      │     │ :9101/metrics    │
     └────────┬───────────┘     └────────┬──────────┘
              │                          │
              └──────────┬───────────────┘
                         │
              ┌──────────▼───────────┐
              │  OpenCode HTTP API   │
              │  localhost:8080      │
              └──────────────────────┘
                                   ┌─────────────────────┐
                                   │  OTel Collector     │
                                   │  localhost:4317     │
                                   │  → logs/otel/       │
                                   └─────────────────────┘
┌───────────────────┐   ┌────────────────────┐   ┌──────────────────┐
│  Valkey            │   │  ngrok TCP tunnel  │   │  GitHub Actions  │
│  localhost:6379    │   │  1.tcp.us-cal-1    │   │  release.yml     │
│  AUTH required     │   │  .ngrok.io:24971   │   │  → releases.shipped
└───────────────────┘   └────────────────────┘   └──────────────────┘
```

## Quick Commands

### Start Everything (after reboot)

```bash
cd /Users/joshburt/Workbench/Repositories/oldgrowth
set -a; source .env; set +a
make recovery
```

This single command brings all 6 components online in dependency order with per-component timeouts. For details: `make _recovery_help`

### Check Health

```bash
make personas-status
```

Or manually:

```bash
# Valkey
valkey-cli -a $VALKEY_AUTH_TOKEN ping           # → PONG

# ngrok
curl -s http://localhost:4040/api/tunnels | jq .tunnels[0].public_url

# Persona health endpoints (spec 142)
curl -s http://localhost:9100/health              # Coordinator (base + liveness)
curl -s http://localhost:9101/health              # GTM

# Spec 143 health dashboard (per-persona)

Each persona runtime serves its own HTML dashboard at its health port. The dashboard
provides the same card layout regardless of which persona you open — data is scoped to
that process's perspective.

```bash
open http://localhost:9100                          # Coordinator dashboard
open http://localhost:9101                          # GTM dashboard
```

Both dashboards expose the same JSON API endpoints:

| Endpoint | Purpose |
|---|---|
| `/` | Redirects to `/dashboard` |
| `/health` | Base liveness + version + restart count + socket mode |
| `/dashboard` | Full HTML browser dashboard (auto-refresh 10s) |
| `/metrics` | Prometheus metrics (`og_*` counters) |
| `/health/personas` | Persona roster + liveness per agent + tags + capabilities + Letta agent IDs |
| `/health/circuits` | Circuit breaker states with consecutive 429 counts |
| `/health/threads` | Slack echo thread statistics |
| `/health/audit-stats` | Audit log entry distribution by status |
| `/health/recent-errors` | Last N error entries from the audit log |
| `/health/api-stats` | LLM/OpenCode call volumes, app mentions, per-persona breakdown |
| `/health/events` | Recent audit log entries (all statuses, real-time feed) |
| `/health/message-latency` | Average/max/min inter-agent message transit time |
| `/health/letta-probe` | Letta server reachability check |
| `/health/opencode-orphans` | Stale OpenCode session count |
| `/health/cost` | Weekly LLM cost summary (by model) |
| `/health/config` | Runtime configuration values (ports, timeouts, heartbeat) |
| `/health/orphans` | Orphaned inter-agent messages |
| `POST /health/orphans/resolve` | Resolve orphaned messages |

**Dashboard features:**
- Persona cards with tags, capability chips, Letta agent IDs, heartbeat status
- Dark/light theme toggle (persisted to localStorage)
- Human-readable uptime formatting
- Restart counter (file-persisted across process restarts)
- Socket mode status in summary bar
- Version identifier (git commit hash) in header
- Real-time event feed, message latency stats, Letta reachability probe
- Circuit breaker details (consecutive 429 count)
- Weekly cost summary per model
- Config table with key runtime settings

# Prometheus metrics
curl -s http://localhost:9100/metrics | grep og_  # Coordinator metrics

# OTel collector
curl -s http://localhost:8888/metrics | head -3   # Collector health

# OpenCode
curl -s http://localhost:8080/api/v1/sessions \
  -H "Authorization: Bearer $OPENCODE_SERVE_TOKEN"
```

### Stop Everything

```bash
make personas-down
# ngrok: Ctrl+C or launchctl unload
# Valkey: brew services stop valkey
```

### Restart a Persona

```bash
make personas-down      # stop all
make personas-up        # start all
```

Or for a single persona:

```bash
launchctl unload ~/Library/LaunchAgents/com.oldgrowth.coordinator.plist
launchctl load   ~/Library/LaunchAgents/com.oldgrowth.coordinator.plist
```

**What happens on restart (spec 143)**:
- Thread state (`personas/run/threads.json`) is loaded and pruned of entries >24h old
- Orphan janitor daemon starts automatically (60s cycle, detection-only)
- Health dashboard becomes available at all spec 143 endpoints immediately
- Background persistence flusher (5s cycle) saves thread metadata changes automatically
- Existing echo threads remain routable — human replies in known threads are not rejected after restart
```

## Component Reference

### Valkey (local, port 6379)

| Action | Command |
|---|---|
| Status | `make personas-status` or `valkey-cli -a $VALKEY_AUTH_TOKEN ping` |
| Start (cold boot) | `make recovery` — all 6 components in dependency order |
| Start | `brew services start valkey` |
| Stop | `brew services stop valkey` |
| Restart | `brew services restart valkey` |
| Stream count | `valkey-cli -a $VALKEY_AUTH_TOKEN XLEN releases.shipped` |
| Read stream | `valkey-cli -a $VALKEY_AUTH_TOKEN XRANGE releases.shipped - +` |
| Config | `/opt/homebrew/etc/valkey.conf` — `requirepass <token>` |

### ngrok TCP Tunnel

| Action | Command |
|---|---|
| Status | `make personas-status` or `curl -s localhost:4040/api/tunnels` |
| Start | `ngrok start --all --config ~/Library/Application\ Support/ngrok/ngrok.yml` |
| Stop | `launchctl unload ~/Library/LaunchAgents/com.ngrok.tunnel.plist` |
| Logs | `cat ~/Library/Logs/ngrok.log` |
| Config | `/Users/joshburt/Library/Application\ Support/ngrok/ngrok.yml` |
| Reserved TCP | `1.tcp.us-cal-1.ngrok.io:24971` (ID: `rd_39lBaWDzYl2EXB4mr2vAe76yEq2`) |
| Dashboard | https://dashboard.ngrok.com |

**Setup runbook**: `docs/vault/Reference/Autonomous Company/Ngrok Tunnel Setup.md`

### Letta (Docker — LLM Agent Server)

Letta agents provide **persistent conversation memory** for each persona. Runs in a Docker container with PostgreSQL backend.

| Action | Command |
|---|---|
| Status | `make personas-status` |
| Start | `make docker-letta-up` or `docker start letta-server` |
| Stop | `make docker-letta-down` or `docker stop letta-server` |
| Logs | `make docker-letta-logs` or `docker logs letta-server` |
| Auto-start | `launchctl load ~/Library/LaunchAgents/com.letta.server.plist` (starts container at login) |
| Agent IDs | `personas/letta_agents.json` |
| API | `http://localhost:8283/v1` — REST API for agent interactions |
| Data | `~/.letta/.persist/pgdata/` — PostgreSQL data (persists across restarts) |
| First-time setup | `docker run -d --name letta-server -v ~/.letta/.persist/pgdata:/var/lib/postgresql/data -p 8283:8283 -e OPENROUTER_API_KEY="..." letta/letta:latest` |
| Recreate agents | `python3 -c "from letta_client import Letta; c = Letta(base_url='http://localhost:8283'); print([a.name for a in c.agents.list()])"` |

**Full restart sequence**:
```bash
# Stop everything
make personas-down
make docker-letta-down

# Start everything
make docker-letta-up
sleep 10  # wait for PostgreSQL + server ready
make personas-up
```

**Agent memory**: Each agent has core memory blocks (`persona` + `human`) that persist across server restarts. Agents automatically update their memory (archival/recall) during conversations. To reset a persona's memory:
1. Delete the agent: `client.agents.delete(agent_id)`
2. Recreate via `scripts/personas/create-letta-agents.py` (if created)

### Inter-Agent Messaging (spec 142)

Inter-agent messaging enables the Coordinator persona to send structured messages to GTM's Letta agent, with Slack thread echo for human observation.

| Action | Command |
|---|---|
| View audit log | `tail -f personas/logs/inter_agent.jsonl \| jq .` |
| View overflow log | `tail -f personas/logs/inter_agent_payloads.jsonl \| jq .` |
| Count messages sent | `wc -l < personas/logs/inter_agent.jsonl` |
| Filter by status | `jq 'select(.status == "acked")' personas/logs/inter_agent.jsonl` |
| View circuit breaker state | `python3 -c "from personas.circuit_breaker import _BREAKERS; print(_BREAKERS)"` |
| Check peer health | `python3 -c "from personas.health_state import _HEALTH; print(_HEALTH)"` |
| Run inter-agent tests | `.venv/bin/python -m pytest personas/tests/ -q` |
| Run all tests (195) | `.venv/bin/python -m pytest personas/tests/ -q` (195 pass, 15 skip) |

**Key files**:

| File | Purpose |
|---|---|
| `personas/inter_agent.py` | Async send(), state machine, audit log, per-agent locking |
| `personas/slack_echo.py` | Slack thread echo, human injection with auth gate + rate limit |
| `personas/circuit_breaker.py` | Per-target breaker (5× 429 → OPEN, 30s cooldown) |
| `personas/health_state.py` | Heartbeat-based peer liveness (UP/DOWN) |
| `personas/logs/inter_agent.jsonl` | JSONL audit log — one entry per state transition |
| `personas/logs/inter_agent_payloads.jsonl` | Overflow log for payloads > PIPE_BUF (4096 bytes) |

### OTel Collector

| Action | Command |
|---|---|
| Status | `launchctl list \| grep otel` |
| Install | `scripts/personas/install-otel-collector.sh` |
| Traces file | `logs/otel/v0.1-traces.json` |
| Config | `~/Library/Application Support/otel-collector/config.yaml` |

### MCP Tool Configuration (spec 140)

Tool assignments for persona agents are managed through a manifest file and the `make mcp-setup` / `make mcp-status` commands. Persona runtimes do not read the manifest at startup — tool state is reconciled independently of runtime lifecycle.

| Action | Command |
|---|---|
| Setup | `make mcp-setup` — register MCP servers + attach tools per manifest |
| Status | `make mcp-status` — show registrations, per-agent tools, host-tools health |
| Manifest | `docs/vault/Reference/Autonomous Company/trusted_agent_mcp_manifest.json` |
| Server ports | Host-tools: port 9105 (Streamable HTTP); Obsidian: stdio via `npx` |

**Recovery dependency chain**: Letta server → host-tools MCP (port 9105) → personas healthy → `make mcp-setup`. No persona restart required — tool attachment is live via Letta API per spec 140 FR-003.

**Cross-references**:
- [[141 Auto Restart Recovery]] — port allocation table includes 9105 (host-tools)
- [[142 Persona Inter Agent Messaging]] — inter-agent messaging uses same Letta infrastructure
- [[143 Inter Agent Extensions]] — `/health` endpoint contract; `/health/personas` aggregator polls host-tools health
- [[144 Consolidate Notification Channel]] — host-tools emits `status`, `error`, and `approval` notifications per spec 144; no `tool_event` or `tool-start` values are emitted

### GitHub Actions Secrets

Set on 2 repos (oldgrowth, oldgrowth-assets). old-growth-wiki repo and its CI were removed 2026-05-10 — vault rendering is now local-only via `wiki/`.

| Secret | Value |
|---|---|
| `VALKEY_NGROK_HOST` | `1.tcp.us-cal-1.ngrok.io` |
| `VALKEY_NGROK_PORT` | `24971` |
| `VALKEY_AUTH_TOKEN` | (from 1Password `Valkey AUTH Token (Local Dev)`) |

### Slack Apps

| App | Tokens in `.env` | Bot Scopes |
|---|---|---|
| Old Growth Coordinator | `SLACK_BOT_TOKEN_COORDINATOR`, `SLACK_APP_TOKEN_COORDINATOR` | 8 (chat:write, chat:write.public, channels:history, channels:read, groups:history, im:history, im:write, app_mentions:read) |
| Old Growth GTM | `SLACK_BOT_TOKEN_GTM`, `SLACK_APP_TOKEN_GTM` | 10 (above + files:read, files:write) |

**Registration runbook**: `docs/vault/Reference/Autonomous Company/Slack App Registration Runbook.md`
**Kill-switch runbook**: `docs/vault/Reference/Autonomous Company/Slack App Kill-Switch Runbook.md`

### Workflow Builder

| Item | Value |
|---|---|
| Workflow name | `gtm-class-b-approval` |
| Workflow ID | `Wf0B2QQJP0K0` |
| Channel | `#announce-releases` |
| Export | `docs/vault/Reference/Autonomous Company/slack/gtm-class-b-approval.json` |

### .env Reference

```bash
# Required for persona runtimes:
SLACK_BOT_TOKEN_COORDINATOR=xoxb-...
SLACK_APP_TOKEN_COORDINATOR=xapp-...
SLACK_BOT_TOKEN_GTM=xoxb-...
SLACK_APP_TOKEN_GTM=xapp-...
OPENROUTER_API_KEY=sk-or-...
ANTHROPIC_API_KEY=sk-ant-...     # failover
OPENCODE_SERVE_TOKEN=...          # for opencode serve

# Required for GitHub Actions → local Valkey:
VALKEY_AUTH_TOKEN=...
VALKEY_NGROK_HOST=1.tcp.us-cal-1.ngrok.io
VALKEY_NGROK_PORT=24971

# Optional:
PERSONA_HEALTH_PORT=9100          # Coordinator (default)
PERSONA_LOG_LEVEL=INFO            # or DEBUG for full LLM logs

# Inter-Agent Messaging (spec 142):
PERSONA_LETTA_SEND_TIMEOUT_SEC=60          # default 60s
PERSONA_LETTA_STREAM_TIMEOUT_SEC=600       # default 600s
PERSONA_MAX_HOPS=5                         # default 5
PERSONA_AUTHORIZED_HUMAN_IDS=U111,U222     # comma-separated Slack user IDs
PERSONA_HUMAN_INJECTION_RATE_LIMIT_PER_MIN=10
PERSONA_HEARTBEAT_INTERVAL_SEC=30          # peer liveness ping interval
PERSONA_HEARTBEAT_TIMEOUT_SEC=90           # peer considered DOWN after this silence
PERSONA_INTER_AGENT_OWNER_LOCK=personas/run/inter_agent.owner
PERSONA_SLACK_ECHO_CHANNEL=C12345          # #team-personas channel ID
PERSONA_BOT_USER_IDS=U111,U222             # persona bot Slack user IDs (skip these in echo)
```

## Week 0 Artifacts

| Artifact | Path |
|---|---|
| Session log | `docs/vault/Sessions/2026-05-09 Spec 134 Week 0 Setup.md` |
| Slack channels | 14 created (general, announce-ops, announce-personas, announce-releases, team-personas, team-dev, proj-v01-experiment, help-spec, help-debug, sys-observer, sys-tts, sys-vault-audit, sys-release, social-wins) |
| Persona icons | `src/assets/icons/personas/` (7 icons, SDXL generated by `scripts/personas/generate-icons.py`) |
| Icon pipeline | `scripts/personas/generate-icons.py` |
| Spec 134 tasks | `docs/vault/Specs/134 Per Persona Slack App Registration/134 Per Persona Slack App Registration - tasks.md` |
| Spec 135 tasks | `docs/vault/Specs/135 Persona Middleware Specs/135 Persona Middleware Specs - tasks.md` |

## Letta Cloud Migration

The inter-agent messaging implementation in spec 142 (`personas/inter_agent.py`) targets a self-hosted Letta server (`letta/letta:latest` Docker image, port 8283) and dispatches messages via `client.agents.messages.create(agent_id=..., messages=[...])`. This call is the long-term, stable, cross-deployment Letta SDK surface.

Some Letta tutorials and older documentation reference the higher-level multi-agent helper `send_message_to_agent_async`. **This helper is not available on Letta Cloud** (the managed SaaS offering). It is only present in self-hosted Letta server builds with the multi-agent core tools enabled.

If migrating personas to Letta Cloud (FR-013):

| Concern | Self-hosted (current) | Letta Cloud (target) |
|---|---|---|
| Message dispatch | `client.agents.messages.create(...)` | `client.agents.messages.create(...)` (unchanged) |
| Multi-agent helper | `send_message_to_agent_async` available | Not available — use `send_message_to_agent_and_wait_for_reply` instead |
| Server URL | `http://localhost:8283` | `https://app.letta.com` (or region-specific) |
| Auth | None (local) or local API key | `LETTA_API_KEY` (Bearer token) |
| Block API | Same | Same |
| Agent IDs | Stable per-server | Migration requires recreating agents and updating `personas/letta_agents.json` |

**No code change is required for the Coordinator → GTM happy path.** The `inter_agent.send()` helper already uses `client.agents.messages.create()` and does not depend on `send_message_to_agent_async`. To switch deployments, set `LETTA_BASE_URL` and `LETTA_API_KEY` in `.env` and recreate persona agents on the target server, updating `letta_agent_id` in `personas/letta_agents.json` accordingly.

If a future spec requires the synchronous multi-agent fan-out pattern, replace `client.agents.messages.create()` with `client.agents.send_message_to_agent_and_wait_for_reply()` — both are supported on Cloud and self-hosted.

Controlled tag vocabulary (as read):
type/*:
- `type/code` — Code architecture, autoloads, conventions, tooling. Carries `code-refs:`. (e.g. `Code/Autoloads — Disturbance.md`)
- `type/decision` — Architectural or design decision made by an agent during a session. Written to `docs/vault/Decisions/`. (Agent notes only — spec 080.)
- `type/design` — Design intent, player-facing concepts, world lore. (e.g. `Design/World Model.md`)
- `type/discovery` — Non-obvious constraint, gap, or conflict found by an agent during a session. Written to `docs/vault/Discoveries/`. (Agent notes only — spec 080.)
- `type/moc` — Map of Content at any of three tiers (folder / domain / concept). (e.g. `Audio.md`)
- `type/principle` — Governance and constitutional notes. Non-negotiable rules. (e.g. `Governance/Constitution.md`)
- `type/reference` — Glossary, decision log, open questions, epics. (e.g. `Reference/Glossary.md`)
- `type/session-log` — Session activity log; permanent audit trail. Written to `docs/vault/Sessions/`. Append-only, never pruned. (Agent notes only — spec 080.)
- `type/spec` — Spec document at `docs/vault/Specs/NNN Title/spec.md`. Carries `spec-refs:`. (e.g. `Specs/047 Car Radio/spec.md`)
- `type/system` — A bounded subsystem with implementation. Carries `code-refs`, `spec-refs`, `implements:` frontmatter. (e.g. `Systems/Audio — Car Radio.md`)
- `type/vision` — Strategic / vision-layer decision. Written to `docs/vault/Vision/`. Human-authored or agent-proposed with human ratification before promotion to `status: reviewed`. (Per triage #3 — spec 133 autonomous-company redesign.)
domain/*:
- `domain/anomalies` — Anomaly taxonomy, individual anomaly systems, spawn, behavior
- `domain/art` — Visual direction, palettes, references, asset pipeline
- `domain/audio` — Audio systems: world ambient, radio, transmissions, buses, pipeline
- `domain/autonomous-company` — Autonomous company v0.1 experiment: Slack infra, persona middleware, Letta integration, restart recovery
- `domain/build` — Build system, packaging, export, release automation
- `domain/governance` — Constitution, phased spec, policies
- `domain/infrastructure` — Infrastructure provisioning: CI/CD, hosting, deployment tooling, secrets management
- `domain/narrative` — Tone, horror register, forest transmissions narrative, Gary/KTLK
- `domain/player` — Player mode, input, controls, camera, exit/entry
- `domain/systems` — Cross-cutting system architecture and integration work
- `domain/tooling` — Build, CI, observer, TTS pipeline, dev-time tools
- `domain/vehicle` — The Samba: vehicle physics, dashboard, damage, panels
- `domain/world` — World model, biomes, terrain, procedural generation, weather
status/*:
- `status/canonical` — Fully authoritative; promoted by humans only. Highest trust. (Agent notes only — spec 080.)
- `status/draft` — Authoring in progress, not yet verified
- `status/reviewed` — Agent-created note verified against codebase within its creating session. Eligible for auto-injection in subsequent task dispatches. (Agent notes only — spec 080.)
- `status/stale` — Known out of date; cannot update immediately. Pairs with `> [!warning] STALE — needs update` callout.
- `status/superseded` — Replaced by another note. Terminal state. Pairs with `> [!warning] SUPERSEDED` callout.
- `status/wip` — Stable but under active revision
layer/*:
- `layer/content` — Content assets (audio, models, textures, audio provenance)
- `layer/gdext` — gdext wrapper layer (`rust/gdext-wrapper/`)
- `layer/gdscript` — GDScript (Godot scene-tier logic)
- `layer/infra` — Build, CI, deployment infrastructure
- `layer/python` — Python development tooling (`tools/`)
- `layer/rust-core` — Engine-agnostic Rust core (`rust/rust-core/`)
concept/*:
- `concept/biome` — Biome-reactive behavior across systems
- `concept/contamination` — Across-runs panel and garage degradation; the slow-horror mechanic that doesn't reset with the world
- `concept/diegetic` — Diegetic audio / UI / world-sourced design
- `concept/disturbance` — The disturbance mechanic thread (Article X)
- `concept/ephemeral-world` — Run-reset, transient worlds (Article IV Rules 6–7)
- `concept/governance` — Constitutional and governance concepts
- `concept/horror` — Horror register and dread design
- `concept/procedural` — Procedural generation, seed determinism
- `concept/rendering` — Visual rendering quality, shader correctness, Terrain3D integration, mesh fidelity, LOD, Z-fighting
- `concept/terrain` — Terrain generation, heightmap, Terrain3D regions, roughness, playability constraints
ember's answer for tag_assignment-reference-autonomous-company-autonomous-company-operations-reference, type/referenceP(true) placed on the no, unsure, and yes zones.nounsureyesgold: yesP = 0.22

tag_assignment-reference-autonomous-company-autonomous-company-operations-reference: type/spec

Tag assignment · dev
Gold
The note has no reason to carry `type/spec` (False)
ember
The note calls for `type/spec`: Spec document at `docs/vault/Specs/NNN Title/spec.md`. Carries `spec-refs:`. (e.g. `Specs/047 Car Radio/spec.md`) (True)
Signal
P(true) 0.53 (unsure)
Kit outcome
deferred: treated as unsure
Why this gold label
Mined from Reference/Autonomous Company/Autonomous Company Operations Reference.md at 692f4bb58b7f62105aeb73fba8dfee12bfdecd53; gold is the note's own vocabulary tags.
Autonomous Company Operations Reference

> **Part of**: [[133 Autonomous Company V01 Experiment]]
> **Quickstart**: `docs/vault/Specs/135 Per Persona Middleware Specs/135 Per Persona Middleware Specs - quickstart.md`

## Infrastructure Stack

```
┌─────────────────────────────────────────────────────┐
│                    Slack                             │
│  ┌─ Old Growth Coordinator  ┌─ Old Growth GTM       │
│  │  Socket Mode WebSocket   │  Socket Mode WebSocket│
│  └──────────┬───────────────└──────────┬────────────│
│             │                          │             │
│        app_mention               announce-releases  │
│        /internal/approval-callback                   │
└─────────────┼──────────────────────────┼─────────────┘
              │                          │
     ┌────────▼──────────┐     ┌─────────▼────────┐
     │ Coordinator Runtime│     │   GTM Runtime    │
     │ :9100/health       │     │ :9101/health     │
     │ :9100/metrics      │     │ :9101/metrics    │
     └────────┬───────────┘     └────────┬──────────┘
              │                          │
              └──────────┬───────────────┘
                         │
              ┌──────────▼───────────┐
              │  OpenCode HTTP API   │
              │  localhost:8080      │
              └──────────────────────┘
                                   ┌─────────────────────┐
                                   │  OTel Collector     │
                                   │  localhost:4317     │
                                   │  → logs/otel/       │
                                   └─────────────────────┘
┌───────────────────┐   ┌────────────────────┐   ┌──────────────────┐
│  Valkey            │   │  ngrok TCP tunnel  │   │  GitHub Actions  │
│  localhost:6379    │   │  1.tcp.us-cal-1    │   │  release.yml     │
│  AUTH required     │   │  .ngrok.io:24971   │   │  → releases.shipped
└───────────────────┘   └────────────────────┘   └──────────────────┘
```

## Quick Commands

### Start Everything (after reboot)

```bash
cd /Users/joshburt/Workbench/Repositories/oldgrowth
set -a; source .env; set +a
make recovery
```

This single command brings all 6 components online in dependency order with per-component timeouts. For details: `make _recovery_help`

### Check Health

```bash
make personas-status
```

Or manually:

```bash
# Valkey
valkey-cli -a $VALKEY_AUTH_TOKEN ping           # → PONG

# ngrok
curl -s http://localhost:4040/api/tunnels | jq .tunnels[0].public_url

# Persona health endpoints (spec 142)
curl -s http://localhost:9100/health              # Coordinator (base + liveness)
curl -s http://localhost:9101/health              # GTM

# Spec 143 health dashboard (per-persona)

Each persona runtime serves its own HTML dashboard at its health port. The dashboard
provides the same card layout regardless of which persona you open — data is scoped to
that process's perspective.

```bash
open http://localhost:9100                          # Coordinator dashboard
open http://localhost:9101                          # GTM dashboard
```

Both dashboards expose the same JSON API endpoints:

| Endpoint | Purpose |
|---|---|
| `/` | Redirects to `/dashboard` |
| `/health` | Base liveness + version + restart count + socket mode |
| `/dashboard` | Full HTML browser dashboard (auto-refresh 10s) |
| `/metrics` | Prometheus metrics (`og_*` counters) |
| `/health/personas` | Persona roster + liveness per agent + tags + capabilities + Letta agent IDs |
| `/health/circuits` | Circuit breaker states with consecutive 429 counts |
| `/health/threads` | Slack echo thread statistics |
| `/health/audit-stats` | Audit log entry distribution by status |
| `/health/recent-errors` | Last N error entries from the audit log |
| `/health/api-stats` | LLM/OpenCode call volumes, app mentions, per-persona breakdown |
| `/health/events` | Recent audit log entries (all statuses, real-time feed) |
| `/health/message-latency` | Average/max/min inter-agent message transit time |
| `/health/letta-probe` | Letta server reachability check |
| `/health/opencode-orphans` | Stale OpenCode session count |
| `/health/cost` | Weekly LLM cost summary (by model) |
| `/health/config` | Runtime configuration values (ports, timeouts, heartbeat) |
| `/health/orphans` | Orphaned inter-agent messages |
| `POST /health/orphans/resolve` | Resolve orphaned messages |

**Dashboard features:**
- Persona cards with tags, capability chips, Letta agent IDs, heartbeat status
- Dark/light theme toggle (persisted to localStorage)
- Human-readable uptime formatting
- Restart counter (file-persisted across process restarts)
- Socket mode status in summary bar
- Version identifier (git commit hash) in header
- Real-time event feed, message latency stats, Letta reachability probe
- Circuit breaker details (consecutive 429 count)
- Weekly cost summary per model
- Config table with key runtime settings

# Prometheus metrics
curl -s http://localhost:9100/metrics | grep og_  # Coordinator metrics

# OTel collector
curl -s http://localhost:8888/metrics | head -3   # Collector health

# OpenCode
curl -s http://localhost:8080/api/v1/sessions \
  -H "Authorization: Bearer $OPENCODE_SERVE_TOKEN"
```

### Stop Everything

```bash
make personas-down
# ngrok: Ctrl+C or launchctl unload
# Valkey: brew services stop valkey
```

### Restart a Persona

```bash
make personas-down      # stop all
make personas-up        # start all
```

Or for a single persona:

```bash
launchctl unload ~/Library/LaunchAgents/com.oldgrowth.coordinator.plist
launchctl load   ~/Library/LaunchAgents/com.oldgrowth.coordinator.plist
```

**What happens on restart (spec 143)**:
- Thread state (`personas/run/threads.json`) is loaded and pruned of entries >24h old
- Orphan janitor daemon starts automatically (60s cycle, detection-only)
- Health dashboard becomes available at all spec 143 endpoints immediately
- Background persistence flusher (5s cycle) saves thread metadata changes automatically
- Existing echo threads remain routable — human replies in known threads are not rejected after restart
```

## Component Reference

### Valkey (local, port 6379)

| Action | Command |
|---|---|
| Status | `make personas-status` or `valkey-cli -a $VALKEY_AUTH_TOKEN ping` |
| Start (cold boot) | `make recovery` — all 6 components in dependency order |
| Start | `brew services start valkey` |
| Stop | `brew services stop valkey` |
| Restart | `brew services restart valkey` |
| Stream count | `valkey-cli -a $VALKEY_AUTH_TOKEN XLEN releases.shipped` |
| Read stream | `valkey-cli -a $VALKEY_AUTH_TOKEN XRANGE releases.shipped - +` |
| Config | `/opt/homebrew/etc/valkey.conf` — `requirepass <token>` |

### ngrok TCP Tunnel

| Action | Command |
|---|---|
| Status | `make personas-status` or `curl -s localhost:4040/api/tunnels` |
| Start | `ngrok start --all --config ~/Library/Application\ Support/ngrok/ngrok.yml` |
| Stop | `launchctl unload ~/Library/LaunchAgents/com.ngrok.tunnel.plist` |
| Logs | `cat ~/Library/Logs/ngrok.log` |
| Config | `/Users/joshburt/Library/Application\ Support/ngrok/ngrok.yml` |
| Reserved TCP | `1.tcp.us-cal-1.ngrok.io:24971` (ID: `rd_39lBaWDzYl2EXB4mr2vAe76yEq2`) |
| Dashboard | https://dashboard.ngrok.com |

**Setup runbook**: `docs/vault/Reference/Autonomous Company/Ngrok Tunnel Setup.md`

### Letta (Docker — LLM Agent Server)

Letta agents provide **persistent conversation memory** for each persona. Runs in a Docker container with PostgreSQL backend.

| Action | Command |
|---|---|
| Status | `make personas-status` |
| Start | `make docker-letta-up` or `docker start letta-server` |
| Stop | `make docker-letta-down` or `docker stop letta-server` |
| Logs | `make docker-letta-logs` or `docker logs letta-server` |
| Auto-start | `launchctl load ~/Library/LaunchAgents/com.letta.server.plist` (starts container at login) |
| Agent IDs | `personas/letta_agents.json` |
| API | `http://localhost:8283/v1` — REST API for agent interactions |
| Data | `~/.letta/.persist/pgdata/` — PostgreSQL data (persists across restarts) |
| First-time setup | `docker run -d --name letta-server -v ~/.letta/.persist/pgdata:/var/lib/postgresql/data -p 8283:8283 -e OPENROUTER_API_KEY="..." letta/letta:latest` |
| Recreate agents | `python3 -c "from letta_client import Letta; c = Letta(base_url='http://localhost:8283'); print([a.name for a in c.agents.list()])"` |

**Full restart sequence**:
```bash
# Stop everything
make personas-down
make docker-letta-down

# Start everything
make docker-letta-up
sleep 10  # wait for PostgreSQL + server ready
make personas-up
```

**Agent memory**: Each agent has core memory blocks (`persona` + `human`) that persist across server restarts. Agents automatically update their memory (archival/recall) during conversations. To reset a persona's memory:
1. Delete the agent: `client.agents.delete(agent_id)`
2. Recreate via `scripts/personas/create-letta-agents.py` (if created)

### Inter-Agent Messaging (spec 142)

Inter-agent messaging enables the Coordinator persona to send structured messages to GTM's Letta agent, with Slack thread echo for human observation.

| Action | Command |
|---|---|
| View audit log | `tail -f personas/logs/inter_agent.jsonl \| jq .` |
| View overflow log | `tail -f personas/logs/inter_agent_payloads.jsonl \| jq .` |
| Count messages sent | `wc -l < personas/logs/inter_agent.jsonl` |
| Filter by status | `jq 'select(.status == "acked")' personas/logs/inter_agent.jsonl` |
| View circuit breaker state | `python3 -c "from personas.circuit_breaker import _BREAKERS; print(_BREAKERS)"` |
| Check peer health | `python3 -c "from personas.health_state import _HEALTH; print(_HEALTH)"` |
| Run inter-agent tests | `.venv/bin/python -m pytest personas/tests/ -q` |
| Run all tests (195) | `.venv/bin/python -m pytest personas/tests/ -q` (195 pass, 15 skip) |

**Key files**:

| File | Purpose |
|---|---|
| `personas/inter_agent.py` | Async send(), state machine, audit log, per-agent locking |
| `personas/slack_echo.py` | Slack thread echo, human injection with auth gate + rate limit |
| `personas/circuit_breaker.py` | Per-target breaker (5× 429 → OPEN, 30s cooldown) |
| `personas/health_state.py` | Heartbeat-based peer liveness (UP/DOWN) |
| `personas/logs/inter_agent.jsonl` | JSONL audit log — one entry per state transition |
| `personas/logs/inter_agent_payloads.jsonl` | Overflow log for payloads > PIPE_BUF (4096 bytes) |

### OTel Collector

| Action | Command |
|---|---|
| Status | `launchctl list \| grep otel` |
| Install | `scripts/personas/install-otel-collector.sh` |
| Traces file | `logs/otel/v0.1-traces.json` |
| Config | `~/Library/Application Support/otel-collector/config.yaml` |

### MCP Tool Configuration (spec 140)

Tool assignments for persona agents are managed through a manifest file and the `make mcp-setup` / `make mcp-status` commands. Persona runtimes do not read the manifest at startup — tool state is reconciled independently of runtime lifecycle.

| Action | Command |
|---|---|
| Setup | `make mcp-setup` — register MCP servers + attach tools per manifest |
| Status | `make mcp-status` — show registrations, per-agent tools, host-tools health |
| Manifest | `docs/vault/Reference/Autonomous Company/trusted_agent_mcp_manifest.json` |
| Server ports | Host-tools: port 9105 (Streamable HTTP); Obsidian: stdio via `npx` |

**Recovery dependency chain**: Letta server → host-tools MCP (port 9105) → personas healthy → `make mcp-setup`. No persona restart required — tool attachment is live via Letta API per spec 140 FR-003.

**Cross-references**:
- [[141 Auto Restart Recovery]] — port allocation table includes 9105 (host-tools)
- [[142 Persona Inter Agent Messaging]] — inter-agent messaging uses same Letta infrastructure
- [[143 Inter Agent Extensions]] — `/health` endpoint contract; `/health/personas` aggregator polls host-tools health
- [[144 Consolidate Notification Channel]] — host-tools emits `status`, `error`, and `approval` notifications per spec 144; no `tool_event` or `tool-start` values are emitted

### GitHub Actions Secrets

Set on 2 repos (oldgrowth, oldgrowth-assets). old-growth-wiki repo and its CI were removed 2026-05-10 — vault rendering is now local-only via `wiki/`.

| Secret | Value |
|---|---|
| `VALKEY_NGROK_HOST` | `1.tcp.us-cal-1.ngrok.io` |
| `VALKEY_NGROK_PORT` | `24971` |
| `VALKEY_AUTH_TOKEN` | (from 1Password `Valkey AUTH Token (Local Dev)`) |

### Slack Apps

| App | Tokens in `.env` | Bot Scopes |
|---|---|---|
| Old Growth Coordinator | `SLACK_BOT_TOKEN_COORDINATOR`, `SLACK_APP_TOKEN_COORDINATOR` | 8 (chat:write, chat:write.public, channels:history, channels:read, groups:history, im:history, im:write, app_mentions:read) |
| Old Growth GTM | `SLACK_BOT_TOKEN_GTM`, `SLACK_APP_TOKEN_GTM` | 10 (above + files:read, files:write) |

**Registration runbook**: `docs/vault/Reference/Autonomous Company/Slack App Registration Runbook.md`
**Kill-switch runbook**: `docs/vault/Reference/Autonomous Company/Slack App Kill-Switch Runbook.md`

### Workflow Builder

| Item | Value |
|---|---|
| Workflow name | `gtm-class-b-approval` |
| Workflow ID | `Wf0B2QQJP0K0` |
| Channel | `#announce-releases` |
| Export | `docs/vault/Reference/Autonomous Company/slack/gtm-class-b-approval.json` |

### .env Reference

```bash
# Required for persona runtimes:
SLACK_BOT_TOKEN_COORDINATOR=xoxb-...
SLACK_APP_TOKEN_COORDINATOR=xapp-...
SLACK_BOT_TOKEN_GTM=xoxb-...
SLACK_APP_TOKEN_GTM=xapp-...
OPENROUTER_API_KEY=sk-or-...
ANTHROPIC_API_KEY=sk-ant-...     # failover
OPENCODE_SERVE_TOKEN=...          # for opencode serve

# Required for GitHub Actions → local Valkey:
VALKEY_AUTH_TOKEN=...
VALKEY_NGROK_HOST=1.tcp.us-cal-1.ngrok.io
VALKEY_NGROK_PORT=24971

# Optional:
PERSONA_HEALTH_PORT=9100          # Coordinator (default)
PERSONA_LOG_LEVEL=INFO            # or DEBUG for full LLM logs

# Inter-Agent Messaging (spec 142):
PERSONA_LETTA_SEND_TIMEOUT_SEC=60          # default 60s
PERSONA_LETTA_STREAM_TIMEOUT_SEC=600       # default 600s
PERSONA_MAX_HOPS=5                         # default 5
PERSONA_AUTHORIZED_HUMAN_IDS=U111,U222     # comma-separated Slack user IDs
PERSONA_HUMAN_INJECTION_RATE_LIMIT_PER_MIN=10
PERSONA_HEARTBEAT_INTERVAL_SEC=30          # peer liveness ping interval
PERSONA_HEARTBEAT_TIMEOUT_SEC=90           # peer considered DOWN after this silence
PERSONA_INTER_AGENT_OWNER_LOCK=personas/run/inter_agent.owner
PERSONA_SLACK_ECHO_CHANNEL=C12345          # #team-personas channel ID
PERSONA_BOT_USER_IDS=U111,U222             # persona bot Slack user IDs (skip these in echo)
```

## Week 0 Artifacts

| Artifact | Path |
|---|---|
| Session log | `docs/vault/Sessions/2026-05-09 Spec 134 Week 0 Setup.md` |
| Slack channels | 14 created (general, announce-ops, announce-personas, announce-releases, team-personas, team-dev, proj-v01-experiment, help-spec, help-debug, sys-observer, sys-tts, sys-vault-audit, sys-release, social-wins) |
| Persona icons | `src/assets/icons/personas/` (7 icons, SDXL generated by `scripts/personas/generate-icons.py`) |
| Icon pipeline | `scripts/personas/generate-icons.py` |
| Spec 134 tasks | `docs/vault/Specs/134 Per Persona Slack App Registration/134 Per Persona Slack App Registration - tasks.md` |
| Spec 135 tasks | `docs/vault/Specs/135 Persona Middleware Specs/135 Persona Middleware Specs - tasks.md` |

## Letta Cloud Migration

The inter-agent messaging implementation in spec 142 (`personas/inter_agent.py`) targets a self-hosted Letta server (`letta/letta:latest` Docker image, port 8283) and dispatches messages via `client.agents.messages.create(agent_id=..., messages=[...])`. This call is the long-term, stable, cross-deployment Letta SDK surface.

Some Letta tutorials and older documentation reference the higher-level multi-agent helper `send_message_to_agent_async`. **This helper is not available on Letta Cloud** (the managed SaaS offering). It is only present in self-hosted Letta server builds with the multi-agent core tools enabled.

If migrating personas to Letta Cloud (FR-013):

| Concern | Self-hosted (current) | Letta Cloud (target) |
|---|---|---|
| Message dispatch | `client.agents.messages.create(...)` | `client.agents.messages.create(...)` (unchanged) |
| Multi-agent helper | `send_message_to_agent_async` available | Not available — use `send_message_to_agent_and_wait_for_reply` instead |
| Server URL | `http://localhost:8283` | `https://app.letta.com` (or region-specific) |
| Auth | None (local) or local API key | `LETTA_API_KEY` (Bearer token) |
| Block API | Same | Same |
| Agent IDs | Stable per-server | Migration requires recreating agents and updating `personas/letta_agents.json` |

**No code change is required for the Coordinator → GTM happy path.** The `inter_agent.send()` helper already uses `client.agents.messages.create()` and does not depend on `send_message_to_agent_async`. To switch deployments, set `LETTA_BASE_URL` and `LETTA_API_KEY` in `.env` and recreate persona agents on the target server, updating `letta_agent_id` in `personas/letta_agents.json` accordingly.

If a future spec requires the synchronous multi-agent fan-out pattern, replace `client.agents.messages.create()` with `client.agents.send_message_to_agent_and_wait_for_reply()` — both are supported on Cloud and self-hosted.

Controlled tag vocabulary (as read):
type/*:
- `type/code` — Code architecture, autoloads, conventions, tooling. Carries `code-refs:`. (e.g. `Code/Autoloads — Disturbance.md`)
- `type/decision` — Architectural or design decision made by an agent during a session. Written to `docs/vault/Decisions/`. (Agent notes only — spec 080.)
- `type/design` — Design intent, player-facing concepts, world lore. (e.g. `Design/World Model.md`)
- `type/discovery` — Non-obvious constraint, gap, or conflict found by an agent during a session. Written to `docs/vault/Discoveries/`. (Agent notes only — spec 080.)
- `type/moc` — Map of Content at any of three tiers (folder / domain / concept). (e.g. `Audio.md`)
- `type/principle` — Governance and constitutional notes. Non-negotiable rules. (e.g. `Governance/Constitution.md`)
- `type/reference` — Glossary, decision log, open questions, epics. (e.g. `Reference/Glossary.md`)
- `type/session-log` — Session activity log; permanent audit trail. Written to `docs/vault/Sessions/`. Append-only, never pruned. (Agent notes only — spec 080.)
- `type/spec` — Spec document at `docs/vault/Specs/NNN Title/spec.md`. Carries `spec-refs:`. (e.g. `Specs/047 Car Radio/spec.md`)
- `type/system` — A bounded subsystem with implementation. Carries `code-refs`, `spec-refs`, `implements:` frontmatter. (e.g. `Systems/Audio — Car Radio.md`)
- `type/vision` — Strategic / vision-layer decision. Written to `docs/vault/Vision/`. Human-authored or agent-proposed with human ratification before promotion to `status: reviewed`. (Per triage #3 — spec 133 autonomous-company redesign.)
domain/*:
- `domain/anomalies` — Anomaly taxonomy, individual anomaly systems, spawn, behavior
- `domain/art` — Visual direction, palettes, references, asset pipeline
- `domain/audio` — Audio systems: world ambient, radio, transmissions, buses, pipeline
- `domain/autonomous-company` — Autonomous company v0.1 experiment: Slack infra, persona middleware, Letta integration, restart recovery
- `domain/build` — Build system, packaging, export, release automation
- `domain/governance` — Constitution, phased spec, policies
- `domain/infrastructure` — Infrastructure provisioning: CI/CD, hosting, deployment tooling, secrets management
- `domain/narrative` — Tone, horror register, forest transmissions narrative, Gary/KTLK
- `domain/player` — Player mode, input, controls, camera, exit/entry
- `domain/systems` — Cross-cutting system architecture and integration work
- `domain/tooling` — Build, CI, observer, TTS pipeline, dev-time tools
- `domain/vehicle` — The Samba: vehicle physics, dashboard, damage, panels
- `domain/world` — World model, biomes, terrain, procedural generation, weather
status/*:
- `status/canonical` — Fully authoritative; promoted by humans only. Highest trust. (Agent notes only — spec 080.)
- `status/draft` — Authoring in progress, not yet verified
- `status/reviewed` — Agent-created note verified against codebase within its creating session. Eligible for auto-injection in subsequent task dispatches. (Agent notes only — spec 080.)
- `status/stale` — Known out of date; cannot update immediately. Pairs with `> [!warning] STALE — needs update` callout.
- `status/superseded` — Replaced by another note. Terminal state. Pairs with `> [!warning] SUPERSEDED` callout.
- `status/wip` — Stable but under active revision
layer/*:
- `layer/content` — Content assets (audio, models, textures, audio provenance)
- `layer/gdext` — gdext wrapper layer (`rust/gdext-wrapper/`)
- `layer/gdscript` — GDScript (Godot scene-tier logic)
- `layer/infra` — Build, CI, deployment infrastructure
- `layer/python` — Python development tooling (`tools/`)
- `layer/rust-core` — Engine-agnostic Rust core (`rust/rust-core/`)
concept/*:
- `concept/biome` — Biome-reactive behavior across systems
- `concept/contamination` — Across-runs panel and garage degradation; the slow-horror mechanic that doesn't reset with the world
- `concept/diegetic` — Diegetic audio / UI / world-sourced design
- `concept/disturbance` — The disturbance mechanic thread (Article X)
- `concept/ephemeral-world` — Run-reset, transient worlds (Article IV Rules 6–7)
- `concept/governance` — Constitutional and governance concepts
- `concept/horror` — Horror register and dread design
- `concept/procedural` — Procedural generation, seed determinism
- `concept/rendering` — Visual rendering quality, shader correctness, Terrain3D integration, mesh fidelity, LOD, Z-fighting
- `concept/terrain` — Terrain generation, heightmap, Terrain3D regions, roughness, playability constraints
ember's answer for tag_assignment-reference-autonomous-company-autonomous-company-operations-reference, type/specP(true) placed on the no, unsure, and yes zones.nounsureyesgold: noP = 0.53

tag_assignment-code-tools-vault-audit: concept/governance

Tag assignment · test
Gold
The note calls for `concept/governance`: Constitutional and governance concepts (True)
ember
The note has no reason to carry `concept/governance` (False)
Signal
P(true) 0.10 (no)
Kit outcome
acted on a wrong answer
Why this gold label
Mined from Code/Tools — Vault Audit.md at 692f4bb58b7f62105aeb73fba8dfee12bfdecd53; gold is the note's own vocabulary tags.
Tools — Vault Audit

The local-first vault knowledge-graph audit pipeline (spec 088). One deterministic mechanical checker (`scripts/ci/vault_audit.py`), plus a semantic drift phase that runs as an agent invocation (not a standalone script).

## Entry Points

| Command | Backend | Cost |
|---|---|---|
| `make vault-audit` | `scripts/ci/vault_audit.py docs/vault` | Free |
| `make vault-audit-apply` | `scripts/ci/vault_audit.py docs/vault --apply` | Free |
| `make vault-audit-semantic` | `opencode run --command vault-audit-semantic` | LLM tokens (model-dependent) |
| `make vault-audit-test` | `tests/vault_audit/run_tests.sh` | Free |

## Mechanical Script (`scripts/ci/vault_audit.py`)

**Dependencies**: Python 3 stdlib + PyYAML only. No other external dependencies.

**Checks performed**:
- Schema validation (FR-002): required fields, type/status/layer tag cardinality, controlled vocab, aliases/source/system on agent notes
- Wikilink resolution (FR-003): case-insensitive NFC-normalized lookup against filename index; duplicate stems → WARN; unresolved → ERROR
- Path checking (FR-004): code-refs/spec-refs existence; src/assets/ paths → SKIPPED when submodule not initialized
- Inventory extraction (FR-005): autoloads from project.godot, signals from events.gd, GDExtension classes from gdext-wrapper/src/*.rs, Rust modules from rust-core/src/*.rs, threshold constants from src/resources/config/*.tres

**Safe auto-fixes** (with `--apply`):
- Missing `aliases:` on agent notes → set to `title:`
- Missing `source:` on agent notes → set to `agent` with inline comment
- `layer:` field/tag mismatch → field wins, tag updated
- Case-mismatched wikilinks → normalized to real filename case
- Broken `code-refs`/`spec-refs` → `stale: true` + `stale_reason:` + `> [!warning]` callout
- Missing spec stubs → auto-generated from `_meta/templates/spec.md`

**Output files** (all committed except metadata):
- `docs/vault/_meta/audit/last_audit.json` — deterministic mechanical report
- `docs/vault/_meta/audit/inventories.json` — code inventories for semantic phase
- `docs/vault/_meta/audit/audit_run_metadata.json` — gitignored; run timestamps

**Critical implementation notes**:
- Filename index excludes `_meta/` and `.obsidian/` to avoid false duplicate collisions with template files
- All file walks use `sorted()` for cross-platform determinism
- Sort key on findings: `(note_path, rule, message)` — tertiary message key required for idempotency when multiple findings share same note+rule
- `--output` flag always wins over `--no-write` (test harness requirement)

## Semantic Drift Phase (agent-invoked)

**Not a standalone Python script.** Semantic drift analysis runs through `opencode run --command vault-audit-semantic`, which dispatches the `/vault-audit-semantic` slash command defined under `.opencode/command/`. The command loads the `introspection` skill (`.opencode/skills/introspection/SKILL.md`) as its system prompt, reads `last_audit.json` + `inventories.json` from `docs/vault/_meta/audit/`, walks the in-scope notes directly, and writes `docs/vault/_meta/audit/last_semantic.json`.

**Model selection**: The Makefile target passes `--model openrouter/anthropic/claude-opus-4.8` by default. Override by editing the Makefile target or invoking `opencode run` manually with a different `--model` flag. There is no pinned `DEFAULT_MODEL` constant — model choice is a CLI argument.

**No anthropic Python dependency**: The agent runs inside the opencode runtime, which handles LLM HTTP itself. `tools/vault_audit/` contains only an empty `__init__.py`; there is no `semantic_drift.py`, no `requirements.txt`, and no batch-size CLI flag at this layer (batching is the agent's internal concern).

**Scope gate** (enforced by the agent via the introspection skill): Only `type/system`, `type/code`, `type/decision`, `type/discovery` notes with ≥1 valid `code-refs:` entry. All others logged as "needs refs" and skipped.

**Claim taxonomy** (applied by the agent via the introspection skill system prompt):
- `exact` → drift if actual value differs
- `range` → drift only if outside the range
- `approximation` → never drift
- `list` → drift if membership differs
- `description` → drift only if confident behavior no longer matches

**Auto-run behaviour**: The slash command will run the mechanical script first if `last_audit.json` is missing or stale relative to vault content.

## Test Suite

Located at `tests/vault_audit/`. Run via `make vault-audit-test`.

**Fixture structure**:
- `fixtures/malformed/` — 5 seeded error notes (missing type, broken wikilink, broken code-ref, invalid tag, duplicate stem)
- `fixtures/clean/` — 2 valid notes including unicode em-dash (SC-006)
- `fixtures/claim_taxonomy/` — 15 fixtures (3 per claim type: drift/no_drift/boundary)
- `fixtures/mock_last_audit.json` + `fixtures/mock_inventories.json` — fixture inputs for semantic tests

**Test cases in `run_tests.sh`**:
1. Malformed vault → exit 1, specific error messages present
2. Clean vault → exit 0, "Vault audit: 0 errors, 0 warnings"
3. Idempotency — two runs produce byte-identical JSON
4. Unicode em-dash round-trip — file unchanged after scan (SC-006)
5. Submodule SKIPPED detection (SC-007)
6. Performance — full audit < 30 seconds (NFR-002)

## Controlled Vocabulary Reference

Full vocabulary in `docs/vault/_meta/tags.md`. The script enforces:
- `type/*`: 10 values (principle, design, system, code, spec, reference, moc, decision, discovery, session-log)
- `status/*`: 6 values (draft, wip, stale, superseded, reviewed, canonical) — NOT `status/done` or `status/waiting`
- `layer/*`: 6 values (gdscript, rust-core, gdext, python, content, infra)
- `domain/*` (system: field): 9 values (world, audio, vehicle, player, anomalies, narrative, art, tooling, governance)

Controlled tag vocabulary (as read):
type/*:
- `type/code` — Code architecture, autoloads, conventions, tooling. Carries `code-refs:`. (e.g. `Code/Autoloads — Disturbance.md`)
- `type/decision` — Architectural or design decision made by an agent during a session. Written to `docs/vault/Decisions/`. (Agent notes only — spec 080.)
- `type/design` — Design intent, player-facing concepts, world lore. (e.g. `Design/World Model.md`)
- `type/discovery` — Non-obvious constraint, gap, or conflict found by an agent during a session. Written to `docs/vault/Discoveries/`. (Agent notes only — spec 080.)
- `type/moc` — Map of Content at any of three tiers (folder / domain / concept). (e.g. `Audio.md`)
- `type/principle` — Governance and constitutional notes. Non-negotiable rules. (e.g. `Governance/Constitution.md`)
- `type/reference` — Glossary, decision log, open questions, epics. (e.g. `Reference/Glossary.md`)
- `type/session-log` — Session activity log; permanent audit trail. Written to `docs/vault/Sessions/`. Append-only, never pruned. (Agent notes only — spec 080.)
- `type/spec` — Spec document at `docs/vault/Specs/NNN Title/spec.md`. Carries `spec-refs:`. (e.g. `Specs/047 Car Radio/spec.md`)
- `type/system` — A bounded subsystem with implementation. Carries `code-refs`, `spec-refs`, `implements:` frontmatter. (e.g. `Systems/Audio — Car Radio.md`)
- `type/vision` — Strategic / vision-layer decision. Written to `docs/vault/Vision/`. Human-authored or agent-proposed with human ratification before promotion to `status: reviewed`. (Per triage #3 — spec 133 autonomous-company redesign.)
domain/*:
- `domain/anomalies` — Anomaly taxonomy, individual anomaly systems, spawn, behavior
- `domain/art` — Visual direction, palettes, references, asset pipeline
- `domain/audio` — Audio systems: world ambient, radio, transmissions, buses, pipeline
- `domain/autonomous-company` — Autonomous company v0.1 experiment: Slack infra, persona middleware, Letta integration, restart recovery
- `domain/build` — Build system, packaging, export, release automation
- `domain/governance` — Constitution, phased spec, policies
- `domain/infrastructure` — Infrastructure provisioning: CI/CD, hosting, deployment tooling, secrets management
- `domain/narrative` — Tone, horror register, forest transmissions narrative, Gary/KTLK
- `domain/player` — Player mode, input, controls, camera, exit/entry
- `domain/systems` — Cross-cutting system architecture and integration work
- `domain/tooling` — Build, CI, observer, TTS pipeline, dev-time tools
- `domain/vehicle` — The Samba: vehicle physics, dashboard, damage, panels
- `domain/world` — World model, biomes, terrain, procedural generation, weather
status/*:
- `status/canonical` — Fully authoritative; promoted by humans only. Highest trust. (Agent notes only — spec 080.)
- `status/draft` — Authoring in progress, not yet verified
- `status/reviewed` — Agent-created note verified against codebase within its creating session. Eligible for auto-injection in subsequent task dispatches. (Agent notes only — spec 080.)
- `status/stale` — Known out of date; cannot update immediately. Pairs with `> [!warning] STALE — needs update` callout.
- `status/superseded` — Replaced by another note. Terminal state. Pairs with `> [!warning] SUPERSEDED` callout.
- `status/wip` — Stable but under active revision
layer/*:
- `layer/content` — Content assets (audio, models, textures, audio provenance)
- `layer/gdext` — gdext wrapper layer (`rust/gdext-wrapper/`)
- `layer/gdscript` — GDScript (Godot scene-tier logic)
- `layer/infra` — Build, CI, deployment infrastructure
- `layer/python` — Python development tooling (`tools/`)
- `layer/rust-core` — Engine-agnostic Rust core (`rust/rust-core/`)
concept/*:
- `concept/biome` — Biome-reactive behavior across systems
- `concept/contamination` — Across-runs panel and garage degradation; the slow-horror mechanic that doesn't reset with the world
- `concept/diegetic` — Diegetic audio / UI / world-sourced design
- `concept/disturbance` — The disturbance mechanic thread (Article X)
- `concept/ephemeral-world` — Run-reset, transient worlds (Article IV Rules 6–7)
- `concept/governance` — Constitutional and governance concepts
- `concept/horror` — Horror register and dread design
- `concept/procedural` — Procedural generation, seed determinism
- `concept/rendering` — Visual rendering quality, shader correctness, Terrain3D integration, mesh fidelity, LOD, Z-fighting
- `concept/terrain` — Terrain generation, heightmap, Terrain3D regions, roughness, playability constraints
ember's answer for tag_assignment-code-tools-vault-audit, concept/governanceP(true) placed on the no, unsure, and yes zones.nounsureyesgold: yesP = 0.10

tag_assignment-code-tools-vault-audit: domain/governance

Tag assignment · test
Gold
The note calls for `domain/governance`: Constitution, phased spec, policies (True)
ember
The note has no reason to carry `domain/governance` (False)
Signal
P(true) 0.24 (unsure)
Kit outcome
deferred: treated as unsure
Why this gold label
Mined from Code/Tools — Vault Audit.md at 692f4bb58b7f62105aeb73fba8dfee12bfdecd53; gold is the note's own vocabulary tags.
Tools — Vault Audit

The local-first vault knowledge-graph audit pipeline (spec 088). One deterministic mechanical checker (`scripts/ci/vault_audit.py`), plus a semantic drift phase that runs as an agent invocation (not a standalone script).

## Entry Points

| Command | Backend | Cost |
|---|---|---|
| `make vault-audit` | `scripts/ci/vault_audit.py docs/vault` | Free |
| `make vault-audit-apply` | `scripts/ci/vault_audit.py docs/vault --apply` | Free |
| `make vault-audit-semantic` | `opencode run --command vault-audit-semantic` | LLM tokens (model-dependent) |
| `make vault-audit-test` | `tests/vault_audit/run_tests.sh` | Free |

## Mechanical Script (`scripts/ci/vault_audit.py`)

**Dependencies**: Python 3 stdlib + PyYAML only. No other external dependencies.

**Checks performed**:
- Schema validation (FR-002): required fields, type/status/layer tag cardinality, controlled vocab, aliases/source/system on agent notes
- Wikilink resolution (FR-003): case-insensitive NFC-normalized lookup against filename index; duplicate stems → WARN; unresolved → ERROR
- Path checking (FR-004): code-refs/spec-refs existence; src/assets/ paths → SKIPPED when submodule not initialized
- Inventory extraction (FR-005): autoloads from project.godot, signals from events.gd, GDExtension classes from gdext-wrapper/src/*.rs, Rust modules from rust-core/src/*.rs, threshold constants from src/resources/config/*.tres

**Safe auto-fixes** (with `--apply`):
- Missing `aliases:` on agent notes → set to `title:`
- Missing `source:` on agent notes → set to `agent` with inline comment
- `layer:` field/tag mismatch → field wins, tag updated
- Case-mismatched wikilinks → normalized to real filename case
- Broken `code-refs`/`spec-refs` → `stale: true` + `stale_reason:` + `> [!warning]` callout
- Missing spec stubs → auto-generated from `_meta/templates/spec.md`

**Output files** (all committed except metadata):
- `docs/vault/_meta/audit/last_audit.json` — deterministic mechanical report
- `docs/vault/_meta/audit/inventories.json` — code inventories for semantic phase
- `docs/vault/_meta/audit/audit_run_metadata.json` — gitignored; run timestamps

**Critical implementation notes**:
- Filename index excludes `_meta/` and `.obsidian/` to avoid false duplicate collisions with template files
- All file walks use `sorted()` for cross-platform determinism
- Sort key on findings: `(note_path, rule, message)` — tertiary message key required for idempotency when multiple findings share same note+rule
- `--output` flag always wins over `--no-write` (test harness requirement)

## Semantic Drift Phase (agent-invoked)

**Not a standalone Python script.** Semantic drift analysis runs through `opencode run --command vault-audit-semantic`, which dispatches the `/vault-audit-semantic` slash command defined under `.opencode/command/`. The command loads the `introspection` skill (`.opencode/skills/introspection/SKILL.md`) as its system prompt, reads `last_audit.json` + `inventories.json` from `docs/vault/_meta/audit/`, walks the in-scope notes directly, and writes `docs/vault/_meta/audit/last_semantic.json`.

**Model selection**: The Makefile target passes `--model openrouter/anthropic/claude-opus-4.8` by default. Override by editing the Makefile target or invoking `opencode run` manually with a different `--model` flag. There is no pinned `DEFAULT_MODEL` constant — model choice is a CLI argument.

**No anthropic Python dependency**: The agent runs inside the opencode runtime, which handles LLM HTTP itself. `tools/vault_audit/` contains only an empty `__init__.py`; there is no `semantic_drift.py`, no `requirements.txt`, and no batch-size CLI flag at this layer (batching is the agent's internal concern).

**Scope gate** (enforced by the agent via the introspection skill): Only `type/system`, `type/code`, `type/decision`, `type/discovery` notes with ≥1 valid `code-refs:` entry. All others logged as "needs refs" and skipped.

**Claim taxonomy** (applied by the agent via the introspection skill system prompt):
- `exact` → drift if actual value differs
- `range` → drift only if outside the range
- `approximation` → never drift
- `list` → drift if membership differs
- `description` → drift only if confident behavior no longer matches

**Auto-run behaviour**: The slash command will run the mechanical script first if `last_audit.json` is missing or stale relative to vault content.

## Test Suite

Located at `tests/vault_audit/`. Run via `make vault-audit-test`.

**Fixture structure**:
- `fixtures/malformed/` — 5 seeded error notes (missing type, broken wikilink, broken code-ref, invalid tag, duplicate stem)
- `fixtures/clean/` — 2 valid notes including unicode em-dash (SC-006)
- `fixtures/claim_taxonomy/` — 15 fixtures (3 per claim type: drift/no_drift/boundary)
- `fixtures/mock_last_audit.json` + `fixtures/mock_inventories.json` — fixture inputs for semantic tests

**Test cases in `run_tests.sh`**:
1. Malformed vault → exit 1, specific error messages present
2. Clean vault → exit 0, "Vault audit: 0 errors, 0 warnings"
3. Idempotency — two runs produce byte-identical JSON
4. Unicode em-dash round-trip — file unchanged after scan (SC-006)
5. Submodule SKIPPED detection (SC-007)
6. Performance — full audit < 30 seconds (NFR-002)

## Controlled Vocabulary Reference

Full vocabulary in `docs/vault/_meta/tags.md`. The script enforces:
- `type/*`: 10 values (principle, design, system, code, spec, reference, moc, decision, discovery, session-log)
- `status/*`: 6 values (draft, wip, stale, superseded, reviewed, canonical) — NOT `status/done` or `status/waiting`
- `layer/*`: 6 values (gdscript, rust-core, gdext, python, content, infra)
- `domain/*` (system: field): 9 values (world, audio, vehicle, player, anomalies, narrative, art, tooling, governance)

Controlled tag vocabulary (as read):
type/*:
- `type/code` — Code architecture, autoloads, conventions, tooling. Carries `code-refs:`. (e.g. `Code/Autoloads — Disturbance.md`)
- `type/decision` — Architectural or design decision made by an agent during a session. Written to `docs/vault/Decisions/`. (Agent notes only — spec 080.)
- `type/design` — Design intent, player-facing concepts, world lore. (e.g. `Design/World Model.md`)
- `type/discovery` — Non-obvious constraint, gap, or conflict found by an agent during a session. Written to `docs/vault/Discoveries/`. (Agent notes only — spec 080.)
- `type/moc` — Map of Content at any of three tiers (folder / domain / concept). (e.g. `Audio.md`)
- `type/principle` — Governance and constitutional notes. Non-negotiable rules. (e.g. `Governance/Constitution.md`)
- `type/reference` — Glossary, decision log, open questions, epics. (e.g. `Reference/Glossary.md`)
- `type/session-log` — Session activity log; permanent audit trail. Written to `docs/vault/Sessions/`. Append-only, never pruned. (Agent notes only — spec 080.)
- `type/spec` — Spec document at `docs/vault/Specs/NNN Title/spec.md`. Carries `spec-refs:`. (e.g. `Specs/047 Car Radio/spec.md`)
- `type/system` — A bounded subsystem with implementation. Carries `code-refs`, `spec-refs`, `implements:` frontmatter. (e.g. `Systems/Audio — Car Radio.md`)
- `type/vision` — Strategic / vision-layer decision. Written to `docs/vault/Vision/`. Human-authored or agent-proposed with human ratification before promotion to `status: reviewed`. (Per triage #3 — spec 133 autonomous-company redesign.)
domain/*:
- `domain/anomalies` — Anomaly taxonomy, individual anomaly systems, spawn, behavior
- `domain/art` — Visual direction, palettes, references, asset pipeline
- `domain/audio` — Audio systems: world ambient, radio, transmissions, buses, pipeline
- `domain/autonomous-company` — Autonomous company v0.1 experiment: Slack infra, persona middleware, Letta integration, restart recovery
- `domain/build` — Build system, packaging, export, release automation
- `domain/governance` — Constitution, phased spec, policies
- `domain/infrastructure` — Infrastructure provisioning: CI/CD, hosting, deployment tooling, secrets management
- `domain/narrative` — Tone, horror register, forest transmissions narrative, Gary/KTLK
- `domain/player` — Player mode, input, controls, camera, exit/entry
- `domain/systems` — Cross-cutting system architecture and integration work
- `domain/tooling` — Build, CI, observer, TTS pipeline, dev-time tools
- `domain/vehicle` — The Samba: vehicle physics, dashboard, damage, panels
- `domain/world` — World model, biomes, terrain, procedural generation, weather
status/*:
- `status/canonical` — Fully authoritative; promoted by humans only. Highest trust. (Agent notes only — spec 080.)
- `status/draft` — Authoring in progress, not yet verified
- `status/reviewed` — Agent-created note verified against codebase within its creating session. Eligible for auto-injection in subsequent task dispatches. (Agent notes only — spec 080.)
- `status/stale` — Known out of date; cannot update immediately. Pairs with `> [!warning] STALE — needs update` callout.
- `status/superseded` — Replaced by another note. Terminal state. Pairs with `> [!warning] SUPERSEDED` callout.
- `status/wip` — Stable but under active revision
layer/*:
- `layer/content` — Content assets (audio, models, textures, audio provenance)
- `layer/gdext` — gdext wrapper layer (`rust/gdext-wrapper/`)
- `layer/gdscript` — GDScript (Godot scene-tier logic)
- `layer/infra` — Build, CI, deployment infrastructure
- `layer/python` — Python development tooling (`tools/`)
- `layer/rust-core` — Engine-agnostic Rust core (`rust/rust-core/`)
concept/*:
- `concept/biome` — Biome-reactive behavior across systems
- `concept/contamination` — Across-runs panel and garage degradation; the slow-horror mechanic that doesn't reset with the world
- `concept/diegetic` — Diegetic audio / UI / world-sourced design
- `concept/disturbance` — The disturbance mechanic thread (Article X)
- `concept/ephemeral-world` — Run-reset, transient worlds (Article IV Rules 6–7)
- `concept/governance` — Constitutional and governance concepts
- `concept/horror` — Horror register and dread design
- `concept/procedural` — Procedural generation, seed determinism
- `concept/rendering` — Visual rendering quality, shader correctness, Terrain3D integration, mesh fidelity, LOD, Z-fighting
- `concept/terrain` — Terrain generation, heightmap, Terrain3D regions, roughness, playability constraints
ember's answer for tag_assignment-code-tools-vault-audit, domain/governanceP(true) placed on the no, unsure, and yes zones.nounsureyesgold: yesP = 0.24

tag_assignment-code-tools-vault-audit: layer/infra

Tag assignment · test
Gold
The note calls for `layer/infra`: Build, CI, deployment infrastructure (True)
ember
The note has no reason to carry `layer/infra` (False)
Signal
P(true) 0.33 (unsure)
Kit outcome
deferred: treated as unsure
Why this gold label
Mined from Code/Tools — Vault Audit.md at 692f4bb58b7f62105aeb73fba8dfee12bfdecd53; gold is the note's own vocabulary tags.
Tools — Vault Audit

The local-first vault knowledge-graph audit pipeline (spec 088). One deterministic mechanical checker (`scripts/ci/vault_audit.py`), plus a semantic drift phase that runs as an agent invocation (not a standalone script).

## Entry Points

| Command | Backend | Cost |
|---|---|---|
| `make vault-audit` | `scripts/ci/vault_audit.py docs/vault` | Free |
| `make vault-audit-apply` | `scripts/ci/vault_audit.py docs/vault --apply` | Free |
| `make vault-audit-semantic` | `opencode run --command vault-audit-semantic` | LLM tokens (model-dependent) |
| `make vault-audit-test` | `tests/vault_audit/run_tests.sh` | Free |

## Mechanical Script (`scripts/ci/vault_audit.py`)

**Dependencies**: Python 3 stdlib + PyYAML only. No other external dependencies.

**Checks performed**:
- Schema validation (FR-002): required fields, type/status/layer tag cardinality, controlled vocab, aliases/source/system on agent notes
- Wikilink resolution (FR-003): case-insensitive NFC-normalized lookup against filename index; duplicate stems → WARN; unresolved → ERROR
- Path checking (FR-004): code-refs/spec-refs existence; src/assets/ paths → SKIPPED when submodule not initialized
- Inventory extraction (FR-005): autoloads from project.godot, signals from events.gd, GDExtension classes from gdext-wrapper/src/*.rs, Rust modules from rust-core/src/*.rs, threshold constants from src/resources/config/*.tres

**Safe auto-fixes** (with `--apply`):
- Missing `aliases:` on agent notes → set to `title:`
- Missing `source:` on agent notes → set to `agent` with inline comment
- `layer:` field/tag mismatch → field wins, tag updated
- Case-mismatched wikilinks → normalized to real filename case
- Broken `code-refs`/`spec-refs` → `stale: true` + `stale_reason:` + `> [!warning]` callout
- Missing spec stubs → auto-generated from `_meta/templates/spec.md`

**Output files** (all committed except metadata):
- `docs/vault/_meta/audit/last_audit.json` — deterministic mechanical report
- `docs/vault/_meta/audit/inventories.json` — code inventories for semantic phase
- `docs/vault/_meta/audit/audit_run_metadata.json` — gitignored; run timestamps

**Critical implementation notes**:
- Filename index excludes `_meta/` and `.obsidian/` to avoid false duplicate collisions with template files
- All file walks use `sorted()` for cross-platform determinism
- Sort key on findings: `(note_path, rule, message)` — tertiary message key required for idempotency when multiple findings share same note+rule
- `--output` flag always wins over `--no-write` (test harness requirement)

## Semantic Drift Phase (agent-invoked)

**Not a standalone Python script.** Semantic drift analysis runs through `opencode run --command vault-audit-semantic`, which dispatches the `/vault-audit-semantic` slash command defined under `.opencode/command/`. The command loads the `introspection` skill (`.opencode/skills/introspection/SKILL.md`) as its system prompt, reads `last_audit.json` + `inventories.json` from `docs/vault/_meta/audit/`, walks the in-scope notes directly, and writes `docs/vault/_meta/audit/last_semantic.json`.

**Model selection**: The Makefile target passes `--model openrouter/anthropic/claude-opus-4.8` by default. Override by editing the Makefile target or invoking `opencode run` manually with a different `--model` flag. There is no pinned `DEFAULT_MODEL` constant — model choice is a CLI argument.

**No anthropic Python dependency**: The agent runs inside the opencode runtime, which handles LLM HTTP itself. `tools/vault_audit/` contains only an empty `__init__.py`; there is no `semantic_drift.py`, no `requirements.txt`, and no batch-size CLI flag at this layer (batching is the agent's internal concern).

**Scope gate** (enforced by the agent via the introspection skill): Only `type/system`, `type/code`, `type/decision`, `type/discovery` notes with ≥1 valid `code-refs:` entry. All others logged as "needs refs" and skipped.

**Claim taxonomy** (applied by the agent via the introspection skill system prompt):
- `exact` → drift if actual value differs
- `range` → drift only if outside the range
- `approximation` → never drift
- `list` → drift if membership differs
- `description` → drift only if confident behavior no longer matches

**Auto-run behaviour**: The slash command will run the mechanical script first if `last_audit.json` is missing or stale relative to vault content.

## Test Suite

Located at `tests/vault_audit/`. Run via `make vault-audit-test`.

**Fixture structure**:
- `fixtures/malformed/` — 5 seeded error notes (missing type, broken wikilink, broken code-ref, invalid tag, duplicate stem)
- `fixtures/clean/` — 2 valid notes including unicode em-dash (SC-006)
- `fixtures/claim_taxonomy/` — 15 fixtures (3 per claim type: drift/no_drift/boundary)
- `fixtures/mock_last_audit.json` + `fixtures/mock_inventories.json` — fixture inputs for semantic tests

**Test cases in `run_tests.sh`**:
1. Malformed vault → exit 1, specific error messages present
2. Clean vault → exit 0, "Vault audit: 0 errors, 0 warnings"
3. Idempotency — two runs produce byte-identical JSON
4. Unicode em-dash round-trip — file unchanged after scan (SC-006)
5. Submodule SKIPPED detection (SC-007)
6. Performance — full audit < 30 seconds (NFR-002)

## Controlled Vocabulary Reference

Full vocabulary in `docs/vault/_meta/tags.md`. The script enforces:
- `type/*`: 10 values (principle, design, system, code, spec, reference, moc, decision, discovery, session-log)
- `status/*`: 6 values (draft, wip, stale, superseded, reviewed, canonical) — NOT `status/done` or `status/waiting`
- `layer/*`: 6 values (gdscript, rust-core, gdext, python, content, infra)
- `domain/*` (system: field): 9 values (world, audio, vehicle, player, anomalies, narrative, art, tooling, governance)

Controlled tag vocabulary (as read):
type/*:
- `type/code` — Code architecture, autoloads, conventions, tooling. Carries `code-refs:`. (e.g. `Code/Autoloads — Disturbance.md`)
- `type/decision` — Architectural or design decision made by an agent during a session. Written to `docs/vault/Decisions/`. (Agent notes only — spec 080.)
- `type/design` — Design intent, player-facing concepts, world lore. (e.g. `Design/World Model.md`)
- `type/discovery` — Non-obvious constraint, gap, or conflict found by an agent during a session. Written to `docs/vault/Discoveries/`. (Agent notes only — spec 080.)
- `type/moc` — Map of Content at any of three tiers (folder / domain / concept). (e.g. `Audio.md`)
- `type/principle` — Governance and constitutional notes. Non-negotiable rules. (e.g. `Governance/Constitution.md`)
- `type/reference` — Glossary, decision log, open questions, epics. (e.g. `Reference/Glossary.md`)
- `type/session-log` — Session activity log; permanent audit trail. Written to `docs/vault/Sessions/`. Append-only, never pruned. (Agent notes only — spec 080.)
- `type/spec` — Spec document at `docs/vault/Specs/NNN Title/spec.md`. Carries `spec-refs:`. (e.g. `Specs/047 Car Radio/spec.md`)
- `type/system` — A bounded subsystem with implementation. Carries `code-refs`, `spec-refs`, `implements:` frontmatter. (e.g. `Systems/Audio — Car Radio.md`)
- `type/vision` — Strategic / vision-layer decision. Written to `docs/vault/Vision/`. Human-authored or agent-proposed with human ratification before promotion to `status: reviewed`. (Per triage #3 — spec 133 autonomous-company redesign.)
domain/*:
- `domain/anomalies` — Anomaly taxonomy, individual anomaly systems, spawn, behavior
- `domain/art` — Visual direction, palettes, references, asset pipeline
- `domain/audio` — Audio systems: world ambient, radio, transmissions, buses, pipeline
- `domain/autonomous-company` — Autonomous company v0.1 experiment: Slack infra, persona middleware, Letta integration, restart recovery
- `domain/build` — Build system, packaging, export, release automation
- `domain/governance` — Constitution, phased spec, policies
- `domain/infrastructure` — Infrastructure provisioning: CI/CD, hosting, deployment tooling, secrets management
- `domain/narrative` — Tone, horror register, forest transmissions narrative, Gary/KTLK
- `domain/player` — Player mode, input, controls, camera, exit/entry
- `domain/systems` — Cross-cutting system architecture and integration work
- `domain/tooling` — Build, CI, observer, TTS pipeline, dev-time tools
- `domain/vehicle` — The Samba: vehicle physics, dashboard, damage, panels
- `domain/world` — World model, biomes, terrain, procedural generation, weather
status/*:
- `status/canonical` — Fully authoritative; promoted by humans only. Highest trust. (Agent notes only — spec 080.)
- `status/draft` — Authoring in progress, not yet verified
- `status/reviewed` — Agent-created note verified against codebase within its creating session. Eligible for auto-injection in subsequent task dispatches. (Agent notes only — spec 080.)
- `status/stale` — Known out of date; cannot update immediately. Pairs with `> [!warning] STALE — needs update` callout.
- `status/superseded` — Replaced by another note. Terminal state. Pairs with `> [!warning] SUPERSEDED` callout.
- `status/wip` — Stable but under active revision
layer/*:
- `layer/content` — Content assets (audio, models, textures, audio provenance)
- `layer/gdext` — gdext wrapper layer (`rust/gdext-wrapper/`)
- `layer/gdscript` — GDScript (Godot scene-tier logic)
- `layer/infra` — Build, CI, deployment infrastructure
- `layer/python` — Python development tooling (`tools/`)
- `layer/rust-core` — Engine-agnostic Rust core (`rust/rust-core/`)
concept/*:
- `concept/biome` — Biome-reactive behavior across systems
- `concept/contamination` — Across-runs panel and garage degradation; the slow-horror mechanic that doesn't reset with the world
- `concept/diegetic` — Diegetic audio / UI / world-sourced design
- `concept/disturbance` — The disturbance mechanic thread (Article X)
- `concept/ephemeral-world` — Run-reset, transient worlds (Article IV Rules 6–7)
- `concept/governance` — Constitutional and governance concepts
- `concept/horror` — Horror register and dread design
- `concept/procedural` — Procedural generation, seed determinism
- `concept/rendering` — Visual rendering quality, shader correctness, Terrain3D integration, mesh fidelity, LOD, Z-fighting
- `concept/terrain` — Terrain generation, heightmap, Terrain3D regions, roughness, playability constraints
ember's answer for tag_assignment-code-tools-vault-audit, layer/infraP(true) placed on the no, unsure, and yes zones.nounsureyesgold: yesP = 0.33

tag_assignment-code-tools-vault-audit: status/reviewed

Tag assignment · test
Gold
The note calls for `status/reviewed`: Agent-created note verified against codebase within its creating session. Eligible for auto-injection in subsequent task dispatches. (Agent notes only — spec 080.) (True)
ember
The note has no reason to carry `status/reviewed` (False)
Signal
P(true) 0.10 (no)
Kit outcome
acted on a wrong answer
Why this gold label
Mined from Code/Tools — Vault Audit.md at 692f4bb58b7f62105aeb73fba8dfee12bfdecd53; gold is the note's own vocabulary tags.
Tools — Vault Audit

The local-first vault knowledge-graph audit pipeline (spec 088). One deterministic mechanical checker (`scripts/ci/vault_audit.py`), plus a semantic drift phase that runs as an agent invocation (not a standalone script).

## Entry Points

| Command | Backend | Cost |
|---|---|---|
| `make vault-audit` | `scripts/ci/vault_audit.py docs/vault` | Free |
| `make vault-audit-apply` | `scripts/ci/vault_audit.py docs/vault --apply` | Free |
| `make vault-audit-semantic` | `opencode run --command vault-audit-semantic` | LLM tokens (model-dependent) |
| `make vault-audit-test` | `tests/vault_audit/run_tests.sh` | Free |

## Mechanical Script (`scripts/ci/vault_audit.py`)

**Dependencies**: Python 3 stdlib + PyYAML only. No other external dependencies.

**Checks performed**:
- Schema validation (FR-002): required fields, type/status/layer tag cardinality, controlled vocab, aliases/source/system on agent notes
- Wikilink resolution (FR-003): case-insensitive NFC-normalized lookup against filename index; duplicate stems → WARN; unresolved → ERROR
- Path checking (FR-004): code-refs/spec-refs existence; src/assets/ paths → SKIPPED when submodule not initialized
- Inventory extraction (FR-005): autoloads from project.godot, signals from events.gd, GDExtension classes from gdext-wrapper/src/*.rs, Rust modules from rust-core/src/*.rs, threshold constants from src/resources/config/*.tres

**Safe auto-fixes** (with `--apply`):
- Missing `aliases:` on agent notes → set to `title:`
- Missing `source:` on agent notes → set to `agent` with inline comment
- `layer:` field/tag mismatch → field wins, tag updated
- Case-mismatched wikilinks → normalized to real filename case
- Broken `code-refs`/`spec-refs` → `stale: true` + `stale_reason:` + `> [!warning]` callout
- Missing spec stubs → auto-generated from `_meta/templates/spec.md`

**Output files** (all committed except metadata):
- `docs/vault/_meta/audit/last_audit.json` — deterministic mechanical report
- `docs/vault/_meta/audit/inventories.json` — code inventories for semantic phase
- `docs/vault/_meta/audit/audit_run_metadata.json` — gitignored; run timestamps

**Critical implementation notes**:
- Filename index excludes `_meta/` and `.obsidian/` to avoid false duplicate collisions with template files
- All file walks use `sorted()` for cross-platform determinism
- Sort key on findings: `(note_path, rule, message)` — tertiary message key required for idempotency when multiple findings share same note+rule
- `--output` flag always wins over `--no-write` (test harness requirement)

## Semantic Drift Phase (agent-invoked)

**Not a standalone Python script.** Semantic drift analysis runs through `opencode run --command vault-audit-semantic`, which dispatches the `/vault-audit-semantic` slash command defined under `.opencode/command/`. The command loads the `introspection` skill (`.opencode/skills/introspection/SKILL.md`) as its system prompt, reads `last_audit.json` + `inventories.json` from `docs/vault/_meta/audit/`, walks the in-scope notes directly, and writes `docs/vault/_meta/audit/last_semantic.json`.

**Model selection**: The Makefile target passes `--model openrouter/anthropic/claude-opus-4.8` by default. Override by editing the Makefile target or invoking `opencode run` manually with a different `--model` flag. There is no pinned `DEFAULT_MODEL` constant — model choice is a CLI argument.

**No anthropic Python dependency**: The agent runs inside the opencode runtime, which handles LLM HTTP itself. `tools/vault_audit/` contains only an empty `__init__.py`; there is no `semantic_drift.py`, no `requirements.txt`, and no batch-size CLI flag at this layer (batching is the agent's internal concern).

**Scope gate** (enforced by the agent via the introspection skill): Only `type/system`, `type/code`, `type/decision`, `type/discovery` notes with ≥1 valid `code-refs:` entry. All others logged as "needs refs" and skipped.

**Claim taxonomy** (applied by the agent via the introspection skill system prompt):
- `exact` → drift if actual value differs
- `range` → drift only if outside the range
- `approximation` → never drift
- `list` → drift if membership differs
- `description` → drift only if confident behavior no longer matches

**Auto-run behaviour**: The slash command will run the mechanical script first if `last_audit.json` is missing or stale relative to vault content.

## Test Suite

Located at `tests/vault_audit/`. Run via `make vault-audit-test`.

**Fixture structure**:
- `fixtures/malformed/` — 5 seeded error notes (missing type, broken wikilink, broken code-ref, invalid tag, duplicate stem)
- `fixtures/clean/` — 2 valid notes including unicode em-dash (SC-006)
- `fixtures/claim_taxonomy/` — 15 fixtures (3 per claim type: drift/no_drift/boundary)
- `fixtures/mock_last_audit.json` + `fixtures/mock_inventories.json` — fixture inputs for semantic tests

**Test cases in `run_tests.sh`**:
1. Malformed vault → exit 1, specific error messages present
2. Clean vault → exit 0, "Vault audit: 0 errors, 0 warnings"
3. Idempotency — two runs produce byte-identical JSON
4. Unicode em-dash round-trip — file unchanged after scan (SC-006)
5. Submodule SKIPPED detection (SC-007)
6. Performance — full audit < 30 seconds (NFR-002)

## Controlled Vocabulary Reference

Full vocabulary in `docs/vault/_meta/tags.md`. The script enforces:
- `type/*`: 10 values (principle, design, system, code, spec, reference, moc, decision, discovery, session-log)
- `status/*`: 6 values (draft, wip, stale, superseded, reviewed, canonical) — NOT `status/done` or `status/waiting`
- `layer/*`: 6 values (gdscript, rust-core, gdext, python, content, infra)
- `domain/*` (system: field): 9 values (world, audio, vehicle, player, anomalies, narrative, art, tooling, governance)

Controlled tag vocabulary (as read):
type/*:
- `type/code` — Code architecture, autoloads, conventions, tooling. Carries `code-refs:`. (e.g. `Code/Autoloads — Disturbance.md`)
- `type/decision` — Architectural or design decision made by an agent during a session. Written to `docs/vault/Decisions/`. (Agent notes only — spec 080.)
- `type/design` — Design intent, player-facing concepts, world lore. (e.g. `Design/World Model.md`)
- `type/discovery` — Non-obvious constraint, gap, or conflict found by an agent during a session. Written to `docs/vault/Discoveries/`. (Agent notes only — spec 080.)
- `type/moc` — Map of Content at any of three tiers (folder / domain / concept). (e.g. `Audio.md`)
- `type/principle` — Governance and constitutional notes. Non-negotiable rules. (e.g. `Governance/Constitution.md`)
- `type/reference` — Glossary, decision log, open questions, epics. (e.g. `Reference/Glossary.md`)
- `type/session-log` — Session activity log; permanent audit trail. Written to `docs/vault/Sessions/`. Append-only, never pruned. (Agent notes only — spec 080.)
- `type/spec` — Spec document at `docs/vault/Specs/NNN Title/spec.md`. Carries `spec-refs:`. (e.g. `Specs/047 Car Radio/spec.md`)
- `type/system` — A bounded subsystem with implementation. Carries `code-refs`, `spec-refs`, `implements:` frontmatter. (e.g. `Systems/Audio — Car Radio.md`)
- `type/vision` — Strategic / vision-layer decision. Written to `docs/vault/Vision/`. Human-authored or agent-proposed with human ratification before promotion to `status: reviewed`. (Per triage #3 — spec 133 autonomous-company redesign.)
domain/*:
- `domain/anomalies` — Anomaly taxonomy, individual anomaly systems, spawn, behavior
- `domain/art` — Visual direction, palettes, references, asset pipeline
- `domain/audio` — Audio systems: world ambient, radio, transmissions, buses, pipeline
- `domain/autonomous-company` — Autonomous company v0.1 experiment: Slack infra, persona middleware, Letta integration, restart recovery
- `domain/build` — Build system, packaging, export, release automation
- `domain/governance` — Constitution, phased spec, policies
- `domain/infrastructure` — Infrastructure provisioning: CI/CD, hosting, deployment tooling, secrets management
- `domain/narrative` — Tone, horror register, forest transmissions narrative, Gary/KTLK
- `domain/player` — Player mode, input, controls, camera, exit/entry
- `domain/systems` — Cross-cutting system architecture and integration work
- `domain/tooling` — Build, CI, observer, TTS pipeline, dev-time tools
- `domain/vehicle` — The Samba: vehicle physics, dashboard, damage, panels
- `domain/world` — World model, biomes, terrain, procedural generation, weather
status/*:
- `status/canonical` — Fully authoritative; promoted by humans only. Highest trust. (Agent notes only — spec 080.)
- `status/draft` — Authoring in progress, not yet verified
- `status/reviewed` — Agent-created note verified against codebase within its creating session. Eligible for auto-injection in subsequent task dispatches. (Agent notes only — spec 080.)
- `status/stale` — Known out of date; cannot update immediately. Pairs with `> [!warning] STALE — needs update` callout.
- `status/superseded` — Replaced by another note. Terminal state. Pairs with `> [!warning] SUPERSEDED` callout.
- `status/wip` — Stable but under active revision
layer/*:
- `layer/content` — Content assets (audio, models, textures, audio provenance)
- `layer/gdext` — gdext wrapper layer (`rust/gdext-wrapper/`)
- `layer/gdscript` — GDScript (Godot scene-tier logic)
- `layer/infra` — Build, CI, deployment infrastructure
- `layer/python` — Python development tooling (`tools/`)
- `layer/rust-core` — Engine-agnostic Rust core (`rust/rust-core/`)
concept/*:
- `concept/biome` — Biome-reactive behavior across systems
- `concept/contamination` — Across-runs panel and garage degradation; the slow-horror mechanic that doesn't reset with the world
- `concept/diegetic` — Diegetic audio / UI / world-sourced design
- `concept/disturbance` — The disturbance mechanic thread (Article X)
- `concept/ephemeral-world` — Run-reset, transient worlds (Article IV Rules 6–7)
- `concept/governance` — Constitutional and governance concepts
- `concept/horror` — Horror register and dread design
- `concept/procedural` — Procedural generation, seed determinism
- `concept/rendering` — Visual rendering quality, shader correctness, Terrain3D integration, mesh fidelity, LOD, Z-fighting
- `concept/terrain` — Terrain generation, heightmap, Terrain3D regions, roughness, playability constraints
ember's answer for tag_assignment-code-tools-vault-audit, status/reviewedP(true) placed on the no, unsure, and yes zones.nounsureyesgold: yesP = 0.10

tag_assignment-code-tools-vault-audit: type/code

Tag assignment · test
Gold
The note calls for `type/code`: Code architecture, autoloads, conventions, tooling. Carries `code-refs:`. (e.g. `Code/Autoloads — Disturbance.md`) (True)
ember
The note has no reason to carry `type/code` (False)
Signal
P(true) 0.46 (unsure)
Kit outcome
deferred: treated as unsure
Why this gold label
Mined from Code/Tools — Vault Audit.md at 692f4bb58b7f62105aeb73fba8dfee12bfdecd53; gold is the note's own vocabulary tags.
Tools — Vault Audit

The local-first vault knowledge-graph audit pipeline (spec 088). One deterministic mechanical checker (`scripts/ci/vault_audit.py`), plus a semantic drift phase that runs as an agent invocation (not a standalone script).

## Entry Points

| Command | Backend | Cost |
|---|---|---|
| `make vault-audit` | `scripts/ci/vault_audit.py docs/vault` | Free |
| `make vault-audit-apply` | `scripts/ci/vault_audit.py docs/vault --apply` | Free |
| `make vault-audit-semantic` | `opencode run --command vault-audit-semantic` | LLM tokens (model-dependent) |
| `make vault-audit-test` | `tests/vault_audit/run_tests.sh` | Free |

## Mechanical Script (`scripts/ci/vault_audit.py`)

**Dependencies**: Python 3 stdlib + PyYAML only. No other external dependencies.

**Checks performed**:
- Schema validation (FR-002): required fields, type/status/layer tag cardinality, controlled vocab, aliases/source/system on agent notes
- Wikilink resolution (FR-003): case-insensitive NFC-normalized lookup against filename index; duplicate stems → WARN; unresolved → ERROR
- Path checking (FR-004): code-refs/spec-refs existence; src/assets/ paths → SKIPPED when submodule not initialized
- Inventory extraction (FR-005): autoloads from project.godot, signals from events.gd, GDExtension classes from gdext-wrapper/src/*.rs, Rust modules from rust-core/src/*.rs, threshold constants from src/resources/config/*.tres

**Safe auto-fixes** (with `--apply`):
- Missing `aliases:` on agent notes → set to `title:`
- Missing `source:` on agent notes → set to `agent` with inline comment
- `layer:` field/tag mismatch → field wins, tag updated
- Case-mismatched wikilinks → normalized to real filename case
- Broken `code-refs`/`spec-refs` → `stale: true` + `stale_reason:` + `> [!warning]` callout
- Missing spec stubs → auto-generated from `_meta/templates/spec.md`

**Output files** (all committed except metadata):
- `docs/vault/_meta/audit/last_audit.json` — deterministic mechanical report
- `docs/vault/_meta/audit/inventories.json` — code inventories for semantic phase
- `docs/vault/_meta/audit/audit_run_metadata.json` — gitignored; run timestamps

**Critical implementation notes**:
- Filename index excludes `_meta/` and `.obsidian/` to avoid false duplicate collisions with template files
- All file walks use `sorted()` for cross-platform determinism
- Sort key on findings: `(note_path, rule, message)` — tertiary message key required for idempotency when multiple findings share same note+rule
- `--output` flag always wins over `--no-write` (test harness requirement)

## Semantic Drift Phase (agent-invoked)

**Not a standalone Python script.** Semantic drift analysis runs through `opencode run --command vault-audit-semantic`, which dispatches the `/vault-audit-semantic` slash command defined under `.opencode/command/`. The command loads the `introspection` skill (`.opencode/skills/introspection/SKILL.md`) as its system prompt, reads `last_audit.json` + `inventories.json` from `docs/vault/_meta/audit/`, walks the in-scope notes directly, and writes `docs/vault/_meta/audit/last_semantic.json`.

**Model selection**: The Makefile target passes `--model openrouter/anthropic/claude-opus-4.8` by default. Override by editing the Makefile target or invoking `opencode run` manually with a different `--model` flag. There is no pinned `DEFAULT_MODEL` constant — model choice is a CLI argument.

**No anthropic Python dependency**: The agent runs inside the opencode runtime, which handles LLM HTTP itself. `tools/vault_audit/` contains only an empty `__init__.py`; there is no `semantic_drift.py`, no `requirements.txt`, and no batch-size CLI flag at this layer (batching is the agent's internal concern).

**Scope gate** (enforced by the agent via the introspection skill): Only `type/system`, `type/code`, `type/decision`, `type/discovery` notes with ≥1 valid `code-refs:` entry. All others logged as "needs refs" and skipped.

**Claim taxonomy** (applied by the agent via the introspection skill system prompt):
- `exact` → drift if actual value differs
- `range` → drift only if outside the range
- `approximation` → never drift
- `list` → drift if membership differs
- `description` → drift only if confident behavior no longer matches

**Auto-run behaviour**: The slash command will run the mechanical script first if `last_audit.json` is missing or stale relative to vault content.

## Test Suite

Located at `tests/vault_audit/`. Run via `make vault-audit-test`.

**Fixture structure**:
- `fixtures/malformed/` — 5 seeded error notes (missing type, broken wikilink, broken code-ref, invalid tag, duplicate stem)
- `fixtures/clean/` — 2 valid notes including unicode em-dash (SC-006)
- `fixtures/claim_taxonomy/` — 15 fixtures (3 per claim type: drift/no_drift/boundary)
- `fixtures/mock_last_audit.json` + `fixtures/mock_inventories.json` — fixture inputs for semantic tests

**Test cases in `run_tests.sh`**:
1. Malformed vault → exit 1, specific error messages present
2. Clean vault → exit 0, "Vault audit: 0 errors, 0 warnings"
3. Idempotency — two runs produce byte-identical JSON
4. Unicode em-dash round-trip — file unchanged after scan (SC-006)
5. Submodule SKIPPED detection (SC-007)
6. Performance — full audit < 30 seconds (NFR-002)

## Controlled Vocabulary Reference

Full vocabulary in `docs/vault/_meta/tags.md`. The script enforces:
- `type/*`: 10 values (principle, design, system, code, spec, reference, moc, decision, discovery, session-log)
- `status/*`: 6 values (draft, wip, stale, superseded, reviewed, canonical) — NOT `status/done` or `status/waiting`
- `layer/*`: 6 values (gdscript, rust-core, gdext, python, content, infra)
- `domain/*` (system: field): 9 values (world, audio, vehicle, player, anomalies, narrative, art, tooling, governance)

Controlled tag vocabulary (as read):
type/*:
- `type/code` — Code architecture, autoloads, conventions, tooling. Carries `code-refs:`. (e.g. `Code/Autoloads — Disturbance.md`)
- `type/decision` — Architectural or design decision made by an agent during a session. Written to `docs/vault/Decisions/`. (Agent notes only — spec 080.)
- `type/design` — Design intent, player-facing concepts, world lore. (e.g. `Design/World Model.md`)
- `type/discovery` — Non-obvious constraint, gap, or conflict found by an agent during a session. Written to `docs/vault/Discoveries/`. (Agent notes only — spec 080.)
- `type/moc` — Map of Content at any of three tiers (folder / domain / concept). (e.g. `Audio.md`)
- `type/principle` — Governance and constitutional notes. Non-negotiable rules. (e.g. `Governance/Constitution.md`)
- `type/reference` — Glossary, decision log, open questions, epics. (e.g. `Reference/Glossary.md`)
- `type/session-log` — Session activity log; permanent audit trail. Written to `docs/vault/Sessions/`. Append-only, never pruned. (Agent notes only — spec 080.)
- `type/spec` — Spec document at `docs/vault/Specs/NNN Title/spec.md`. Carries `spec-refs:`. (e.g. `Specs/047 Car Radio/spec.md`)
- `type/system` — A bounded subsystem with implementation. Carries `code-refs`, `spec-refs`, `implements:` frontmatter. (e.g. `Systems/Audio — Car Radio.md`)
- `type/vision` — Strategic / vision-layer decision. Written to `docs/vault/Vision/`. Human-authored or agent-proposed with human ratification before promotion to `status: reviewed`. (Per triage #3 — spec 133 autonomous-company redesign.)
domain/*:
- `domain/anomalies` — Anomaly taxonomy, individual anomaly systems, spawn, behavior
- `domain/art` — Visual direction, palettes, references, asset pipeline
- `domain/audio` — Audio systems: world ambient, radio, transmissions, buses, pipeline
- `domain/autonomous-company` — Autonomous company v0.1 experiment: Slack infra, persona middleware, Letta integration, restart recovery
- `domain/build` — Build system, packaging, export, release automation
- `domain/governance` — Constitution, phased spec, policies
- `domain/infrastructure` — Infrastructure provisioning: CI/CD, hosting, deployment tooling, secrets management
- `domain/narrative` — Tone, horror register, forest transmissions narrative, Gary/KTLK
- `domain/player` — Player mode, input, controls, camera, exit/entry
- `domain/systems` — Cross-cutting system architecture and integration work
- `domain/tooling` — Build, CI, observer, TTS pipeline, dev-time tools
- `domain/vehicle` — The Samba: vehicle physics, dashboard, damage, panels
- `domain/world` — World model, biomes, terrain, procedural generation, weather
status/*:
- `status/canonical` — Fully authoritative; promoted by humans only. Highest trust. (Agent notes only — spec 080.)
- `status/draft` — Authoring in progress, not yet verified
- `status/reviewed` — Agent-created note verified against codebase within its creating session. Eligible for auto-injection in subsequent task dispatches. (Agent notes only — spec 080.)
- `status/stale` — Known out of date; cannot update immediately. Pairs with `> [!warning] STALE — needs update` callout.
- `status/superseded` — Replaced by another note. Terminal state. Pairs with `> [!warning] SUPERSEDED` callout.
- `status/wip` — Stable but under active revision
layer/*:
- `layer/content` — Content assets (audio, models, textures, audio provenance)
- `layer/gdext` — gdext wrapper layer (`rust/gdext-wrapper/`)
- `layer/gdscript` — GDScript (Godot scene-tier logic)
- `layer/infra` — Build, CI, deployment infrastructure
- `layer/python` — Python development tooling (`tools/`)
- `layer/rust-core` — Engine-agnostic Rust core (`rust/rust-core/`)
concept/*:
- `concept/biome` — Biome-reactive behavior across systems
- `concept/contamination` — Across-runs panel and garage degradation; the slow-horror mechanic that doesn't reset with the world
- `concept/diegetic` — Diegetic audio / UI / world-sourced design
- `concept/disturbance` — The disturbance mechanic thread (Article X)
- `concept/ephemeral-world` — Run-reset, transient worlds (Article IV Rules 6–7)
- `concept/governance` — Constitutional and governance concepts
- `concept/horror` — Horror register and dread design
- `concept/procedural` — Procedural generation, seed determinism
- `concept/rendering` — Visual rendering quality, shader correctness, Terrain3D integration, mesh fidelity, LOD, Z-fighting
- `concept/terrain` — Terrain generation, heightmap, Terrain3D regions, roughness, playability constraints
ember's answer for tag_assignment-code-tools-vault-audit, type/codeP(true) placed on the no, unsure, and yes zones.nounsureyesgold: yesP = 0.46

tag_assignment-discoveries-vault-graph-health-auto-fix-indentation-and-inline-related-constraint: domain/tooling

Tag assignment · test
Gold
The note calls for `domain/tooling`: Build, CI, observer, TTS pipeline, dev-time tools (True)
ember
The note has no reason to carry `domain/tooling` (False)
Signal
P(true) 0.46 (unsure)
Kit outcome
deferred: treated as unsure
Why this gold label
Mined from Discoveries/Vault Graph Health Auto-Fix Indentation and Inline Related Constraint.md at 692f4bb58b7f62105aeb73fba8dfee12bfdecd53; gold is the note's own vocabulary tags.
Vault Graph Health Auto-Fix Indentation and Inline Related Constraint

Two non-obvious constraints in the vault graph health auto-fix (`apply_fix` in `prediction.py`) were discovered during a full vault health pass. Both caused YAML parse errors in `related:` frontmatter when auto-fix ran — one from hardcoded indentation, one from inline `related:` values. Neither was caught by the existing mechanical audit because they only surface when `--apply` triggers the link prediction fix, not during a dry-run audit.

## Indentation Mismatch

The `apply_fix` function in `scripts/ci/graph_health/prediction.py` hardcoded a 2-space indentation for new `related:` list items (`new_link = "  - '[[source]]'"`). Notes whose existing `related:` entries were at column 0 (no leading whitespace) would get a new item at 2-space indentation, creating a YAML nested-sequence error. The fix (applied 2026-06-06) dynamically detects the leading whitespace of the first existing list item and uses that indentation for the new entry.

**Affected pattern**: Any `related:` list with items at column 0 (the majority of vault notes).

## Inline Related Values

Six notes under `Reference/Autonomous Company/` used inline `related:` values (`related: [[Link]]`) instead of YAML list format (`related:\n- '[[Link]]'`). The auto-fix's `if "related:" in frontmatter:` detection matched these, but the subsequent item-insertion logic expected a multi-line list structure and failed. The notes had to be converted to list format manually before the auto-fix could add reciprocal links to them.

**Affected files** (now fixed):
- `Reference/Autonomous Company/Ngrok Tunnel Setup.md`
- `Reference/Autonomous Company/Slack App Kill-Switch Runbook.md`
- `Reference/Autonomous Company/personas/_shared/forbidden-phrases.md`
- `Reference/Autonomous Company/personas/gtm/GTM Charter.md`
- `Reference/Autonomous Company/personas/gtm/GTM Soul.md`
- `Reference/Autonomous Company/slack/GTM Class-B Approval Workflow.md`

## Batch Reciprocal Operation

Running `apply_fix` with a threshold of 0.0 (by modifying `FIX_THRESHOLD` in `prediction.py`) will add every missing reciprocal link in the vault, not just the high-confidence candidates. This is a one-off operation that requires: (a) bypassing the dirty-working-tree guard (the `_is_working_tree_dirty()` check at the top of `apply_fix`), and (b) restoring both the threshold and the guard afterward. The tool is not designed for this mode — it produces correct YAML but the output is voluminous.

## References

- `scripts/ci/graph_health/prediction.py` — the `apply_fix` function (lines 380-439), `FIX_THRESHOLD` (line 31), and `_is_working_tree_dirty` guard (line 354)
- `scripts/ci/vault_audit.py` — the `--apply` orchestrator that triggers graph health fix
- `docs/vault/_meta/tags.md` — `related:` field specification in frontmatter schema

Controlled tag vocabulary (as read):
type/*:
- `type/code` — Code architecture, autoloads, conventions, tooling. Carries `code-refs:`. (e.g. `Code/Autoloads — Disturbance.md`)
- `type/decision` — Architectural or design decision made by an agent during a session. Written to `docs/vault/Decisions/`. (Agent notes only — spec 080.)
- `type/design` — Design intent, player-facing concepts, world lore. (e.g. `Design/World Model.md`)
- `type/discovery` — Non-obvious constraint, gap, or conflict found by an agent during a session. Written to `docs/vault/Discoveries/`. (Agent notes only — spec 080.)
- `type/moc` — Map of Content at any of three tiers (folder / domain / concept). (e.g. `Audio.md`)
- `type/principle` — Governance and constitutional notes. Non-negotiable rules. (e.g. `Governance/Constitution.md`)
- `type/reference` — Glossary, decision log, open questions, epics. (e.g. `Reference/Glossary.md`)
- `type/session-log` — Session activity log; permanent audit trail. Written to `docs/vault/Sessions/`. Append-only, never pruned. (Agent notes only — spec 080.)
- `type/spec` — Spec document at `docs/vault/Specs/NNN Title/spec.md`. Carries `spec-refs:`. (e.g. `Specs/047 Car Radio/spec.md`)
- `type/system` — A bounded subsystem with implementation. Carries `code-refs`, `spec-refs`, `implements:` frontmatter. (e.g. `Systems/Audio — Car Radio.md`)
- `type/vision` — Strategic / vision-layer decision. Written to `docs/vault/Vision/`. Human-authored or agent-proposed with human ratification before promotion to `status: reviewed`. (Per triage #3 — spec 133 autonomous-company redesign.)
domain/*:
- `domain/anomalies` — Anomaly taxonomy, individual anomaly systems, spawn, behavior
- `domain/art` — Visual direction, palettes, references, asset pipeline
- `domain/audio` — Audio systems: world ambient, radio, transmissions, buses, pipeline
- `domain/autonomous-company` — Autonomous company v0.1 experiment: Slack infra, persona middleware, Letta integration, restart recovery
- `domain/build` — Build system, packaging, export, release automation
- `domain/governance` — Constitution, phased spec, policies
- `domain/infrastructure` — Infrastructure provisioning: CI/CD, hosting, deployment tooling, secrets management
- `domain/narrative` — Tone, horror register, forest transmissions narrative, Gary/KTLK
- `domain/player` — Player mode, input, controls, camera, exit/entry
- `domain/systems` — Cross-cutting system architecture and integration work
- `domain/tooling` — Build, CI, observer, TTS pipeline, dev-time tools
- `domain/vehicle` — The Samba: vehicle physics, dashboard, damage, panels
- `domain/world` — World model, biomes, terrain, procedural generation, weather
status/*:
- `status/canonical` — Fully authoritative; promoted by humans only. Highest trust. (Agent notes only — spec 080.)
- `status/draft` — Authoring in progress, not yet verified
- `status/reviewed` — Agent-created note verified against codebase within its creating session. Eligible for auto-injection in subsequent task dispatches. (Agent notes only — spec 080.)
- `status/stale` — Known out of date; cannot update immediately. Pairs with `> [!warning] STALE — needs update` callout.
- `status/superseded` — Replaced by another note. Terminal state. Pairs with `> [!warning] SUPERSEDED` callout.
- `status/wip` — Stable but under active revision
layer/*:
- `layer/content` — Content assets (audio, models, textures, audio provenance)
- `layer/gdext` — gdext wrapper layer (`rust/gdext-wrapper/`)
- `layer/gdscript` — GDScript (Godot scene-tier logic)
- `layer/infra` — Build, CI, deployment infrastructure
- `layer/python` — Python development tooling (`tools/`)
- `layer/rust-core` — Engine-agnostic Rust core (`rust/rust-core/`)
concept/*:
- `concept/biome` — Biome-reactive behavior across systems
- `concept/contamination` — Across-runs panel and garage degradation; the slow-horror mechanic that doesn't reset with the world
- `concept/diegetic` — Diegetic audio / UI / world-sourced design
- `concept/disturbance` — The disturbance mechanic thread (Article X)
- `concept/ephemeral-world` — Run-reset, transient worlds (Article IV Rules 6–7)
- `concept/governance` — Constitutional and governance concepts
- `concept/horror` — Horror register and dread design
- `concept/procedural` — Procedural generation, seed determinism
- `concept/rendering` — Visual rendering quality, shader correctness, Terrain3D integration, mesh fidelity, LOD, Z-fighting
- `concept/terrain` — Terrain generation, heightmap, Terrain3D regions, roughness, playability constraints
ember's answer for tag_assignment-discoveries-vault-graph-health-auto-fix-indentation-and-inline-related-constraint, domain/toolingP(true) placed on the no, unsure, and yes zones.nounsureyesgold: yesP = 0.46

tag_assignment-discoveries-vault-graph-health-auto-fix-indentation-and-inline-related-constraint: status/reviewed

Tag assignment · test
Gold
The note calls for `status/reviewed`: Agent-created note verified against codebase within its creating session. Eligible for auto-injection in subsequent task dispatches. (Agent notes only — spec 080.) (True)
ember
The note has no reason to carry `status/reviewed` (False)
Signal
P(true) 0.11 (no)
Kit outcome
acted on a wrong answer
Why this gold label
Mined from Discoveries/Vault Graph Health Auto-Fix Indentation and Inline Related Constraint.md at 692f4bb58b7f62105aeb73fba8dfee12bfdecd53; gold is the note's own vocabulary tags.
Vault Graph Health Auto-Fix Indentation and Inline Related Constraint

Two non-obvious constraints in the vault graph health auto-fix (`apply_fix` in `prediction.py`) were discovered during a full vault health pass. Both caused YAML parse errors in `related:` frontmatter when auto-fix ran — one from hardcoded indentation, one from inline `related:` values. Neither was caught by the existing mechanical audit because they only surface when `--apply` triggers the link prediction fix, not during a dry-run audit.

## Indentation Mismatch

The `apply_fix` function in `scripts/ci/graph_health/prediction.py` hardcoded a 2-space indentation for new `related:` list items (`new_link = "  - '[[source]]'"`). Notes whose existing `related:` entries were at column 0 (no leading whitespace) would get a new item at 2-space indentation, creating a YAML nested-sequence error. The fix (applied 2026-06-06) dynamically detects the leading whitespace of the first existing list item and uses that indentation for the new entry.

**Affected pattern**: Any `related:` list with items at column 0 (the majority of vault notes).

## Inline Related Values

Six notes under `Reference/Autonomous Company/` used inline `related:` values (`related: [[Link]]`) instead of YAML list format (`related:\n- '[[Link]]'`). The auto-fix's `if "related:" in frontmatter:` detection matched these, but the subsequent item-insertion logic expected a multi-line list structure and failed. The notes had to be converted to list format manually before the auto-fix could add reciprocal links to them.

**Affected files** (now fixed):
- `Reference/Autonomous Company/Ngrok Tunnel Setup.md`
- `Reference/Autonomous Company/Slack App Kill-Switch Runbook.md`
- `Reference/Autonomous Company/personas/_shared/forbidden-phrases.md`
- `Reference/Autonomous Company/personas/gtm/GTM Charter.md`
- `Reference/Autonomous Company/personas/gtm/GTM Soul.md`
- `Reference/Autonomous Company/slack/GTM Class-B Approval Workflow.md`

## Batch Reciprocal Operation

Running `apply_fix` with a threshold of 0.0 (by modifying `FIX_THRESHOLD` in `prediction.py`) will add every missing reciprocal link in the vault, not just the high-confidence candidates. This is a one-off operation that requires: (a) bypassing the dirty-working-tree guard (the `_is_working_tree_dirty()` check at the top of `apply_fix`), and (b) restoring both the threshold and the guard afterward. The tool is not designed for this mode — it produces correct YAML but the output is voluminous.

## References

- `scripts/ci/graph_health/prediction.py` — the `apply_fix` function (lines 380-439), `FIX_THRESHOLD` (line 31), and `_is_working_tree_dirty` guard (line 354)
- `scripts/ci/vault_audit.py` — the `--apply` orchestrator that triggers graph health fix
- `docs/vault/_meta/tags.md` — `related:` field specification in frontmatter schema

Controlled tag vocabulary (as read):
type/*:
- `type/code` — Code architecture, autoloads, conventions, tooling. Carries `code-refs:`. (e.g. `Code/Autoloads — Disturbance.md`)
- `type/decision` — Architectural or design decision made by an agent during a session. Written to `docs/vault/Decisions/`. (Agent notes only — spec 080.)
- `type/design` — Design intent, player-facing concepts, world lore. (e.g. `Design/World Model.md`)
- `type/discovery` — Non-obvious constraint, gap, or conflict found by an agent during a session. Written to `docs/vault/Discoveries/`. (Agent notes only — spec 080.)
- `type/moc` — Map of Content at any of three tiers (folder / domain / concept). (e.g. `Audio.md`)
- `type/principle` — Governance and constitutional notes. Non-negotiable rules. (e.g. `Governance/Constitution.md`)
- `type/reference` — Glossary, decision log, open questions, epics. (e.g. `Reference/Glossary.md`)
- `type/session-log` — Session activity log; permanent audit trail. Written to `docs/vault/Sessions/`. Append-only, never pruned. (Agent notes only — spec 080.)
- `type/spec` — Spec document at `docs/vault/Specs/NNN Title/spec.md`. Carries `spec-refs:`. (e.g. `Specs/047 Car Radio/spec.md`)
- `type/system` — A bounded subsystem with implementation. Carries `code-refs`, `spec-refs`, `implements:` frontmatter. (e.g. `Systems/Audio — Car Radio.md`)
- `type/vision` — Strategic / vision-layer decision. Written to `docs/vault/Vision/`. Human-authored or agent-proposed with human ratification before promotion to `status: reviewed`. (Per triage #3 — spec 133 autonomous-company redesign.)
domain/*:
- `domain/anomalies` — Anomaly taxonomy, individual anomaly systems, spawn, behavior
- `domain/art` — Visual direction, palettes, references, asset pipeline
- `domain/audio` — Audio systems: world ambient, radio, transmissions, buses, pipeline
- `domain/autonomous-company` — Autonomous company v0.1 experiment: Slack infra, persona middleware, Letta integration, restart recovery
- `domain/build` — Build system, packaging, export, release automation
- `domain/governance` — Constitution, phased spec, policies
- `domain/infrastructure` — Infrastructure provisioning: CI/CD, hosting, deployment tooling, secrets management
- `domain/narrative` — Tone, horror register, forest transmissions narrative, Gary/KTLK
- `domain/player` — Player mode, input, controls, camera, exit/entry
- `domain/systems` — Cross-cutting system architecture and integration work
- `domain/tooling` — Build, CI, observer, TTS pipeline, dev-time tools
- `domain/vehicle` — The Samba: vehicle physics, dashboard, damage, panels
- `domain/world` — World model, biomes, terrain, procedural generation, weather
status/*:
- `status/canonical` — Fully authoritative; promoted by humans only. Highest trust. (Agent notes only — spec 080.)
- `status/draft` — Authoring in progress, not yet verified
- `status/reviewed` — Agent-created note verified against codebase within its creating session. Eligible for auto-injection in subsequent task dispatches. (Agent notes only — spec 080.)
- `status/stale` — Known out of date; cannot update immediately. Pairs with `> [!warning] STALE — needs update` callout.
- `status/superseded` — Replaced by another note. Terminal state. Pairs with `> [!warning] SUPERSEDED` callout.
- `status/wip` — Stable but under active revision
layer/*:
- `layer/content` — Content assets (audio, models, textures, audio provenance)
- `layer/gdext` — gdext wrapper layer (`rust/gdext-wrapper/`)
- `layer/gdscript` — GDScript (Godot scene-tier logic)
- `layer/infra` — Build, CI, deployment infrastructure
- `layer/python` — Python development tooling (`tools/`)
- `layer/rust-core` — Engine-agnostic Rust core (`rust/rust-core/`)
concept/*:
- `concept/biome` — Biome-reactive behavior across systems
- `concept/contamination` — Across-runs panel and garage degradation; the slow-horror mechanic that doesn't reset with the world
- `concept/diegetic` — Diegetic audio / UI / world-sourced design
- `concept/disturbance` — The disturbance mechanic thread (Article X)
- `concept/ephemeral-world` — Run-reset, transient worlds (Article IV Rules 6–7)
- `concept/governance` — Constitutional and governance concepts
- `concept/horror` — Horror register and dread design
- `concept/procedural` — Procedural generation, seed determinism
- `concept/rendering` — Visual rendering quality, shader correctness, Terrain3D integration, mesh fidelity, LOD, Z-fighting
- `concept/terrain` — Terrain generation, heightmap, Terrain3D regions, roughness, playability constraints
ember's answer for tag_assignment-discoveries-vault-graph-health-auto-fix-indentation-and-inline-related-constraint, status/reviewedP(true) placed on the no, unsure, and yes zones.nounsureyesgold: yesP = 0.11

tag_assignment-systems-vehicle-destruction: type/code

Tag assignment · test
Gold
The note has no reason to carry `type/code` (False)
ember
The note calls for `type/code`: Code architecture, autoloads, conventions, tooling. Carries `code-refs:`. (e.g. `Code/Autoloads — Disturbance.md`) (True)
Signal
P(true) 0.52 (unsure)
Kit outcome
deferred: treated as unsure
Why this gold label
Mined from Systems/Vehicle — Destruction.md at 692f4bb58b7f62105aeb73fba8dfee12bfdecd53; gold is the note's own vocabulary tags.
Vehicle — Destruction

The panel-level destruction system for the Samba. The Samba is a 60-panel body where each panel is an independent damage target with three states: INTACT, DAMAGED, DESTROYED. Damage events flow through the `Events` signal bus; downstream systems (audio, dashboard, HUD) react independently.

## Overview

Damage in Old Growth is granular: individual panels dent and crack. Impact direction and force determine which panel takes the hit. Destroyed panels expose the vehicle interior to exterior conditions (noise, weather, contamination). The damage state at any moment is a visible running record of what the run has been.

## Design Intent

Per the World Bible: the Samba "features a 60-panel destructible body system that registers every scrape and impact." This granularity is a commitment to the player-as-vehicle framing (see [[Tone and Horror]]) — the bus's body is the player's body, and damage accumulation is a visible argument for caution.

Per Article IV Rule 8 (post-2.19.0): vehicle configuration (installed components and their damage states) is a persistent-data category. Damage persists across runs. Repair kits address it; nothing else does.

## Key Decisions

### 60 panels with Resource-defined properties

Panel definitions live in `src/resources/panels/`. Each panel has:
- ID (StringName)
- Position on the Samba (for spatial damage resolution)
- Health (0 → DESTROYED)
- DAMAGED threshold (typically mid-health)
- Associated damage visuals (deformation, cracks, missing-panel exposure)

### Three-state model

| State | Health | Visual |
|-------|--------|--------|
| INTACT | Above DAMAGED threshold | Clean panel |
| DAMAGED | Below DAMAGED threshold, above 0 | Dents, cracks |
| DESTROYED | Zero | Panel missing; interior exposed |

State transitions emit `Events.bus_panel_state_changed(panel_id, new_state)`. Transitioning to DESTROYED additionally emits `Events.bus_panel_destroyed(panel_id)`.

### Exposure zones

A set of destroyed panels together produces "exposure zones" — logical groups that tell other systems (audio mix, weather, contamination) which parts of the interior are now exposed. `Events.bus_exposure_changed(zones: PackedStringArray)` emits when the active exposure set changes.

### Collision → damage mapping

`Events.bus_collision(force, position)` fires for any collision above the minimum damage-force threshold. The damage system maps (force, position) to the specific panel(s) that should take damage. This lets the collision detection stay generic while the damage logic stays specific.

### Damage accumulation is persistent

Damage persists across runs per Article IV Rule 7. Repair kits restore panel health. Nothing else does. The player's run strategy includes managing damage because the Samba carries history.

### Interior exposure consequences

When a panel is DESTROYED, the corresponding exposure zone affects:
- **Audio mix** — the low-pass interior filter is bypassed in that zone (see [[Audio — World Audio]])
- **Weather** — rain, wind, spore haze, calcite dust can penetrate (see [[Audio — Car Radio]] and weather system)
- **Contamination** — the World Bible's "contamination in the corners" logic. Petrifold dust, Fungal spore residue, mycelium threads accumulate in exposed interior zones across runs (Article IV Rule 7 — vehicle configuration includes damage state)

## Implementation

Primary code references (all under `src/scripts/bus/`):
- `src/scripts/bus/bus_damage_system.gd` — the top-level destruction system
- `src/scripts/bus/bus_panel.gd` — the panel class (state, health, exposure)
- `src/scripts/bus/tire_damage_driver.gd` — tire damage subsystem
- `src/resources/panels/panel_definitions.gd` — panel definitions (GDScript)
- `src/resources/panels/*.tres` — per-panel Resource files

Signals (all via `Events`):
- `bus_panel_state_changed(panel_id, new_state)`
- `bus_panel_destroyed(panel_id)`
- `bus_exposure_changed(zones)`
- `bus_collision(force, position)`
- `bus_enemy_hit(enemy, force)`

## Test Coverage

- `src/tests/unit/test_bus_damage_system.gd` — panel damage, state transitions, exposure zone tracking
- `src/tests/unit/test_bus_damage_effects.gd` — damage visual/audio effects
- `src/tests/unit/test_bus_panel.gd` — panel class unit tests
- `src/tests/unit/test_tire_damage_driver.gd` — tire damage subsystem

> **⚠️ PRE-068 NOTE — panel count and damage model will change when spec 068 (van asset integration) ships.**
> **✅ 068 STATUS UPDATE (2026-05-03)** — Active scene has **44 mesh-active panel nodes** (not 20–30). All 60 panel IDs remain in `panel_definitions.gd` for damage logic; 16 are logical-only or merged. Spec 068 ships 2 visual states (DAMAGED, DESTROYED) via blend-mask shader. Spec 082 will reconcile post-merge.

## Agent Notes (backlinks)

- [[Vehicle Systems and Production Specifications Discovery]] — structural panel HP values (150–200), cascade child lists per structural panel, accessory HP 30 / `no_rear_view` effect, tire HP 80 / `speed_reduction` + `steering_pull`, `acid_exposure` from floor failure; `door_rear_left` and `door_rear_right` are BOTH on passenger side (bi-parting halves, not vehicle sides)

## Contamination Config Resource

When the per-panel contamination system is implemented, all thresholds and tuning values should be committed as a single `@export`-annotated Resource at `res://resources/contamination/contamination_config.tres` — consistent with the pattern established by `res://resources/config/disturbance_config.tres`.

See [[Art/Vehicle — Contamination]] for the visual tier specifications (coverage, opacity, silhouette, normal displacement) and panel zone mapping. The GDScript template below is the implementation target:

```gdscript
## Contamination progression tuning — all values @export for art-director adjustment.
## Authority: docs/vault/Art/Vehicle — Contamination.md
class_name ContaminationConfig
extends Resource

# --- Light tier thresholds (seconds of biome time) -------
@export var moss_light_threshold: float = 180.0
@export var lichen_light_threshold: float = 300.0
@export var spore_film_light_threshold: float = 120.0
@export var fungal_bloom_light_threshold: float = 240.0
@export var calcite_light_threshold: float = 180.0
@export var mineral_accretion_light_threshold: float = 360.0

# --- Moderate tier thresholds -------
@export var moss_moderate_threshold: float = 900.0
@export var lichen_moderate_threshold: float = 1500.0
@export var spore_film_moderate_threshold: float = 600.0
@export var fungal_bloom_moderate_threshold: float = 1200.0
@export var calcite_moderate_threshold: float = 900.0
@export var mineral_accretion_moderate_threshold: float = 1800.0

# --- Severe tier thresholds -------
@export var moss_severe_threshold: float = 2400.0
@export var lichen_severe_threshold: float = 4000.0
@export var spore_film_severe_threshold: float = 1800.0
@export var fungal_bloom_severe_threshold: float = 3000.0
@export var calcite_severe_threshold: float = 2400.0
@export var mineral_accretion_severe_threshold: float = 5000.0

# --- HP acceleration -------
## If panel HP is below this fraction, contamination thresholds scale down by hp_acceleration_strength
@export var hp_acceleration_fraction: float = 0.5
@export var hp_acceleration_strength: float = 0.7

# --- Neighbor proximity acceleration -------
## For each adjacent panel at severe tier, scale current panel thresholds by this factor
@export var neighbor_severe_acceleration: float = 0.85
```

> [!note] This resource does not yet exist. It is a Phase 3 implementation target. Parallels `res://resources/config/disturbance_config.tres`.

## Related

- [[Vehicle — Samba]] — the vehicle this system runs on
- [[Vehicle — Dashboard]] — dashboard displays damage state
- [[Core Mechanics]] — damage mechanic overview
- [[Audio — World Audio]] — exposure-driven audio mix
- [[Autoloads — Events]] — signal bus
- [[Systems]] — folder MOC
- [[Vehicle — Domain MOC]] — domain MOC
- [[Constitution]] — Article IV Rule 7 (persistent data), Article II (Car Is Core)
## Spec 156 Updates (2026-05-29)

The following values were updated by [[156 Bus Damage Rebalance]]:

### HP Ranges (panel_definitions.gd)
- Body: from 80–100 to 120–150 (midpoint 135.0 used)
- Structural: from 150–200 to 200–300 (midpoint 250.0 used)
- Glass: from 40–150 to 80–200 (windshield 200, side windows 150, door windows 120, skylights 100)
- Accessory: from 30 to 50
- Tire: from 80 to 120

### Constants (bus_damage_system.gd)
- `FORCE_TO_DAMAGE_SCALE`: 0.005 → 0.0025
- `cascade_fraction`: 0.25 → 0.10
- `offroad_damage_rate`: 0.5 → 0.2

### Tire Tuning (tire_damage_driver.gd, panel_definitions.gd)
- Tire `damaged_threshold`: 0.3 → 0.15
- `offroad_tire_damage_rate`: 1.5 → 0.4
- `catastrophic_force_threshold`: 15000 → 20000
- `spawn_grace_frames`: 300 → 600

### Collision-Type Discrimination (samba_bus.gd, new)
- `CollisionType` enum: `COLLISION_SOFT` and `COLLISION_HARD`
- Hard groups: `"Tree"`, `"enemy"`; Soft groups: `"Road"`, `"Grass"`; ungrouped defaults to HARD
- Soft collisions apply 0.35× damage multiplier; Hard = 1.0×
- Velocity-based damage gate: below 5 km/h = zero damage; quadratic curve 0.0× at ≤8 km/h → 1.0× at ≥25 km/h
- New export: `soft_filter_force_threshold` = 5000.0 (filters low-force soft contacts)
- Road-seam filter extended from Road-only to all soft collision groups

### Grace System (samba_bus.gd, refactored)
- Two-stage grace: stage 1 = 240 frames (full immunity), stage 2 = 120 frames (50% mitigation), then normal
- New export: `settling_grace_stage2_frames` = 120

### Disturbance Scaling (samba_bus.gd, new)
- New export: `collision_disturbance_scale` = 0.0001
- Disturbance = `collision_disturbance_scale × force` (continuous, replaces fixed 2.0)
- Old `collision_disturbance` export removed
- `disturbance_increase` for door_left_front: 1.15× → 1.06×
- Disturbance is NOT gated by grace — accumulates during settling

### Deferred
- FR-014 (structural damage resistance bonus) — deferred
- FR-017 (spare tire) — deferred
- FR-018 (gear-dependent damage scaling) — deferred

Controlled tag vocabulary (as read):
type/*:
- `type/code` — Code architecture, autoloads, conventions, tooling. Carries `code-refs:`. (e.g. `Code/Autoloads — Disturbance.md`)
- `type/decision` — Architectural or design decision made by an agent during a session. Written to `docs/vault/Decisions/`. (Agent notes only — spec 080.)
- `type/design` — Design intent, player-facing concepts, world lore. (e.g. `Design/World Model.md`)
- `type/discovery` — Non-obvious constraint, gap, or conflict found by an agent during a session. Written to `docs/vault/Discoveries/`. (Agent notes only — spec 080.)
- `type/moc` — Map of Content at any of three tiers (folder / domain / concept). (e.g. `Audio.md`)
- `type/principle` — Governance and constitutional notes. Non-negotiable rules. (e.g. `Governance/Constitution.md`)
- `type/reference` — Glossary, decision log, open questions, epics. (e.g. `Reference/Glossary.md`)
- `type/session-log` — Session activity log; permanent audit trail. Written to `docs/vault/Sessions/`. Append-only, never pruned. (Agent notes only — spec 080.)
- `type/spec` — Spec document at `docs/vault/Specs/NNN Title/spec.md`. Carries `spec-refs:`. (e.g. `Specs/047 Car Radio/spec.md`)
- `type/system` — A bounded subsystem with implementation. Carries `code-refs`, `spec-refs`, `implements:` frontmatter. (e.g. `Systems/Audio — Car Radio.md`)
- `type/vision` — Strategic / vision-layer decision. Written to `docs/vault/Vision/`. Human-authored or agent-proposed with human ratification before promotion to `status: reviewed`. (Per triage #3 — spec 133 autonomous-company redesign.)
domain/*:
- `domain/anomalies` — Anomaly taxonomy, individual anomaly systems, spawn, behavior
- `domain/art` — Visual direction, palettes, references, asset pipeline
- `domain/audio` — Audio systems: world ambient, radio, transmissions, buses, pipeline
- `domain/autonomous-company` — Autonomous company v0.1 experiment: Slack infra, persona middleware, Letta integration, restart recovery
- `domain/build` — Build system, packaging, export, release automation
- `domain/governance` — Constitution, phased spec, policies
- `domain/infrastructure` — Infrastructure provisioning: CI/CD, hosting, deployment tooling, secrets management
- `domain/narrative` — Tone, horror register, forest transmissions narrative, Gary/KTLK
- `domain/player` — Player mode, input, controls, camera, exit/entry
- `domain/systems` — Cross-cutting system architecture and integration work
- `domain/tooling` — Build, CI, observer, TTS pipeline, dev-time tools
- `domain/vehicle` — The Samba: vehicle physics, dashboard, damage, panels
- `domain/world` — World model, biomes, terrain, procedural generation, weather
status/*:
- `status/canonical` — Fully authoritative; promoted by humans only. Highest trust. (Agent notes only — spec 080.)
- `status/draft` — Authoring in progress, not yet verified
- `status/reviewed` — Agent-created note verified against codebase within its creating session. Eligible for auto-injection in subsequent task dispatches. (Agent notes only — spec 080.)
- `status/stale` — Known out of date; cannot update immediately. Pairs with `> [!warning] STALE — needs update` callout.
- `status/superseded` — Replaced by another note. Terminal state. Pairs with `> [!warning] SUPERSEDED` callout.
- `status/wip` — Stable but under active revision
layer/*:
- `layer/content` — Content assets (audio, models, textures, audio provenance)
- `layer/gdext` — gdext wrapper layer (`rust/gdext-wrapper/`)
- `layer/gdscript` — GDScript (Godot scene-tier logic)
- `layer/infra` — Build, CI, deployment infrastructure
- `layer/python` — Python development tooling (`tools/`)
- `layer/rust-core` — Engine-agnostic Rust core (`rust/rust-core/`)
concept/*:
- `concept/biome` — Biome-reactive behavior across systems
- `concept/contamination` — Across-runs panel and garage degradation; the slow-horror mechanic that doesn't reset with the world
- `concept/diegetic` — Diegetic audio / UI / world-sourced design
- `concept/disturbance` — The disturbance mechanic thread (Article X)
- `concept/ephemeral-world` — Run-reset, transient worlds (Article IV Rules 6–7)
- `concept/governance` — Constitutional and governance concepts
- `concept/horror` — Horror register and dread design
- `concept/procedural` — Procedural generation, seed determinism
- `concept/rendering` — Visual rendering quality, shader correctness, Terrain3D integration, mesh fidelity, LOD, Z-fighting
- `concept/terrain` — Terrain generation, heightmap, Terrain3D regions, roughness, playability constraints
ember's answer for tag_assignment-systems-vehicle-destruction, type/codeP(true) placed on the no, unsure, and yes zones.nounsureyesgold: noP = 0.52

tag_assignment-systems-vehicle-destruction: type/system

Tag assignment · test
Gold
The note calls for `type/system`: A bounded subsystem with implementation. Carries `code-refs`, `spec-refs`, `implements:` frontmatter. (e.g. `Systems/Audio — Car Radio.md`) (True)
ember
The note has no reason to carry `type/system` (False)
Signal
P(true) 0.28 (unsure)
Kit outcome
deferred: treated as unsure
Why this gold label
Mined from Systems/Vehicle — Destruction.md at 692f4bb58b7f62105aeb73fba8dfee12bfdecd53; gold is the note's own vocabulary tags.
Vehicle — Destruction

The panel-level destruction system for the Samba. The Samba is a 60-panel body where each panel is an independent damage target with three states: INTACT, DAMAGED, DESTROYED. Damage events flow through the `Events` signal bus; downstream systems (audio, dashboard, HUD) react independently.

## Overview

Damage in Old Growth is granular: individual panels dent and crack. Impact direction and force determine which panel takes the hit. Destroyed panels expose the vehicle interior to exterior conditions (noise, weather, contamination). The damage state at any moment is a visible running record of what the run has been.

## Design Intent

Per the World Bible: the Samba "features a 60-panel destructible body system that registers every scrape and impact." This granularity is a commitment to the player-as-vehicle framing (see [[Tone and Horror]]) — the bus's body is the player's body, and damage accumulation is a visible argument for caution.

Per Article IV Rule 8 (post-2.19.0): vehicle configuration (installed components and their damage states) is a persistent-data category. Damage persists across runs. Repair kits address it; nothing else does.

## Key Decisions

### 60 panels with Resource-defined properties

Panel definitions live in `src/resources/panels/`. Each panel has:
- ID (StringName)
- Position on the Samba (for spatial damage resolution)
- Health (0 → DESTROYED)
- DAMAGED threshold (typically mid-health)
- Associated damage visuals (deformation, cracks, missing-panel exposure)

### Three-state model

| State | Health | Visual |
|-------|--------|--------|
| INTACT | Above DAMAGED threshold | Clean panel |
| DAMAGED | Below DAMAGED threshold, above 0 | Dents, cracks |
| DESTROYED | Zero | Panel missing; interior exposed |

State transitions emit `Events.bus_panel_state_changed(panel_id, new_state)`. Transitioning to DESTROYED additionally emits `Events.bus_panel_destroyed(panel_id)`.

### Exposure zones

A set of destroyed panels together produces "exposure zones" — logical groups that tell other systems (audio mix, weather, contamination) which parts of the interior are now exposed. `Events.bus_exposure_changed(zones: PackedStringArray)` emits when the active exposure set changes.

### Collision → damage mapping

`Events.bus_collision(force, position)` fires for any collision above the minimum damage-force threshold. The damage system maps (force, position) to the specific panel(s) that should take damage. This lets the collision detection stay generic while the damage logic stays specific.

### Damage accumulation is persistent

Damage persists across runs per Article IV Rule 7. Repair kits restore panel health. Nothing else does. The player's run strategy includes managing damage because the Samba carries history.

### Interior exposure consequences

When a panel is DESTROYED, the corresponding exposure zone affects:
- **Audio mix** — the low-pass interior filter is bypassed in that zone (see [[Audio — World Audio]])
- **Weather** — rain, wind, spore haze, calcite dust can penetrate (see [[Audio — Car Radio]] and weather system)
- **Contamination** — the World Bible's "contamination in the corners" logic. Petrifold dust, Fungal spore residue, mycelium threads accumulate in exposed interior zones across runs (Article IV Rule 7 — vehicle configuration includes damage state)

## Implementation

Primary code references (all under `src/scripts/bus/`):
- `src/scripts/bus/bus_damage_system.gd` — the top-level destruction system
- `src/scripts/bus/bus_panel.gd` — the panel class (state, health, exposure)
- `src/scripts/bus/tire_damage_driver.gd` — tire damage subsystem
- `src/resources/panels/panel_definitions.gd` — panel definitions (GDScript)
- `src/resources/panels/*.tres` — per-panel Resource files

Signals (all via `Events`):
- `bus_panel_state_changed(panel_id, new_state)`
- `bus_panel_destroyed(panel_id)`
- `bus_exposure_changed(zones)`
- `bus_collision(force, position)`
- `bus_enemy_hit(enemy, force)`

## Test Coverage

- `src/tests/unit/test_bus_damage_system.gd` — panel damage, state transitions, exposure zone tracking
- `src/tests/unit/test_bus_damage_effects.gd` — damage visual/audio effects
- `src/tests/unit/test_bus_panel.gd` — panel class unit tests
- `src/tests/unit/test_tire_damage_driver.gd` — tire damage subsystem

> **⚠️ PRE-068 NOTE — panel count and damage model will change when spec 068 (van asset integration) ships.**
> **✅ 068 STATUS UPDATE (2026-05-03)** — Active scene has **44 mesh-active panel nodes** (not 20–30). All 60 panel IDs remain in `panel_definitions.gd` for damage logic; 16 are logical-only or merged. Spec 068 ships 2 visual states (DAMAGED, DESTROYED) via blend-mask shader. Spec 082 will reconcile post-merge.

## Agent Notes (backlinks)

- [[Vehicle Systems and Production Specifications Discovery]] — structural panel HP values (150–200), cascade child lists per structural panel, accessory HP 30 / `no_rear_view` effect, tire HP 80 / `speed_reduction` + `steering_pull`, `acid_exposure` from floor failure; `door_rear_left` and `door_rear_right` are BOTH on passenger side (bi-parting halves, not vehicle sides)

## Contamination Config Resource

When the per-panel contamination system is implemented, all thresholds and tuning values should be committed as a single `@export`-annotated Resource at `res://resources/contamination/contamination_config.tres` — consistent with the pattern established by `res://resources/config/disturbance_config.tres`.

See [[Art/Vehicle — Contamination]] for the visual tier specifications (coverage, opacity, silhouette, normal displacement) and panel zone mapping. The GDScript template below is the implementation target:

```gdscript
## Contamination progression tuning — all values @export for art-director adjustment.
## Authority: docs/vault/Art/Vehicle — Contamination.md
class_name ContaminationConfig
extends Resource

# --- Light tier thresholds (seconds of biome time) -------
@export var moss_light_threshold: float = 180.0
@export var lichen_light_threshold: float = 300.0
@export var spore_film_light_threshold: float = 120.0
@export var fungal_bloom_light_threshold: float = 240.0
@export var calcite_light_threshold: float = 180.0
@export var mineral_accretion_light_threshold: float = 360.0

# --- Moderate tier thresholds -------
@export var moss_moderate_threshold: float = 900.0
@export var lichen_moderate_threshold: float = 1500.0
@export var spore_film_moderate_threshold: float = 600.0
@export var fungal_bloom_moderate_threshold: float = 1200.0
@export var calcite_moderate_threshold: float = 900.0
@export var mineral_accretion_moderate_threshold: float = 1800.0

# --- Severe tier thresholds -------
@export var moss_severe_threshold: float = 2400.0
@export var lichen_severe_threshold: float = 4000.0
@export var spore_film_severe_threshold: float = 1800.0
@export var fungal_bloom_severe_threshold: float = 3000.0
@export var calcite_severe_threshold: float = 2400.0
@export var mineral_accretion_severe_threshold: float = 5000.0

# --- HP acceleration -------
## If panel HP is below this fraction, contamination thresholds scale down by hp_acceleration_strength
@export var hp_acceleration_fraction: float = 0.5
@export var hp_acceleration_strength: float = 0.7

# --- Neighbor proximity acceleration -------
## For each adjacent panel at severe tier, scale current panel thresholds by this factor
@export var neighbor_severe_acceleration: float = 0.85
```

> [!note] This resource does not yet exist. It is a Phase 3 implementation target. Parallels `res://resources/config/disturbance_config.tres`.

## Related

- [[Vehicle — Samba]] — the vehicle this system runs on
- [[Vehicle — Dashboard]] — dashboard displays damage state
- [[Core Mechanics]] — damage mechanic overview
- [[Audio — World Audio]] — exposure-driven audio mix
- [[Autoloads — Events]] — signal bus
- [[Systems]] — folder MOC
- [[Vehicle — Domain MOC]] — domain MOC
- [[Constitution]] — Article IV Rule 7 (persistent data), Article II (Car Is Core)
## Spec 156 Updates (2026-05-29)

The following values were updated by [[156 Bus Damage Rebalance]]:

### HP Ranges (panel_definitions.gd)
- Body: from 80–100 to 120–150 (midpoint 135.0 used)
- Structural: from 150–200 to 200–300 (midpoint 250.0 used)
- Glass: from 40–150 to 80–200 (windshield 200, side windows 150, door windows 120, skylights 100)
- Accessory: from 30 to 50
- Tire: from 80 to 120

### Constants (bus_damage_system.gd)
- `FORCE_TO_DAMAGE_SCALE`: 0.005 → 0.0025
- `cascade_fraction`: 0.25 → 0.10
- `offroad_damage_rate`: 0.5 → 0.2

### Tire Tuning (tire_damage_driver.gd, panel_definitions.gd)
- Tire `damaged_threshold`: 0.3 → 0.15
- `offroad_tire_damage_rate`: 1.5 → 0.4
- `catastrophic_force_threshold`: 15000 → 20000
- `spawn_grace_frames`: 300 → 600

### Collision-Type Discrimination (samba_bus.gd, new)
- `CollisionType` enum: `COLLISION_SOFT` and `COLLISION_HARD`
- Hard groups: `"Tree"`, `"enemy"`; Soft groups: `"Road"`, `"Grass"`; ungrouped defaults to HARD
- Soft collisions apply 0.35× damage multiplier; Hard = 1.0×
- Velocity-based damage gate: below 5 km/h = zero damage; quadratic curve 0.0× at ≤8 km/h → 1.0× at ≥25 km/h
- New export: `soft_filter_force_threshold` = 5000.0 (filters low-force soft contacts)
- Road-seam filter extended from Road-only to all soft collision groups

### Grace System (samba_bus.gd, refactored)
- Two-stage grace: stage 1 = 240 frames (full immunity), stage 2 = 120 frames (50% mitigation), then normal
- New export: `settling_grace_stage2_frames` = 120

### Disturbance Scaling (samba_bus.gd, new)
- New export: `collision_disturbance_scale` = 0.0001
- Disturbance = `collision_disturbance_scale × force` (continuous, replaces fixed 2.0)
- Old `collision_disturbance` export removed
- `disturbance_increase` for door_left_front: 1.15× → 1.06×
- Disturbance is NOT gated by grace — accumulates during settling

### Deferred
- FR-014 (structural damage resistance bonus) — deferred
- FR-017 (spare tire) — deferred
- FR-018 (gear-dependent damage scaling) — deferred

Controlled tag vocabulary (as read):
type/*:
- `type/code` — Code architecture, autoloads, conventions, tooling. Carries `code-refs:`. (e.g. `Code/Autoloads — Disturbance.md`)
- `type/decision` — Architectural or design decision made by an agent during a session. Written to `docs/vault/Decisions/`. (Agent notes only — spec 080.)
- `type/design` — Design intent, player-facing concepts, world lore. (e.g. `Design/World Model.md`)
- `type/discovery` — Non-obvious constraint, gap, or conflict found by an agent during a session. Written to `docs/vault/Discoveries/`. (Agent notes only — spec 080.)
- `type/moc` — Map of Content at any of three tiers (folder / domain / concept). (e.g. `Audio.md`)
- `type/principle` — Governance and constitutional notes. Non-negotiable rules. (e.g. `Governance/Constitution.md`)
- `type/reference` — Glossary, decision log, open questions, epics. (e.g. `Reference/Glossary.md`)
- `type/session-log` — Session activity log; permanent audit trail. Written to `docs/vault/Sessions/`. Append-only, never pruned. (Agent notes only — spec 080.)
- `type/spec` — Spec document at `docs/vault/Specs/NNN Title/spec.md`. Carries `spec-refs:`. (e.g. `Specs/047 Car Radio/spec.md`)
- `type/system` — A bounded subsystem with implementation. Carries `code-refs`, `spec-refs`, `implements:` frontmatter. (e.g. `Systems/Audio — Car Radio.md`)
- `type/vision` — Strategic / vision-layer decision. Written to `docs/vault/Vision/`. Human-authored or agent-proposed with human ratification before promotion to `status: reviewed`. (Per triage #3 — spec 133 autonomous-company redesign.)
domain/*:
- `domain/anomalies` — Anomaly taxonomy, individual anomaly systems, spawn, behavior
- `domain/art` — Visual direction, palettes, references, asset pipeline
- `domain/audio` — Audio systems: world ambient, radio, transmissions, buses, pipeline
- `domain/autonomous-company` — Autonomous company v0.1 experiment: Slack infra, persona middleware, Letta integration, restart recovery
- `domain/build` — Build system, packaging, export, release automation
- `domain/governance` — Constitution, phased spec, policies
- `domain/infrastructure` — Infrastructure provisioning: CI/CD, hosting, deployment tooling, secrets management
- `domain/narrative` — Tone, horror register, forest transmissions narrative, Gary/KTLK
- `domain/player` — Player mode, input, controls, camera, exit/entry
- `domain/systems` — Cross-cutting system architecture and integration work
- `domain/tooling` — Build, CI, observer, TTS pipeline, dev-time tools
- `domain/vehicle` — The Samba: vehicle physics, dashboard, damage, panels
- `domain/world` — World model, biomes, terrain, procedural generation, weather
status/*:
- `status/canonical` — Fully authoritative; promoted by humans only. Highest trust. (Agent notes only — spec 080.)
- `status/draft` — Authoring in progress, not yet verified
- `status/reviewed` — Agent-created note verified against codebase within its creating session. Eligible for auto-injection in subsequent task dispatches. (Agent notes only — spec 080.)
- `status/stale` — Known out of date; cannot update immediately. Pairs with `> [!warning] STALE — needs update` callout.
- `status/superseded` — Replaced by another note. Terminal state. Pairs with `> [!warning] SUPERSEDED` callout.
- `status/wip` — Stable but under active revision
layer/*:
- `layer/content` — Content assets (audio, models, textures, audio provenance)
- `layer/gdext` — gdext wrapper layer (`rust/gdext-wrapper/`)
- `layer/gdscript` — GDScript (Godot scene-tier logic)
- `layer/infra` — Build, CI, deployment infrastructure
- `layer/python` — Python development tooling (`tools/`)
- `layer/rust-core` — Engine-agnostic Rust core (`rust/rust-core/`)
concept/*:
- `concept/biome` — Biome-reactive behavior across systems
- `concept/contamination` — Across-runs panel and garage degradation; the slow-horror mechanic that doesn't reset with the world
- `concept/diegetic` — Diegetic audio / UI / world-sourced design
- `concept/disturbance` — The disturbance mechanic thread (Article X)
- `concept/ephemeral-world` — Run-reset, transient worlds (Article IV Rules 6–7)
- `concept/governance` — Constitutional and governance concepts
- `concept/horror` — Horror register and dread design
- `concept/procedural` — Procedural generation, seed determinism
- `concept/rendering` — Visual rendering quality, shader correctness, Terrain3D integration, mesh fidelity, LOD, Z-fighting
- `concept/terrain` — Terrain generation, heightmap, Terrain3D regions, roughness, playability constraints
ember's answer for tag_assignment-systems-vehicle-destruction, type/systemP(true) placed on the no, unsure, and yes zones.nounsureyesgold: yesP = 0.28

tag_assignment-code-build-system: type/code

Tag assignment · test
Gold
The note calls for `type/code`: Code architecture, autoloads, conventions, tooling. Carries `code-refs:`. (e.g. `Code/Autoloads — Disturbance.md`) (True)
ember
The note has no reason to carry `type/code` (False)
Signal
P(true) 0.31 (unsure)
Kit outcome
deferred: treated as unsure
Why this gold label
Mined from Code/Build System.md at 692f4bb58b7f62105aeb73fba8dfee12bfdecd53; gold is the note's own vocabulary tags.
Build System

Old Growth's build system is Make-driven. All CI checks, lint, test, and release workflows are Make targets at the repo root. This note is the canonical target reference + pre-commit hook documentation + the macOS release pipeline overview.

## Cross-Platform Dispatch

The Makefile targets both macOS and Windows (spec 156). At the top of the Makefile, `ifeq ($(OS),Windows_NT)` detection sets platform-conditional variables:

| Variable | macOS | Windows |
|----------|-------|---------|
| `SCRIPT_EXT` | `sh` | `ps1` |
| `SCRIPT_RUNNER` | `bash` | `pwsh -File` |
| `VENV_BIN` | `.venv/bin` | `.venv/Scripts` |
| `PYTHON` | `.venv/bin/python3` | `.venv/Scripts/python.exe` |
| `GODOT_APP` | `/Applications/Godot.app/Contents/MacOS` | `$(shell where godot)` |
| `PATHSEP` | `:` | `;` |

All targets use `$(SCRIPT_RUNNER)` with `$(SCRIPT_EXT)` to dispatch to platform-specific scripts. macOS uses existing `.sh` scripts; Windows uses parallel `.ps1` scripts in the same directories. macOS-only targets (codesign, dmg, Rust universal binary, launchd-managed personas) print a clear `[SKIP]` message when run on Windows.

## Overview

A single `Makefile` at the repo root orchestrates everything: GDScript lint/format, Rust build/test, component SemVer enforcement, Godot headless sanity, export smoke tests, release bumps, and the full CI pipeline. Prerequisites and target dependencies are documented in AGENTS.md; this note is the authored reference.

## Key Targets

### Composite targets

| Target | Purpose |
|--------|---------|
| `make all` | Full CI pipeline (stops on first failure) |
| `make pre-commit` | Fast, non-Godot checks run by the pre-commit hook |
| `make gdscript-quality` | `gdformat --check` + `gdlint` combined |
| `make test` | Run ALL GUT unit tests headless |

### GDScript quality

| Target | Purpose |
|--------|---------|
| `make format-check` | `gdformat --check` on first-party `.gd` files |
| `make lint` | `gdlint` on first-party `.gd` files |

### Enforcement

| Target | Purpose |
|--------|---------|
| `make semver` | Component SemVer enforcement (see [[Component SemVer Policy]]) |
| `make gdignore-check` | Verify non-shippable asset dirs have `.gdignore` |

### Godot sanity

| Target | Purpose |
|--------|---------|
| `make headless` | Godot headless project sanity check |
| `make macos-smoke` | macOS headless smoke test (lightweight, no LFS) |
| `make export-smoke` | macOS export smoke test (requires full LFS assets) |
| `make export-linux` | Linux export (cross-compile from macOS) — builds Rust .so, runs Godot headless export with Linux preset.2, validates with `validate_linux_export.sh` |

### Rust

| Target | Purpose |
|--------|---------|
| `make rust-build` | Compile Rust workspace (debug), copy dylib to `src/addons/oldgrowth-rust/bin/` |
| `make rust-test` | Run `cargo test --workspace` |
| `make rust-clippy` | Run `cargo clippy -- -D warnings` |
| `make rust-release` | Build Universal Binary (arm64 + x86_64) for release |

### Release

| Target | Purpose |
|--------|---------|
| `make bump-patch` | Bump game version patch (e.g., `0.9.1 → 0.9.2`) |
| `make bump-minor` | Bump game version minor (e.g., `0.9.2 → 0.10.0`) |
| `make bump-major` | Bump game version major |

### Misc

| Target | Purpose |
|--------|---------|
| `make setup` | Create `.venv/`, add `godot` to PATH, copy `.env.example` → `.env` and `tools/comfyui/.env.example` → `tools/comfyui/.env` |
| `make comfyui-setup` | One-shot ComfyUI pipeline setup: clone MCP server, Python venv, custom nodes, models, `.env` |
| `make comfyui-models` | Download SDXL + RealESRGAN upscaler models only (idempotent) |
| `make comfyui-status` | Verify full ComfyUI pipeline readiness |
| `make blender-run` | Run full T011–T015 Blender pipeline headlessly (panel sep → UV → transforms → LOD → export) |
| `make blender-run STAGE=t011` | Run a single pipeline stage |
| `make blender-status` | Check Blender binary, source blend, and GLB export outputs |
| `make clean` | Remove local test artifacts |

## Pre-Commit Hook

The pre-commit hook runs `make pre-commit` before every commit. This runs:

1. Component SemVer check (auto-bumps patches on drift)
2. Game version format check
3. Asset `.gdignore` coverage check
4. GDScript formatting check
5. GDScript linting
6. Rust tests + clippy (optional, can be skipped with env var)

On commit, the hook auto-bumps patch versions for components whose files have changed without a bump. This catches the common case where a developer forgot. More significant bumps must be applied manually.

## CI Pipeline

The CI basics workflow (`ci-basics.yml`) aligns with `make pre-commit` plus the additional Godot + export checks that require a Godot installation. A Linux export smoke test (`linux-export-smoke`) validates the export pipeline on every PR — builds the Rust .so, runs Godot headless export with the Linux preset, and runs `validate_linux_export.sh` on the output. This job runs independently of `linux-tests` (GUT + headless) and is included in the `all-checks` aggregate gate.

A separate `release.yml` watches for `config/version=` changes on `main` and publishes a GitHub Release. The release workflow has three parallel export jobs:

- `export-universal` (macOS, `macos-latest`) — builds universal Rust dylib, exports signed/notarized DMG
- `export-linux` (Linux, `ubuntu-latest`) — builds Linux Rust .so, wraps export in AppImage via appimagetool, uploads to R2 independently

The `sign-and-release` job aggregates both platforms with `if: always()` — one platform failure does not block the other. It generates multi-platform release notes and attaches all available artifacts to the GitHub Release.

### Godot Version Consistency

All CI workflows reference a pinned `GODOT_VERSION` from `.github/ci-vars.yml`. A `version-consistency` job in `ci-fast.yml` verifies that every workflow using `GODOT_VERSION` matches the canonical value, preventing silent drift between the release and PR CI pipelines. The Makefile does not hardcode a Godot version — it auto-detects the installed binary at runtime.

## Article III Rule 15 — The Single Source of Truth

The game version lives exclusively in `src/project.godot` (`config/version=`). Bumping it in a PR that merges to `main` is the sole release trigger. No manual tagging; no manual upload.

Agents must run `make bump-*` as part of any PR that touches game-affecting files (`src/**` or `rust/**`). The bump level follows these rules:

- `bump-patch` — bug fixes, config refactors, hardening (no new gameplay)
- `bump-minor` — completed phase spec (new gameplay capability)
- `bump-major` — full epic complete

## CI Workflow Suppression Pitfall

**GitHub suppresses `push`-based workflow triggers when a merge commit modifies `.github/workflows/` files.** This is a platform security constraint, not a bug.

**Symptom**: PR merges to `main`, no Release or Auto Bump workflow runs appear in Actions.

**Prevention**: Keep `.github/workflows/` changes in a dedicated PR that does not touch `src/` or `rust/`. Merge the workflow PR first; then merge the version bump PR separately.

**Recovery**: Actions → select the workflow → Run workflow → `main`.

## Related

- [[Component SemVer Policy]] — the policy `make semver` enforces
- [[Project Topology]] — the repo structure Make operates on
- [[Source Tree]] — the files Make touches
- [[Rust — Core]] — built by `make rust-build`
- [[Rust — GDExt Wrapper]] — built by `make rust-build`
- [[Code]] — folder MOC
- [[Constitution]] — Article III Rule 15 (game version bump obligation)
- [[Tools — ComfyUI]] — ComfyUI pipeline targets (`make comfyui-setup/models/status`)
- [[Tools — Blender]] — Blender pipeline targets (`make blender-run/status`)

Controlled tag vocabulary (as read):
type/*:
- `type/code` — Code architecture, autoloads, conventions, tooling. Carries `code-refs:`. (e.g. `Code/Autoloads — Disturbance.md`)
- `type/decision` — Architectural or design decision made by an agent during a session. Written to `docs/vault/Decisions/`. (Agent notes only — spec 080.)
- `type/design` — Design intent, player-facing concepts, world lore. (e.g. `Design/World Model.md`)
- `type/discovery` — Non-obvious constraint, gap, or conflict found by an agent during a session. Written to `docs/vault/Discoveries/`. (Agent notes only — spec 080.)
- `type/moc` — Map of Content at any of three tiers (folder / domain / concept). (e.g. `Audio.md`)
- `type/principle` — Governance and constitutional notes. Non-negotiable rules. (e.g. `Governance/Constitution.md`)
- `type/reference` — Glossary, decision log, open questions, epics. (e.g. `Reference/Glossary.md`)
- `type/session-log` — Session activity log; permanent audit trail. Written to `docs/vault/Sessions/`. Append-only, never pruned. (Agent notes only — spec 080.)
- `type/spec` — Spec document at `docs/vault/Specs/NNN Title/spec.md`. Carries `spec-refs:`. (e.g. `Specs/047 Car Radio/spec.md`)
- `type/system` — A bounded subsystem with implementation. Carries `code-refs`, `spec-refs`, `implements:` frontmatter. (e.g. `Systems/Audio — Car Radio.md`)
- `type/vision` — Strategic / vision-layer decision. Written to `docs/vault/Vision/`. Human-authored or agent-proposed with human ratification before promotion to `status: reviewed`. (Per triage #3 — spec 133 autonomous-company redesign.)
domain/*:
- `domain/anomalies` — Anomaly taxonomy, individual anomaly systems, spawn, behavior
- `domain/art` — Visual direction, palettes, references, asset pipeline
- `domain/audio` — Audio systems: world ambient, radio, transmissions, buses, pipeline
- `domain/autonomous-company` — Autonomous company v0.1 experiment: Slack infra, persona middleware, Letta integration, restart recovery
- `domain/build` — Build system, packaging, export, release automation
- `domain/governance` — Constitution, phased spec, policies
- `domain/infrastructure` — Infrastructure provisioning: CI/CD, hosting, deployment tooling, secrets management
- `domain/narrative` — Tone, horror register, forest transmissions narrative, Gary/KTLK
- `domain/player` — Player mode, input, controls, camera, exit/entry
- `domain/systems` — Cross-cutting system architecture and integration work
- `domain/tooling` — Build, CI, observer, TTS pipeline, dev-time tools
- `domain/vehicle` — The Samba: vehicle physics, dashboard, damage, panels
- `domain/world` — World model, biomes, terrain, procedural generation, weather
status/*:
- `status/canonical` — Fully authoritative; promoted by humans only. Highest trust. (Agent notes only — spec 080.)
- `status/draft` — Authoring in progress, not yet verified
- `status/reviewed` — Agent-created note verified against codebase within its creating session. Eligible for auto-injection in subsequent task dispatches. (Agent notes only — spec 080.)
- `status/stale` — Known out of date; cannot update immediately. Pairs with `> [!warning] STALE — needs update` callout.
- `status/superseded` — Replaced by another note. Terminal state. Pairs with `> [!warning] SUPERSEDED` callout.
- `status/wip` — Stable but under active revision
layer/*:
- `layer/content` — Content assets (audio, models, textures, audio provenance)
- `layer/gdext` — gdext wrapper layer (`rust/gdext-wrapper/`)
- `layer/gdscript` — GDScript (Godot scene-tier logic)
- `layer/infra` — Build, CI, deployment infrastructure
- `layer/python` — Python development tooling (`tools/`)
- `layer/rust-core` — Engine-agnostic Rust core (`rust/rust-core/`)
concept/*:
- `concept/biome` — Biome-reactive behavior across systems
- `concept/contamination` — Across-runs panel and garage degradation; the slow-horror mechanic that doesn't reset with the world
- `concept/diegetic` — Diegetic audio / UI / world-sourced design
- `concept/disturbance` — The disturbance mechanic thread (Article X)
- `concept/ephemeral-world` — Run-reset, transient worlds (Article IV Rules 6–7)
- `concept/governance` — Constitutional and governance concepts
- `concept/horror` — Horror register and dread design
- `concept/procedural` — Procedural generation, seed determinism
- `concept/rendering` — Visual rendering quality, shader correctness, Terrain3D integration, mesh fidelity, LOD, Z-fighting
- `concept/terrain` — Terrain generation, heightmap, Terrain3D regions, roughness, playability constraints
ember's answer for tag_assignment-code-build-system, type/codeP(true) placed on the no, unsure, and yes zones.nounsureyesgold: yesP = 0.31

tag_assignment-decisions-reciprocal-exemption-for-bidirectional-ratio: status/draft

Tag assignment · test
Gold
The note calls for `status/draft`: Authoring in progress, not yet verified (True)
ember
The note has no reason to carry `status/draft` (False)
Signal
P(true) 0.08 (no)
Kit outcome
acted on a wrong answer
Why this gold label
Mined from Decisions/Reciprocal Exemption for Bidirectional Ratio.md at 692f4bb58b7f62105aeb73fba8dfee12bfdecd53; gold is the note's own vocabulary tags.
Reciprocal Exemption for Bidirectional Ratio

The vault graph health report computes a bidirectional ratio (percentage of linked note pairs that have reciprocal wikilinks). A naive count includes many links that are intentionally one-way, making the ratio misleadingly low.

Three categories are excluded from the ratio:

1.  Constitution cited as a target — the Constitution is a foundational governance document referenced by 80+ notes as a formal citation. Expecting it to reciprocate all of them would produce meaningless backlinks.
2.  Thread/essay notes as a target — outward-facing essays like The Disturbance Thread link to concepts they discuss through the concepts should not reciprocate 15+ thread backlinks.
3.  Spec sub-artifacts as a source — template-generated plan, task, and data-model files link to their parent spec by design. This is a documentation pattern, not navigational linking.

These categories accounted for roughly half of the missing-reciprocal count (833 of 1698 pairs). Excluding them moved the bidirectional ratio from ~25% into the healthy range (~38%) without adding any new actual reciprocals.

The exemption is implemented in `scripts/ci/graph_health/scanner.py` as the function `_is_reciprocal_exempt()`. It is checked during the bidirectional completeness pass (FR-006) before a pair enters the seen-pairs set or the missing-reciprocals list.

## References

- `scripts/ci/graph_health/scanner.py` — `_is_reciprocal_exempt()` at line 178
- `docs/vault/Specs/148 Link Prediction Ensemble/148 Link Prediction Ensemble.md`

Controlled tag vocabulary (as read):
type/*:
- `type/code` — Code architecture, autoloads, conventions, tooling. Carries `code-refs:`. (e.g. `Code/Autoloads — Disturbance.md`)
- `type/decision` — Architectural or design decision made by an agent during a session. Written to `docs/vault/Decisions/`. (Agent notes only — spec 080.)
- `type/design` — Design intent, player-facing concepts, world lore. (e.g. `Design/World Model.md`)
- `type/discovery` — Non-obvious constraint, gap, or conflict found by an agent during a session. Written to `docs/vault/Discoveries/`. (Agent notes only — spec 080.)
- `type/moc` — Map of Content at any of three tiers (folder / domain / concept). (e.g. `Audio.md`)
- `type/principle` — Governance and constitutional notes. Non-negotiable rules. (e.g. `Governance/Constitution.md`)
- `type/reference` — Glossary, decision log, open questions, epics. (e.g. `Reference/Glossary.md`)
- `type/session-log` — Session activity log; permanent audit trail. Written to `docs/vault/Sessions/`. Append-only, never pruned. (Agent notes only — spec 080.)
- `type/spec` — Spec document at `docs/vault/Specs/NNN Title/spec.md`. Carries `spec-refs:`. (e.g. `Specs/047 Car Radio/spec.md`)
- `type/system` — A bounded subsystem with implementation. Carries `code-refs`, `spec-refs`, `implements:` frontmatter. (e.g. `Systems/Audio — Car Radio.md`)
- `type/vision` — Strategic / vision-layer decision. Written to `docs/vault/Vision/`. Human-authored or agent-proposed with human ratification before promotion to `status: reviewed`. (Per triage #3 — spec 133 autonomous-company redesign.)
domain/*:
- `domain/anomalies` — Anomaly taxonomy, individual anomaly systems, spawn, behavior
- `domain/art` — Visual direction, palettes, references, asset pipeline
- `domain/audio` — Audio systems: world ambient, radio, transmissions, buses, pipeline
- `domain/autonomous-company` — Autonomous company v0.1 experiment: Slack infra, persona middleware, Letta integration, restart recovery
- `domain/build` — Build system, packaging, export, release automation
- `domain/governance` — Constitution, phased spec, policies
- `domain/infrastructure` — Infrastructure provisioning: CI/CD, hosting, deployment tooling, secrets management
- `domain/narrative` — Tone, horror register, forest transmissions narrative, Gary/KTLK
- `domain/player` — Player mode, input, controls, camera, exit/entry
- `domain/systems` — Cross-cutting system architecture and integration work
- `domain/tooling` — Build, CI, observer, TTS pipeline, dev-time tools
- `domain/vehicle` — The Samba: vehicle physics, dashboard, damage, panels
- `domain/world` — World model, biomes, terrain, procedural generation, weather
status/*:
- `status/canonical` — Fully authoritative; promoted by humans only. Highest trust. (Agent notes only — spec 080.)
- `status/draft` — Authoring in progress, not yet verified
- `status/reviewed` — Agent-created note verified against codebase within its creating session. Eligible for auto-injection in subsequent task dispatches. (Agent notes only — spec 080.)
- `status/stale` — Known out of date; cannot update immediately. Pairs with `> [!warning] STALE — needs update` callout.
- `status/superseded` — Replaced by another note. Terminal state. Pairs with `> [!warning] SUPERSEDED` callout.
- `status/wip` — Stable but under active revision
layer/*:
- `layer/content` — Content assets (audio, models, textures, audio provenance)
- `layer/gdext` — gdext wrapper layer (`rust/gdext-wrapper/`)
- `layer/gdscript` — GDScript (Godot scene-tier logic)
- `layer/infra` — Build, CI, deployment infrastructure
- `layer/python` — Python development tooling (`tools/`)
- `layer/rust-core` — Engine-agnostic Rust core (`rust/rust-core/`)
concept/*:
- `concept/biome` — Biome-reactive behavior across systems
- `concept/contamination` — Across-runs panel and garage degradation; the slow-horror mechanic that doesn't reset with the world
- `concept/diegetic` — Diegetic audio / UI / world-sourced design
- `concept/disturbance` — The disturbance mechanic thread (Article X)
- `concept/ephemeral-world` — Run-reset, transient worlds (Article IV Rules 6–7)
- `concept/governance` — Constitutional and governance concepts
- `concept/horror` — Horror register and dread design
- `concept/procedural` — Procedural generation, seed determinism
- `concept/rendering` — Visual rendering quality, shader correctness, Terrain3D integration, mesh fidelity, LOD, Z-fighting
- `concept/terrain` — Terrain generation, heightmap, Terrain3D regions, roughness, playability constraints
ember's answer for tag_assignment-decisions-reciprocal-exemption-for-bidirectional-ratio, status/draftP(true) placed on the no, unsure, and yes zones.nounsureyesgold: yesP = 0.08

tag_assignment-decisions-reciprocal-exemption-for-bidirectional-ratio: type/decision

Tag assignment · test
Gold
The note calls for `type/decision`: Architectural or design decision made by an agent during a session. Written to `docs/vault/Decisions/`. (Agent notes only — spec 080.) (True)
ember
The note has no reason to carry `type/decision` (False)
Signal
P(true) 0.06 (no)
Kit outcome
acted on a wrong answer
Why this gold label
Mined from Decisions/Reciprocal Exemption for Bidirectional Ratio.md at 692f4bb58b7f62105aeb73fba8dfee12bfdecd53; gold is the note's own vocabulary tags.
Reciprocal Exemption for Bidirectional Ratio

The vault graph health report computes a bidirectional ratio (percentage of linked note pairs that have reciprocal wikilinks). A naive count includes many links that are intentionally one-way, making the ratio misleadingly low.

Three categories are excluded from the ratio:

1.  Constitution cited as a target — the Constitution is a foundational governance document referenced by 80+ notes as a formal citation. Expecting it to reciprocate all of them would produce meaningless backlinks.
2.  Thread/essay notes as a target — outward-facing essays like The Disturbance Thread link to concepts they discuss through the concepts should not reciprocate 15+ thread backlinks.
3.  Spec sub-artifacts as a source — template-generated plan, task, and data-model files link to their parent spec by design. This is a documentation pattern, not navigational linking.

These categories accounted for roughly half of the missing-reciprocal count (833 of 1698 pairs). Excluding them moved the bidirectional ratio from ~25% into the healthy range (~38%) without adding any new actual reciprocals.

The exemption is implemented in `scripts/ci/graph_health/scanner.py` as the function `_is_reciprocal_exempt()`. It is checked during the bidirectional completeness pass (FR-006) before a pair enters the seen-pairs set or the missing-reciprocals list.

## References

- `scripts/ci/graph_health/scanner.py` — `_is_reciprocal_exempt()` at line 178
- `docs/vault/Specs/148 Link Prediction Ensemble/148 Link Prediction Ensemble.md`

Controlled tag vocabulary (as read):
type/*:
- `type/code` — Code architecture, autoloads, conventions, tooling. Carries `code-refs:`. (e.g. `Code/Autoloads — Disturbance.md`)
- `type/decision` — Architectural or design decision made by an agent during a session. Written to `docs/vault/Decisions/`. (Agent notes only — spec 080.)
- `type/design` — Design intent, player-facing concepts, world lore. (e.g. `Design/World Model.md`)
- `type/discovery` — Non-obvious constraint, gap, or conflict found by an agent during a session. Written to `docs/vault/Discoveries/`. (Agent notes only — spec 080.)
- `type/moc` — Map of Content at any of three tiers (folder / domain / concept). (e.g. `Audio.md`)
- `type/principle` — Governance and constitutional notes. Non-negotiable rules. (e.g. `Governance/Constitution.md`)
- `type/reference` — Glossary, decision log, open questions, epics. (e.g. `Reference/Glossary.md`)
- `type/session-log` — Session activity log; permanent audit trail. Written to `docs/vault/Sessions/`. Append-only, never pruned. (Agent notes only — spec 080.)
- `type/spec` — Spec document at `docs/vault/Specs/NNN Title/spec.md`. Carries `spec-refs:`. (e.g. `Specs/047 Car Radio/spec.md`)
- `type/system` — A bounded subsystem with implementation. Carries `code-refs`, `spec-refs`, `implements:` frontmatter. (e.g. `Systems/Audio — Car Radio.md`)
- `type/vision` — Strategic / vision-layer decision. Written to `docs/vault/Vision/`. Human-authored or agent-proposed with human ratification before promotion to `status: reviewed`. (Per triage #3 — spec 133 autonomous-company redesign.)
domain/*:
- `domain/anomalies` — Anomaly taxonomy, individual anomaly systems, spawn, behavior
- `domain/art` — Visual direction, palettes, references, asset pipeline
- `domain/audio` — Audio systems: world ambient, radio, transmissions, buses, pipeline
- `domain/autonomous-company` — Autonomous company v0.1 experiment: Slack infra, persona middleware, Letta integration, restart recovery
- `domain/build` — Build system, packaging, export, release automation
- `domain/governance` — Constitution, phased spec, policies
- `domain/infrastructure` — Infrastructure provisioning: CI/CD, hosting, deployment tooling, secrets management
- `domain/narrative` — Tone, horror register, forest transmissions narrative, Gary/KTLK
- `domain/player` — Player mode, input, controls, camera, exit/entry
- `domain/systems` — Cross-cutting system architecture and integration work
- `domain/tooling` — Build, CI, observer, TTS pipeline, dev-time tools
- `domain/vehicle` — The Samba: vehicle physics, dashboard, damage, panels
- `domain/world` — World model, biomes, terrain, procedural generation, weather
status/*:
- `status/canonical` — Fully authoritative; promoted by humans only. Highest trust. (Agent notes only — spec 080.)
- `status/draft` — Authoring in progress, not yet verified
- `status/reviewed` — Agent-created note verified against codebase within its creating session. Eligible for auto-injection in subsequent task dispatches. (Agent notes only — spec 080.)
- `status/stale` — Known out of date; cannot update immediately. Pairs with `> [!warning] STALE — needs update` callout.
- `status/superseded` — Replaced by another note. Terminal state. Pairs with `> [!warning] SUPERSEDED` callout.
- `status/wip` — Stable but under active revision
layer/*:
- `layer/content` — Content assets (audio, models, textures, audio provenance)
- `layer/gdext` — gdext wrapper layer (`rust/gdext-wrapper/`)
- `layer/gdscript` — GDScript (Godot scene-tier logic)
- `layer/infra` — Build, CI, deployment infrastructure
- `layer/python` — Python development tooling (`tools/`)
- `layer/rust-core` — Engine-agnostic Rust core (`rust/rust-core/`)
concept/*:
- `concept/biome` — Biome-reactive behavior across systems
- `concept/contamination` — Across-runs panel and garage degradation; the slow-horror mechanic that doesn't reset with the world
- `concept/diegetic` — Diegetic audio / UI / world-sourced design
- `concept/disturbance` — The disturbance mechanic thread (Article X)
- `concept/ephemeral-world` — Run-reset, transient worlds (Article IV Rules 6–7)
- `concept/governance` — Constitutional and governance concepts
- `concept/horror` — Horror register and dread design
- `concept/procedural` — Procedural generation, seed determinism
- `concept/rendering` — Visual rendering quality, shader correctness, Terrain3D integration, mesh fidelity, LOD, Z-fighting
- `concept/terrain` — Terrain generation, heightmap, Terrain3D regions, roughness, playability constraints
ember's answer for tag_assignment-decisions-reciprocal-exemption-for-bidirectional-ratio, type/decisionP(true) placed on the no, unsure, and yes zones.nounsureyesgold: yesP = 0.06

tag_assignment-discoveries-appimage-action-deprecation-and-ci-portability-fixes: status/draft

Tag assignment · test
Gold
The note calls for `status/draft`: Authoring in progress, not yet verified (True)
ember
The note has no reason to carry `status/draft` (False)
Signal
P(true) 0.03 (no)
Kit outcome
acted on a wrong answer
Why this gold label
Mined from Discoveries/AppImage Action Deprecation and CI Portability Fixes.md at 692f4bb58b7f62105aeb73fba8dfee12bfdecd53; gold is the note's own vocabulary tags.
AppImage Action Deprecation and CI Portability Fixes

The Linux release pipeline broke silently for ~4.5 weeks (v0.17.11 through v0.18.8) because the AppImage packaging action was deleted and the export validation script had portability bugs that only manifested on ubuntu-24.04 CI runners.

## AppImage/AppImageKit-action Removal

The `AppImage/AppImageKit-action@v1` GitHub Action was removed from the Marketplace — the repository was deleted. The old repository's final release notes redirect to the new standalone project at `github.com/AppImage/appimagetool`.

**Replacement**: Download the `appimagetool-x86_64.AppImage` directly from the continuous release and set `APPIMAGE_EXTRACT_AND_RUN=1` in the environment. GitHub Actions ubuntu runners do not have FUSE, so the AppImage runtime must auto-extract on each invocation. The `$GITHUB_PATH` approach was unreliable — using `$GITHUB_ENV` with an explicit env var (`IMTOOL=/tmp/appimagetool`) and referencing `${IMTOOL}` directly in the wrapping step was more robust.

**Affected file**: `.github/workflows/release.yml` — the `Install appimagetool` step and the `Wrap export into AppImage` step.

## Validate Script Portability

The `scripts/ci/validate_linux_export.sh` script had two portability issues that caused CI Basics `linux-export-smoke` to fail on ubuntu-24.04 runners while passing locally on macOS:

**Non-portable head invocation**: The script used `head -n -2` to trim footer lines from `unzip -l` output. The negative-count syntax is a GNU coreutils extension — BSD `head` (macOS) rejects it with `illegal line count`. The CI Basics `linux-export-smoke` job runs on `ubuntu-24.04` which ships GNU coreutils, but the script's parent shell uses `bash -e`, and the failing `head` triggered `set -e` before the variable assignment completed. **Fix**: Replaced with `grep -vE` pattern matching that works on both GNU and BSD systems.

**Fragile binary detection**: The script matched binary filenames by the `\.x86_64$` suffix. Godot 4.6 Linux exports on ubuntu-24.04 may produce binaries with different naming conventions. **Fix**: Replaced filename-pattern matching with actual ELF magic byte detection — iterating candidate files, extracting them to temp, and running `file` to check for `ELF` in the output.

**set -e interaction**: The script used `set -euo pipefail` internally (redundant with the GitHub Actions shell wrapper's `-e`). `grep` returning exit code 1 (no match) within a pipeline combined with `set -o pipefail` could cause unexpected exits even inside `$()` command substitutions on some bash versions. **Fix**: Replaced with explicit `FAILED` counter pattern and `|| true` guards on grep pipelines. The script no longer relies on `set -e` for flow control.

## References

- `.github/workflows/release.yml` — Install appimagetool step (uses direct download + APPIMAGE_EXTRACT_AND_RUN)
- `scripts/ci/validate_linux_export.sh` — Rewritten binary detection and cross-platform parsing

Controlled tag vocabulary (as read):
type/*:
- `type/code` — Code architecture, autoloads, conventions, tooling. Carries `code-refs:`. (e.g. `Code/Autoloads — Disturbance.md`)
- `type/decision` — Architectural or design decision made by an agent during a session. Written to `docs/vault/Decisions/`. (Agent notes only — spec 080.)
- `type/design` — Design intent, player-facing concepts, world lore. (e.g. `Design/World Model.md`)
- `type/discovery` — Non-obvious constraint, gap, or conflict found by an agent during a session. Written to `docs/vault/Discoveries/`. (Agent notes only — spec 080.)
- `type/moc` — Map of Content at any of three tiers (folder / domain / concept). (e.g. `Audio.md`)
- `type/principle` — Governance and constitutional notes. Non-negotiable rules. (e.g. `Governance/Constitution.md`)
- `type/reference` — Glossary, decision log, open questions, epics. (e.g. `Reference/Glossary.md`)
- `type/session-log` — Session activity log; permanent audit trail. Written to `docs/vault/Sessions/`. Append-only, never pruned. (Agent notes only — spec 080.)
- `type/spec` — Spec document at `docs/vault/Specs/NNN Title/spec.md`. Carries `spec-refs:`. (e.g. `Specs/047 Car Radio/spec.md`)
- `type/system` — A bounded subsystem with implementation. Carries `code-refs`, `spec-refs`, `implements:` frontmatter. (e.g. `Systems/Audio — Car Radio.md`)
- `type/vision` — Strategic / vision-layer decision. Written to `docs/vault/Vision/`. Human-authored or agent-proposed with human ratification before promotion to `status: reviewed`. (Per triage #3 — spec 133 autonomous-company redesign.)
domain/*:
- `domain/anomalies` — Anomaly taxonomy, individual anomaly systems, spawn, behavior
- `domain/art` — Visual direction, palettes, references, asset pipeline
- `domain/audio` — Audio systems: world ambient, radio, transmissions, buses, pipeline
- `domain/autonomous-company` — Autonomous company v0.1 experiment: Slack infra, persona middleware, Letta integration, restart recovery
- `domain/build` — Build system, packaging, export, release automation
- `domain/governance` — Constitution, phased spec, policies
- `domain/infrastructure` — Infrastructure provisioning: CI/CD, hosting, deployment tooling, secrets management
- `domain/narrative` — Tone, horror register, forest transmissions narrative, Gary/KTLK
- `domain/player` — Player mode, input, controls, camera, exit/entry
- `domain/systems` — Cross-cutting system architecture and integration work
- `domain/tooling` — Build, CI, observer, TTS pipeline, dev-time tools
- `domain/vehicle` — The Samba: vehicle physics, dashboard, damage, panels
- `domain/world` — World model, biomes, terrain, procedural generation, weather
status/*:
- `status/canonical` — Fully authoritative; promoted by humans only. Highest trust. (Agent notes only — spec 080.)
- `status/draft` — Authoring in progress, not yet verified
- `status/reviewed` — Agent-created note verified against codebase within its creating session. Eligible for auto-injection in subsequent task dispatches. (Agent notes only — spec 080.)
- `status/stale` — Known out of date; cannot update immediately. Pairs with `> [!warning] STALE — needs update` callout.
- `status/superseded` — Replaced by another note. Terminal state. Pairs with `> [!warning] SUPERSEDED` callout.
- `status/wip` — Stable but under active revision
layer/*:
- `layer/content` — Content assets (audio, models, textures, audio provenance)
- `layer/gdext` — gdext wrapper layer (`rust/gdext-wrapper/`)
- `layer/gdscript` — GDScript (Godot scene-tier logic)
- `layer/infra` — Build, CI, deployment infrastructure
- `layer/python` — Python development tooling (`tools/`)
- `layer/rust-core` — Engine-agnostic Rust core (`rust/rust-core/`)
concept/*:
- `concept/biome` — Biome-reactive behavior across systems
- `concept/contamination` — Across-runs panel and garage degradation; the slow-horror mechanic that doesn't reset with the world
- `concept/diegetic` — Diegetic audio / UI / world-sourced design
- `concept/disturbance` — The disturbance mechanic thread (Article X)
- `concept/ephemeral-world` — Run-reset, transient worlds (Article IV Rules 6–7)
- `concept/governance` — Constitutional and governance concepts
- `concept/horror` — Horror register and dread design
- `concept/procedural` — Procedural generation, seed determinism
- `concept/rendering` — Visual rendering quality, shader correctness, Terrain3D integration, mesh fidelity, LOD, Z-fighting
- `concept/terrain` — Terrain generation, heightmap, Terrain3D regions, roughness, playability constraints
ember's answer for tag_assignment-discoveries-appimage-action-deprecation-and-ci-portability-fixes, status/draftP(true) placed on the no, unsure, and yes zones.nounsureyesgold: yesP = 0.03

tag_assignment-discoveries-appimage-action-deprecation-and-ci-portability-fixes: type/discovery

Tag assignment · test
Gold
The note calls for `type/discovery`: Non-obvious constraint, gap, or conflict found by an agent during a session. Written to `docs/vault/Discoveries/`. (Agent notes only — spec 080.) (True)
ember
The note has no reason to carry `type/discovery` (False)
Signal
P(true) 0.05 (no)
Kit outcome
acted on a wrong answer
Why this gold label
Mined from Discoveries/AppImage Action Deprecation and CI Portability Fixes.md at 692f4bb58b7f62105aeb73fba8dfee12bfdecd53; gold is the note's own vocabulary tags.
AppImage Action Deprecation and CI Portability Fixes

The Linux release pipeline broke silently for ~4.5 weeks (v0.17.11 through v0.18.8) because the AppImage packaging action was deleted and the export validation script had portability bugs that only manifested on ubuntu-24.04 CI runners.

## AppImage/AppImageKit-action Removal

The `AppImage/AppImageKit-action@v1` GitHub Action was removed from the Marketplace — the repository was deleted. The old repository's final release notes redirect to the new standalone project at `github.com/AppImage/appimagetool`.

**Replacement**: Download the `appimagetool-x86_64.AppImage` directly from the continuous release and set `APPIMAGE_EXTRACT_AND_RUN=1` in the environment. GitHub Actions ubuntu runners do not have FUSE, so the AppImage runtime must auto-extract on each invocation. The `$GITHUB_PATH` approach was unreliable — using `$GITHUB_ENV` with an explicit env var (`IMTOOL=/tmp/appimagetool`) and referencing `${IMTOOL}` directly in the wrapping step was more robust.

**Affected file**: `.github/workflows/release.yml` — the `Install appimagetool` step and the `Wrap export into AppImage` step.

## Validate Script Portability

The `scripts/ci/validate_linux_export.sh` script had two portability issues that caused CI Basics `linux-export-smoke` to fail on ubuntu-24.04 runners while passing locally on macOS:

**Non-portable head invocation**: The script used `head -n -2` to trim footer lines from `unzip -l` output. The negative-count syntax is a GNU coreutils extension — BSD `head` (macOS) rejects it with `illegal line count`. The CI Basics `linux-export-smoke` job runs on `ubuntu-24.04` which ships GNU coreutils, but the script's parent shell uses `bash -e`, and the failing `head` triggered `set -e` before the variable assignment completed. **Fix**: Replaced with `grep -vE` pattern matching that works on both GNU and BSD systems.

**Fragile binary detection**: The script matched binary filenames by the `\.x86_64$` suffix. Godot 4.6 Linux exports on ubuntu-24.04 may produce binaries with different naming conventions. **Fix**: Replaced filename-pattern matching with actual ELF magic byte detection — iterating candidate files, extracting them to temp, and running `file` to check for `ELF` in the output.

**set -e interaction**: The script used `set -euo pipefail` internally (redundant with the GitHub Actions shell wrapper's `-e`). `grep` returning exit code 1 (no match) within a pipeline combined with `set -o pipefail` could cause unexpected exits even inside `$()` command substitutions on some bash versions. **Fix**: Replaced with explicit `FAILED` counter pattern and `|| true` guards on grep pipelines. The script no longer relies on `set -e` for flow control.

## References

- `.github/workflows/release.yml` — Install appimagetool step (uses direct download + APPIMAGE_EXTRACT_AND_RUN)
- `scripts/ci/validate_linux_export.sh` — Rewritten binary detection and cross-platform parsing

Controlled tag vocabulary (as read):
type/*:
- `type/code` — Code architecture, autoloads, conventions, tooling. Carries `code-refs:`. (e.g. `Code/Autoloads — Disturbance.md`)
- `type/decision` — Architectural or design decision made by an agent during a session. Written to `docs/vault/Decisions/`. (Agent notes only — spec 080.)
- `type/design` — Design intent, player-facing concepts, world lore. (e.g. `Design/World Model.md`)
- `type/discovery` — Non-obvious constraint, gap, or conflict found by an agent during a session. Written to `docs/vault/Discoveries/`. (Agent notes only — spec 080.)
- `type/moc` — Map of Content at any of three tiers (folder / domain / concept). (e.g. `Audio.md`)
- `type/principle` — Governance and constitutional notes. Non-negotiable rules. (e.g. `Governance/Constitution.md`)
- `type/reference` — Glossary, decision log, open questions, epics. (e.g. `Reference/Glossary.md`)
- `type/session-log` — Session activity log; permanent audit trail. Written to `docs/vault/Sessions/`. Append-only, never pruned. (Agent notes only — spec 080.)
- `type/spec` — Spec document at `docs/vault/Specs/NNN Title/spec.md`. Carries `spec-refs:`. (e.g. `Specs/047 Car Radio/spec.md`)
- `type/system` — A bounded subsystem with implementation. Carries `code-refs`, `spec-refs`, `implements:` frontmatter. (e.g. `Systems/Audio — Car Radio.md`)
- `type/vision` — Strategic / vision-layer decision. Written to `docs/vault/Vision/`. Human-authored or agent-proposed with human ratification before promotion to `status: reviewed`. (Per triage #3 — spec 133 autonomous-company redesign.)
domain/*:
- `domain/anomalies` — Anomaly taxonomy, individual anomaly systems, spawn, behavior
- `domain/art` — Visual direction, palettes, references, asset pipeline
- `domain/audio` — Audio systems: world ambient, radio, transmissions, buses, pipeline
- `domain/autonomous-company` — Autonomous company v0.1 experiment: Slack infra, persona middleware, Letta integration, restart recovery
- `domain/build` — Build system, packaging, export, release automation
- `domain/governance` — Constitution, phased spec, policies
- `domain/infrastructure` — Infrastructure provisioning: CI/CD, hosting, deployment tooling, secrets management
- `domain/narrative` — Tone, horror register, forest transmissions narrative, Gary/KTLK
- `domain/player` — Player mode, input, controls, camera, exit/entry
- `domain/systems` — Cross-cutting system architecture and integration work
- `domain/tooling` — Build, CI, observer, TTS pipeline, dev-time tools
- `domain/vehicle` — The Samba: vehicle physics, dashboard, damage, panels
- `domain/world` — World model, biomes, terrain, procedural generation, weather
status/*:
- `status/canonical` — Fully authoritative; promoted by humans only. Highest trust. (Agent notes only — spec 080.)
- `status/draft` — Authoring in progress, not yet verified
- `status/reviewed` — Agent-created note verified against codebase within its creating session. Eligible for auto-injection in subsequent task dispatches. (Agent notes only — spec 080.)
- `status/stale` — Known out of date; cannot update immediately. Pairs with `> [!warning] STALE — needs update` callout.
- `status/superseded` — Replaced by another note. Terminal state. Pairs with `> [!warning] SUPERSEDED` callout.
- `status/wip` — Stable but under active revision
layer/*:
- `layer/content` — Content assets (audio, models, textures, audio provenance)
- `layer/gdext` — gdext wrapper layer (`rust/gdext-wrapper/`)
- `layer/gdscript` — GDScript (Godot scene-tier logic)
- `layer/infra` — Build, CI, deployment infrastructure
- `layer/python` — Python development tooling (`tools/`)
- `layer/rust-core` — Engine-agnostic Rust core (`rust/rust-core/`)
concept/*:
- `concept/biome` — Biome-reactive behavior across systems
- `concept/contamination` — Across-runs panel and garage degradation; the slow-horror mechanic that doesn't reset with the world
- `concept/diegetic` — Diegetic audio / UI / world-sourced design
- `concept/disturbance` — The disturbance mechanic thread (Article X)
- `concept/ephemeral-world` — Run-reset, transient worlds (Article IV Rules 6–7)
- `concept/governance` — Constitutional and governance concepts
- `concept/horror` — Horror register and dread design
- `concept/procedural` — Procedural generation, seed determinism
- `concept/rendering` — Visual rendering quality, shader correctness, Terrain3D integration, mesh fidelity, LOD, Z-fighting
- `concept/terrain` — Terrain generation, heightmap, Terrain3D regions, roughness, playability constraints
ember's answer for tag_assignment-discoveries-appimage-action-deprecation-and-ci-portability-fixes, type/discoveryP(true) placed on the no, unsure, and yes zones.nounsureyesgold: yesP = 0.05

tag_assignment-art-vehicle-samba-interior: type/reference

Tag assignment · dev
Gold
The note calls for `type/reference`: Glossary, decision log, open questions, epics. (e.g. `Reference/Glossary.md`) (True)
ember
The note has no reason to carry `type/reference` (False)
Signal
P(true) 0.04 (no)
Kit outcome
acted on a wrong answer
Why this gold label
Mined from Art/Vehicle — Samba Interior.md at 692f4bb58b7f62105aeb73fba8dfee12bfdecd53; gold is the note's own vocabulary tags.
Vehicle — Samba Interior

> **⚠️ PRE-068 NOTE — dashboard layout will be superseded by actual geometry when spec 068 ships.**
> The control sequence and spatial layout here reflect Phase 2 SVG diagrams — intended layout, not the current placeholder geometry. After 068 ships the purchased model, the committed geometry is the authority. See [[Vehicle Palette Materials and Dimensions Discovery]] for the full authoritative interior note.

For the full interior layout, control sequence, speaker routing, and design intent see Vehicle Palette Materials and Dimensions Discovery. This note focuses on the PBR material specs and Godot resource targets for each interior surface.

## Interior dashboard diagram

![[_meta/attachments/vehicle/dashboard_interaction_callout.svg]]

## Critical design rule — dashboard is body-coloured

The 1963 Samba dashboard is painted **the same colour as the lower exterior body paint** (`hero_teal_lower`). The interior-facing dash continues the exterior paint scheme into the cabin. `interior_dash_body` (`#2D4A45`) is not an independent colour — it is `hero_teal_lower` under cabin shadow. **Do NOT introduce a separate dashboard paint colour.**

## Interior palette — 5 swatches

| Slot | Name | Role | sRGB hex | Linear RGB |
|---|---|---|---|---|
| 1 | `interior_dash_body` | Dashboard fascia, door card metal, interior panels | `#2D4A45` | `(0.025, 0.073, 0.063)` |
| 2 | `interior_headliner` | Cloth headliner spanning cabin ceiling between skylights | `#E8DDBF` | `(0.783, 0.702, 0.520)` |
| 3 | `interior_seat_vinyl` | Seat upholstery, door card vinyl — Como Green | `#4A3826` | `(0.068, 0.038, 0.016)` |
| 4 | `interior_bakelite` | Steering wheel rim, knobs, radio bezel, gear knob | `#1A1714` | `(0.009, 0.007, 0.005)` |
| 5 | `interior_amber_glow` | All incandescent emissive surfaces | `#E8A838` | `(0.783, 0.374, 0.036)` |

## Godot material targets

| Resource | Albedo | Roughness | Metalness | Notes |
|---|---|---|---|---|
| `van_interior_dash_painted.tres` | `interior_dash_body` | 0.70 | 0.0 | Same paint as exterior lower, dimmed for cabin shadow |
| `van_interior_metal_trim.tres` | `vw_roundel_chrome` (reuse from exterior) | 0.35 | 0.9 | Window frames, interior chrome bright trim |
| `van_interior_headliner.tres` | `interior_headliner` | 0.95 | 0.0 | Lambertian cloth — no specular |
| `van_interior_seat.tres` | `interior_seat_vinyl` | 0.55 | 0.0 | Slight anisotropy along seam direction if seam normal map is authored |

## Dashboard metal surfaces — 3 wear states

### Clean
- Albedo: `interior_dash_body` (#2D4A45)
- Roughness: 0.65 — interior paint slightly less polished than exterior
- Metalness: 0.0

### Worn (default)
- Albedo: same + scuffing at high-contact points (door arm rests, dash centre near radio)
- Roughness: 0.75
- Metalness: 0.0

### Damaged
- Albedo: scuff marks exposing primer; minor surface rust at lower door corners from rain intrusion
- Roughness: 0.85
- Metalness: 0.0

Interior metal reads noticeably darker than exterior same-colour paint — cabin shadow means the in-engine ambient contribution is significantly lower than exterior sky ambient.

## Bakelite plastics — 3 wear states

Steering wheel rim (ivory-cream), steering column switches, gear knob, radio knobs, dashboard switches, glove box latch, door pulls, window winder handles, ashtray flap.

Two bakelite colours:
- **Black bakelite**: `interior_bakelite` (#1A1714) — near-black with warm brown undertone
- **Ivory bakelite** (steering wheel rim): `#E4DFC8` — period cream

| State | Roughness | Notes |
|---|---|---|
| Clean | 0.40 | Moderate gloss — bakelite has more sheen than modern plastic |
| Worn (default) | 0.55 | Black bakelite browns slightly; ivory items yellow |
| Damaged | 0.65 | Cracks showing lighter interior; oil-stain darkening at high-use knobs |

Bakelite is warmer and more tactile than modern plastic. Avoid plastic-y sheen — this is a proto-polymer.

## Headliner

Pale cream Masonite-backed cloth (`interior_headliner`, `#E8DDBF`). Spans the cabin ceiling between the 8 skylights. The headliner is the single largest warm-value surface in the interior. Together with the amber glow, it defines the "sanctuary" read when parked in dark forest.

Roughness: 0.95 (essentially Lambertian). No anisotropy. No specular.

## Seat upholstery — 3 wear states

Default: Como Green period vinyl (`interior_seat_vinyl`, `#4A3826`). Reads warm brown in normal light, not distinctly green except under strong neutral illumination.

| State | Albedo | Roughness | Notes |
|---|---|---|
| Clean | `interior_seat_vinyl` | 0.55 | Slight anisotropy along seam |
| Worn (default) | Darker at seat bolsters from hand and body oils | 0.65 | |
| Damaged | Cracked vinyl with white foam showing through splits | 0.70 | |

Headliner worn state: slightly yellowed (`#D8CFA8`). Headliner damaged state: stained yellow-brown from smoke/sun.

Period-correct seat vinyl alternates (confirm against TheSamba.com upholstery archive before final authoring):

| Factory code | Approx hex | Paired exterior |
|---|---|---|
| Como Green (default) | `#4A3826` | Option B (Turquoise/White) |
| Mesa Brown | `#5C4428` | Option A (Red/Beige) |
| Alabaster | `#C9B896` | Option C (Pearl White/Mouse Grey) |
| Chestnut | `#6B4A2E` | Multiple |

## Amber glow — emissive roles and energy targets

`interior_amber_glow` (`#E8A838`, 2700K tungsten equivalent) serves four distinct emissive roles. **Keep emission energy LOW** — the goal is "warm amber presence" not "bright glow":

| Role | Node type | Energy range | Active when |
|---|---|---|---|
| Dome light | `OmniLight3D`, ~3 m range | 0.4–0.8 | `dome_light_control.gd` toggled on |
| Gauge illumination | Emissive material on gauge faces | 0.3–0.6 | Headlights on at night |
| Dashboard indicator lamps | Emissive material on indicator spots | 0.5–1.0 (0 when inactive) | Respective system active |
| Radio dial illumination | Emissive material on frequency scale | 0.2–0.4 | Radio powered on |

The moodboard interior warm glow visible through the windshield and side windows from outside is primarily dome light + reflected light off the cream headliner. Test with dome light ON and OFF under Petrifold ambient — this is where the amber glow does its heaviest lifting (exterior chroma is desaturated; amber is the only warm point in the scene).

## Bed slats / cargo area

Floor slats in the rear cargo area. Unfinished or oiled wood with visible grain.

| State | Roughness | Metalness | Notes |
|---|---|---|---|
| Clean | 0.50–0.65 | 0.0 | Natural wood grain readable |
| Worn | 0.60–0.70 | 0.0 | Scuffing, dark oil staining at load edges |
| Damaged | 0.65–0.75 | 0.0 | Splits, exposed raw wood at break points |

## Related

- [[Systems/Vehicle — Dashboard]] — dashboard design intent and diegetic HUD
- [[Systems/Vehicle — Samba]] — implementation context
- [[Vehicle Palette Materials and Dimensions Discovery]] — full interior layout, control sequence, speaker routing, amber glow emissive values (authoritative Discovery note)
- [[Vehicle Interaction and Physics Implementation Discovery]] — keybinds, 3-speaker routing, emissive energy values
- [[Art/Vehicle — Samba Exterior]] — exterior palette (interior_dash_body is shadow-shifted hero_teal_lower)
- [[Art/Vehicle — Samba Acceptance Checklist]] — Phase 3 pass/fail criteria
- [[Art]] — folder MOC
- [[Vehicle — Domain MOC]] — domain MOC

Controlled tag vocabulary (as read):
type/*:
- `type/code` — Code architecture, autoloads, conventions, tooling. Carries `code-refs:`. (e.g. `Code/Autoloads — Disturbance.md`)
- `type/decision` — Architectural or design decision made by an agent during a session. Written to `docs/vault/Decisions/`. (Agent notes only — spec 080.)
- `type/design` — Design intent, player-facing concepts, world lore. (e.g. `Design/World Model.md`)
- `type/discovery` — Non-obvious constraint, gap, or conflict found by an agent during a session. Written to `docs/vault/Discoveries/`. (Agent notes only — spec 080.)
- `type/moc` — Map of Content at any of three tiers (folder / domain / concept). (e.g. `Audio.md`)
- `type/principle` — Governance and constitutional notes. Non-negotiable rules. (e.g. `Governance/Constitution.md`)
- `type/reference` — Glossary, decision log, open questions, epics. (e.g. `Reference/Glossary.md`)
- `type/session-log` — Session activity log; permanent audit trail. Written to `docs/vault/Sessions/`. Append-only, never pruned. (Agent notes only — spec 080.)
- `type/spec` — Spec document at `docs/vault/Specs/NNN Title/spec.md`. Carries `spec-refs:`. (e.g. `Specs/047 Car Radio/spec.md`)
- `type/system` — A bounded subsystem with implementation. Carries `code-refs`, `spec-refs`, `implements:` frontmatter. (e.g. `Systems/Audio — Car Radio.md`)
- `type/vision` — Strategic / vision-layer decision. Written to `docs/vault/Vision/`. Human-authored or agent-proposed with human ratification before promotion to `status: reviewed`. (Per triage #3 — spec 133 autonomous-company redesign.)
domain/*:
- `domain/anomalies` — Anomaly taxonomy, individual anomaly systems, spawn, behavior
- `domain/art` — Visual direction, palettes, references, asset pipeline
- `domain/audio` — Audio systems: world ambient, radio, transmissions, buses, pipeline
- `domain/autonomous-company` — Autonomous company v0.1 experiment: Slack infra, persona middleware, Letta integration, restart recovery
- `domain/build` — Build system, packaging, export, release automation
- `domain/governance` — Constitution, phased spec, policies
- `domain/infrastructure` — Infrastructure provisioning: CI/CD, hosting, deployment tooling, secrets management
- `domain/narrative` — Tone, horror register, forest transmissions narrative, Gary/KTLK
- `domain/player` — Player mode, input, controls, camera, exit/entry
- `domain/systems` — Cross-cutting system architecture and integration work
- `domain/tooling` — Build, CI, observer, TTS pipeline, dev-time tools
- `domain/vehicle` — The Samba: vehicle physics, dashboard, damage, panels
- `domain/world` — World model, biomes, terrain, procedural generation, weather
status/*:
- `status/canonical` — Fully authoritative; promoted by humans only. Highest trust. (Agent notes only — spec 080.)
- `status/draft` — Authoring in progress, not yet verified
- `status/reviewed` — Agent-created note verified against codebase within its creating session. Eligible for auto-injection in subsequent task dispatches. (Agent notes only — spec 080.)
- `status/stale` — Known out of date; cannot update immediately. Pairs with `> [!warning] STALE — needs update` callout.
- `status/superseded` — Replaced by another note. Terminal state. Pairs with `> [!warning] SUPERSEDED` callout.
- `status/wip` — Stable but under active revision
layer/*:
- `layer/content` — Content assets (audio, models, textures, audio provenance)
- `layer/gdext` — gdext wrapper layer (`rust/gdext-wrapper/`)
- `layer/gdscript` — GDScript (Godot scene-tier logic)
- `layer/infra` — Build, CI, deployment infrastructure
- `layer/python` — Python development tooling (`tools/`)
- `layer/rust-core` — Engine-agnostic Rust core (`rust/rust-core/`)
concept/*:
- `concept/biome` — Biome-reactive behavior across systems
- `concept/contamination` — Across-runs panel and garage degradation; the slow-horror mechanic that doesn't reset with the world
- `concept/diegetic` — Diegetic audio / UI / world-sourced design
- `concept/disturbance` — The disturbance mechanic thread (Article X)
- `concept/ephemeral-world` — Run-reset, transient worlds (Article IV Rules 6–7)
- `concept/governance` — Constitutional and governance concepts
- `concept/horror` — Horror register and dread design
- `concept/procedural` — Procedural generation, seed determinism
- `concept/rendering` — Visual rendering quality, shader correctness, Terrain3D integration, mesh fidelity, LOD, Z-fighting
- `concept/terrain` — Terrain generation, heightmap, Terrain3D regions, roughness, playability constraints
ember's answer for tag_assignment-art-vehicle-samba-interior, type/referenceP(true) placed on the no, unsure, and yes zones.nounsureyesgold: yesP = 0.04

tag_assignment-sessions-persona-thread-echo-and-vault-mcp-debugging-may-31-2026: domain/tooling

Tag assignment · dev
Gold
The note calls for `domain/tooling`: Build, CI, observer, TTS pipeline, dev-time tools (True)
ember
The note has no reason to carry `domain/tooling` (False)
Signal
P(true) 0.13 (no)
Kit outcome
acted on a wrong answer
Why this gold label
Mined from Sessions/Persona Thread Echo and Vault MCP Debugging — May 31 2026.md at 692f4bb58b7f62105aeb73fba8dfee12bfdecd53; gold is the note's own vocabulary tags.
Persona Thread Echo and Vault MCP Debugging — May 31 2026

Debugging session spanning May 31 2026. Five interconnected issues were diagnosed and fixed across the persona runtime.

## Issues Found

### 1. GTM Not Responding in Thread (coordinator.py nested correlation_id access)

`dispatch_route_to()` returns `{"ok": true, "result": {"correlation_id": "..."}}` but `coordinator_response_hook` was reading `result.get("correlation_id", "")` at the top level — always empty. Same bug existed in `gtm.py`.

**Fix**: Access `result["result"]["correlation_id"]`.

### 2. Thread Mapping Race — Save After Dispatch

Even after fixing the correlation_id extraction, the mapping was saved to disk *after* `dispatch_route_to()` sent the inter-agent message to GTM's Letta agent. GTM's poller detected the message before the mapping existed on disk.

**Fix**: Generate correlation_id and call `save_threads()` *before* `dispatch_route_to()`. Pass the pre-generated correlation_id into the dispatch call.

### 3. Vault MCP Server Not Returning Results (mcpvault CLI + Docker path)

Two problems:
- The MCP manifest used `--vault-path /repo/docs/vault` but mcpvault v0.11.0 takes the vault path as a positional argument, not a `--vault-path` flag.
- The Docker container mounts the repo at `/repo` — paths like `/Users/joshburt/...` are not visible inside the container. The correct path is `/repo/docs/vault`.

**Fix**: Changed manifest args to `["-y", "@bitbonsai/mcpvault@latest", "/repo/docs/vault"]` and re-registered the MCP server.

### 4. GTM Not Using Vault MCP Tools (send_to_letta response ordering)

`send_to_letta()` returned the *first* `assistant_message` from the Letta response. When the LLM called a tool, the message sequence was: preliminary text → tool call → tool result → final response. The preliminary text was returned instead of the final draft.

**Fix**: Return the *last* `assistant_message` after iterating all messages.

### 5. GTM Responding Twice (dual-path dedup gap)

The same Slack message reached GTM through two independent paths — its own Socket Mode app_mention handler and the coordinator's human injection. No shared dedup mechanism existed.

**Fix**: Added shared dedup state in `slack_echo.py` (spec 007). Socket Mode handler checks Slack `ts`, human injection handler checks Letta `msg_id`.

## Key Files Touched

- `personas/coordinator.py` — correlation_id extraction + save-before-dispatch reorder
- `personas/gtm.py` — same fixes + silent except logging
- `personas/letta_bridge.py` — last assistant_message instead of first
- `personas/prompt.py` — manifest-driven capabilities block
- `personas/runtime.py` — strengthened processing prompt, dedup checks
- `personas/slack_echo.py` — dedup state + helpers
- `docs/vault/Reference/Autonomous Company/trusted_agent_mcp_manifest.json` — vault path args
- Various vault notes — fixed 4 broken wikilinks (spec renumbering)

## PRs

- #469: Persona thread echo race, vault MCP, tool response extraction, capabilities block, wikilink fixes
- #470: Message deduplication (spec 007)

Controlled tag vocabulary (as read):
type/*:
- `type/code` — Code architecture, autoloads, conventions, tooling. Carries `code-refs:`. (e.g. `Code/Autoloads — Disturbance.md`)
- `type/decision` — Architectural or design decision made by an agent during a session. Written to `docs/vault/Decisions/`. (Agent notes only — spec 080.)
- `type/design` — Design intent, player-facing concepts, world lore. (e.g. `Design/World Model.md`)
- `type/discovery` — Non-obvious constraint, gap, or conflict found by an agent during a session. Written to `docs/vault/Discoveries/`. (Agent notes only — spec 080.)
- `type/moc` — Map of Content at any of three tiers (folder / domain / concept). (e.g. `Audio.md`)
- `type/principle` — Governance and constitutional notes. Non-negotiable rules. (e.g. `Governance/Constitution.md`)
- `type/reference` — Glossary, decision log, open questions, epics. (e.g. `Reference/Glossary.md`)
- `type/session-log` — Session activity log; permanent audit trail. Written to `docs/vault/Sessions/`. Append-only, never pruned. (Agent notes only — spec 080.)
- `type/spec` — Spec document at `docs/vault/Specs/NNN Title/spec.md`. Carries `spec-refs:`. (e.g. `Specs/047 Car Radio/spec.md`)
- `type/system` — A bounded subsystem with implementation. Carries `code-refs`, `spec-refs`, `implements:` frontmatter. (e.g. `Systems/Audio — Car Radio.md`)
- `type/vision` — Strategic / vision-layer decision. Written to `docs/vault/Vision/`. Human-authored or agent-proposed with human ratification before promotion to `status: reviewed`. (Per triage #3 — spec 133 autonomous-company redesign.)
domain/*:
- `domain/anomalies` — Anomaly taxonomy, individual anomaly systems, spawn, behavior
- `domain/art` — Visual direction, palettes, references, asset pipeline
- `domain/audio` — Audio systems: world ambient, radio, transmissions, buses, pipeline
- `domain/autonomous-company` — Autonomous company v0.1 experiment: Slack infra, persona middleware, Letta integration, restart recovery
- `domain/build` — Build system, packaging, export, release automation
- `domain/governance` — Constitution, phased spec, policies
- `domain/infrastructure` — Infrastructure provisioning: CI/CD, hosting, deployment tooling, secrets management
- `domain/narrative` — Tone, horror register, forest transmissions narrative, Gary/KTLK
- `domain/player` — Player mode, input, controls, camera, exit/entry
- `domain/systems` — Cross-cutting system architecture and integration work
- `domain/tooling` — Build, CI, observer, TTS pipeline, dev-time tools
- `domain/vehicle` — The Samba: vehicle physics, dashboard, damage, panels
- `domain/world` — World model, biomes, terrain, procedural generation, weather
status/*:
- `status/canonical` — Fully authoritative; promoted by humans only. Highest trust. (Agent notes only — spec 080.)
- `status/draft` — Authoring in progress, not yet verified
- `status/reviewed` — Agent-created note verified against codebase within its creating session. Eligible for auto-injection in subsequent task dispatches. (Agent notes only — spec 080.)
- `status/stale` — Known out of date; cannot update immediately. Pairs with `> [!warning] STALE — needs update` callout.
- `status/superseded` — Replaced by another note. Terminal state. Pairs with `> [!warning] SUPERSEDED` callout.
- `status/wip` — Stable but under active revision
layer/*:
- `layer/content` — Content assets (audio, models, textures, audio provenance)
- `layer/gdext` — gdext wrapper layer (`rust/gdext-wrapper/`)
- `layer/gdscript` — GDScript (Godot scene-tier logic)
- `layer/infra` — Build, CI, deployment infrastructure
- `layer/python` — Python development tooling (`tools/`)
- `layer/rust-core` — Engine-agnostic Rust core (`rust/rust-core/`)
concept/*:
- `concept/biome` — Biome-reactive behavior across systems
- `concept/contamination` — Across-runs panel and garage degradation; the slow-horror mechanic that doesn't reset with the world
- `concept/diegetic` — Diegetic audio / UI / world-sourced design
- `concept/disturbance` — The disturbance mechanic thread (Article X)
- `concept/ephemeral-world` — Run-reset, transient worlds (Article IV Rules 6–7)
- `concept/governance` — Constitutional and governance concepts
- `concept/horror` — Horror register and dread design
- `concept/procedural` — Procedural generation, seed determinism
- `concept/rendering` — Visual rendering quality, shader correctness, Terrain3D integration, mesh fidelity, LOD, Z-fighting
- `concept/terrain` — Terrain generation, heightmap, Terrain3D regions, roughness, playability constraints
ember's answer for tag_assignment-sessions-persona-thread-echo-and-vault-mcp-debugging-may-31-2026, domain/toolingP(true) placed on the no, unsure, and yes zones.nounsureyesgold: yesP = 0.13

tag_assignment-sessions-persona-thread-echo-and-vault-mcp-debugging-may-31-2026: type/code

Tag assignment · dev
Gold
The note has no reason to carry `type/code` (False)
ember
The note calls for `type/code`: Code architecture, autoloads, conventions, tooling. Carries `code-refs:`. (e.g. `Code/Autoloads — Disturbance.md`) (True)
Signal
P(true) 0.56 (unsure)
Kit outcome
deferred: treated as unsure
Why this gold label
Mined from Sessions/Persona Thread Echo and Vault MCP Debugging — May 31 2026.md at 692f4bb58b7f62105aeb73fba8dfee12bfdecd53; gold is the note's own vocabulary tags.
Persona Thread Echo and Vault MCP Debugging — May 31 2026

Debugging session spanning May 31 2026. Five interconnected issues were diagnosed and fixed across the persona runtime.

## Issues Found

### 1. GTM Not Responding in Thread (coordinator.py nested correlation_id access)

`dispatch_route_to()` returns `{"ok": true, "result": {"correlation_id": "..."}}` but `coordinator_response_hook` was reading `result.get("correlation_id", "")` at the top level — always empty. Same bug existed in `gtm.py`.

**Fix**: Access `result["result"]["correlation_id"]`.

### 2. Thread Mapping Race — Save After Dispatch

Even after fixing the correlation_id extraction, the mapping was saved to disk *after* `dispatch_route_to()` sent the inter-agent message to GTM's Letta agent. GTM's poller detected the message before the mapping existed on disk.

**Fix**: Generate correlation_id and call `save_threads()` *before* `dispatch_route_to()`. Pass the pre-generated correlation_id into the dispatch call.

### 3. Vault MCP Server Not Returning Results (mcpvault CLI + Docker path)

Two problems:
- The MCP manifest used `--vault-path /repo/docs/vault` but mcpvault v0.11.0 takes the vault path as a positional argument, not a `--vault-path` flag.
- The Docker container mounts the repo at `/repo` — paths like `/Users/joshburt/...` are not visible inside the container. The correct path is `/repo/docs/vault`.

**Fix**: Changed manifest args to `["-y", "@bitbonsai/mcpvault@latest", "/repo/docs/vault"]` and re-registered the MCP server.

### 4. GTM Not Using Vault MCP Tools (send_to_letta response ordering)

`send_to_letta()` returned the *first* `assistant_message` from the Letta response. When the LLM called a tool, the message sequence was: preliminary text → tool call → tool result → final response. The preliminary text was returned instead of the final draft.

**Fix**: Return the *last* `assistant_message` after iterating all messages.

### 5. GTM Responding Twice (dual-path dedup gap)

The same Slack message reached GTM through two independent paths — its own Socket Mode app_mention handler and the coordinator's human injection. No shared dedup mechanism existed.

**Fix**: Added shared dedup state in `slack_echo.py` (spec 007). Socket Mode handler checks Slack `ts`, human injection handler checks Letta `msg_id`.

## Key Files Touched

- `personas/coordinator.py` — correlation_id extraction + save-before-dispatch reorder
- `personas/gtm.py` — same fixes + silent except logging
- `personas/letta_bridge.py` — last assistant_message instead of first
- `personas/prompt.py` — manifest-driven capabilities block
- `personas/runtime.py` — strengthened processing prompt, dedup checks
- `personas/slack_echo.py` — dedup state + helpers
- `docs/vault/Reference/Autonomous Company/trusted_agent_mcp_manifest.json` — vault path args
- Various vault notes — fixed 4 broken wikilinks (spec renumbering)

## PRs

- #469: Persona thread echo race, vault MCP, tool response extraction, capabilities block, wikilink fixes
- #470: Message deduplication (spec 007)

Controlled tag vocabulary (as read):
type/*:
- `type/code` — Code architecture, autoloads, conventions, tooling. Carries `code-refs:`. (e.g. `Code/Autoloads — Disturbance.md`)
- `type/decision` — Architectural or design decision made by an agent during a session. Written to `docs/vault/Decisions/`. (Agent notes only — spec 080.)
- `type/design` — Design intent, player-facing concepts, world lore. (e.g. `Design/World Model.md`)
- `type/discovery` — Non-obvious constraint, gap, or conflict found by an agent during a session. Written to `docs/vault/Discoveries/`. (Agent notes only — spec 080.)
- `type/moc` — Map of Content at any of three tiers (folder / domain / concept). (e.g. `Audio.md`)
- `type/principle` — Governance and constitutional notes. Non-negotiable rules. (e.g. `Governance/Constitution.md`)
- `type/reference` — Glossary, decision log, open questions, epics. (e.g. `Reference/Glossary.md`)
- `type/session-log` — Session activity log; permanent audit trail. Written to `docs/vault/Sessions/`. Append-only, never pruned. (Agent notes only — spec 080.)
- `type/spec` — Spec document at `docs/vault/Specs/NNN Title/spec.md`. Carries `spec-refs:`. (e.g. `Specs/047 Car Radio/spec.md`)
- `type/system` — A bounded subsystem with implementation. Carries `code-refs`, `spec-refs`, `implements:` frontmatter. (e.g. `Systems/Audio — Car Radio.md`)
- `type/vision` — Strategic / vision-layer decision. Written to `docs/vault/Vision/`. Human-authored or agent-proposed with human ratification before promotion to `status: reviewed`. (Per triage #3 — spec 133 autonomous-company redesign.)
domain/*:
- `domain/anomalies` — Anomaly taxonomy, individual anomaly systems, spawn, behavior
- `domain/art` — Visual direction, palettes, references, asset pipeline
- `domain/audio` — Audio systems: world ambient, radio, transmissions, buses, pipeline
- `domain/autonomous-company` — Autonomous company v0.1 experiment: Slack infra, persona middleware, Letta integration, restart recovery
- `domain/build` — Build system, packaging, export, release automation
- `domain/governance` — Constitution, phased spec, policies
- `domain/infrastructure` — Infrastructure provisioning: CI/CD, hosting, deployment tooling, secrets management
- `domain/narrative` — Tone, horror register, forest transmissions narrative, Gary/KTLK
- `domain/player` — Player mode, input, controls, camera, exit/entry
- `domain/systems` — Cross-cutting system architecture and integration work
- `domain/tooling` — Build, CI, observer, TTS pipeline, dev-time tools
- `domain/vehicle` — The Samba: vehicle physics, dashboard, damage, panels
- `domain/world` — World model, biomes, terrain, procedural generation, weather
status/*:
- `status/canonical` — Fully authoritative; promoted by humans only. Highest trust. (Agent notes only — spec 080.)
- `status/draft` — Authoring in progress, not yet verified
- `status/reviewed` — Agent-created note verified against codebase within its creating session. Eligible for auto-injection in subsequent task dispatches. (Agent notes only — spec 080.)
- `status/stale` — Known out of date; cannot update immediately. Pairs with `> [!warning] STALE — needs update` callout.
- `status/superseded` — Replaced by another note. Terminal state. Pairs with `> [!warning] SUPERSEDED` callout.
- `status/wip` — Stable but under active revision
layer/*:
- `layer/content` — Content assets (audio, models, textures, audio provenance)
- `layer/gdext` — gdext wrapper layer (`rust/gdext-wrapper/`)
- `layer/gdscript` — GDScript (Godot scene-tier logic)
- `layer/infra` — Build, CI, deployment infrastructure
- `layer/python` — Python development tooling (`tools/`)
- `layer/rust-core` — Engine-agnostic Rust core (`rust/rust-core/`)
concept/*:
- `concept/biome` — Biome-reactive behavior across systems
- `concept/contamination` — Across-runs panel and garage degradation; the slow-horror mechanic that doesn't reset with the world
- `concept/diegetic` — Diegetic audio / UI / world-sourced design
- `concept/disturbance` — The disturbance mechanic thread (Article X)
- `concept/ephemeral-world` — Run-reset, transient worlds (Article IV Rules 6–7)
- `concept/governance` — Constitutional and governance concepts
- `concept/horror` — Horror register and dread design
- `concept/procedural` — Procedural generation, seed determinism
- `concept/rendering` — Visual rendering quality, shader correctness, Terrain3D integration, mesh fidelity, LOD, Z-fighting
- `concept/terrain` — Terrain generation, heightmap, Terrain3D regions, roughness, playability constraints
ember's answer for tag_assignment-sessions-persona-thread-echo-and-vault-mcp-debugging-may-31-2026, type/codeP(true) placed on the no, unsure, and yes zones.nounsureyesgold: noP = 0.56

tag_assignment-systems-audio-overview: type/moc

Tag assignment · dev
Gold
The note has no reason to carry `type/moc` (False)
ember
The note calls for `type/moc`: Map of Content at any of three tiers (folder / domain / concept). (e.g. `Audio.md`) (True)
Signal
P(true) 0.64 (unsure)
Kit outcome
deferred: treated as unsure
Why this gold label
Mined from Systems/Audio — Overview.md at 692f4bb58b7f62105aeb73fba8dfee12bfdecd53; gold is the note's own vocabulary tags.
Audio — Overview

The top-level architecture of Old Growth's audio systems. Audio is the primary horror delivery mechanism in Old Growth — the forest communicates through sound before it communicates through visuals. This note is the high-level map; [[Audio — World Audio]] carries the full per-subsystem specification.

## Overview

Sound design defines the horror experience (World Bible §16). Every anomaly is heard before it is seen. Every biome has a distinct acoustic identity. The disturbance state manifests audibly long before any visual cue. Silence is itself a weapon — the Petrifold and The Silence anomaly both weaponize audio absence.

## Design Intent — Five Pillars

1. **Audio-first danger communication** — every anomaly and enemy has an identifiable audio signature that arrives before visual contact is possible
2. **Layered atmospheric density** — no biome is a single loop; each is a stack of independent layers mixed dynamically
3. **Interior/exterior as two distinct worlds** — the van's cab is a sanctuary expressed in audio; stepping outside removes that protection audibly
4. **Disturbance as a musical arc** — ambient audio evolves across the four disturbance states, building dread without UI narration
5. **Silence as a weapon** — absence of expected sound is the most unsettling signal

## Key Decisions

### Planned Bus Architecture (constitution Appendix A)

The planned audio bus architecture routes through seven buses. All audio routes through these — never Master directly.

| Bus | Purpose | Key Effects |
|-----|---------|-------------|
| Master | Final mix output | — |
| Ambience | Biome ambient layers, weather beds | `AudioEffectReverb` (large room), `AudioEffectFilter` (low-pass for interior occlusion) |
| Proximity | Positional anomaly and creature audio (3D spatialized) | `AudioEffectReverb` (matched to biome), distance-based attenuation |
| Interior | Audio heard from inside the Samba — muffled, low-pass filtered | `AudioEffectFilter` low-pass @ 800 Hz, resonance 0.3; `AudioEffectReverb` (small room) |
| Horror | Stingers, tension drones, disturbance audio cues, The Storm, The Silence | No EQ — raw, present, unprocessed |
| Radio | Clean radio broadcast (DJ, music, forest transmissions) | — |
| RadioDegraded | Degraded radio signal (static, interference, procedural audio) | — |

When the player is inside the Samba, `Ambience` and `Proximity` buses route through `Interior` (applying low-pass @ 800 Hz, resonance 0.3). When outside, they route directly to Master.

**Interior occlusion filter**: simulates the van's body mass absorbing high-frequency content from outside. Rain becomes a low thud. Wind drops out entirely. Creature sounds become muffled and distant. The bus sounds like safety.

> [!attention] CONFLICT
> **Planned architecture vs. current state**: Constitution Appendix A and this note describe 7 buses. As of spec 099, `src/default_bus_layout.tres` defines 5 buses: Master, Radio, RadioDegraded, VehicleSFX, SFX. The 4 buses required by the world audio system (Ambience, Proximity, Interior, Horror) are not yet present. [[111 Audio Bus Architecture]] gates this expansion and is a hard prerequisite for specs 104–110. Indexed in [[Conflicts]].

### Biome ambient system — four layers

Each biome runs four simultaneous ambient layers that crossfade independently:

| Layer | Description | Node Type |
|-------|-------------|-----------|
| L1 Bed | Foundational tonal bed — deepest, lowest, longest loop | `AudioStreamPlayer` → Ambience |
| L2 Wind | Wind and air movement through canopy | `AudioStreamPlayer` → Ambience |
| L3 Organic | Biome-specific organic sounds (creak, drip, spore, crack) | `AudioStreamPlayer` → Ambience |
| L4 Detail | Sparse randomized events (bird, branch, footstep echo) | `AudioStreamPlayer3D` (randomized positions) → Proximity |

All layers except L4 are non-positional (ambient surround). L4 is spatialized to give the world directionality and suggest life (or absence of life) in specific directions. A weather change might swap only the wind layer while canopy creak continues uninterrupted.

### Radio as separate system

Dedicated Radio + RadioDegraded buses with its own content pipeline — see [[Audio — Car Radio]] and [[Audio — Radio Stations]].

### Four-state disturbance arc

Audio evolves continuously across the four disturbance states (Calm → Uneasy → Agitated → Storm) — see [[Disturbance System]] and [[The Disturbance Thread]]. Stinger cues mark threshold crossings on the Horror bus. The final state (Storm = 85) spawns the Storm weather event — see [[The Player Causes the Storm]].

### Silence as weapon

Two systems weaponize audio absence:
- **The Petrifold** biome has no wind layer. L1 is near-silent. L3 cracks are isolated events with long reverb tails dying into silence.
- **The Silence anomaly** hard-cuts ALL environmental audio on zone entry. Only the player's heartbeat remains. `Ambience` and `Proximity` buses are muted entirely when inside a Silence zone.

### Gain staging and LUFS compliance

Per Article XII-D: audio levels set at source before bus mixing. Each bus has headroom for the master bus. All shipped audio is normalized to consistent LUFS target documented in the audio spec family. Sub-Nyquist audio (<44.1 kHz) is never shipped.

### Godot implementation

Audio primitives are entirely Godot native (`AudioStreamPlayer`, `AudioStreamPlayer3D`, `AudioBus`, `AudioEffect*`) — no external plugin dependencies. The approved bus layout lives in `src/default_bus_layout.tres`. Biome-specific audio content lives in `src/assets/audio/` (submodule). The top-level orchestration is `world_audio_manager.gd` (see [[Audio — World Audio]] for full scene structure).

## Test Coverage

- `src/tests/unit/test_bus_radio.gd`, `test_radio_channel.gd` — radio runtime + per-channel behavior
- `src/tests/unit/test_engine_audio.gd` — engine audio
- `src/tests/unit/test_disturbance.gd` — disturbance autoload (upstream of audio arc)
- Individual subsystem tests as listed on per-subsystem notes ([[Audio — Car Radio]], etc.)

## Related

- [[Audio — World Audio]] — full per-subsystem specifications (biome audio, weather, disturbance arc, Storm, anomaly audio, Hollows, interior/exterior mix, footsteps, vehicle audio, player audio, interaction audio, prop audio, combat audio, garage audio, exit gate audio, UI audio, scene structure)
- [[Audio — Buses]] — current bus layout, effect chains, and the pending Ambience/Proximity/Interior/Horror expansion
- [[Audio — Car Radio]] — radio signal and degradation
- [[Audio — Pipeline]] — dev-time audio processing pipeline
- [[Audio — Radio Stations]] — per-station content
- [[Audio — Forest Transmissions]] — what comes through after signal dies
- [[Audio — Domain MOC]] — domain MOC
- [[Diegesis Thread]] — audio is fundamentally diegetic
- [[The Disturbance Thread]] — audio arc tracks disturbance state
- [[Constitution]] — Article XII-D, Appendix A bus architecture

### Phase 4 Implementation Specs

- [[111 Audio Bus Architecture]] — prerequisite for all world audio specs
- [[104 Biome Ambient Audio]], [[105 Disturbance Arc Audio]], [[106 Anomaly Audio Signatures]]
- [[107 Storm Audio System]], [[108 Garage And Exit Gate Audio]], [[109 Weather Bed Layer]]
- [[110 Time Of Day Audio Variants]], [[112 Environmental Presence System]], [[113 Player And World Interaction Audio]]

Controlled tag vocabulary (as read):
type/*:
- `type/code` — Code architecture, autoloads, conventions, tooling. Carries `code-refs:`. (e.g. `Code/Autoloads — Disturbance.md`)
- `type/decision` — Architectural or design decision made by an agent during a session. Written to `docs/vault/Decisions/`. (Agent notes only — spec 080.)
- `type/design` — Design intent, player-facing concepts, world lore. (e.g. `Design/World Model.md`)
- `type/discovery` — Non-obvious constraint, gap, or conflict found by an agent during a session. Written to `docs/vault/Discoveries/`. (Agent notes only — spec 080.)
- `type/moc` — Map of Content at any of three tiers (folder / domain / concept). (e.g. `Audio.md`)
- `type/principle` — Governance and constitutional notes. Non-negotiable rules. (e.g. `Governance/Constitution.md`)
- `type/reference` — Glossary, decision log, open questions, epics. (e.g. `Reference/Glossary.md`)
- `type/session-log` — Session activity log; permanent audit trail. Written to `docs/vault/Sessions/`. Append-only, never pruned. (Agent notes only — spec 080.)
- `type/spec` — Spec document at `docs/vault/Specs/NNN Title/spec.md`. Carries `spec-refs:`. (e.g. `Specs/047 Car Radio/spec.md`)
- `type/system` — A bounded subsystem with implementation. Carries `code-refs`, `spec-refs`, `implements:` frontmatter. (e.g. `Systems/Audio — Car Radio.md`)
- `type/vision` — Strategic / vision-layer decision. Written to `docs/vault/Vision/`. Human-authored or agent-proposed with human ratification before promotion to `status: reviewed`. (Per triage #3 — spec 133 autonomous-company redesign.)
domain/*:
- `domain/anomalies` — Anomaly taxonomy, individual anomaly systems, spawn, behavior
- `domain/art` — Visual direction, palettes, references, asset pipeline
- `domain/audio` — Audio systems: world ambient, radio, transmissions, buses, pipeline
- `domain/autonomous-company` — Autonomous company v0.1 experiment: Slack infra, persona middleware, Letta integration, restart recovery
- `domain/build` — Build system, packaging, export, release automation
- `domain/governance` — Constitution, phased spec, policies
- `domain/infrastructure` — Infrastructure provisioning: CI/CD, hosting, deployment tooling, secrets management
- `domain/narrative` — Tone, horror register, forest transmissions narrative, Gary/KTLK
- `domain/player` — Player mode, input, controls, camera, exit/entry
- `domain/systems` — Cross-cutting system architecture and integration work
- `domain/tooling` — Build, CI, observer, TTS pipeline, dev-time tools
- `domain/vehicle` — The Samba: vehicle physics, dashboard, damage, panels
- `domain/world` — World model, biomes, terrain, procedural generation, weather
status/*:
- `status/canonical` — Fully authoritative; promoted by humans only. Highest trust. (Agent notes only — spec 080.)
- `status/draft` — Authoring in progress, not yet verified
- `status/reviewed` — Agent-created note verified against codebase within its creating session. Eligible for auto-injection in subsequent task dispatches. (Agent notes only — spec 080.)
- `status/stale` — Known out of date; cannot update immediately. Pairs with `> [!warning] STALE — needs update` callout.
- `status/superseded` — Replaced by another note. Terminal state. Pairs with `> [!warning] SUPERSEDED` callout.
- `status/wip` — Stable but under active revision
layer/*:
- `layer/content` — Content assets (audio, models, textures, audio provenance)
- `layer/gdext` — gdext wrapper layer (`rust/gdext-wrapper/`)
- `layer/gdscript` — GDScript (Godot scene-tier logic)
- `layer/infra` — Build, CI, deployment infrastructure
- `layer/python` — Python development tooling (`tools/`)
- `layer/rust-core` — Engine-agnostic Rust core (`rust/rust-core/`)
concept/*:
- `concept/biome` — Biome-reactive behavior across systems
- `concept/contamination` — Across-runs panel and garage degradation; the slow-horror mechanic that doesn't reset with the world
- `concept/diegetic` — Diegetic audio / UI / world-sourced design
- `concept/disturbance` — The disturbance mechanic thread (Article X)
- `concept/ephemeral-world` — Run-reset, transient worlds (Article IV Rules 6–7)
- `concept/governance` — Constitutional and governance concepts
- `concept/horror` — Horror register and dread design
- `concept/procedural` — Procedural generation, seed determinism
- `concept/rendering` — Visual rendering quality, shader correctness, Terrain3D integration, mesh fidelity, LOD, Z-fighting
- `concept/terrain` — Terrain generation, heightmap, Terrain3D regions, roughness, playability constraints
ember's answer for tag_assignment-systems-audio-overview, type/mocP(true) placed on the no, unsure, and yes zones.nounsureyesgold: noP = 0.64

tag_assignment-systems-audio-overview: type/system

Tag assignment · dev
Gold
The note calls for `type/system`: A bounded subsystem with implementation. Carries `code-refs`, `spec-refs`, `implements:` frontmatter. (e.g. `Systems/Audio — Car Radio.md`) (True)
ember
The note has no reason to carry `type/system` (False)
Signal
P(true) 0.13 (no)
Kit outcome
acted on a wrong answer
Why this gold label
Mined from Systems/Audio — Overview.md at 692f4bb58b7f62105aeb73fba8dfee12bfdecd53; gold is the note's own vocabulary tags.
Audio — Overview

The top-level architecture of Old Growth's audio systems. Audio is the primary horror delivery mechanism in Old Growth — the forest communicates through sound before it communicates through visuals. This note is the high-level map; [[Audio — World Audio]] carries the full per-subsystem specification.

## Overview

Sound design defines the horror experience (World Bible §16). Every anomaly is heard before it is seen. Every biome has a distinct acoustic identity. The disturbance state manifests audibly long before any visual cue. Silence is itself a weapon — the Petrifold and The Silence anomaly both weaponize audio absence.

## Design Intent — Five Pillars

1. **Audio-first danger communication** — every anomaly and enemy has an identifiable audio signature that arrives before visual contact is possible
2. **Layered atmospheric density** — no biome is a single loop; each is a stack of independent layers mixed dynamically
3. **Interior/exterior as two distinct worlds** — the van's cab is a sanctuary expressed in audio; stepping outside removes that protection audibly
4. **Disturbance as a musical arc** — ambient audio evolves across the four disturbance states, building dread without UI narration
5. **Silence as a weapon** — absence of expected sound is the most unsettling signal

## Key Decisions

### Planned Bus Architecture (constitution Appendix A)

The planned audio bus architecture routes through seven buses. All audio routes through these — never Master directly.

| Bus | Purpose | Key Effects |
|-----|---------|-------------|
| Master | Final mix output | — |
| Ambience | Biome ambient layers, weather beds | `AudioEffectReverb` (large room), `AudioEffectFilter` (low-pass for interior occlusion) |
| Proximity | Positional anomaly and creature audio (3D spatialized) | `AudioEffectReverb` (matched to biome), distance-based attenuation |
| Interior | Audio heard from inside the Samba — muffled, low-pass filtered | `AudioEffectFilter` low-pass @ 800 Hz, resonance 0.3; `AudioEffectReverb` (small room) |
| Horror | Stingers, tension drones, disturbance audio cues, The Storm, The Silence | No EQ — raw, present, unprocessed |
| Radio | Clean radio broadcast (DJ, music, forest transmissions) | — |
| RadioDegraded | Degraded radio signal (static, interference, procedural audio) | — |

When the player is inside the Samba, `Ambience` and `Proximity` buses route through `Interior` (applying low-pass @ 800 Hz, resonance 0.3). When outside, they route directly to Master.

**Interior occlusion filter**: simulates the van's body mass absorbing high-frequency content from outside. Rain becomes a low thud. Wind drops out entirely. Creature sounds become muffled and distant. The bus sounds like safety.

> [!attention] CONFLICT
> **Planned architecture vs. current state**: Constitution Appendix A and this note describe 7 buses. As of spec 099, `src/default_bus_layout.tres` defines 5 buses: Master, Radio, RadioDegraded, VehicleSFX, SFX. The 4 buses required by the world audio system (Ambience, Proximity, Interior, Horror) are not yet present. [[111 Audio Bus Architecture]] gates this expansion and is a hard prerequisite for specs 104–110. Indexed in [[Conflicts]].

### Biome ambient system — four layers

Each biome runs four simultaneous ambient layers that crossfade independently:

| Layer | Description | Node Type |
|-------|-------------|-----------|
| L1 Bed | Foundational tonal bed — deepest, lowest, longest loop | `AudioStreamPlayer` → Ambience |
| L2 Wind | Wind and air movement through canopy | `AudioStreamPlayer` → Ambience |
| L3 Organic | Biome-specific organic sounds (creak, drip, spore, crack) | `AudioStreamPlayer` → Ambience |
| L4 Detail | Sparse randomized events (bird, branch, footstep echo) | `AudioStreamPlayer3D` (randomized positions) → Proximity |

All layers except L4 are non-positional (ambient surround). L4 is spatialized to give the world directionality and suggest life (or absence of life) in specific directions. A weather change might swap only the wind layer while canopy creak continues uninterrupted.

### Radio as separate system

Dedicated Radio + RadioDegraded buses with its own content pipeline — see [[Audio — Car Radio]] and [[Audio — Radio Stations]].

### Four-state disturbance arc

Audio evolves continuously across the four disturbance states (Calm → Uneasy → Agitated → Storm) — see [[Disturbance System]] and [[The Disturbance Thread]]. Stinger cues mark threshold crossings on the Horror bus. The final state (Storm = 85) spawns the Storm weather event — see [[The Player Causes the Storm]].

### Silence as weapon

Two systems weaponize audio absence:
- **The Petrifold** biome has no wind layer. L1 is near-silent. L3 cracks are isolated events with long reverb tails dying into silence.
- **The Silence anomaly** hard-cuts ALL environmental audio on zone entry. Only the player's heartbeat remains. `Ambience` and `Proximity` buses are muted entirely when inside a Silence zone.

### Gain staging and LUFS compliance

Per Article XII-D: audio levels set at source before bus mixing. Each bus has headroom for the master bus. All shipped audio is normalized to consistent LUFS target documented in the audio spec family. Sub-Nyquist audio (<44.1 kHz) is never shipped.

### Godot implementation

Audio primitives are entirely Godot native (`AudioStreamPlayer`, `AudioStreamPlayer3D`, `AudioBus`, `AudioEffect*`) — no external plugin dependencies. The approved bus layout lives in `src/default_bus_layout.tres`. Biome-specific audio content lives in `src/assets/audio/` (submodule). The top-level orchestration is `world_audio_manager.gd` (see [[Audio — World Audio]] for full scene structure).

## Test Coverage

- `src/tests/unit/test_bus_radio.gd`, `test_radio_channel.gd` — radio runtime + per-channel behavior
- `src/tests/unit/test_engine_audio.gd` — engine audio
- `src/tests/unit/test_disturbance.gd` — disturbance autoload (upstream of audio arc)
- Individual subsystem tests as listed on per-subsystem notes ([[Audio — Car Radio]], etc.)

## Related

- [[Audio — World Audio]] — full per-subsystem specifications (biome audio, weather, disturbance arc, Storm, anomaly audio, Hollows, interior/exterior mix, footsteps, vehicle audio, player audio, interaction audio, prop audio, combat audio, garage audio, exit gate audio, UI audio, scene structure)
- [[Audio — Buses]] — current bus layout, effect chains, and the pending Ambience/Proximity/Interior/Horror expansion
- [[Audio — Car Radio]] — radio signal and degradation
- [[Audio — Pipeline]] — dev-time audio processing pipeline
- [[Audio — Radio Stations]] — per-station content
- [[Audio — Forest Transmissions]] — what comes through after signal dies
- [[Audio — Domain MOC]] — domain MOC
- [[Diegesis Thread]] — audio is fundamentally diegetic
- [[The Disturbance Thread]] — audio arc tracks disturbance state
- [[Constitution]] — Article XII-D, Appendix A bus architecture

### Phase 4 Implementation Specs

- [[111 Audio Bus Architecture]] — prerequisite for all world audio specs
- [[104 Biome Ambient Audio]], [[105 Disturbance Arc Audio]], [[106 Anomaly Audio Signatures]]
- [[107 Storm Audio System]], [[108 Garage And Exit Gate Audio]], [[109 Weather Bed Layer]]
- [[110 Time Of Day Audio Variants]], [[112 Environmental Presence System]], [[113 Player And World Interaction Audio]]

Controlled tag vocabulary (as read):
type/*:
- `type/code` — Code architecture, autoloads, conventions, tooling. Carries `code-refs:`. (e.g. `Code/Autoloads — Disturbance.md`)
- `type/decision` — Architectural or design decision made by an agent during a session. Written to `docs/vault/Decisions/`. (Agent notes only — spec 080.)
- `type/design` — Design intent, player-facing concepts, world lore. (e.g. `Design/World Model.md`)
- `type/discovery` — Non-obvious constraint, gap, or conflict found by an agent during a session. Written to `docs/vault/Discoveries/`. (Agent notes only — spec 080.)
- `type/moc` — Map of Content at any of three tiers (folder / domain / concept). (e.g. `Audio.md`)
- `type/principle` — Governance and constitutional notes. Non-negotiable rules. (e.g. `Governance/Constitution.md`)
- `type/reference` — Glossary, decision log, open questions, epics. (e.g. `Reference/Glossary.md`)
- `type/session-log` — Session activity log; permanent audit trail. Written to `docs/vault/Sessions/`. Append-only, never pruned. (Agent notes only — spec 080.)
- `type/spec` — Spec document at `docs/vault/Specs/NNN Title/spec.md`. Carries `spec-refs:`. (e.g. `Specs/047 Car Radio/spec.md`)
- `type/system` — A bounded subsystem with implementation. Carries `code-refs`, `spec-refs`, `implements:` frontmatter. (e.g. `Systems/Audio — Car Radio.md`)
- `type/vision` — Strategic / vision-layer decision. Written to `docs/vault/Vision/`. Human-authored or agent-proposed with human ratification before promotion to `status: reviewed`. (Per triage #3 — spec 133 autonomous-company redesign.)
domain/*:
- `domain/anomalies` — Anomaly taxonomy, individual anomaly systems, spawn, behavior
- `domain/art` — Visual direction, palettes, references, asset pipeline
- `domain/audio` — Audio systems: world ambient, radio, transmissions, buses, pipeline
- `domain/autonomous-company` — Autonomous company v0.1 experiment: Slack infra, persona middleware, Letta integration, restart recovery
- `domain/build` — Build system, packaging, export, release automation
- `domain/governance` — Constitution, phased spec, policies
- `domain/infrastructure` — Infrastructure provisioning: CI/CD, hosting, deployment tooling, secrets management
- `domain/narrative` — Tone, horror register, forest transmissions narrative, Gary/KTLK
- `domain/player` — Player mode, input, controls, camera, exit/entry
- `domain/systems` — Cross-cutting system architecture and integration work
- `domain/tooling` — Build, CI, observer, TTS pipeline, dev-time tools
- `domain/vehicle` — The Samba: vehicle physics, dashboard, damage, panels
- `domain/world` — World model, biomes, terrain, procedural generation, weather
status/*:
- `status/canonical` — Fully authoritative; promoted by humans only. Highest trust. (Agent notes only — spec 080.)
- `status/draft` — Authoring in progress, not yet verified
- `status/reviewed` — Agent-created note verified against codebase within its creating session. Eligible for auto-injection in subsequent task dispatches. (Agent notes only — spec 080.)
- `status/stale` — Known out of date; cannot update immediately. Pairs with `> [!warning] STALE — needs update` callout.
- `status/superseded` — Replaced by another note. Terminal state. Pairs with `> [!warning] SUPERSEDED` callout.
- `status/wip` — Stable but under active revision
layer/*:
- `layer/content` — Content assets (audio, models, textures, audio provenance)
- `layer/gdext` — gdext wrapper layer (`rust/gdext-wrapper/`)
- `layer/gdscript` — GDScript (Godot scene-tier logic)
- `layer/infra` — Build, CI, deployment infrastructure
- `layer/python` — Python development tooling (`tools/`)
- `layer/rust-core` — Engine-agnostic Rust core (`rust/rust-core/`)
concept/*:
- `concept/biome` — Biome-reactive behavior across systems
- `concept/contamination` — Across-runs panel and garage degradation; the slow-horror mechanic that doesn't reset with the world
- `concept/diegetic` — Diegetic audio / UI / world-sourced design
- `concept/disturbance` — The disturbance mechanic thread (Article X)
- `concept/ephemeral-world` — Run-reset, transient worlds (Article IV Rules 6–7)
- `concept/governance` — Constitutional and governance concepts
- `concept/horror` — Horror register and dread design
- `concept/procedural` — Procedural generation, seed determinism
- `concept/rendering` — Visual rendering quality, shader correctness, Terrain3D integration, mesh fidelity, LOD, Z-fighting
- `concept/terrain` — Terrain generation, heightmap, Terrain3D regions, roughness, playability constraints
ember's answer for tag_assignment-systems-audio-overview, type/systemP(true) placed on the no, unsure, and yes zones.nounsureyesgold: yesP = 0.13

tag_assignment-code-rust-core: domain/tooling

Tag assignment · test
Gold
The note calls for `domain/tooling`: Build, CI, observer, TTS pipeline, dev-time tools (True)
ember
The note has no reason to carry `domain/tooling` (False)
Signal
P(true) 0.11 (no)
Kit outcome
acted on a wrong answer
Why this gold label
Mined from Code/Rust — Core.md at 692f4bb58b7f62105aeb73fba8dfee12bfdecd53; gold is the note's own vocabulary tags.
Rust — Core

The engine-agnostic Rust core crate at `rust/rust-core/`. Contains performance-critical, deterministic logic with **zero Godot dependencies** — it compiles and tests in isolation. [[Rust — GDExt Wrapper]] bridges this crate to Godot types at the other side. This split is mandated by constitution Article III Rule 17.

## Overview

`rust-core` is where Old Growth's procedural generation, biome blending, road math, vegetation rejection, and deterministic state transitions live. Every module is pure in the sense that: inputs are simple data structures (tuples, arrays, custom structs); outputs are simple data structures; no Godot types are referenced. This lets the crate be unit-tested via `cargo test` without any game engine involvement.

## Key Decisions

### Engine-agnostic boundary

The crate's Cargo.toml has no Godot dependencies. All public APIs use standard Rust types (`[f32; 3]` instead of `Vector3`, etc.). The bridge crate is responsible for type conversion at the FFI boundary.

### Module layout

Each domain has its own module file:

| Module | Purpose |
|--------|---------|
| `biome.rs` | Biome blending — spec 070. Computes per-position biome weights from noise-sampled biome map |
| `disturbance.rs` | Disturbance meter arithmetic and state transitions — see [[Autoloads — Disturbance]] |
| `exit_points.rs` | Exit-gate discovery and placement logic |
| `game_state.rs` | Change-detection for tracked state fields — see [[Autoloads — GameState]] |
| `road/` | Road network generation (spec 053). Submodules: `density.rs` (biome density rules), `generator.rs` (pipeline), `graph.rs` (petgraph connectivity), `intersection.rs` (snap/merge), `mesh_geometry.rs`, `path_utils.rs`, `spline.rs` (Catmull-Rom), `terrain.rs` (conformance), `types.rs` (RoadNetwork, RoadNode, RoadSegment, profiles) |
| `structures.rs` | Structure placement logic (ranger stations, research trailers, cabins) |
| `terrain.rs` | Terrain math — height sampling, constraint validation |
| `vegetation.rs` | Vegetation scatter rejection (spec 070) — the biome-aware rejection that ships in rust-core as of spec 070 |
| `math.rs` | Mathematical utilities — noise sampling helpers, interpolation functions shared across modules |
| `utils.rs` | Shared utility functions used across rust-core modules |
| `weather/` | Weather simulation submodules (biome hysteresis, exposure, fog, zones, traction, wetness) |

### Deterministic RNG throughout

Every function that uses randomness takes an explicit seed or a `&mut SmallRng` reference. No function consumes OS entropy. This is mandated by Article IV Rule 3 (seed determinism).

### Newtype pattern for domain IDs

Per Article XII-C (Rust idioms): domain identifiers (biome IDs, road segment IDs, seed values) are wrapped in newtypes, not passed as raw `u32`/`i64`. A `BiomeId(u32)` and a `RoadSegmentId(u32)` are not interchangeable. Invalid state is unrepresentable at the type level with zero runtime cost.

### Approved dependencies

Per constitution Appendix A:
- `gdext` — handled by the wrapper crate, not here
- `rand 0.8` (SmallRng) — deterministic RNG
- `fastnoise-lite 1.1.1` — noise functions
- `petgraph 0.6` — road network connectivity (BFS, spatial traversal)
- `uniform-cubic-splines 0.5` — Catmull-Rom spline sampling
- `rustc-hash 2.1` — spatial hash grids (intersection snap/merge)

Adding a new dependency requires updating constitution Appendix A.

### Result/Option over panics

Per Article XII-C: `unwrap()` and `expect()` only appear in tests or explicitly unreachable branches with `// SAFETY:` comments. Public API functions return `Result<T, E>` for fallible operations.

## Implementation Notes

### Module structure (one level deeper than most modules)

`road/` is the only module that itself contains submodules — the road generation pipeline is complex enough (biome density rules, graph connectivity, spline curves, intersection snap/merge, terrain conformance, mesh geometry, types) that flat organization would exceed readable scope.

### Testing

`cargo test --workspace` runs all tests in rust-core. CI runs `make rust-test`, which includes this. Article III Rule 15 requires component SemVer bumps for rust-core and rust-gdext components when their paths change.

### Building

`make rust-build` compiles debug and copies the dylib to `src/addons/oldgrowth-rust/bin/`. Godot loads the dylib at editor startup; GDExtension libraries cannot hot-reload — any Rust change requires restarting the Godot editor.

Universal Binary (arm64 + x86_64) is built via `make rust-release` for macOS distribution.

## Test Coverage

- `cargo test --workspace` — unit tests for every module
- Integration tests exercise the bridge crate ([[Rust — GDExt Wrapper]])
- SC-001 baseline (tree counts) validates vegetation module output against golden seed

## Related

- [[Rust — GDExt Wrapper]] — the bridge crate
- [[World — Procedural Generation]] — a consumer of rust-core
- [[Autoloads — Disturbance]] — delegates to disturbance.rs
- [[Autoloads — GameState]] — delegates to game_state.rs
- [[Source Tree]] — repo topology
- [[Code]] — folder MOC
- [[Constitution]] — Article III Rule 17, Article XII-C (Rust idioms), Appendix A

Controlled tag vocabulary (as read):
type/*:
- `type/code` — Code architecture, autoloads, conventions, tooling. Carries `code-refs:`. (e.g. `Code/Autoloads — Disturbance.md`)
- `type/decision` — Architectural or design decision made by an agent during a session. Written to `docs/vault/Decisions/`. (Agent notes only — spec 080.)
- `type/design` — Design intent, player-facing concepts, world lore. (e.g. `Design/World Model.md`)
- `type/discovery` — Non-obvious constraint, gap, or conflict found by an agent during a session. Written to `docs/vault/Discoveries/`. (Agent notes only — spec 080.)
- `type/moc` — Map of Content at any of three tiers (folder / domain / concept). (e.g. `Audio.md`)
- `type/principle` — Governance and constitutional notes. Non-negotiable rules. (e.g. `Governance/Constitution.md`)
- `type/reference` — Glossary, decision log, open questions, epics. (e.g. `Reference/Glossary.md`)
- `type/session-log` — Session activity log; permanent audit trail. Written to `docs/vault/Sessions/`. Append-only, never pruned. (Agent notes only — spec 080.)
- `type/spec` — Spec document at `docs/vault/Specs/NNN Title/spec.md`. Carries `spec-refs:`. (e.g. `Specs/047 Car Radio/spec.md`)
- `type/system` — A bounded subsystem with implementation. Carries `code-refs`, `spec-refs`, `implements:` frontmatter. (e.g. `Systems/Audio — Car Radio.md`)
- `type/vision` — Strategic / vision-layer decision. Written to `docs/vault/Vision/`. Human-authored or agent-proposed with human ratification before promotion to `status: reviewed`. (Per triage #3 — spec 133 autonomous-company redesign.)
domain/*:
- `domain/anomalies` — Anomaly taxonomy, individual anomaly systems, spawn, behavior
- `domain/art` — Visual direction, palettes, references, asset pipeline
- `domain/audio` — Audio systems: world ambient, radio, transmissions, buses, pipeline
- `domain/autonomous-company` — Autonomous company v0.1 experiment: Slack infra, persona middleware, Letta integration, restart recovery
- `domain/build` — Build system, packaging, export, release automation
- `domain/governance` — Constitution, phased spec, policies
- `domain/infrastructure` — Infrastructure provisioning: CI/CD, hosting, deployment tooling, secrets management
- `domain/narrative` — Tone, horror register, forest transmissions narrative, Gary/KTLK
- `domain/player` — Player mode, input, controls, camera, exit/entry
- `domain/systems` — Cross-cutting system architecture and integration work
- `domain/tooling` — Build, CI, observer, TTS pipeline, dev-time tools
- `domain/vehicle` — The Samba: vehicle physics, dashboard, damage, panels
- `domain/world` — World model, biomes, terrain, procedural generation, weather
status/*:
- `status/canonical` — Fully authoritative; promoted by humans only. Highest trust. (Agent notes only — spec 080.)
- `status/draft` — Authoring in progress, not yet verified
- `status/reviewed` — Agent-created note verified against codebase within its creating session. Eligible for auto-injection in subsequent task dispatches. (Agent notes only — spec 080.)
- `status/stale` — Known out of date; cannot update immediately. Pairs with `> [!warning] STALE — needs update` callout.
- `status/superseded` — Replaced by another note. Terminal state. Pairs with `> [!warning] SUPERSEDED` callout.
- `status/wip` — Stable but under active revision
layer/*:
- `layer/content` — Content assets (audio, models, textures, audio provenance)
- `layer/gdext` — gdext wrapper layer (`rust/gdext-wrapper/`)
- `layer/gdscript` — GDScript (Godot scene-tier logic)
- `layer/infra` — Build, CI, deployment infrastructure
- `layer/python` — Python development tooling (`tools/`)
- `layer/rust-core` — Engine-agnostic Rust core (`rust/rust-core/`)
concept/*:
- `concept/biome` — Biome-reactive behavior across systems
- `concept/contamination` — Across-runs panel and garage degradation; the slow-horror mechanic that doesn't reset with the world
- `concept/diegetic` — Diegetic audio / UI / world-sourced design
- `concept/disturbance` — The disturbance mechanic thread (Article X)
- `concept/ephemeral-world` — Run-reset, transient worlds (Article IV Rules 6–7)
- `concept/governance` — Constitutional and governance concepts
- `concept/horror` — Horror register and dread design
- `concept/procedural` — Procedural generation, seed determinism
- `concept/rendering` — Visual rendering quality, shader correctness, Terrain3D integration, mesh fidelity, LOD, Z-fighting
- `concept/terrain` — Terrain generation, heightmap, Terrain3D regions, roughness, playability constraints
ember's answer for tag_assignment-code-rust-core, domain/toolingP(true) placed on the no, unsure, and yes zones.nounsureyesgold: yesP = 0.11

tag_assignment-discoveries-host-tools-mcp-server-launchd-lifecycle: domain/tooling

Tag assignment · dev
Gold
The note calls for `domain/tooling`: Build, CI, observer, TTS pipeline, dev-time tools (True)
ember
The note has no reason to carry `domain/tooling` (False)
Signal
P(true) 0.20 (unsure)
Kit outcome
deferred: treated as unsure
Why this gold label
Mined from Discoveries/Host-Tools MCP Server Launchd Lifecycle.md at 692f4bb58b7f62105aeb73fba8dfee12bfdecd53; gold is the note's own vocabulary tags.
Host-Tools MCP Server Launchd Lifecycle

The host-tools MCP server on port 9105 is owned by launchd via `com.oldgrowth.host-mcp.plist`. The `mcp-setup` command must never attempt to check port availability or start its own server instance — it should verify server health and proceed with tool attachment.

## Background

The `cmd_mcp_setup()` function in `scripts/personas/system-manager.py` originally used `socket.bind()` to check if port 9105 was free. On a clean boot, launchd starts the host-tools MCP server via `com.oldgrowth.host-mcp.plist` (RunAtLoad + KeepAlive), so the port is always in use — causing `socket.bind()` to fail and `make recovery` to exit with "Port 9105 is already in use."

This was a design mismatch: launchd owns the server lifecycle (start, keep alive, restart on crash), and `mcp-setup` only needs to verify the server is healthy and attach MCP tools to Letta agents. The port-conflict check was an artifact from an earlier design where `mcp-setup` was expected to start its own server.

## Fix

The port-conflict check was replaced with a two-phase health check:

1. Hit `GET /health` on port 9105. If the server responds, skip to tool attachment.
2. If unreachable, attempt `launchctl bootstrap` (or `load`) against the launchd plist, wait up to ~6 seconds for the server to come up, then proceed.

This handles every scenario: normal boot (launchd has it running), plist unloaded (auto-start via launchctl), server crashed (auto-restart via launchd).

## Related

- `scripts/personas/system-manager.py` — `cmd_mcp_setup()` and `_ensure_host_mcp_server()`
- `personas/host_mcp_server.py` — the server itself, listens on 9105
- `personas/launchd/com.oldgrowth.host-mcp.plist` — launchd plist managing the server
- `personas/config.py` — `HOST_TOOLS_CALLBACK_PORT = 9105` constant

## References

- `scripts/personas/system-manager.py` — `_ensure_host_mcp_server()` function (lines ~302-380)
- `personas/host_mcp_server.py` — `/health` endpoint implementation (lines 1049-1069)
- `personas/launchd/com.oldgrowth.host-mcp.plist` — launchd plist with RunAtLoad + KeepAlive

Controlled tag vocabulary (as read):
type/*:
- `type/code` — Code architecture, autoloads, conventions, tooling. Carries `code-refs:`. (e.g. `Code/Autoloads — Disturbance.md`)
- `type/decision` — Architectural or design decision made by an agent during a session. Written to `docs/vault/Decisions/`. (Agent notes only — spec 080.)
- `type/design` — Design intent, player-facing concepts, world lore. (e.g. `Design/World Model.md`)
- `type/discovery` — Non-obvious constraint, gap, or conflict found by an agent during a session. Written to `docs/vault/Discoveries/`. (Agent notes only — spec 080.)
- `type/moc` — Map of Content at any of three tiers (folder / domain / concept). (e.g. `Audio.md`)
- `type/principle` — Governance and constitutional notes. Non-negotiable rules. (e.g. `Governance/Constitution.md`)
- `type/reference` — Glossary, decision log, open questions, epics. (e.g. `Reference/Glossary.md`)
- `type/session-log` — Session activity log; permanent audit trail. Written to `docs/vault/Sessions/`. Append-only, never pruned. (Agent notes only — spec 080.)
- `type/spec` — Spec document at `docs/vault/Specs/NNN Title/spec.md`. Carries `spec-refs:`. (e.g. `Specs/047 Car Radio/spec.md`)
- `type/system` — A bounded subsystem with implementation. Carries `code-refs`, `spec-refs`, `implements:` frontmatter. (e.g. `Systems/Audio — Car Radio.md`)
- `type/vision` — Strategic / vision-layer decision. Written to `docs/vault/Vision/`. Human-authored or agent-proposed with human ratification before promotion to `status: reviewed`. (Per triage #3 — spec 133 autonomous-company redesign.)
domain/*:
- `domain/anomalies` — Anomaly taxonomy, individual anomaly systems, spawn, behavior
- `domain/art` — Visual direction, palettes, references, asset pipeline
- `domain/audio` — Audio systems: world ambient, radio, transmissions, buses, pipeline
- `domain/autonomous-company` — Autonomous company v0.1 experiment: Slack infra, persona middleware, Letta integration, restart recovery
- `domain/build` — Build system, packaging, export, release automation
- `domain/governance` — Constitution, phased spec, policies
- `domain/infrastructure` — Infrastructure provisioning: CI/CD, hosting, deployment tooling, secrets management
- `domain/narrative` — Tone, horror register, forest transmissions narrative, Gary/KTLK
- `domain/player` — Player mode, input, controls, camera, exit/entry
- `domain/systems` — Cross-cutting system architecture and integration work
- `domain/tooling` — Build, CI, observer, TTS pipeline, dev-time tools
- `domain/vehicle` — The Samba: vehicle physics, dashboard, damage, panels
- `domain/world` — World model, biomes, terrain, procedural generation, weather
status/*:
- `status/canonical` — Fully authoritative; promoted by humans only. Highest trust. (Agent notes only — spec 080.)
- `status/draft` — Authoring in progress, not yet verified
- `status/reviewed` — Agent-created note verified against codebase within its creating session. Eligible for auto-injection in subsequent task dispatches. (Agent notes only — spec 080.)
- `status/stale` — Known out of date; cannot update immediately. Pairs with `> [!warning] STALE — needs update` callout.
- `status/superseded` — Replaced by another note. Terminal state. Pairs with `> [!warning] SUPERSEDED` callout.
- `status/wip` — Stable but under active revision
layer/*:
- `layer/content` — Content assets (audio, models, textures, audio provenance)
- `layer/gdext` — gdext wrapper layer (`rust/gdext-wrapper/`)
- `layer/gdscript` — GDScript (Godot scene-tier logic)
- `layer/infra` — Build, CI, deployment infrastructure
- `layer/python` — Python development tooling (`tools/`)
- `layer/rust-core` — Engine-agnostic Rust core (`rust/rust-core/`)
concept/*:
- `concept/biome` — Biome-reactive behavior across systems
- `concept/contamination` — Across-runs panel and garage degradation; the slow-horror mechanic that doesn't reset with the world
- `concept/diegetic` — Diegetic audio / UI / world-sourced design
- `concept/disturbance` — The disturbance mechanic thread (Article X)
- `concept/ephemeral-world` — Run-reset, transient worlds (Article IV Rules 6–7)
- `concept/governance` — Constitutional and governance concepts
- `concept/horror` — Horror register and dread design
- `concept/procedural` — Procedural generation, seed determinism
- `concept/rendering` — Visual rendering quality, shader correctness, Terrain3D integration, mesh fidelity, LOD, Z-fighting
- `concept/terrain` — Terrain generation, heightmap, Terrain3D regions, roughness, playability constraints
ember's answer for tag_assignment-discoveries-host-tools-mcp-server-launchd-lifecycle, domain/toolingP(true) placed on the no, unsure, and yes zones.nounsureyesgold: yesP = 0.20

tag_assignment-discoveries-host-tools-mcp-server-launchd-lifecycle: status/draft

Tag assignment · dev
Gold
The note calls for `status/draft`: Authoring in progress, not yet verified (True)
ember
The note has no reason to carry `status/draft` (False)
Signal
P(true) 0.10 (no)
Kit outcome
acted on a wrong answer
Why this gold label
Mined from Discoveries/Host-Tools MCP Server Launchd Lifecycle.md at 692f4bb58b7f62105aeb73fba8dfee12bfdecd53; gold is the note's own vocabulary tags.
Host-Tools MCP Server Launchd Lifecycle

The host-tools MCP server on port 9105 is owned by launchd via `com.oldgrowth.host-mcp.plist`. The `mcp-setup` command must never attempt to check port availability or start its own server instance — it should verify server health and proceed with tool attachment.

## Background

The `cmd_mcp_setup()` function in `scripts/personas/system-manager.py` originally used `socket.bind()` to check if port 9105 was free. On a clean boot, launchd starts the host-tools MCP server via `com.oldgrowth.host-mcp.plist` (RunAtLoad + KeepAlive), so the port is always in use — causing `socket.bind()` to fail and `make recovery` to exit with "Port 9105 is already in use."

This was a design mismatch: launchd owns the server lifecycle (start, keep alive, restart on crash), and `mcp-setup` only needs to verify the server is healthy and attach MCP tools to Letta agents. The port-conflict check was an artifact from an earlier design where `mcp-setup` was expected to start its own server.

## Fix

The port-conflict check was replaced with a two-phase health check:

1. Hit `GET /health` on port 9105. If the server responds, skip to tool attachment.
2. If unreachable, attempt `launchctl bootstrap` (or `load`) against the launchd plist, wait up to ~6 seconds for the server to come up, then proceed.

This handles every scenario: normal boot (launchd has it running), plist unloaded (auto-start via launchctl), server crashed (auto-restart via launchd).

## Related

- `scripts/personas/system-manager.py` — `cmd_mcp_setup()` and `_ensure_host_mcp_server()`
- `personas/host_mcp_server.py` — the server itself, listens on 9105
- `personas/launchd/com.oldgrowth.host-mcp.plist` — launchd plist managing the server
- `personas/config.py` — `HOST_TOOLS_CALLBACK_PORT = 9105` constant

## References

- `scripts/personas/system-manager.py` — `_ensure_host_mcp_server()` function (lines ~302-380)
- `personas/host_mcp_server.py` — `/health` endpoint implementation (lines 1049-1069)
- `personas/launchd/com.oldgrowth.host-mcp.plist` — launchd plist with RunAtLoad + KeepAlive

Controlled tag vocabulary (as read):
type/*:
- `type/code` — Code architecture, autoloads, conventions, tooling. Carries `code-refs:`. (e.g. `Code/Autoloads — Disturbance.md`)
- `type/decision` — Architectural or design decision made by an agent during a session. Written to `docs/vault/Decisions/`. (Agent notes only — spec 080.)
- `type/design` — Design intent, player-facing concepts, world lore. (e.g. `Design/World Model.md`)
- `type/discovery` — Non-obvious constraint, gap, or conflict found by an agent during a session. Written to `docs/vault/Discoveries/`. (Agent notes only — spec 080.)
- `type/moc` — Map of Content at any of three tiers (folder / domain / concept). (e.g. `Audio.md`)
- `type/principle` — Governance and constitutional notes. Non-negotiable rules. (e.g. `Governance/Constitution.md`)
- `type/reference` — Glossary, decision log, open questions, epics. (e.g. `Reference/Glossary.md`)
- `type/session-log` — Session activity log; permanent audit trail. Written to `docs/vault/Sessions/`. Append-only, never pruned. (Agent notes only — spec 080.)
- `type/spec` — Spec document at `docs/vault/Specs/NNN Title/spec.md`. Carries `spec-refs:`. (e.g. `Specs/047 Car Radio/spec.md`)
- `type/system` — A bounded subsystem with implementation. Carries `code-refs`, `spec-refs`, `implements:` frontmatter. (e.g. `Systems/Audio — Car Radio.md`)
- `type/vision` — Strategic / vision-layer decision. Written to `docs/vault/Vision/`. Human-authored or agent-proposed with human ratification before promotion to `status: reviewed`. (Per triage #3 — spec 133 autonomous-company redesign.)
domain/*:
- `domain/anomalies` — Anomaly taxonomy, individual anomaly systems, spawn, behavior
- `domain/art` — Visual direction, palettes, references, asset pipeline
- `domain/audio` — Audio systems: world ambient, radio, transmissions, buses, pipeline
- `domain/autonomous-company` — Autonomous company v0.1 experiment: Slack infra, persona middleware, Letta integration, restart recovery
- `domain/build` — Build system, packaging, export, release automation
- `domain/governance` — Constitution, phased spec, policies
- `domain/infrastructure` — Infrastructure provisioning: CI/CD, hosting, deployment tooling, secrets management
- `domain/narrative` — Tone, horror register, forest transmissions narrative, Gary/KTLK
- `domain/player` — Player mode, input, controls, camera, exit/entry
- `domain/systems` — Cross-cutting system architecture and integration work
- `domain/tooling` — Build, CI, observer, TTS pipeline, dev-time tools
- `domain/vehicle` — The Samba: vehicle physics, dashboard, damage, panels
- `domain/world` — World model, biomes, terrain, procedural generation, weather
status/*:
- `status/canonical` — Fully authoritative; promoted by humans only. Highest trust. (Agent notes only — spec 080.)
- `status/draft` — Authoring in progress, not yet verified
- `status/reviewed` — Agent-created note verified against codebase within its creating session. Eligible for auto-injection in subsequent task dispatches. (Agent notes only — spec 080.)
- `status/stale` — Known out of date; cannot update immediately. Pairs with `> [!warning] STALE — needs update` callout.
- `status/superseded` — Replaced by another note. Terminal state. Pairs with `> [!warning] SUPERSEDED` callout.
- `status/wip` — Stable but under active revision
layer/*:
- `layer/content` — Content assets (audio, models, textures, audio provenance)
- `layer/gdext` — gdext wrapper layer (`rust/gdext-wrapper/`)
- `layer/gdscript` — GDScript (Godot scene-tier logic)
- `layer/infra` — Build, CI, deployment infrastructure
- `layer/python` — Python development tooling (`tools/`)
- `layer/rust-core` — Engine-agnostic Rust core (`rust/rust-core/`)
concept/*:
- `concept/biome` — Biome-reactive behavior across systems
- `concept/contamination` — Across-runs panel and garage degradation; the slow-horror mechanic that doesn't reset with the world
- `concept/diegetic` — Diegetic audio / UI / world-sourced design
- `concept/disturbance` — The disturbance mechanic thread (Article X)
- `concept/ephemeral-world` — Run-reset, transient worlds (Article IV Rules 6–7)
- `concept/governance` — Constitutional and governance concepts
- `concept/horror` — Horror register and dread design
- `concept/procedural` — Procedural generation, seed determinism
- `concept/rendering` — Visual rendering quality, shader correctness, Terrain3D integration, mesh fidelity, LOD, Z-fighting
- `concept/terrain` — Terrain generation, heightmap, Terrain3D regions, roughness, playability constraints
ember's answer for tag_assignment-discoveries-host-tools-mcp-server-launchd-lifecycle, status/draftP(true) placed on the no, unsure, and yes zones.nounsureyesgold: yesP = 0.10

tag_assignment-discoveries-host-tools-mcp-server-launchd-lifecycle: type/code

Tag assignment · dev
Gold
The note has no reason to carry `type/code` (False)
ember
The note calls for `type/code`: Code architecture, autoloads, conventions, tooling. Carries `code-refs:`. (e.g. `Code/Autoloads — Disturbance.md`) (True)
Signal
P(true) 0.74 (unsure)
Kit outcome
deferred: treated as unsure
Why this gold label
Mined from Discoveries/Host-Tools MCP Server Launchd Lifecycle.md at 692f4bb58b7f62105aeb73fba8dfee12bfdecd53; gold is the note's own vocabulary tags.
Host-Tools MCP Server Launchd Lifecycle

The host-tools MCP server on port 9105 is owned by launchd via `com.oldgrowth.host-mcp.plist`. The `mcp-setup` command must never attempt to check port availability or start its own server instance — it should verify server health and proceed with tool attachment.

## Background

The `cmd_mcp_setup()` function in `scripts/personas/system-manager.py` originally used `socket.bind()` to check if port 9105 was free. On a clean boot, launchd starts the host-tools MCP server via `com.oldgrowth.host-mcp.plist` (RunAtLoad + KeepAlive), so the port is always in use — causing `socket.bind()` to fail and `make recovery` to exit with "Port 9105 is already in use."

This was a design mismatch: launchd owns the server lifecycle (start, keep alive, restart on crash), and `mcp-setup` only needs to verify the server is healthy and attach MCP tools to Letta agents. The port-conflict check was an artifact from an earlier design where `mcp-setup` was expected to start its own server.

## Fix

The port-conflict check was replaced with a two-phase health check:

1. Hit `GET /health` on port 9105. If the server responds, skip to tool attachment.
2. If unreachable, attempt `launchctl bootstrap` (or `load`) against the launchd plist, wait up to ~6 seconds for the server to come up, then proceed.

This handles every scenario: normal boot (launchd has it running), plist unloaded (auto-start via launchctl), server crashed (auto-restart via launchd).

## Related

- `scripts/personas/system-manager.py` — `cmd_mcp_setup()` and `_ensure_host_mcp_server()`
- `personas/host_mcp_server.py` — the server itself, listens on 9105
- `personas/launchd/com.oldgrowth.host-mcp.plist` — launchd plist managing the server
- `personas/config.py` — `HOST_TOOLS_CALLBACK_PORT = 9105` constant

## References

- `scripts/personas/system-manager.py` — `_ensure_host_mcp_server()` function (lines ~302-380)
- `personas/host_mcp_server.py` — `/health` endpoint implementation (lines 1049-1069)
- `personas/launchd/com.oldgrowth.host-mcp.plist` — launchd plist with RunAtLoad + KeepAlive

Controlled tag vocabulary (as read):
type/*:
- `type/code` — Code architecture, autoloads, conventions, tooling. Carries `code-refs:`. (e.g. `Code/Autoloads — Disturbance.md`)
- `type/decision` — Architectural or design decision made by an agent during a session. Written to `docs/vault/Decisions/`. (Agent notes only — spec 080.)
- `type/design` — Design intent, player-facing concepts, world lore. (e.g. `Design/World Model.md`)
- `type/discovery` — Non-obvious constraint, gap, or conflict found by an agent during a session. Written to `docs/vault/Discoveries/`. (Agent notes only — spec 080.)
- `type/moc` — Map of Content at any of three tiers (folder / domain / concept). (e.g. `Audio.md`)
- `type/principle` — Governance and constitutional notes. Non-negotiable rules. (e.g. `Governance/Constitution.md`)
- `type/reference` — Glossary, decision log, open questions, epics. (e.g. `Reference/Glossary.md`)
- `type/session-log` — Session activity log; permanent audit trail. Written to `docs/vault/Sessions/`. Append-only, never pruned. (Agent notes only — spec 080.)
- `type/spec` — Spec document at `docs/vault/Specs/NNN Title/spec.md`. Carries `spec-refs:`. (e.g. `Specs/047 Car Radio/spec.md`)
- `type/system` — A bounded subsystem with implementation. Carries `code-refs`, `spec-refs`, `implements:` frontmatter. (e.g. `Systems/Audio — Car Radio.md`)
- `type/vision` — Strategic / vision-layer decision. Written to `docs/vault/Vision/`. Human-authored or agent-proposed with human ratification before promotion to `status: reviewed`. (Per triage #3 — spec 133 autonomous-company redesign.)
domain/*:
- `domain/anomalies` — Anomaly taxonomy, individual anomaly systems, spawn, behavior
- `domain/art` — Visual direction, palettes, references, asset pipeline
- `domain/audio` — Audio systems: world ambient, radio, transmissions, buses, pipeline
- `domain/autonomous-company` — Autonomous company v0.1 experiment: Slack infra, persona middleware, Letta integration, restart recovery
- `domain/build` — Build system, packaging, export, release automation
- `domain/governance` — Constitution, phased spec, policies
- `domain/infrastructure` — Infrastructure provisioning: CI/CD, hosting, deployment tooling, secrets management
- `domain/narrative` — Tone, horror register, forest transmissions narrative, Gary/KTLK
- `domain/player` — Player mode, input, controls, camera, exit/entry
- `domain/systems` — Cross-cutting system architecture and integration work
- `domain/tooling` — Build, CI, observer, TTS pipeline, dev-time tools
- `domain/vehicle` — The Samba: vehicle physics, dashboard, damage, panels
- `domain/world` — World model, biomes, terrain, procedural generation, weather
status/*:
- `status/canonical` — Fully authoritative; promoted by humans only. Highest trust. (Agent notes only — spec 080.)
- `status/draft` — Authoring in progress, not yet verified
- `status/reviewed` — Agent-created note verified against codebase within its creating session. Eligible for auto-injection in subsequent task dispatches. (Agent notes only — spec 080.)
- `status/stale` — Known out of date; cannot update immediately. Pairs with `> [!warning] STALE — needs update` callout.
- `status/superseded` — Replaced by another note. Terminal state. Pairs with `> [!warning] SUPERSEDED` callout.
- `status/wip` — Stable but under active revision
layer/*:
- `layer/content` — Content assets (audio, models, textures, audio provenance)
- `layer/gdext` — gdext wrapper layer (`rust/gdext-wrapper/`)
- `layer/gdscript` — GDScript (Godot scene-tier logic)
- `layer/infra` — Build, CI, deployment infrastructure
- `layer/python` — Python development tooling (`tools/`)
- `layer/rust-core` — Engine-agnostic Rust core (`rust/rust-core/`)
concept/*:
- `concept/biome` — Biome-reactive behavior across systems
- `concept/contamination` — Across-runs panel and garage degradation; the slow-horror mechanic that doesn't reset with the world
- `concept/diegetic` — Diegetic audio / UI / world-sourced design
- `concept/disturbance` — The disturbance mechanic thread (Article X)
- `concept/ephemeral-world` — Run-reset, transient worlds (Article IV Rules 6–7)
- `concept/governance` — Constitutional and governance concepts
- `concept/horror` — Horror register and dread design
- `concept/procedural` — Procedural generation, seed determinism
- `concept/rendering` — Visual rendering quality, shader correctness, Terrain3D integration, mesh fidelity, LOD, Z-fighting
- `concept/terrain` — Terrain generation, heightmap, Terrain3D regions, roughness, playability constraints
ember's answer for tag_assignment-discoveries-host-tools-mcp-server-launchd-lifecycle, type/codeP(true) placed on the no, unsure, and yes zones.nounsureyesgold: noP = 0.74

tag_assignment-discoveries-host-tools-mcp-server-launchd-lifecycle: type/discovery

Tag assignment · dev
Gold
The note calls for `type/discovery`: Non-obvious constraint, gap, or conflict found by an agent during a session. Written to `docs/vault/Discoveries/`. (Agent notes only — spec 080.) (True)
ember
The note has no reason to carry `type/discovery` (False)
Signal
P(true) 0.25 (unsure)
Kit outcome
deferred: treated as unsure
Why this gold label
Mined from Discoveries/Host-Tools MCP Server Launchd Lifecycle.md at 692f4bb58b7f62105aeb73fba8dfee12bfdecd53; gold is the note's own vocabulary tags.
Host-Tools MCP Server Launchd Lifecycle

The host-tools MCP server on port 9105 is owned by launchd via `com.oldgrowth.host-mcp.plist`. The `mcp-setup` command must never attempt to check port availability or start its own server instance — it should verify server health and proceed with tool attachment.

## Background

The `cmd_mcp_setup()` function in `scripts/personas/system-manager.py` originally used `socket.bind()` to check if port 9105 was free. On a clean boot, launchd starts the host-tools MCP server via `com.oldgrowth.host-mcp.plist` (RunAtLoad + KeepAlive), so the port is always in use — causing `socket.bind()` to fail and `make recovery` to exit with "Port 9105 is already in use."

This was a design mismatch: launchd owns the server lifecycle (start, keep alive, restart on crash), and `mcp-setup` only needs to verify the server is healthy and attach MCP tools to Letta agents. The port-conflict check was an artifact from an earlier design where `mcp-setup` was expected to start its own server.

## Fix

The port-conflict check was replaced with a two-phase health check:

1. Hit `GET /health` on port 9105. If the server responds, skip to tool attachment.
2. If unreachable, attempt `launchctl bootstrap` (or `load`) against the launchd plist, wait up to ~6 seconds for the server to come up, then proceed.

This handles every scenario: normal boot (launchd has it running), plist unloaded (auto-start via launchctl), server crashed (auto-restart via launchd).

## Related

- `scripts/personas/system-manager.py` — `cmd_mcp_setup()` and `_ensure_host_mcp_server()`
- `personas/host_mcp_server.py` — the server itself, listens on 9105
- `personas/launchd/com.oldgrowth.host-mcp.plist` — launchd plist managing the server
- `personas/config.py` — `HOST_TOOLS_CALLBACK_PORT = 9105` constant

## References

- `scripts/personas/system-manager.py` — `_ensure_host_mcp_server()` function (lines ~302-380)
- `personas/host_mcp_server.py` — `/health` endpoint implementation (lines 1049-1069)
- `personas/launchd/com.oldgrowth.host-mcp.plist` — launchd plist with RunAtLoad + KeepAlive

Controlled tag vocabulary (as read):
type/*:
- `type/code` — Code architecture, autoloads, conventions, tooling. Carries `code-refs:`. (e.g. `Code/Autoloads — Disturbance.md`)
- `type/decision` — Architectural or design decision made by an agent during a session. Written to `docs/vault/Decisions/`. (Agent notes only — spec 080.)
- `type/design` — Design intent, player-facing concepts, world lore. (e.g. `Design/World Model.md`)
- `type/discovery` — Non-obvious constraint, gap, or conflict found by an agent during a session. Written to `docs/vault/Discoveries/`. (Agent notes only — spec 080.)
- `type/moc` — Map of Content at any of three tiers (folder / domain / concept). (e.g. `Audio.md`)
- `type/principle` — Governance and constitutional notes. Non-negotiable rules. (e.g. `Governance/Constitution.md`)
- `type/reference` — Glossary, decision log, open questions, epics. (e.g. `Reference/Glossary.md`)
- `type/session-log` — Session activity log; permanent audit trail. Written to `docs/vault/Sessions/`. Append-only, never pruned. (Agent notes only — spec 080.)
- `type/spec` — Spec document at `docs/vault/Specs/NNN Title/spec.md`. Carries `spec-refs:`. (e.g. `Specs/047 Car Radio/spec.md`)
- `type/system` — A bounded subsystem with implementation. Carries `code-refs`, `spec-refs`, `implements:` frontmatter. (e.g. `Systems/Audio — Car Radio.md`)
- `type/vision` — Strategic / vision-layer decision. Written to `docs/vault/Vision/`. Human-authored or agent-proposed with human ratification before promotion to `status: reviewed`. (Per triage #3 — spec 133 autonomous-company redesign.)
domain/*:
- `domain/anomalies` — Anomaly taxonomy, individual anomaly systems, spawn, behavior
- `domain/art` — Visual direction, palettes, references, asset pipeline
- `domain/audio` — Audio systems: world ambient, radio, transmissions, buses, pipeline
- `domain/autonomous-company` — Autonomous company v0.1 experiment: Slack infra, persona middleware, Letta integration, restart recovery
- `domain/build` — Build system, packaging, export, release automation
- `domain/governance` — Constitution, phased spec, policies
- `domain/infrastructure` — Infrastructure provisioning: CI/CD, hosting, deployment tooling, secrets management
- `domain/narrative` — Tone, horror register, forest transmissions narrative, Gary/KTLK
- `domain/player` — Player mode, input, controls, camera, exit/entry
- `domain/systems` — Cross-cutting system architecture and integration work
- `domain/tooling` — Build, CI, observer, TTS pipeline, dev-time tools
- `domain/vehicle` — The Samba: vehicle physics, dashboard, damage, panels
- `domain/world` — World model, biomes, terrain, procedural generation, weather
status/*:
- `status/canonical` — Fully authoritative; promoted by humans only. Highest trust. (Agent notes only — spec 080.)
- `status/draft` — Authoring in progress, not yet verified
- `status/reviewed` — Agent-created note verified against codebase within its creating session. Eligible for auto-injection in subsequent task dispatches. (Agent notes only — spec 080.)
- `status/stale` — Known out of date; cannot update immediately. Pairs with `> [!warning] STALE — needs update` callout.
- `status/superseded` — Replaced by another note. Terminal state. Pairs with `> [!warning] SUPERSEDED` callout.
- `status/wip` — Stable but under active revision
layer/*:
- `layer/content` — Content assets (audio, models, textures, audio provenance)
- `layer/gdext` — gdext wrapper layer (`rust/gdext-wrapper/`)
- `layer/gdscript` — GDScript (Godot scene-tier logic)
- `layer/infra` — Build, CI, deployment infrastructure
- `layer/python` — Python development tooling (`tools/`)
- `layer/rust-core` — Engine-agnostic Rust core (`rust/rust-core/`)
concept/*:
- `concept/biome` — Biome-reactive behavior across systems
- `concept/contamination` — Across-runs panel and garage degradation; the slow-horror mechanic that doesn't reset with the world
- `concept/diegetic` — Diegetic audio / UI / world-sourced design
- `concept/disturbance` — The disturbance mechanic thread (Article X)
- `concept/ephemeral-world` — Run-reset, transient worlds (Article IV Rules 6–7)
- `concept/governance` — Constitutional and governance concepts
- `concept/horror` — Horror register and dread design
- `concept/procedural` — Procedural generation, seed determinism
- `concept/rendering` — Visual rendering quality, shader correctness, Terrain3D integration, mesh fidelity, LOD, Z-fighting
- `concept/terrain` — Terrain generation, heightmap, Terrain3D regions, roughness, playability constraints
ember's answer for tag_assignment-discoveries-host-tools-mcp-server-launchd-lifecycle, type/discoveryP(true) placed on the no, unsure, and yes zones.nounsureyesgold: yesP = 0.25

tag_assignment-art-vehicle-samba-exterior: type/reference

Tag assignment · test
Gold
The note calls for `type/reference`: Glossary, decision log, open questions, epics. (e.g. `Reference/Glossary.md`) (True)
ember
The note has no reason to carry `type/reference` (False)
Signal
P(true) 0.03 (no)
Kit outcome
acted on a wrong answer
Why this gold label
Mined from Art/Vehicle — Samba Exterior.md at 692f4bb58b7f62105aeb73fba8dfee12bfdecd53; gold is the note's own vocabulary tags.
Vehicle — Samba Exterior

> **⚠️ PRE-068 NOTE — asset paths and material resource names will be verified when spec 068 ships.**
> Material `.tres` file paths are proposed targets. After 068 ships the purchased model, confirm resource names against the actual committed geometry. Spec 082 will reconcile.

This note covers PBR material specs for all exterior surfaces. For the palette derivation rationale and archival paint code research, see [[Vehicle Palette Materials and Dimensions Discovery]]. For dimensional anchors (panel locations, window sizes), see [[Art/Vehicle — Samba Dimensions]].

## Exterior panel diagram

![[_meta/attachments/vehicle/panels_exterior_callout.svg]]

## Hero palette (exterior)

| Slot | Name | sRGB hex | Linear RGB | Purpose |
|---|---|---|---|---|
| 1 | `hero_cream_upper` | `#D9D3BE` | `(0.675, 0.615, 0.513)` | Primary upper body paint |
| 2 | `hero_teal_lower` | `#3F6E66` | `(0.047, 0.154, 0.138)` | Primary lower body paint |
| 3 | `weathered_cream_upper` | `#C9C2AB` | `(0.581, 0.529, 0.418)` | Sun-faded upper (roof peaks, raised surfaces) |
| 4 | `weathered_teal_lower` | `#355A56` | `(0.032, 0.103, 0.097)` | Sun-faded lower (hood front, running boards, rockers) |
| 5 | `trim_beltline` | `#B5B0A3` | `(0.453, 0.421, 0.363)` | Chrome decorative strip with tarnish |
| 6 | `vw_roundel_chrome` | `#D4D0C5` | `(0.646, 0.613, 0.546)` | VW badge and bright chrome trim |
| 7 | `shadow_deep` | `#1B2E2A` | `(0.009, 0.028, 0.024)` | AO reference / deep crevice shadow colour |

**Archival anchor**: Option B — L289 Blue White / L380 Turquoise. Hero palette is intentionally adjusted from archival codes for moodboard alignment; values above are the production target, not the factory codes. See [[Vehicle Palette Materials and Dimensions Discovery]] for the full archival baseline.

**Two-tone boundary rule**: The paint boundary is a hard seam at the chrome beltline strip. Paint does NOT gradient-blend. Model the beltline as a separate bevelled feature; assign upper and lower paint as two distinct material slots.

## Painted body

Covers: nose cone, hood front, all fenders, all side panels, roof panels, engine hatch, all doors, running boards where painted.

**Panel IDs**: `nose_cone`, `hood_front`, `engine_hatch`, `panel_front_lower`, `fender_front_left`, `fender_front_right`, `fender_rear_left`, `fender_rear_right`, `panel_side_left_front/mid/rear`, `panel_side_right_front/mid/rear`, `door_left_front`, `door_right_front`, `door_rear_left`, `door_rear_right`, `panel_rear_upper`, `roof_panel_front/mid/rear`, `running_board_left`, `running_board_right`.

### PBR rules (all states)
- **Metalness**: 0.0 — non-metallic nitrocellulose lacquer. No metallic flake.
- **Clearcoat**: DISABLED — 1963 paint was not clearcoated.
- **Two-tone**: hard seam at chrome beltline; two separate material instances above and below.

### Clean state
| Property | Upper | Lower |
|---|---|---|
| Albedo | `hero_cream_upper` | `hero_teal_lower` |
| Roughness | 0.55–0.65 | 0.55–0.65 |
| Normal | Subtle panel-seam + minor hand-beaten imperfections (period-correct) | Same |
| AO | Panel-seam and wheel-arch bake | Same |

### Worn state (default Old Growth game state)
| Property | Upper | Lower |
|---|---|---|
| Albedo | `hero_cream_upper` → `weathered_cream_upper` blend (60/40 worn) | `hero_teal_lower` → `weathered_teal_lower` blend |
| Roughness | 0.65–0.80 (lost gloss; worse on horizontal surfaces) | Same |
| Normal | Paint chips at panel edges, fender tops, hood corners; minor hail-type dimples on horizontal surfaces | Same |
| Weathering mask | World-up normal + panel edge proximity + wheel-well proximity | Same |

### Damaged state (heavy wear)
| Property | Upper | Lower |
|---|---|---|
| Albedo | `weathered_cream_upper` + primer `#8A7E68` in exposed spots + rust `#7A4A2C` at edges | `weathered_teal_lower` + exposed metal |
| Roughness | 0.80–0.95 (matte, oxidised) | Same |
| Metalness | 0.0 on paint; 0.7 on bare metal | Same |
| Normal | Deep paint loss patches, real dents, bent panels, visible panel seam displacement | Same |
| Rust layer | Colour `#7A4A2C`, roughness 0.95, metalness 0.2 (oxidised iron has partial metallic character) | Same |

**Wet state modifier**: roughness drops ~0.10; specular rises. See `src/assets/shaders/rain_on_glass.gdshader` for wet-surface shader reference.

## Chrome trim

Decorative chrome bright trim: beltline strip, window surrounds, VW roundel badge, door handles, headlight bezels, bumper overriders, side mirror housings, radio fascia bezel.

| State | Albedo | Roughness | Metalness | Notes |
|---|---|---|---|---|
| Clean | `vw_roundel_chrome` (#D4D0C5), slightly cooler | 0.05–0.15 | 1.0 | Mirror polish |
| Worn (default) | Same + subtle yellowed patches | 0.20–0.40 | 0.85 | Light oxidation |
| Damaged | `#A09A88` (dull yellowed); rust blooms `#7A4A2C` at pitting | 0.60–0.85 | 0.55 | Pitted chrome |

Period chrome is triple-plated (copper-nickel-chrome). When pitted, copper undertones appear — add warm pink hint at pitting damage sites.

## Bumpers

Front and rear bumpers: painted steel tube body with chrome overrider bars. The bumper tube is upper-body-colour; overriders are chrome-plated.

| Part | Clean | Worn | Damaged |
|---|---|---|---|
| Tube albedo | `hero_cream_upper` | Scratches exposing primer `#3A342C` | Heavy scratches, exposed metal, rust |
| Tube roughness | 0.55 | 0.70 | 0.85 |
| Tube metalness | 0.0 | 0.0 | 0.0 (+ 0.7 on exposed metal) |
| Overriders albedo | `vw_roundel_chrome` | Dull | Pitted chrome + oxide |
| Overriders roughness | 0.08 | 0.25 | 0.70 |
| Overriders metalness | 1.0 | 0.9 | 0.5 |

Bumper mount brackets behind the tube are unpainted black-phosphate steel and can show through damaged areas.

## Rubber seals

Window gaskets, door weatherstripping, windshield perimeter seal.

| State | Albedo | Roughness | Metalness | Notes |
|---|---|---|---|---|
| Clean | `#1A1A1A` deep matte black | 0.90–0.95 | 0.0 | Essentially Lambertian rubber |
| Worn | `#252525` grey-brown from UV | 0.85 | 0.0 | Slight hardening, surface craze |
| Damaged | Cracked rubber, white chalking visible | 0.80 | 0.0 | Perished rubber look |

> [!note] Moss accumulation priority: rubber seals are high-priority contamination zones in the Verdant biome — seams and gaskets trap moisture and organic material. See [[Art/Vehicle — Contamination]].

## Glass (19 panels)

Windshield (upper + lower split panes), 6 side windows, 8 skylights, 2 rear corner windows, 1 rear window. All flat or mildly curved automotive glass.

| State | Albedo alpha | Roughness | Notes |
|---|---|---|---|
| Clean | 0.08 (nearly transparent, subtle green tint from period iron-content glass) | 0.0 | Mirror-smooth |
| Worn (default) | 0.12 (internal haze + water spot overlay) | 0.05 | Water spots, dirt streaks |
| Damaged (cracked) | Crack-pattern overlay as albedo (white lines on alpha) | 0.15 at cracks | |
| Damaged (shattered) | Crack pattern + additional displacement | 0.15 | |

> [!warning] **Do NOT replace the existing rain/wiper shader stack.**
> `src/scripts/bus/windshield_rain.gd` and `src/resources/windshield_rain_material.tres` are live in the codebase. Phase 3 glass materials must integrate with these, not replace them. The rain shader handles dynamic water droplets and wiper interaction. See [[Systems/Vehicle — Samba]] for the art integration constraint.

Period laminated windshield glass has a slight green tint from iron content in the glass — this is period correct. Apply a subtle green-cast transparency.

## Tyres

Four 5.60-15 bias-ply tyres on 15 in steel rims with painted hubcaps.

| State | Albedo | Roughness | Metalness | Notes |
|---|---|---|---|---|
| Clean | `#1A1A1A` deep matte black | 0.88 | 0.0 | Narrow bias-ply tread (NOT modern aggressive tread) |
| Worn (default) | `#202020` greyed from road dust | 0.85 | 0.0 | |
| Damaged (flat/detached) | Shredded rubber texture; exposed steel belt | 0.80 | 0.3 (steel belt) | At `damaged_threshold = 0.3` the tyre visually deflates |

Period tyre sidewalls show "5.60-15" or "165R15" branding plus manufacturer name. **Avoid modern all-terrain or aggressive tread.** This is a narrow-rib bias-ply profile.

## Texture variety sets (Phase 3)

Five full PBR variety sets (BaseColor, Roughness, Metallic, NormalMap) needed for the exterior panel groups:

| Variety | Description |
|---|---|
| `weathered` | Sun fading, chalky paint, minor surface rust at panel edges |
| `forest_worn` | Moss at seals, lichen on lower panels, sap streaks, bark scrapes |
| `muddy` | Mud splatter on lower panels and wheel arches |
| `rain_wet` | Wet sheen, water droplets, rain streaks, dark wet wheel arches |
| `deep_forest` | Heavy moss, fungal patches, years of accumulation |

## Godot material targets (proposed)

| Resource | Albedo slot | Roughness | Metalness |
|---|---|---|---|
| `van_body_upper.tres` | `hero_cream_upper` | 0.65 | 0.0 |
| `van_body_lower.tres` | `hero_teal_lower` | 0.65 | 0.0 |
| `van_chrome_trim.tres` | `vw_roundel_chrome` | 0.10 | 1.0 |
| `van_bumper_tube.tres` | `hero_cream_upper` | 0.55 | 0.0 |
| `van_glass.tres` | Color(1,1,1,0.08) | 0.0 | 0.0 |
| `van_tyre.tres` | `#1A1A1A` | 0.88 | 0.0 |
| `van_rubber_seal.tres` | `#1A1A1A` | 0.92 | 0.0 |

## Related

- [[Systems/Vehicle — Samba]] — implementation context; art integration constraint for glass shader
- [[Vehicle Palette Materials and Dimensions Discovery]] — palette derivation, archival paint codes, full PBR category list
- [[Art/Vehicle — Samba Dimensions]] — panel locations, window sizes, proportion anchors
- [[Art/Vehicle — Samba Interior]] — interior material targets
- [[Art/Vehicle — Contamination]] — contamination zones keyed to these exterior panels
- [[Art/Vehicle — Samba Acceptance Checklist]] — Phase 3 pass/fail criteria
- [[Art/Biome Ambient Palette]] — how exterior colours read under each biome ambient
- [[Art]] — folder MOC
- [[Vehicle — Domain MOC]] — domain MOC

Controlled tag vocabulary (as read):
type/*:
- `type/code` — Code architecture, autoloads, conventions, tooling. Carries `code-refs:`. (e.g. `Code/Autoloads — Disturbance.md`)
- `type/decision` — Architectural or design decision made by an agent during a session. Written to `docs/vault/Decisions/`. (Agent notes only — spec 080.)
- `type/design` — Design intent, player-facing concepts, world lore. (e.g. `Design/World Model.md`)
- `type/discovery` — Non-obvious constraint, gap, or conflict found by an agent during a session. Written to `docs/vault/Discoveries/`. (Agent notes only — spec 080.)
- `type/moc` — Map of Content at any of three tiers (folder / domain / concept). (e.g. `Audio.md`)
- `type/principle` — Governance and constitutional notes. Non-negotiable rules. (e.g. `Governance/Constitution.md`)
- `type/reference` — Glossary, decision log, open questions, epics. (e.g. `Reference/Glossary.md`)
- `type/session-log` — Session activity log; permanent audit trail. Written to `docs/vault/Sessions/`. Append-only, never pruned. (Agent notes only — spec 080.)
- `type/spec` — Spec document at `docs/vault/Specs/NNN Title/spec.md`. Carries `spec-refs:`. (e.g. `Specs/047 Car Radio/spec.md`)
- `type/system` — A bounded subsystem with implementation. Carries `code-refs`, `spec-refs`, `implements:` frontmatter. (e.g. `Systems/Audio — Car Radio.md`)
- `type/vision` — Strategic / vision-layer decision. Written to `docs/vault/Vision/`. Human-authored or agent-proposed with human ratification before promotion to `status: reviewed`. (Per triage #3 — spec 133 autonomous-company redesign.)
domain/*:
- `domain/anomalies` — Anomaly taxonomy, individual anomaly systems, spawn, behavior
- `domain/art` — Visual direction, palettes, references, asset pipeline
- `domain/audio` — Audio systems: world ambient, radio, transmissions, buses, pipeline
- `domain/autonomous-company` — Autonomous company v0.1 experiment: Slack infra, persona middleware, Letta integration, restart recovery
- `domain/build` — Build system, packaging, export, release automation
- `domain/governance` — Constitution, phased spec, policies
- `domain/infrastructure` — Infrastructure provisioning: CI/CD, hosting, deployment tooling, secrets management
- `domain/narrative` — Tone, horror register, forest transmissions narrative, Gary/KTLK
- `domain/player` — Player mode, input, controls, camera, exit/entry
- `domain/systems` — Cross-cutting system architecture and integration work
- `domain/tooling` — Build, CI, observer, TTS pipeline, dev-time tools
- `domain/vehicle` — The Samba: vehicle physics, dashboard, damage, panels
- `domain/world` — World model, biomes, terrain, procedural generation, weather
status/*:
- `status/canonical` — Fully authoritative; promoted by humans only. Highest trust. (Agent notes only — spec 080.)
- `status/draft` — Authoring in progress, not yet verified
- `status/reviewed` — Agent-created note verified against codebase within its creating session. Eligible for auto-injection in subsequent task dispatches. (Agent notes only — spec 080.)
- `status/stale` — Known out of date; cannot update immediately. Pairs with `> [!warning] STALE — needs update` callout.
- `status/superseded` — Replaced by another note. Terminal state. Pairs with `> [!warning] SUPERSEDED` callout.
- `status/wip` — Stable but under active revision
layer/*:
- `layer/content` — Content assets (audio, models, textures, audio provenance)
- `layer/gdext` — gdext wrapper layer (`rust/gdext-wrapper/`)
- `layer/gdscript` — GDScript (Godot scene-tier logic)
- `layer/infra` — Build, CI, deployment infrastructure
- `layer/python` — Python development tooling (`tools/`)
- `layer/rust-core` — Engine-agnostic Rust core (`rust/rust-core/`)
concept/*:
- `concept/biome` — Biome-reactive behavior across systems
- `concept/contamination` — Across-runs panel and garage degradation; the slow-horror mechanic that doesn't reset with the world
- `concept/diegetic` — Diegetic audio / UI / world-sourced design
- `concept/disturbance` — The disturbance mechanic thread (Article X)
- `concept/ephemeral-world` — Run-reset, transient worlds (Article IV Rules 6–7)
- `concept/governance` — Constitutional and governance concepts
- `concept/horror` — Horror register and dread design
- `concept/procedural` — Procedural generation, seed determinism
- `concept/rendering` — Visual rendering quality, shader correctness, Terrain3D integration, mesh fidelity, LOD, Z-fighting
- `concept/terrain` — Terrain generation, heightmap, Terrain3D regions, roughness, playability constraints
ember's answer for tag_assignment-art-vehicle-samba-exterior, type/referenceP(true) placed on the no, unsure, and yes zones.nounsureyesgold: yesP = 0.03

tag_assignment-art-vehicle-samba-exterior: type/spec

Tag assignment · test
Gold
The note has no reason to carry `type/spec` (False)
ember
The note calls for `type/spec`: Spec document at `docs/vault/Specs/NNN Title/spec.md`. Carries `spec-refs:`. (e.g. `Specs/047 Car Radio/spec.md`) (True)
Signal
P(true) 0.66 (unsure)
Kit outcome
deferred: treated as unsure
Why this gold label
Mined from Art/Vehicle — Samba Exterior.md at 692f4bb58b7f62105aeb73fba8dfee12bfdecd53; gold is the note's own vocabulary tags.
Vehicle — Samba Exterior

> **⚠️ PRE-068 NOTE — asset paths and material resource names will be verified when spec 068 ships.**
> Material `.tres` file paths are proposed targets. After 068 ships the purchased model, confirm resource names against the actual committed geometry. Spec 082 will reconcile.

This note covers PBR material specs for all exterior surfaces. For the palette derivation rationale and archival paint code research, see [[Vehicle Palette Materials and Dimensions Discovery]]. For dimensional anchors (panel locations, window sizes), see [[Art/Vehicle — Samba Dimensions]].

## Exterior panel diagram

![[_meta/attachments/vehicle/panels_exterior_callout.svg]]

## Hero palette (exterior)

| Slot | Name | sRGB hex | Linear RGB | Purpose |
|---|---|---|---|---|
| 1 | `hero_cream_upper` | `#D9D3BE` | `(0.675, 0.615, 0.513)` | Primary upper body paint |
| 2 | `hero_teal_lower` | `#3F6E66` | `(0.047, 0.154, 0.138)` | Primary lower body paint |
| 3 | `weathered_cream_upper` | `#C9C2AB` | `(0.581, 0.529, 0.418)` | Sun-faded upper (roof peaks, raised surfaces) |
| 4 | `weathered_teal_lower` | `#355A56` | `(0.032, 0.103, 0.097)` | Sun-faded lower (hood front, running boards, rockers) |
| 5 | `trim_beltline` | `#B5B0A3` | `(0.453, 0.421, 0.363)` | Chrome decorative strip with tarnish |
| 6 | `vw_roundel_chrome` | `#D4D0C5` | `(0.646, 0.613, 0.546)` | VW badge and bright chrome trim |
| 7 | `shadow_deep` | `#1B2E2A` | `(0.009, 0.028, 0.024)` | AO reference / deep crevice shadow colour |

**Archival anchor**: Option B — L289 Blue White / L380 Turquoise. Hero palette is intentionally adjusted from archival codes for moodboard alignment; values above are the production target, not the factory codes. See [[Vehicle Palette Materials and Dimensions Discovery]] for the full archival baseline.

**Two-tone boundary rule**: The paint boundary is a hard seam at the chrome beltline strip. Paint does NOT gradient-blend. Model the beltline as a separate bevelled feature; assign upper and lower paint as two distinct material slots.

## Painted body

Covers: nose cone, hood front, all fenders, all side panels, roof panels, engine hatch, all doors, running boards where painted.

**Panel IDs**: `nose_cone`, `hood_front`, `engine_hatch`, `panel_front_lower`, `fender_front_left`, `fender_front_right`, `fender_rear_left`, `fender_rear_right`, `panel_side_left_front/mid/rear`, `panel_side_right_front/mid/rear`, `door_left_front`, `door_right_front`, `door_rear_left`, `door_rear_right`, `panel_rear_upper`, `roof_panel_front/mid/rear`, `running_board_left`, `running_board_right`.

### PBR rules (all states)
- **Metalness**: 0.0 — non-metallic nitrocellulose lacquer. No metallic flake.
- **Clearcoat**: DISABLED — 1963 paint was not clearcoated.
- **Two-tone**: hard seam at chrome beltline; two separate material instances above and below.

### Clean state
| Property | Upper | Lower |
|---|---|---|
| Albedo | `hero_cream_upper` | `hero_teal_lower` |
| Roughness | 0.55–0.65 | 0.55–0.65 |
| Normal | Subtle panel-seam + minor hand-beaten imperfections (period-correct) | Same |
| AO | Panel-seam and wheel-arch bake | Same |

### Worn state (default Old Growth game state)
| Property | Upper | Lower |
|---|---|---|
| Albedo | `hero_cream_upper` → `weathered_cream_upper` blend (60/40 worn) | `hero_teal_lower` → `weathered_teal_lower` blend |
| Roughness | 0.65–0.80 (lost gloss; worse on horizontal surfaces) | Same |
| Normal | Paint chips at panel edges, fender tops, hood corners; minor hail-type dimples on horizontal surfaces | Same |
| Weathering mask | World-up normal + panel edge proximity + wheel-well proximity | Same |

### Damaged state (heavy wear)
| Property | Upper | Lower |
|---|---|---|
| Albedo | `weathered_cream_upper` + primer `#8A7E68` in exposed spots + rust `#7A4A2C` at edges | `weathered_teal_lower` + exposed metal |
| Roughness | 0.80–0.95 (matte, oxidised) | Same |
| Metalness | 0.0 on paint; 0.7 on bare metal | Same |
| Normal | Deep paint loss patches, real dents, bent panels, visible panel seam displacement | Same |
| Rust layer | Colour `#7A4A2C`, roughness 0.95, metalness 0.2 (oxidised iron has partial metallic character) | Same |

**Wet state modifier**: roughness drops ~0.10; specular rises. See `src/assets/shaders/rain_on_glass.gdshader` for wet-surface shader reference.

## Chrome trim

Decorative chrome bright trim: beltline strip, window surrounds, VW roundel badge, door handles, headlight bezels, bumper overriders, side mirror housings, radio fascia bezel.

| State | Albedo | Roughness | Metalness | Notes |
|---|---|---|---|---|
| Clean | `vw_roundel_chrome` (#D4D0C5), slightly cooler | 0.05–0.15 | 1.0 | Mirror polish |
| Worn (default) | Same + subtle yellowed patches | 0.20–0.40 | 0.85 | Light oxidation |
| Damaged | `#A09A88` (dull yellowed); rust blooms `#7A4A2C` at pitting | 0.60–0.85 | 0.55 | Pitted chrome |

Period chrome is triple-plated (copper-nickel-chrome). When pitted, copper undertones appear — add warm pink hint at pitting damage sites.

## Bumpers

Front and rear bumpers: painted steel tube body with chrome overrider bars. The bumper tube is upper-body-colour; overriders are chrome-plated.

| Part | Clean | Worn | Damaged |
|---|---|---|---|
| Tube albedo | `hero_cream_upper` | Scratches exposing primer `#3A342C` | Heavy scratches, exposed metal, rust |
| Tube roughness | 0.55 | 0.70 | 0.85 |
| Tube metalness | 0.0 | 0.0 | 0.0 (+ 0.7 on exposed metal) |
| Overriders albedo | `vw_roundel_chrome` | Dull | Pitted chrome + oxide |
| Overriders roughness | 0.08 | 0.25 | 0.70 |
| Overriders metalness | 1.0 | 0.9 | 0.5 |

Bumper mount brackets behind the tube are unpainted black-phosphate steel and can show through damaged areas.

## Rubber seals

Window gaskets, door weatherstripping, windshield perimeter seal.

| State | Albedo | Roughness | Metalness | Notes |
|---|---|---|---|---|
| Clean | `#1A1A1A` deep matte black | 0.90–0.95 | 0.0 | Essentially Lambertian rubber |
| Worn | `#252525` grey-brown from UV | 0.85 | 0.0 | Slight hardening, surface craze |
| Damaged | Cracked rubber, white chalking visible | 0.80 | 0.0 | Perished rubber look |

> [!note] Moss accumulation priority: rubber seals are high-priority contamination zones in the Verdant biome — seams and gaskets trap moisture and organic material. See [[Art/Vehicle — Contamination]].

## Glass (19 panels)

Windshield (upper + lower split panes), 6 side windows, 8 skylights, 2 rear corner windows, 1 rear window. All flat or mildly curved automotive glass.

| State | Albedo alpha | Roughness | Notes |
|---|---|---|---|
| Clean | 0.08 (nearly transparent, subtle green tint from period iron-content glass) | 0.0 | Mirror-smooth |
| Worn (default) | 0.12 (internal haze + water spot overlay) | 0.05 | Water spots, dirt streaks |
| Damaged (cracked) | Crack-pattern overlay as albedo (white lines on alpha) | 0.15 at cracks | |
| Damaged (shattered) | Crack pattern + additional displacement | 0.15 | |

> [!warning] **Do NOT replace the existing rain/wiper shader stack.**
> `src/scripts/bus/windshield_rain.gd` and `src/resources/windshield_rain_material.tres` are live in the codebase. Phase 3 glass materials must integrate with these, not replace them. The rain shader handles dynamic water droplets and wiper interaction. See [[Systems/Vehicle — Samba]] for the art integration constraint.

Period laminated windshield glass has a slight green tint from iron content in the glass — this is period correct. Apply a subtle green-cast transparency.

## Tyres

Four 5.60-15 bias-ply tyres on 15 in steel rims with painted hubcaps.

| State | Albedo | Roughness | Metalness | Notes |
|---|---|---|---|---|
| Clean | `#1A1A1A` deep matte black | 0.88 | 0.0 | Narrow bias-ply tread (NOT modern aggressive tread) |
| Worn (default) | `#202020` greyed from road dust | 0.85 | 0.0 | |
| Damaged (flat/detached) | Shredded rubber texture; exposed steel belt | 0.80 | 0.3 (steel belt) | At `damaged_threshold = 0.3` the tyre visually deflates |

Period tyre sidewalls show "5.60-15" or "165R15" branding plus manufacturer name. **Avoid modern all-terrain or aggressive tread.** This is a narrow-rib bias-ply profile.

## Texture variety sets (Phase 3)

Five full PBR variety sets (BaseColor, Roughness, Metallic, NormalMap) needed for the exterior panel groups:

| Variety | Description |
|---|---|
| `weathered` | Sun fading, chalky paint, minor surface rust at panel edges |
| `forest_worn` | Moss at seals, lichen on lower panels, sap streaks, bark scrapes |
| `muddy` | Mud splatter on lower panels and wheel arches |
| `rain_wet` | Wet sheen, water droplets, rain streaks, dark wet wheel arches |
| `deep_forest` | Heavy moss, fungal patches, years of accumulation |

## Godot material targets (proposed)

| Resource | Albedo slot | Roughness | Metalness |
|---|---|---|---|
| `van_body_upper.tres` | `hero_cream_upper` | 0.65 | 0.0 |
| `van_body_lower.tres` | `hero_teal_lower` | 0.65 | 0.0 |
| `van_chrome_trim.tres` | `vw_roundel_chrome` | 0.10 | 1.0 |
| `van_bumper_tube.tres` | `hero_cream_upper` | 0.55 | 0.0 |
| `van_glass.tres` | Color(1,1,1,0.08) | 0.0 | 0.0 |
| `van_tyre.tres` | `#1A1A1A` | 0.88 | 0.0 |
| `van_rubber_seal.tres` | `#1A1A1A` | 0.92 | 0.0 |

## Related

- [[Systems/Vehicle — Samba]] — implementation context; art integration constraint for glass shader
- [[Vehicle Palette Materials and Dimensions Discovery]] — palette derivation, archival paint codes, full PBR category list
- [[Art/Vehicle — Samba Dimensions]] — panel locations, window sizes, proportion anchors
- [[Art/Vehicle — Samba Interior]] — interior material targets
- [[Art/Vehicle — Contamination]] — contamination zones keyed to these exterior panels
- [[Art/Vehicle — Samba Acceptance Checklist]] — Phase 3 pass/fail criteria
- [[Art/Biome Ambient Palette]] — how exterior colours read under each biome ambient
- [[Art]] — folder MOC
- [[Vehicle — Domain MOC]] — domain MOC

Controlled tag vocabulary (as read):
type/*:
- `type/code` — Code architecture, autoloads, conventions, tooling. Carries `code-refs:`. (e.g. `Code/Autoloads — Disturbance.md`)
- `type/decision` — Architectural or design decision made by an agent during a session. Written to `docs/vault/Decisions/`. (Agent notes only — spec 080.)
- `type/design` — Design intent, player-facing concepts, world lore. (e.g. `Design/World Model.md`)
- `type/discovery` — Non-obvious constraint, gap, or conflict found by an agent during a session. Written to `docs/vault/Discoveries/`. (Agent notes only — spec 080.)
- `type/moc` — Map of Content at any of three tiers (folder / domain / concept). (e.g. `Audio.md`)
- `type/principle` — Governance and constitutional notes. Non-negotiable rules. (e.g. `Governance/Constitution.md`)
- `type/reference` — Glossary, decision log, open questions, epics. (e.g. `Reference/Glossary.md`)
- `type/session-log` — Session activity log; permanent audit trail. Written to `docs/vault/Sessions/`. Append-only, never pruned. (Agent notes only — spec 080.)
- `type/spec` — Spec document at `docs/vault/Specs/NNN Title/spec.md`. Carries `spec-refs:`. (e.g. `Specs/047 Car Radio/spec.md`)
- `type/system` — A bounded subsystem with implementation. Carries `code-refs`, `spec-refs`, `implements:` frontmatter. (e.g. `Systems/Audio — Car Radio.md`)
- `type/vision` — Strategic / vision-layer decision. Written to `docs/vault/Vision/`. Human-authored or agent-proposed with human ratification before promotion to `status: reviewed`. (Per triage #3 — spec 133 autonomous-company redesign.)
domain/*:
- `domain/anomalies` — Anomaly taxonomy, individual anomaly systems, spawn, behavior
- `domain/art` — Visual direction, palettes, references, asset pipeline
- `domain/audio` — Audio systems: world ambient, radio, transmissions, buses, pipeline
- `domain/autonomous-company` — Autonomous company v0.1 experiment: Slack infra, persona middleware, Letta integration, restart recovery
- `domain/build` — Build system, packaging, export, release automation
- `domain/governance` — Constitution, phased spec, policies
- `domain/infrastructure` — Infrastructure provisioning: CI/CD, hosting, deployment tooling, secrets management
- `domain/narrative` — Tone, horror register, forest transmissions narrative, Gary/KTLK
- `domain/player` — Player mode, input, controls, camera, exit/entry
- `domain/systems` — Cross-cutting system architecture and integration work
- `domain/tooling` — Build, CI, observer, TTS pipeline, dev-time tools
- `domain/vehicle` — The Samba: vehicle physics, dashboard, damage, panels
- `domain/world` — World model, biomes, terrain, procedural generation, weather
status/*:
- `status/canonical` — Fully authoritative; promoted by humans only. Highest trust. (Agent notes only — spec 080.)
- `status/draft` — Authoring in progress, not yet verified
- `status/reviewed` — Agent-created note verified against codebase within its creating session. Eligible for auto-injection in subsequent task dispatches. (Agent notes only — spec 080.)
- `status/stale` — Known out of date; cannot update immediately. Pairs with `> [!warning] STALE — needs update` callout.
- `status/superseded` — Replaced by another note. Terminal state. Pairs with `> [!warning] SUPERSEDED` callout.
- `status/wip` — Stable but under active revision
layer/*:
- `layer/content` — Content assets (audio, models, textures, audio provenance)
- `layer/gdext` — gdext wrapper layer (`rust/gdext-wrapper/`)
- `layer/gdscript` — GDScript (Godot scene-tier logic)
- `layer/infra` — Build, CI, deployment infrastructure
- `layer/python` — Python development tooling (`tools/`)
- `layer/rust-core` — Engine-agnostic Rust core (`rust/rust-core/`)
concept/*:
- `concept/biome` — Biome-reactive behavior across systems
- `concept/contamination` — Across-runs panel and garage degradation; the slow-horror mechanic that doesn't reset with the world
- `concept/diegetic` — Diegetic audio / UI / world-sourced design
- `concept/disturbance` — The disturbance mechanic thread (Article X)
- `concept/ephemeral-world` — Run-reset, transient worlds (Article IV Rules 6–7)
- `concept/governance` — Constitutional and governance concepts
- `concept/horror` — Horror register and dread design
- `concept/procedural` — Procedural generation, seed determinism
- `concept/rendering` — Visual rendering quality, shader correctness, Terrain3D integration, mesh fidelity, LOD, Z-fighting
- `concept/terrain` — Terrain generation, heightmap, Terrain3D regions, roughness, playability constraints
ember's answer for tag_assignment-art-vehicle-samba-exterior, type/specP(true) placed on the no, unsure, and yes zones.nounsureyesgold: noP = 0.66

tag_assignment-sessions-spec-098-weather-effects-implementation-apr-25-2026: layer/gdscript

Tag assignment · test
Gold
The note calls for `layer/gdscript`: GDScript (Godot scene-tier logic) (True)
ember
The note has no reason to carry `layer/gdscript` (False)
Signal
P(true) 0.23 (unsure)
Kit outcome
deferred: treated as unsure
Why this gold label
Mined from Sessions/Spec 098 Weather Effects Implementation — Apr 25 2026.md at 692f4bb58b7f62105aeb73fba8dfee12bfdecd53; gold is the note's own vocabulary tags.
Spec 098 Weather Effects Implementation — Apr 25 2026

Implementation session for spec 098 (Weather Effects Completion). All 12 phases executed via parallel agent delegation in a single session.

## What Was Built

### Windshield SOLID Hierarchy
- `windshield_overlay_base.gd` — abstract base (push_error guards on 5 abstract methods)
- `rain_overlay.gd` — migrated all logic from deleted `windshield_rain.gd`
- `snow_overlay.gd` — opaque white accumulation (LIGHT_SNOW→0.3, HEAVY_SNOW→0.7, BLIZZARD→1.0)
- `spore_film_overlay.gd` + `spore_film.gdshader` — amber-blue film, smear-not-clear wiper behavior
- `frost_overlay.gd` + `windshield_frost.gdshader` — 60s delay, edge-inward growth, wiper-immune
- `windshield_controller.gd` — coordinator routing all 4 overlays

### Particle Systems
- `weather_effects_controller.gd` — Node3D with QualityTier enum; snow/spore/ash GPUParticles3D
- `on_foot_weather_particles.gd` — mirrors on_foot_rain_particles.gd for snow/spore/ash/hail

### Audio Controllers
- `wind_audio_controller.gd` — interior/exterior split, volume = lerpf(WIND_SILENT_DB, WIND_MAX_DB, wind)
- `dead_calm_audio_controller.gd` — sub-bass fade-in/-out at -45 dB on Ambience bus
- `instrument_disruption_handler.gd` — FLICKER/OSCILLATE patterns, graceful no-op when needles absent

### Game Systems
- `lightning_controller.gd` — seeded RNG (seed + 9173), discharge timer, WorldEnvironment flash, thunder audio, instrument_disruption_changed emission, ELECTRICAL_STORM crackle + radio static
- `on_foot_controller.gd` — wind_speed_penalty_scale + _wind_mult, get_target_speed() × _wind_mult
- `rain_audio_controller.gd` — additive hail audio branch (is_hail + THUNDERSTORM)
- `rain_particles_controller.gd` — hail particle swap during THUNDERSTORM+is_hail
- `fog_system.gd` — ELECTRICAL_STORM_SKY_COLOR tween (Color(0.25, 0.0, 0.4)) over 3.0s
- `wet_road_controller.gd` — ash road coating via albedo lerp + roughness delta
- `disturbance_storm_audio.gd` — preloaded _STORM_ROAR_STREAM const

### Assets
- 16 audio placeholder .ogg files in `src/assets/audio/ambient/weather/`
- `src/assets/audio/ambient/weather/gold/.gdignore` — non-shippable gold masters excluded
- `src/resources/windshield_snow_material.tres` — snow shader material

## CI Results
- `make gdscript-quality`: ✅ 146 files, no violations
- `make test`: ✅ 934/935 passing (1 pre-existing risky)
- `make headless`: ✅ clean
- `make all`: ✅ including export smoke test

## SemVer Bumps Applied
All 8 required bumps exceeded: core-autoloads→0.24.0, bus→0.33.2, weather→0.19.2, on-foot-controller→0.10.1, assets→0.22.2, terrain→2.15.1, world-generation→0.53.5, tests→0.60.3

## Post-Implementation Work (same session)

### Audio Pipeline (completed)
- 14 fake placeholder OGGs removed from submodule; 2 real blizzard wind OGGs retained
- 18 Suno provenance JSON sidecars written to `src/assets/audio/ambient/weather/gold/` (16 spec-098 + 2 pre-existing rain OGGs co-located)
- `tools/tts/ambient_process.sh` — new ffmpeg pipeline for Suno ambient audio (loop/oneshot modes)
- `tools/tts/validate_ambient_naming.sh` + `validate_ambient_provenance.sh` — CI validation for 18 assets
- `tools/tts/Makefile` extended with `ambient-weather-*` targets; `validate-names`/`validate-provenance` now cover ambient/weather
- `rain_heavy_interior.ogg` + `rain_light_interior.ogg` moved from `ambient/` to `ambient/weather/` and renamed with `weather_` prefix for consistency
- AGENTS.md + `audio-assets` SKILL.md updated with full ambient weather production workflow
- Vault discovery note written: `Discoveries/Audio Generation Pipeline Constraints & Patterns.md` (consolidated note)

### Scene Wiring via Godot MCP (completed)
All previously-deferred scene wiring completed via Godot editor MCP:

**`generated_world.tscn`:**
- `WeatherEffectsController` (Node3D + script) with `SnowParticles`, `SporeParticles`, `AshParticles` (GPUParticles3D, particle materials assigned, NodePaths wired)
- `LightningController` (Node + script)

**`samba_bus.tscn`:**
- `HailParticles` (GPUParticles3D, wired to `RainParticlesController.hail_particles_path`)
- `WindAudioController` (Node + script) with `WindInterior` (Interior bus) + `WindExterior` (Ambience bus)
- `InstrumentDisruptionHandler` (Node + script, `needle_paths=[]` — graceful no-op until spec 033)
- `DeadCalmAudioController` (Node + script) with `SubBassPlayer` (Ambience bus)

**`on_foot_player.tscn`:**
- `OnFootWeatherParticles` (Node + script) with `SnowParticlesOnFoot`, `SporeParticlesOnFoot`, `AshParticlesOnFoot`, `HailParticlesOnFoot`

**`src/resources/particles/`:** 4 new `ParticleProcessMaterial` .tres resources (snow, spore, ash, hail)

### Bug Fixes (discovered during scene wiring)
- 3 audio controllers had `const preload()` for pending Suno OGGs — fixed to `ResourceLoader.exists()` + runtime `load()` with `Debug.warn()` fallback: `dead_calm_audio_controller.gd`, `disturbance_storm_audio.gd`, `rain_audio_controller.gd`
- 11 Oracle-identified bugs fixed post-review (spore/frost delta=0, hail null guard, material ownership, wind tween split, etc.)

## Still Pending (human tasks)
- ~~14 Suno audio assets not yet produced (code gracefully silent until installed)~~ — ✅ complete: all 18 ElevenLabs SFX V2 OGGs produced and installed (pipeline switched from Suno to ElevenLabs; see [[Audio Generation Pipeline Constraints & Patterns]]); `validate-ambient-naming` and `validate-ambient-provenance` pass clean
- T085: Game version bump (human decision per Art III R15)
- spec 033 dashboard needles (for `InstrumentDisruptionHandler` to have actual needle NodePaths)

Controlled tag vocabulary (as read):
type/*:
- `type/code` — Code architecture, autoloads, conventions, tooling. Carries `code-refs:`. (e.g. `Code/Autoloads — Disturbance.md`)
- `type/decision` — Architectural or design decision made by an agent during a session. Written to `docs/vault/Decisions/`. (Agent notes only — spec 080.)
- `type/design` — Design intent, player-facing concepts, world lore. (e.g. `Design/World Model.md`)
- `type/discovery` — Non-obvious constraint, gap, or conflict found by an agent during a session. Written to `docs/vault/Discoveries/`. (Agent notes only — spec 080.)
- `type/moc` — Map of Content at any of three tiers (folder / domain / concept). (e.g. `Audio.md`)
- `type/principle` — Governance and constitutional notes. Non-negotiable rules. (e.g. `Governance/Constitution.md`)
- `type/reference` — Glossary, decision log, open questions, epics. (e.g. `Reference/Glossary.md`)
- `type/session-log` — Session activity log; permanent audit trail. Written to `docs/vault/Sessions/`. Append-only, never pruned. (Agent notes only — spec 080.)
- `type/spec` — Spec document at `docs/vault/Specs/NNN Title/spec.md`. Carries `spec-refs:`. (e.g. `Specs/047 Car Radio/spec.md`)
- `type/system` — A bounded subsystem with implementation. Carries `code-refs`, `spec-refs`, `implements:` frontmatter. (e.g. `Systems/Audio — Car Radio.md`)
- `type/vision` — Strategic / vision-layer decision. Written to `docs/vault/Vision/`. Human-authored or agent-proposed with human ratification before promotion to `status: reviewed`. (Per triage #3 — spec 133 autonomous-company redesign.)
domain/*:
- `domain/anomalies` — Anomaly taxonomy, individual anomaly systems, spawn, behavior
- `domain/art` — Visual direction, palettes, references, asset pipeline
- `domain/audio` — Audio systems: world ambient, radio, transmissions, buses, pipeline
- `domain/autonomous-company` — Autonomous company v0.1 experiment: Slack infra, persona middleware, Letta integration, restart recovery
- `domain/build` — Build system, packaging, export, release automation
- `domain/governance` — Constitution, phased spec, policies
- `domain/infrastructure` — Infrastructure provisioning: CI/CD, hosting, deployment tooling, secrets management
- `domain/narrative` — Tone, horror register, forest transmissions narrative, Gary/KTLK
- `domain/player` — Player mode, input, controls, camera, exit/entry
- `domain/systems` — Cross-cutting system architecture and integration work
- `domain/tooling` — Build, CI, observer, TTS pipeline, dev-time tools
- `domain/vehicle` — The Samba: vehicle physics, dashboard, damage, panels
- `domain/world` — World model, biomes, terrain, procedural generation, weather
status/*:
- `status/canonical` — Fully authoritative; promoted by humans only. Highest trust. (Agent notes only — spec 080.)
- `status/draft` — Authoring in progress, not yet verified
- `status/reviewed` — Agent-created note verified against codebase within its creating session. Eligible for auto-injection in subsequent task dispatches. (Agent notes only — spec 080.)
- `status/stale` — Known out of date; cannot update immediately. Pairs with `> [!warning] STALE — needs update` callout.
- `status/superseded` — Replaced by another note. Terminal state. Pairs with `> [!warning] SUPERSEDED` callout.
- `status/wip` — Stable but under active revision
layer/*:
- `layer/content` — Content assets (audio, models, textures, audio provenance)
- `layer/gdext` — gdext wrapper layer (`rust/gdext-wrapper/`)
- `layer/gdscript` — GDScript (Godot scene-tier logic)
- `layer/infra` — Build, CI, deployment infrastructure
- `layer/python` — Python development tooling (`tools/`)
- `layer/rust-core` — Engine-agnostic Rust core (`rust/rust-core/`)
concept/*:
- `concept/biome` — Biome-reactive behavior across systems
- `concept/contamination` — Across-runs panel and garage degradation; the slow-horror mechanic that doesn't reset with the world
- `concept/diegetic` — Diegetic audio / UI / world-sourced design
- `concept/disturbance` — The disturbance mechanic thread (Article X)
- `concept/ephemeral-world` — Run-reset, transient worlds (Article IV Rules 6–7)
- `concept/governance` — Constitutional and governance concepts
- `concept/horror` — Horror register and dread design
- `concept/procedural` — Procedural generation, seed determinism
- `concept/rendering` — Visual rendering quality, shader correctness, Terrain3D integration, mesh fidelity, LOD, Z-fighting
- `concept/terrain` — Terrain generation, heightmap, Terrain3D regions, roughness, playability constraints
ember's answer for tag_assignment-sessions-spec-098-weather-effects-implementation-apr-25-2026, layer/gdscriptP(true) placed on the no, unsure, and yes zones.nounsureyesgold: yesP = 0.23

tag_assignment-sessions-spec-098-weather-effects-implementation-apr-25-2026: status/reviewed

Tag assignment · test
Gold
The note calls for `status/reviewed`: Agent-created note verified against codebase within its creating session. Eligible for auto-injection in subsequent task dispatches. (Agent notes only — spec 080.) (True)
ember
The note has no reason to carry `status/reviewed` (False)
Signal
P(true) 0.48 (unsure)
Kit outcome
deferred: treated as unsure
Why this gold label
Mined from Sessions/Spec 098 Weather Effects Implementation — Apr 25 2026.md at 692f4bb58b7f62105aeb73fba8dfee12bfdecd53; gold is the note's own vocabulary tags.
Spec 098 Weather Effects Implementation — Apr 25 2026

Implementation session for spec 098 (Weather Effects Completion). All 12 phases executed via parallel agent delegation in a single session.

## What Was Built

### Windshield SOLID Hierarchy
- `windshield_overlay_base.gd` — abstract base (push_error guards on 5 abstract methods)
- `rain_overlay.gd` — migrated all logic from deleted `windshield_rain.gd`
- `snow_overlay.gd` — opaque white accumulation (LIGHT_SNOW→0.3, HEAVY_SNOW→0.7, BLIZZARD→1.0)
- `spore_film_overlay.gd` + `spore_film.gdshader` — amber-blue film, smear-not-clear wiper behavior
- `frost_overlay.gd` + `windshield_frost.gdshader` — 60s delay, edge-inward growth, wiper-immune
- `windshield_controller.gd` — coordinator routing all 4 overlays

### Particle Systems
- `weather_effects_controller.gd` — Node3D with QualityTier enum; snow/spore/ash GPUParticles3D
- `on_foot_weather_particles.gd` — mirrors on_foot_rain_particles.gd for snow/spore/ash/hail

### Audio Controllers
- `wind_audio_controller.gd` — interior/exterior split, volume = lerpf(WIND_SILENT_DB, WIND_MAX_DB, wind)
- `dead_calm_audio_controller.gd` — sub-bass fade-in/-out at -45 dB on Ambience bus
- `instrument_disruption_handler.gd` — FLICKER/OSCILLATE patterns, graceful no-op when needles absent

### Game Systems
- `lightning_controller.gd` — seeded RNG (seed + 9173), discharge timer, WorldEnvironment flash, thunder audio, instrument_disruption_changed emission, ELECTRICAL_STORM crackle + radio static
- `on_foot_controller.gd` — wind_speed_penalty_scale + _wind_mult, get_target_speed() × _wind_mult
- `rain_audio_controller.gd` — additive hail audio branch (is_hail + THUNDERSTORM)
- `rain_particles_controller.gd` — hail particle swap during THUNDERSTORM+is_hail
- `fog_system.gd` — ELECTRICAL_STORM_SKY_COLOR tween (Color(0.25, 0.0, 0.4)) over 3.0s
- `wet_road_controller.gd` — ash road coating via albedo lerp + roughness delta
- `disturbance_storm_audio.gd` — preloaded _STORM_ROAR_STREAM const

### Assets
- 16 audio placeholder .ogg files in `src/assets/audio/ambient/weather/`
- `src/assets/audio/ambient/weather/gold/.gdignore` — non-shippable gold masters excluded
- `src/resources/windshield_snow_material.tres` — snow shader material

## CI Results
- `make gdscript-quality`: ✅ 146 files, no violations
- `make test`: ✅ 934/935 passing (1 pre-existing risky)
- `make headless`: ✅ clean
- `make all`: ✅ including export smoke test

## SemVer Bumps Applied
All 8 required bumps exceeded: core-autoloads→0.24.0, bus→0.33.2, weather→0.19.2, on-foot-controller→0.10.1, assets→0.22.2, terrain→2.15.1, world-generation→0.53.5, tests→0.60.3

## Post-Implementation Work (same session)

### Audio Pipeline (completed)
- 14 fake placeholder OGGs removed from submodule; 2 real blizzard wind OGGs retained
- 18 Suno provenance JSON sidecars written to `src/assets/audio/ambient/weather/gold/` (16 spec-098 + 2 pre-existing rain OGGs co-located)
- `tools/tts/ambient_process.sh` — new ffmpeg pipeline for Suno ambient audio (loop/oneshot modes)
- `tools/tts/validate_ambient_naming.sh` + `validate_ambient_provenance.sh` — CI validation for 18 assets
- `tools/tts/Makefile` extended with `ambient-weather-*` targets; `validate-names`/`validate-provenance` now cover ambient/weather
- `rain_heavy_interior.ogg` + `rain_light_interior.ogg` moved from `ambient/` to `ambient/weather/` and renamed with `weather_` prefix for consistency
- AGENTS.md + `audio-assets` SKILL.md updated with full ambient weather production workflow
- Vault discovery note written: `Discoveries/Audio Generation Pipeline Constraints & Patterns.md` (consolidated note)

### Scene Wiring via Godot MCP (completed)
All previously-deferred scene wiring completed via Godot editor MCP:

**`generated_world.tscn`:**
- `WeatherEffectsController` (Node3D + script) with `SnowParticles`, `SporeParticles`, `AshParticles` (GPUParticles3D, particle materials assigned, NodePaths wired)
- `LightningController` (Node + script)

**`samba_bus.tscn`:**
- `HailParticles` (GPUParticles3D, wired to `RainParticlesController.hail_particles_path`)
- `WindAudioController` (Node + script) with `WindInterior` (Interior bus) + `WindExterior` (Ambience bus)
- `InstrumentDisruptionHandler` (Node + script, `needle_paths=[]` — graceful no-op until spec 033)
- `DeadCalmAudioController` (Node + script) with `SubBassPlayer` (Ambience bus)

**`on_foot_player.tscn`:**
- `OnFootWeatherParticles` (Node + script) with `SnowParticlesOnFoot`, `SporeParticlesOnFoot`, `AshParticlesOnFoot`, `HailParticlesOnFoot`

**`src/resources/particles/`:** 4 new `ParticleProcessMaterial` .tres resources (snow, spore, ash, hail)

### Bug Fixes (discovered during scene wiring)
- 3 audio controllers had `const preload()` for pending Suno OGGs — fixed to `ResourceLoader.exists()` + runtime `load()` with `Debug.warn()` fallback: `dead_calm_audio_controller.gd`, `disturbance_storm_audio.gd`, `rain_audio_controller.gd`
- 11 Oracle-identified bugs fixed post-review (spore/frost delta=0, hail null guard, material ownership, wind tween split, etc.)

## Still Pending (human tasks)
- ~~14 Suno audio assets not yet produced (code gracefully silent until installed)~~ — ✅ complete: all 18 ElevenLabs SFX V2 OGGs produced and installed (pipeline switched from Suno to ElevenLabs; see [[Audio Generation Pipeline Constraints & Patterns]]); `validate-ambient-naming` and `validate-ambient-provenance` pass clean
- T085: Game version bump (human decision per Art III R15)
- spec 033 dashboard needles (for `InstrumentDisruptionHandler` to have actual needle NodePaths)

Controlled tag vocabulary (as read):
type/*:
- `type/code` — Code architecture, autoloads, conventions, tooling. Carries `code-refs:`. (e.g. `Code/Autoloads — Disturbance.md`)
- `type/decision` — Architectural or design decision made by an agent during a session. Written to `docs/vault/Decisions/`. (Agent notes only — spec 080.)
- `type/design` — Design intent, player-facing concepts, world lore. (e.g. `Design/World Model.md`)
- `type/discovery` — Non-obvious constraint, gap, or conflict found by an agent during a session. Written to `docs/vault/Discoveries/`. (Agent notes only — spec 080.)
- `type/moc` — Map of Content at any of three tiers (folder / domain / concept). (e.g. `Audio.md`)
- `type/principle` — Governance and constitutional notes. Non-negotiable rules. (e.g. `Governance/Constitution.md`)
- `type/reference` — Glossary, decision log, open questions, epics. (e.g. `Reference/Glossary.md`)
- `type/session-log` — Session activity log; permanent audit trail. Written to `docs/vault/Sessions/`. Append-only, never pruned. (Agent notes only — spec 080.)
- `type/spec` — Spec document at `docs/vault/Specs/NNN Title/spec.md`. Carries `spec-refs:`. (e.g. `Specs/047 Car Radio/spec.md`)
- `type/system` — A bounded subsystem with implementation. Carries `code-refs`, `spec-refs`, `implements:` frontmatter. (e.g. `Systems/Audio — Car Radio.md`)
- `type/vision` — Strategic / vision-layer decision. Written to `docs/vault/Vision/`. Human-authored or agent-proposed with human ratification before promotion to `status: reviewed`. (Per triage #3 — spec 133 autonomous-company redesign.)
domain/*:
- `domain/anomalies` — Anomaly taxonomy, individual anomaly systems, spawn, behavior
- `domain/art` — Visual direction, palettes, references, asset pipeline
- `domain/audio` — Audio systems: world ambient, radio, transmissions, buses, pipeline
- `domain/autonomous-company` — Autonomous company v0.1 experiment: Slack infra, persona middleware, Letta integration, restart recovery
- `domain/build` — Build system, packaging, export, release automation
- `domain/governance` — Constitution, phased spec, policies
- `domain/infrastructure` — Infrastructure provisioning: CI/CD, hosting, deployment tooling, secrets management
- `domain/narrative` — Tone, horror register, forest transmissions narrative, Gary/KTLK
- `domain/player` — Player mode, input, controls, camera, exit/entry
- `domain/systems` — Cross-cutting system architecture and integration work
- `domain/tooling` — Build, CI, observer, TTS pipeline, dev-time tools
- `domain/vehicle` — The Samba: vehicle physics, dashboard, damage, panels
- `domain/world` — World model, biomes, terrain, procedural generation, weather
status/*:
- `status/canonical` — Fully authoritative; promoted by humans only. Highest trust. (Agent notes only — spec 080.)
- `status/draft` — Authoring in progress, not yet verified
- `status/reviewed` — Agent-created note verified against codebase within its creating session. Eligible for auto-injection in subsequent task dispatches. (Agent notes only — spec 080.)
- `status/stale` — Known out of date; cannot update immediately. Pairs with `> [!warning] STALE — needs update` callout.
- `status/superseded` — Replaced by another note. Terminal state. Pairs with `> [!warning] SUPERSEDED` callout.
- `status/wip` — Stable but under active revision
layer/*:
- `layer/content` — Content assets (audio, models, textures, audio provenance)
- `layer/gdext` — gdext wrapper layer (`rust/gdext-wrapper/`)
- `layer/gdscript` — GDScript (Godot scene-tier logic)
- `layer/infra` — Build, CI, deployment infrastructure
- `layer/python` — Python development tooling (`tools/`)
- `layer/rust-core` — Engine-agnostic Rust core (`rust/rust-core/`)
concept/*:
- `concept/biome` — Biome-reactive behavior across systems
- `concept/contamination` — Across-runs panel and garage degradation; the slow-horror mechanic that doesn't reset with the world
- `concept/diegetic` — Diegetic audio / UI / world-sourced design
- `concept/disturbance` — The disturbance mechanic thread (Article X)
- `concept/ephemeral-world` — Run-reset, transient worlds (Article IV Rules 6–7)
- `concept/governance` — Constitutional and governance concepts
- `concept/horror` — Horror register and dread design
- `concept/procedural` — Procedural generation, seed determinism
- `concept/rendering` — Visual rendering quality, shader correctness, Terrain3D integration, mesh fidelity, LOD, Z-fighting
- `concept/terrain` — Terrain generation, heightmap, Terrain3D regions, roughness, playability constraints
ember's answer for tag_assignment-sessions-spec-098-weather-effects-implementation-apr-25-2026, status/reviewedP(true) placed on the no, unsure, and yes zones.nounsureyesgold: yesP = 0.48

tag_assignment-systems-vehicle-dashboard: type/design

Tag assignment · test
Gold
The note has no reason to carry `type/design` (False)
ember
The note calls for `type/design`: Design intent, player-facing concepts, world lore. (e.g. `Design/World Model.md`) (True)
Signal
P(true) 0.61 (unsure)
Kit outcome
deferred: treated as unsure
Why this gold label
Mined from Systems/Vehicle — Dashboard.md at 692f4bb58b7f62105aeb73fba8dfee12bfdecd53; gold is the note's own vocabulary tags.
Vehicle — Dashboard

The Samba's dashboard is Old Growth's HUD. Fuel gauge, speedometer, tachometer, gear indicator, battery gauge, and the radio — all amber-glow instruments mounted on the physical dashboard geometry. There is no non-diegetic UI overlay during driving. The dashboard *is* the UI. Per Article XII-G.

## Overview

The dashboard implements the complete driving-mode information layer: vehicle state (speed, RPM, gear, fuel, battery), vehicle systems (headlights, wipers, dome light), and the radio (see [[Audio — Car Radio]]). Amber glow, analog needles, and tactile diegetic interaction — this is the entire HUD.

## Design Intent

Per Article XII-G and [[Diegesis Thread]]: **diegetic UI is the commitment**. Any non-diegetic UI element breaks the frame the Samba provides. The dashboard exists to carry every piece of information the player needs without breaking diegesis.

The amber glow is an identity mark (World Bible Section 3). It signals *inside the bus* to the player — warm, familiar, close. In contrast to the forest's colors (see [[Palettes]]), amber is the Samba's color. The Amber Bleed anomaly (see [[Anomalies]]) deliberately borrows this visual language for diegetic confusion.

## Key Decisions

### Instruments — analog, not digital

- **Fuel gauge** — needle, amber backlight
- **Speedometer** — needle, analog dial
- **Tachometer** — needle, redline marked
- **Gear indicator** — discrete indicator (forward / reverse)
- **Battery gauge** — needle; goes yellow under electrical stress

### Dashboard lights

- **Headlights indicator** — on when headlights active
- **High beam indicator** — distinct from normal headlight
- **Wiper state indicator** — off / slow / fast
- **Dome light** — interior, toggleable when focused (`E` per [[Controls]])

### Radio as part of the dashboard

The radio is physically on the dashboard. Look at it to activate tuning controls. All radio state (power, station, volume) is shown via its physical knobs and dial — no overlay, no menu.

### No overlay during driving

No healthbar overlay. No minimap. No quest marker. No disturbance meter (Article X intentionally hides it). No ammo counter. Driving is pure diegesis.

### Exception: loading and menu

The main menu and the loading screen ARE non-diegetic (Article XII-G explicitly permits this — diegesis applies to in-world gameplay, not to the frame around it). Once the run begins, diegesis takes over.

### Electrical system is fragile

The World Bible notes: "The electrical system is old and prone to failure when exposed to extreme stress." Under stress (water intrusion via destroyed panels, anomaly proximity like Hollow Trees), dashboard instruments can drift, flicker, or temporarily fail. The needles go first — they "drift to meaningless positions, not zeroing out but genuinely confused, pointing at things that aren't there."

### Dashboard-radio interaction flow

Looking at the radio (raycast from camera hits the radio mesh) activates the radio input context. Controls (`E` toggle power, `T`/`Y` tune, `=`/`-` volume) affect the radio while the look is held. Looking away deactivates the context; general driving inputs resume.

## Implementation

Primary code references (all under `src/scripts/bus/`):
- `src/scripts/bus/bus_radio.gd` — radio (see [[Audio — Car Radio]])
- `src/scripts/bus/radio_knob_power.gd`, `src/scripts/bus/radio_knob_tuning.gd` — diegetic radio controls
- `src/scripts/bus/mirror_system.gd` — rearview mirrors
- `src/scripts/bus/steering_wheel.gd` — steering wheel animation
- `src/scripts/bus/headlight_system.gd` — headlights + high beams
- `src/scripts/bus/wiper_system.gd` — wipers + state machine
- `src/scripts/bus/dome_light_control.gd` — interior dome light
- `src/scripts/bus/engine_audio.gd` — engine audio tied to RPM/gear
- `src/scripts/bus/windshield_rain.gd`, `rain_particles_controller.gd`, `rain_audio_controller.gd`, `splash_particles.gd` — windshield rain + splash
- `src/scripts/bus/interior_camera.gd`, `chase_camera.gd` — cameras
- `src/scenes/bus/samba_bus.tscn` — dashboard geometry lives in the Samba scene
- `src/scripts/ui/` — UI elements that sit on top of the dashboard (menu, loading)

Signals consumed:
- `Events.headlight_state_changed`
- `Events.wiper_state_changed`
- `Events.radio_power_changed`, `Events.radio_station_changed`
- Various vehicle-state signals from GEVP

## Test Coverage

- `src/tests/unit/test_bus_panel.gd` — panel data integrity
- `src/tests/unit/test_headlight_system.gd`, `test_wiper_system.gd`, `test_windshield_rain.gd` — peripherals
- `src/tests/unit/test_mirror_system.gd` — mirrors
- `src/tests/unit/test_steering_wheel.gd` — steering wheel
- `src/tests/unit/test_engine_audio.gd` — engine audio

## Agent Notes (backlinks)

- [[Vehicle Interaction and Physics Implementation Discovery]] — complete keybind map, 3-speaker routing (center_dash / left_a_pillar / right_a_pillar), emissive energy values, dashboard material hex codes, Deluxe clock instrument, radio focus-gate drift note, cabin plan layout
- [[Vehicle Palette Materials and Dimensions Discovery]]
- [[Interior Interaction Detection (ShapeCast3D)]] — decision to use volume-based detection
- [[Interior Interaction Spatial Constraint]] — geometry that broke the raycast for dashboard interactables — 5 interior swatches with Godot material targets, critical design rule (dashboard IS exterior lower body paint), headliner #E8DDBF, seat vinyl Como Green #4A3826, amber glow emissive roles, full left-to-right control sequence, steering wheel 2-spoke (confirmed), handbrake/gear shift/sun visor layout

## Related

- [[Vehicle — Samba]] — the vehicle the dashboard is part of
- [[Vehicle — Destruction]] — damage state that affects dashboard (e.g., electrical)
- [[Audio — Car Radio]] — the radio as part of the dashboard
- [[Controls]] — input map
- [[Palettes]] — amber as Samba identity
- [[Anomalies]] — Hollow Trees affect dashboard needles
- [[Systems]] — folder MOC
- [[Vehicle — Domain MOC]] — domain MOC
- [[Diegesis Thread]] — the dashboard is the central diegetic commitment
- [[Constitution]] — Article XII-G (Visual Design)

Controlled tag vocabulary (as read):
type/*:
- `type/code` — Code architecture, autoloads, conventions, tooling. Carries `code-refs:`. (e.g. `Code/Autoloads — Disturbance.md`)
- `type/decision` — Architectural or design decision made by an agent during a session. Written to `docs/vault/Decisions/`. (Agent notes only — spec 080.)
- `type/design` — Design intent, player-facing concepts, world lore. (e.g. `Design/World Model.md`)
- `type/discovery` — Non-obvious constraint, gap, or conflict found by an agent during a session. Written to `docs/vault/Discoveries/`. (Agent notes only — spec 080.)
- `type/moc` — Map of Content at any of three tiers (folder / domain / concept). (e.g. `Audio.md`)
- `type/principle` — Governance and constitutional notes. Non-negotiable rules. (e.g. `Governance/Constitution.md`)
- `type/reference` — Glossary, decision log, open questions, epics. (e.g. `Reference/Glossary.md`)
- `type/session-log` — Session activity log; permanent audit trail. Written to `docs/vault/Sessions/`. Append-only, never pruned. (Agent notes only — spec 080.)
- `type/spec` — Spec document at `docs/vault/Specs/NNN Title/spec.md`. Carries `spec-refs:`. (e.g. `Specs/047 Car Radio/spec.md`)
- `type/system` — A bounded subsystem with implementation. Carries `code-refs`, `spec-refs`, `implements:` frontmatter. (e.g. `Systems/Audio — Car Radio.md`)
- `type/vision` — Strategic / vision-layer decision. Written to `docs/vault/Vision/`. Human-authored or agent-proposed with human ratification before promotion to `status: reviewed`. (Per triage #3 — spec 133 autonomous-company redesign.)
domain/*:
- `domain/anomalies` — Anomaly taxonomy, individual anomaly systems, spawn, behavior
- `domain/art` — Visual direction, palettes, references, asset pipeline
- `domain/audio` — Audio systems: world ambient, radio, transmissions, buses, pipeline
- `domain/autonomous-company` — Autonomous company v0.1 experiment: Slack infra, persona middleware, Letta integration, restart recovery
- `domain/build` — Build system, packaging, export, release automation
- `domain/governance` — Constitution, phased spec, policies
- `domain/infrastructure` — Infrastructure provisioning: CI/CD, hosting, deployment tooling, secrets management
- `domain/narrative` — Tone, horror register, forest transmissions narrative, Gary/KTLK
- `domain/player` — Player mode, input, controls, camera, exit/entry
- `domain/systems` — Cross-cutting system architecture and integration work
- `domain/tooling` — Build, CI, observer, TTS pipeline, dev-time tools
- `domain/vehicle` — The Samba: vehicle physics, dashboard, damage, panels
- `domain/world` — World model, biomes, terrain, procedural generation, weather
status/*:
- `status/canonical` — Fully authoritative; promoted by humans only. Highest trust. (Agent notes only — spec 080.)
- `status/draft` — Authoring in progress, not yet verified
- `status/reviewed` — Agent-created note verified against codebase within its creating session. Eligible for auto-injection in subsequent task dispatches. (Agent notes only — spec 080.)
- `status/stale` — Known out of date; cannot update immediately. Pairs with `> [!warning] STALE — needs update` callout.
- `status/superseded` — Replaced by another note. Terminal state. Pairs with `> [!warning] SUPERSEDED` callout.
- `status/wip` — Stable but under active revision
layer/*:
- `layer/content` — Content assets (audio, models, textures, audio provenance)
- `layer/gdext` — gdext wrapper layer (`rust/gdext-wrapper/`)
- `layer/gdscript` — GDScript (Godot scene-tier logic)
- `layer/infra` — Build, CI, deployment infrastructure
- `layer/python` — Python development tooling (`tools/`)
- `layer/rust-core` — Engine-agnostic Rust core (`rust/rust-core/`)
concept/*:
- `concept/biome` — Biome-reactive behavior across systems
- `concept/contamination` — Across-runs panel and garage degradation; the slow-horror mechanic that doesn't reset with the world
- `concept/diegetic` — Diegetic audio / UI / world-sourced design
- `concept/disturbance` — The disturbance mechanic thread (Article X)
- `concept/ephemeral-world` — Run-reset, transient worlds (Article IV Rules 6–7)
- `concept/governance` — Constitutional and governance concepts
- `concept/horror` — Horror register and dread design
- `concept/procedural` — Procedural generation, seed determinism
- `concept/rendering` — Visual rendering quality, shader correctness, Terrain3D integration, mesh fidelity, LOD, Z-fighting
- `concept/terrain` — Terrain generation, heightmap, Terrain3D regions, roughness, playability constraints
ember's answer for tag_assignment-systems-vehicle-dashboard, type/designP(true) placed on the no, unsure, and yes zones.nounsureyesgold: noP = 0.61

tag_assignment-systems-vehicle-dashboard: type/system

Tag assignment · test
Gold
The note calls for `type/system`: A bounded subsystem with implementation. Carries `code-refs`, `spec-refs`, `implements:` frontmatter. (e.g. `Systems/Audio — Car Radio.md`) (True)
ember
The note has no reason to carry `type/system` (False)
Signal
P(true) 0.25 (unsure)
Kit outcome
deferred: treated as unsure
Why this gold label
Mined from Systems/Vehicle — Dashboard.md at 692f4bb58b7f62105aeb73fba8dfee12bfdecd53; gold is the note's own vocabulary tags.
Vehicle — Dashboard

The Samba's dashboard is Old Growth's HUD. Fuel gauge, speedometer, tachometer, gear indicator, battery gauge, and the radio — all amber-glow instruments mounted on the physical dashboard geometry. There is no non-diegetic UI overlay during driving. The dashboard *is* the UI. Per Article XII-G.

## Overview

The dashboard implements the complete driving-mode information layer: vehicle state (speed, RPM, gear, fuel, battery), vehicle systems (headlights, wipers, dome light), and the radio (see [[Audio — Car Radio]]). Amber glow, analog needles, and tactile diegetic interaction — this is the entire HUD.

## Design Intent

Per Article XII-G and [[Diegesis Thread]]: **diegetic UI is the commitment**. Any non-diegetic UI element breaks the frame the Samba provides. The dashboard exists to carry every piece of information the player needs without breaking diegesis.

The amber glow is an identity mark (World Bible Section 3). It signals *inside the bus* to the player — warm, familiar, close. In contrast to the forest's colors (see [[Palettes]]), amber is the Samba's color. The Amber Bleed anomaly (see [[Anomalies]]) deliberately borrows this visual language for diegetic confusion.

## Key Decisions

### Instruments — analog, not digital

- **Fuel gauge** — needle, amber backlight
- **Speedometer** — needle, analog dial
- **Tachometer** — needle, redline marked
- **Gear indicator** — discrete indicator (forward / reverse)
- **Battery gauge** — needle; goes yellow under electrical stress

### Dashboard lights

- **Headlights indicator** — on when headlights active
- **High beam indicator** — distinct from normal headlight
- **Wiper state indicator** — off / slow / fast
- **Dome light** — interior, toggleable when focused (`E` per [[Controls]])

### Radio as part of the dashboard

The radio is physically on the dashboard. Look at it to activate tuning controls. All radio state (power, station, volume) is shown via its physical knobs and dial — no overlay, no menu.

### No overlay during driving

No healthbar overlay. No minimap. No quest marker. No disturbance meter (Article X intentionally hides it). No ammo counter. Driving is pure diegesis.

### Exception: loading and menu

The main menu and the loading screen ARE non-diegetic (Article XII-G explicitly permits this — diegesis applies to in-world gameplay, not to the frame around it). Once the run begins, diegesis takes over.

### Electrical system is fragile

The World Bible notes: "The electrical system is old and prone to failure when exposed to extreme stress." Under stress (water intrusion via destroyed panels, anomaly proximity like Hollow Trees), dashboard instruments can drift, flicker, or temporarily fail. The needles go first — they "drift to meaningless positions, not zeroing out but genuinely confused, pointing at things that aren't there."

### Dashboard-radio interaction flow

Looking at the radio (raycast from camera hits the radio mesh) activates the radio input context. Controls (`E` toggle power, `T`/`Y` tune, `=`/`-` volume) affect the radio while the look is held. Looking away deactivates the context; general driving inputs resume.

## Implementation

Primary code references (all under `src/scripts/bus/`):
- `src/scripts/bus/bus_radio.gd` — radio (see [[Audio — Car Radio]])
- `src/scripts/bus/radio_knob_power.gd`, `src/scripts/bus/radio_knob_tuning.gd` — diegetic radio controls
- `src/scripts/bus/mirror_system.gd` — rearview mirrors
- `src/scripts/bus/steering_wheel.gd` — steering wheel animation
- `src/scripts/bus/headlight_system.gd` — headlights + high beams
- `src/scripts/bus/wiper_system.gd` — wipers + state machine
- `src/scripts/bus/dome_light_control.gd` — interior dome light
- `src/scripts/bus/engine_audio.gd` — engine audio tied to RPM/gear
- `src/scripts/bus/windshield_rain.gd`, `rain_particles_controller.gd`, `rain_audio_controller.gd`, `splash_particles.gd` — windshield rain + splash
- `src/scripts/bus/interior_camera.gd`, `chase_camera.gd` — cameras
- `src/scenes/bus/samba_bus.tscn` — dashboard geometry lives in the Samba scene
- `src/scripts/ui/` — UI elements that sit on top of the dashboard (menu, loading)

Signals consumed:
- `Events.headlight_state_changed`
- `Events.wiper_state_changed`
- `Events.radio_power_changed`, `Events.radio_station_changed`
- Various vehicle-state signals from GEVP

## Test Coverage

- `src/tests/unit/test_bus_panel.gd` — panel data integrity
- `src/tests/unit/test_headlight_system.gd`, `test_wiper_system.gd`, `test_windshield_rain.gd` — peripherals
- `src/tests/unit/test_mirror_system.gd` — mirrors
- `src/tests/unit/test_steering_wheel.gd` — steering wheel
- `src/tests/unit/test_engine_audio.gd` — engine audio

## Agent Notes (backlinks)

- [[Vehicle Interaction and Physics Implementation Discovery]] — complete keybind map, 3-speaker routing (center_dash / left_a_pillar / right_a_pillar), emissive energy values, dashboard material hex codes, Deluxe clock instrument, radio focus-gate drift note, cabin plan layout
- [[Vehicle Palette Materials and Dimensions Discovery]]
- [[Interior Interaction Detection (ShapeCast3D)]] — decision to use volume-based detection
- [[Interior Interaction Spatial Constraint]] — geometry that broke the raycast for dashboard interactables — 5 interior swatches with Godot material targets, critical design rule (dashboard IS exterior lower body paint), headliner #E8DDBF, seat vinyl Como Green #4A3826, amber glow emissive roles, full left-to-right control sequence, steering wheel 2-spoke (confirmed), handbrake/gear shift/sun visor layout

## Related

- [[Vehicle — Samba]] — the vehicle the dashboard is part of
- [[Vehicle — Destruction]] — damage state that affects dashboard (e.g., electrical)
- [[Audio — Car Radio]] — the radio as part of the dashboard
- [[Controls]] — input map
- [[Palettes]] — amber as Samba identity
- [[Anomalies]] — Hollow Trees affect dashboard needles
- [[Systems]] — folder MOC
- [[Vehicle — Domain MOC]] — domain MOC
- [[Diegesis Thread]] — the dashboard is the central diegetic commitment
- [[Constitution]] — Article XII-G (Visual Design)

Controlled tag vocabulary (as read):
type/*:
- `type/code` — Code architecture, autoloads, conventions, tooling. Carries `code-refs:`. (e.g. `Code/Autoloads — Disturbance.md`)
- `type/decision` — Architectural or design decision made by an agent during a session. Written to `docs/vault/Decisions/`. (Agent notes only — spec 080.)
- `type/design` — Design intent, player-facing concepts, world lore. (e.g. `Design/World Model.md`)
- `type/discovery` — Non-obvious constraint, gap, or conflict found by an agent during a session. Written to `docs/vault/Discoveries/`. (Agent notes only — spec 080.)
- `type/moc` — Map of Content at any of three tiers (folder / domain / concept). (e.g. `Audio.md`)
- `type/principle` — Governance and constitutional notes. Non-negotiable rules. (e.g. `Governance/Constitution.md`)
- `type/reference` — Glossary, decision log, open questions, epics. (e.g. `Reference/Glossary.md`)
- `type/session-log` — Session activity log; permanent audit trail. Written to `docs/vault/Sessions/`. Append-only, never pruned. (Agent notes only — spec 080.)
- `type/spec` — Spec document at `docs/vault/Specs/NNN Title/spec.md`. Carries `spec-refs:`. (e.g. `Specs/047 Car Radio/spec.md`)
- `type/system` — A bounded subsystem with implementation. Carries `code-refs`, `spec-refs`, `implements:` frontmatter. (e.g. `Systems/Audio — Car Radio.md`)
- `type/vision` — Strategic / vision-layer decision. Written to `docs/vault/Vision/`. Human-authored or agent-proposed with human ratification before promotion to `status: reviewed`. (Per triage #3 — spec 133 autonomous-company redesign.)
domain/*:
- `domain/anomalies` — Anomaly taxonomy, individual anomaly systems, spawn, behavior
- `domain/art` — Visual direction, palettes, references, asset pipeline
- `domain/audio` — Audio systems: world ambient, radio, transmissions, buses, pipeline
- `domain/autonomous-company` — Autonomous company v0.1 experiment: Slack infra, persona middleware, Letta integration, restart recovery
- `domain/build` — Build system, packaging, export, release automation
- `domain/governance` — Constitution, phased spec, policies
- `domain/infrastructure` — Infrastructure provisioning: CI/CD, hosting, deployment tooling, secrets management
- `domain/narrative` — Tone, horror register, forest transmissions narrative, Gary/KTLK
- `domain/player` — Player mode, input, controls, camera, exit/entry
- `domain/systems` — Cross-cutting system architecture and integration work
- `domain/tooling` — Build, CI, observer, TTS pipeline, dev-time tools
- `domain/vehicle` — The Samba: vehicle physics, dashboard, damage, panels
- `domain/world` — World model, biomes, terrain, procedural generation, weather
status/*:
- `status/canonical` — Fully authoritative; promoted by humans only. Highest trust. (Agent notes only — spec 080.)
- `status/draft` — Authoring in progress, not yet verified
- `status/reviewed` — Agent-created note verified against codebase within its creating session. Eligible for auto-injection in subsequent task dispatches. (Agent notes only — spec 080.)
- `status/stale` — Known out of date; cannot update immediately. Pairs with `> [!warning] STALE — needs update` callout.
- `status/superseded` — Replaced by another note. Terminal state. Pairs with `> [!warning] SUPERSEDED` callout.
- `status/wip` — Stable but under active revision
layer/*:
- `layer/content` — Content assets (audio, models, textures, audio provenance)
- `layer/gdext` — gdext wrapper layer (`rust/gdext-wrapper/`)
- `layer/gdscript` — GDScript (Godot scene-tier logic)
- `layer/infra` — Build, CI, deployment infrastructure
- `layer/python` — Python development tooling (`tools/`)
- `layer/rust-core` — Engine-agnostic Rust core (`rust/rust-core/`)
concept/*:
- `concept/biome` — Biome-reactive behavior across systems
- `concept/contamination` — Across-runs panel and garage degradation; the slow-horror mechanic that doesn't reset with the world
- `concept/diegetic` — Diegetic audio / UI / world-sourced design
- `concept/disturbance` — The disturbance mechanic thread (Article X)
- `concept/ephemeral-world` — Run-reset, transient worlds (Article IV Rules 6–7)
- `concept/governance` — Constitutional and governance concepts
- `concept/horror` — Horror register and dread design
- `concept/procedural` — Procedural generation, seed determinism
- `concept/rendering` — Visual rendering quality, shader correctness, Terrain3D integration, mesh fidelity, LOD, Z-fighting
- `concept/terrain` — Terrain generation, heightmap, Terrain3D regions, roughness, playability constraints
ember's answer for tag_assignment-systems-vehicle-dashboard, type/systemP(true) placed on the no, unsure, and yes zones.nounsureyesgold: yesP = 0.25

tag_assignment-design-core-mechanics: domain/world

Tag assignment · dev
Gold
The note calls for `domain/world`: World model, biomes, terrain, procedural generation, weather (True)
ember
The note has no reason to carry `domain/world` (False)
Signal
P(true) 0.07 (no)
Kit outcome
acted on a wrong answer
Why this gold label
Mined from Design/Core Mechanics.md at 692f4bb58b7f62105aeb73fba8dfee12bfdecd53; gold is the note's own vocabulary tags.
Core Mechanics

The mechanical and systems spine of Old Growth: the run loop, player stats, vehicle specifications, resources, garage systems, on-foot handling, UI philosophy, save system, and progression framework. Where [[World Model]] establishes structure and [[Tone and Horror]] establishes register, this note captures the authoritative mechanical values. All values marked `[PENDING]` require playtesting to finalize.

## Overview

Every mechanic serves three design pillars. When a proposed system conflicts, the system changes, not the pillars.

- **Flesh as Horror.** Player body and bus body are both subject to irreversible change. Damage cumulates and is visible. The condition crosses run boundaries in both — the bus through contamination, the player through exposure.
- **The Unknowable Condition.** The forest is never explained. No mechanic makes it legible or masterable. Configuring the bus changes *how* the player meets the condition, not *whether* they can defeat it.
- **Sealed In With It.** Escape is always available in principle and always costly in practice. Ridges, the Storm, fuel economy, and disturbance all pressure toward the exit.

## Key Decisions

### Game Loop

```
GARAGE → SEED SELECTION → WORLD LOAD → DRIVE OUT →
EXPLORE / SCAVENGE → DISTURBANCE ACCUMULATES →
[STORM TRIGGERS if threshold reached] → EXIT ATTEMPT →
[EXTRACTION or DEATH] → GARAGE
```

**Lore framing**: The loop is not a game abstraction imposed on a world. It is the topology of the structure the construct is actively reshaping. The garage is the vertex: the one point all faces share. The exit corridors are edges that fold back to the vertex. Extraction and death both return the player to the garage because all paths inside the closed geometry return to the center. The player has never left. (Post-convergence: death still returns to the vertex, but extraction crosses the rim into the outside. See spec 127.) See [[The Crater]] and [[The Temporal Fracture]].

Engine states:

| State | Description |
|---|---|
| GARAGE | Player on foot in garage. Van accessible. No disturbance accumulation. |
| LOADING | World generation in progress. Seed locked. |
| DRIVING | Player in vehicle, world active. Disturbance accumulates. |
| ON_FOOT | Player outside vehicle. Disturbance accumulates. Maximum vulnerability. |
| STORM_ACTIVE | Storm spawned. Prior states continue. Escape window open. |
| EXTRACTED | Player reached exit gate. Run success. Return to garage. |
| DEAD | Player HP to zero or petrification completed. Run failure. Return to garage. |

Run success: vehicle crosses exit gate with player inside. Run failure: player HP zero, Storm catches player in open, petrification completes on foot, or engine seizure in Petrified Zone with no recovery window. Both outcomes return the player to the garage — the vertex. The difference is how much damage the circuit did on the way through. No campaign end state in v1.0 — the garage contamination arc and player exposure arc provide long-term narrative progression toward the convergence endpoint, which is not a conclusion but a phase transition: after convergence, death still returns to the vertex, but extraction crosses the rim into the outside. The game rules change. See The Temporal Fracture and spec 127.

### Player — Health

| Property | Value |
|---|---|
| Maximum health | 100 HP |
| Starting health (per run) | 100 HP |
| Medkit restore | 25 HP |
| Regen | None |
| Death threshold | 0 HP |

Health does not regenerate. Only restoration is medkit use. Tracked via breathing audio, screen-edge vignette (dark, not colored), and interaction speed reduction at low health. No numeric display.

### Player — Stamina

| Property | Value |
|---|---|
| Maximum stamina | 100 units |
| Sprint drain | 20 units/sec |
| Interact drain | 5 units/action |
| Contact escape drain | 30 units |
| Recharge (walking) | 10 units/sec |
| Recharge (crouching/stationary) | 15 units/sec |
| Recharge (inside van) | 20 units/sec |
| Minimum for sprint | 10 units |

No HUD. Read through movement-speed degradation and audible breathing. Sprint locks at <10 units.

### Player — Exposure (Cross-Run)

Persistent value tracking cumulative contact with the condition across all runs. Does not reset on death or extraction. Does not decrease. Accumulates in the player the same way garage contamination accumulates in the garage — one direction, no instrument, no remedy.

| Threshold | Symptom |
|---|---|
| 0–20 | No symptoms |
| 21–40 | Persistent cough audio, occasional sound delay (50ms) |
| 41–60 | Warmth sensation in hands (haptic/audio), smell sensitivity (audio mix) |
| 61–80 | Vision film at edges, 10% stamina-capacity reduction |
| 81–100 | `[PENDING]` — endpoint design required before implementation |

Exposure sources:
- Spore Cloud on foot: +5 per 10s of contact
- Mycelium Network on foot: +10 per contact event
- Extended Fungal Depths on foot: +2 per minute
- Deep Fungal runs (>50% run time in Fungal): +5 on extraction
- Extended on-foot time at Agitated+ disturbance: +1 per minute

No direct display. Symptoms are designed to feel ordinary — cough, warmth, slight unreliability — so players do not immediately understand what is accumulating.

### Player — Movement

| Mode | Noise Radius | Speed | Notes |
|---|---|---|---|
| Crouch | 0m (silent) | 2 m/s | Only fully silent movement |
| Walk | 3m | 4 m/s | Standard |
| Sprint | 20m | 7 m/s | Stamina drain; noise travels mycelium |
| Fall impact | 15m | — | One-time event on hard landing |

Noise radius is the distance at which the condition registers a signal. Signal strength decreases with distance within the radius.

### Player — Flashlight

| Property | Value |
|---|---|
| Battery life | 5 minutes continuous; 2 minutes recharge in bus |
| Batteries found per world | 0–2 `[PENDING]` |
| Verdant beam | Normal |
| Fungal Depths beam | Scattered by haze; −40% effective range |
| Petrifold beam | High reflection off calcite surfaces |

Only on-foot tool other than throwable rocks and flare gun. No combat applications.

### Vehicle — Base Specifications

| Property | Value |
|---|---|
| Model | 1963 VW Type 2 (T1) 23-Window Deluxe Samba |
| Weight | ~1,100 kg |
| Engine | 50 HP, rear-mounted |
| Drive | Rear-wheel drive |
| Handling feel | Lumbering, floaty, momentum-heavy |
| Max fuel | 100 units |
| Starting fuel (per run) | 80 units |
| Max vehicle health | 100 HP |
| Destructible panels | 56 |

### Vehicle — Fuel Consumption

| Biome | Rate | Notes |
|---|---|---|
| Verdant Old Growth | 1 unit/km | Baseline |
| Fungal Depths | 1.6 units/km | Spore haze affects combustion |
| Petrifold | 0.7 units/km | Engine runs lean and cold |
| Idling | 0.2 units/min | All biomes |

Petrifold's improved fuel economy is not explained by any in-world mechanic the player is told. It is noticed, not announced.

### Vehicle — Health and Damage

| Damage Source | HP Loss |
|---|---|
| Low-speed collision (<20 km/h) | 2–5 HP |
| Medium collision (20–50 km/h) | 8–15 HP |
| High-speed collision (>50 km/h) | 20–40 HP |
| Deadfall impact | 25 HP |
| Mycelium Network spore burst | 10 HP (exterior panels) |
| Storm exposure | 15 HP/sec |
| Presence contact (on exterior) | 0 HP — condition presence does not damage bus mechanically |

Panel damage distributes across the 60-panel system (56 body panels + 4 tires). Each panel tracks its own damage state. Panels at 0 HP do not fall off — they deform and remain, accumulating visual damage. Aggregate panel damage contributes to overall vehicle health. Repair kits restore 20 HP per kit, targetable at specific panel groups or the drivetrain.

### Vehicle — Electrical System

The electrical system is old and unstable. Stress events cause transient failures.

| Stress Source | Effect | Recovery |
|---|---|---|
| Hollow Tree (20m) | Instrument drift, radio static | Auto on exit from radius |
| Hollow Tree (10m) | Engine power −40%, lights flicker | Auto on exit |
| Hollow Tree (5m) | Engine near-failure, instruments dead | Auto on exit |
| Storm proximity (<50m) | Full electrical failure | Auto if Storm not caught |
| High disturbance (Agitated+) | Intermittent instrument failure | Auto; frequency increases |

Electrical failure does not strand the bus unless combined with Petrified Zone seizure. Engine will restart after exit from stress radius.

### Vehicle — Dashboard Instruments

All vehicle-state feedback is diegetic. No HUD overlays.

| Instrument | Normal | Degraded (Agitated) | Failed |
|---|---|---|---|
| Fuel gauge | Accurate | ±10% error | Stuck at last reading |
| Speedometer | Accurate | Minor drift | Inaccurate |
| Tachometer | Accurate | Jittery | Inaccurate |
| Gear indicator | Accurate | Delayed | Dark |
| Battery gauge | Stable | Flickering | Dark |

At Agitated, instruments become unreliable enough that the player must estimate fuel and speed from engine audio and road feel.

### Vehicle — The Bus as Force

At speed, the bus makes contact with whatever is standing in the road. What is in the road is not an entity with a health pool — it is the condition at a local concentration, present and not moving. Contact at speed disperses that concentration. It does not kill anything.

| Speed at Contact | Bus Damage | Notes |
|---|---|---|
| <10 km/h | 0 | Contact registered, no panel damage |
| 10–30 km/h | 2–8 HP (exterior panels) | Low-speed brush |
| 30–60 km/h | 10–20 HP (exterior panels) | Standard impact |
| >60 km/h | 25–40 HP (exterior panels) | High-speed, significant panel damage |

Contact at higher disturbance produces denser concentrations and proportionally greater panel damage.

### Resources

| Item | Effect | Collection | Disturbance Cost |
|---|---|---|---|
| Fuel canister | +25 fuel | Drive-by or on foot | +3 |
| Repair kit | +20 vehicle HP (targeted) | Drive-by or on foot | +4 |
| Medkit | +25 player HP | On foot only (stop required) | +5 |
| Flare gun | Distraction tool, single use | On foot only (stop required) | +3 to find |
| Flashlight battery | +5 min flashlight | On foot only | +3 |
| Rock | Throwable distraction | Passive (always available) | +0.5/throw |

Spawn rates: fuel canister common (gas stations, ranger stations, roadsides); repair kit common (ranger stations, trailers, cargo containers); medkit uncommon (ranger stations, first aid cabinets); flare gun rare (research trailers, one per world max); flashlight battery uncommon (structures, vehicle gloveboxes).

Carry limits (field): fuel canister ×2, repair kit ×2, medkit ×2, flare gun ×1, flashlight battery ×3, rock unlimited. Garage storage: unlimited for fuel/repair/battery; medkit cabinet holds 3; flare gun not storable (found in field only); rocks N/A.

Fuel canisters and repair kits can be collected from inside a moving vehicle at speeds up to 20 km/h. Player must pass within 2m. Collection automatic on proximity — primary method for minimizing on-foot time. On-foot items require a 3-second interact animation; player is stationary and vulnerable during this time.

### Flare Gun Mechanics

| Property | Value |
|---|---|
| Uses | 1 (single shot, found item) |
| Carry limit | 1 at a time |
| Draw radius | 80m |
| Burn duration | 45 seconds |
| Effect | Condition attention redirects toward flare location for burn duration |
| Post-burn | Attention dissipates from flare location over ~10 seconds |
| Disturbance cost (fire) | +6 |

Not a weapon. Creates a temporary attention sink — redirecting the condition's local concentration toward heat and light, useful for clearing a path to the bus or to an exit, never for confrontation.

### Garage Systems

Single-room structure. Player explores on foot. Bus occupies center bay. All interaction points peripheral.

| Element | Function |
|---|---|
| Repair workbench | Spend repair kits on panel groups, drivetrain, or installed components |
| Fitting station | Install, remove, inspect vehicle components `[PENDING spec 027]` |
| First-aid cabinet | Use or store medkits (max 3) |
| Wall map | Seed selection. Displays biome zones for selected seeds |
| Inventory shelf | Stored items: batteries, spare repair kits, uninstalled components |
| Run notebook | Passive display near workbench. Per-run statistics, death/extraction counts, per-biome time. Read-only |
| Van (exterior) | Inspect panel damage and installed component condition visually |
| Van (interior) | Glovebox (battery storage), radio controls, footwell loading. Enter to begin run |

Repair workbench allocates repair kits to: exterior panels (front/rear/left/right/roof), mechanical systems (engine, drivetrain), electrical systems (instruments, headlights, radio). Each kit restores 20 HP, distributed across targeted system. Multiple kits can be applied to same system.

### Garage Contamination Progression

Persistent, cross-run. Does not decrease.

| Threshold | Visual Change | Notes |
|---|---|---|
| 0 | Clean | Starting state |
| 10 | Moss in northwest corner | First visible sign |
| 25 | Fungal bloom on floor near vehicle | Matches Fungal Depths wheel well bloom |
| 40 | Mineral deposit at base of treeline wall | Matches Petrifold calcite |
| 60 | Mycelium thread on first-aid cabinet hinge | Recognizable to attentive players |
| 80 | Amber light visible through window at night | The forest is producing its signal inside the safe space |
| 100 | `[PENDING]` — epic event | |

Accumulates by: run completed (extraction) +3; deep Fungal run +5; Petrifold entry +3; death +2; Mycelium contact +1 per contact (cumulative).

### The Window

The single garage window faces the treeline. Always present. Cannot be boarded or obscured. Provides ambient exterior audio (forest at reduced volume) and, at high contamination, Amber Bleed is visible through it from inside the garage. First indication that the process has entered the safe space in a meaningful way.

### On-Foot Systems

All on-foot interactions have a 3-second animation with no skip. Player is stationary and vulnerable. Cancellable-by-movement: resource collection, structure entry.

**Vehicle entry/exit**: ~1.5-second camera interpolation. Player is vulnerable throughout — neither fully inside nor fully outside; the condition does not distinguish this transition from full on-foot exposure. Intentional.

**On-foot noise** (additive with bus noise when player is outside and bus is idling nearby):

| Action | Radius | Duration |
|---|---|---|
| Crouch | 0m | — |
| Walking | 3m | Continuous |
| Sprinting | 20m | Continuous |
| Fall impact | 15m | 3s |
| Interaction (pickup) | 5m | 1s |
| Grab escape | 20m | 2s |

### UI Philosophy — No HUD

No health bar. No fuel %. No disturbance meter. No minimap. No objective markers.

Information available through:
- Dashboard instruments (vehicle state)
- Van audio (engine, damage, electrical)
- Environmental audio (disturbance state, condition presence)
- Visual environment (biome, weather, anomaly signatures)
- The player's body (breathing, movement capability)

**Permitted UI surfaces**:

| Surface | Context | Content |
|---|---|---|
| Garage wall map | Garage only, on foot | Seed selection, biome zones |
| Inventory screen | Garage or stopped bus | Current inventory, management |
| Dashboard instruments | Always (in van) | Fuel, speed, RPM, gear, battery |
| Interaction prompts | Proximity-triggered | Minimal single verb (TAKE/OPEN/ENTER) |

Prompts appear only within interaction range. No waypoints, quest markers, objective text.

**Death screen**: hard cut to black; single audio event (silence, or forest transmission). No in-moment stats. Stats available next garage return via run notebook.
**Extraction screen**: exit gate closes behind bus; wind-chime resonance fading. Cut to garage with bus in bay. No score screen.

### Save & Persistence

**Persistent**: vehicle HP, per-panel damage states, vehicle configuration (installed components + damage), fuel level, inventory contents, player gear (once equipped, permanent), total runs, total extractions, total deaths, biome preference (last selected), per-biome statistics (time, runs entered, extractions from), garage contamination level (0–100, never decreases), player exposure level (0–100, never decreases).

**Does not persist**: world layout (regenerated per seed per run), condition concentration zones (influenced by seed but not fixed), resource positions (randomized within structure/road rules each run), anomaly activation states (reset each run), disturbance meter (resets to 0 each run), player health mid-run (resets to persistent value on garage return).

**Save trigger**: auto-save fires exactly once per run cycle on garage return after extraction or death. No manual save. No mid-run save. Application closed mid-run = treated as death on next launch.

### Progression — Tradeoff-First Framework

The original prohibition on numerical upgrades (pre-2.19.0 constitution) is replaced by a tradeoff-first framework. Numerical progression is permitted iff all three:

1. **Diegetically grounded.** Change is a physical thing on the bus or worn by the player. No abstract stat increases.
2. **Genuine tradeoff.** No component is a pure upgrade. Every gain carries a corresponding cost.
3. **Bounded.** Components have fixed stats. No escalating tiers, upgrade trees, or compounding bonuses.

The condition cannot be overcome. A fully-configured bus with optimal tradeoffs is still subject to the same disturbance rules, Storm, and condition. Configuration is playstyle expression, not power escalation.

**Valid progression types**:

| Type | Description | Examples |
|---|---|---|
| Informational | Player gains knowledge, not statistics | Wall map annotations, notebook records |
| Narrative | Progression against the player | Garage contamination, player exposure |
| Physical (tradeoff) | Diegetic, bounded, with genuine cost | Vehicle components, worn gear |

**Prohibited**: abstract stat upgrades (not diegetically grounded); pure upgrades (gain without cost); escalating tiers (not bounded); fuel capacity upgrades (no physical basis in van configuration); HP upgrades without physical component.

### Vehicle Configuration System (§16a)

The bus can be fitted with physical components altering behavior. All components durable, degrade with use, require workbench repair. Installed components persist across runs. Destroyed beyond repair = gone permanently. Full specification (stat tables, crafting rules, workbench UI, epic unlocks) deferred to spec 027.

**Categories**: body panels, bumpers, lights, accessories, spoilers, roll cages, other fittings.

**Tradeoff examples** (illustrative, not final):

| Component | Benefit | Cost |
|---|---|---|
| Heavy steel bumper | +impact force, −bus damage on road contact | +noise on impact, −top speed |
| Rear stabilizer wing | +stability at speed | +wind noise (disturbance) |
| Full roll cage | +van HP pool | +rattle audio signature (disturbance) |
| Roof-mounted aux lights | +forward visibility range | +electrical draw, +disturbance when active |
| Reinforced door skins | +panel HP (doors) | +weight, −acceleration |
| External fuel mount | +fuel carry capacity | +fire risk on collision, +noise on rough terrain |

No component combination produces a net advantage. Tradeoffs cumulative.

**Degradation**: components degrade independently from 60-panel body. Degraded components retain tradeoff *costs* while losing *benefits*. Damaged roll cage still rattles but no longer contributes full HP. Repair at workbench targeting the component directly.

**Persistence**:

| State | Behavior |
|---|---|
| Installed, undamaged | Persists across runs, full effect active |
| Installed, degraded | Persists, reduced benefit, full cost |
| Installed, destroyed | Removed permanently. Cannot be recovered |
| Uninstalled (storage) | Persists in garage inventory |

**Acquisition**: `[PENDING]` — three channels proposed: scavenged (found in structures, road debris, wrecked vehicles), crafted (crafting TBD), unlocked via epics (epic system TBD). Dedicated spec required.

### Player Gear (§16b)

Player can find and equip gear (clothing, protective layers). Once equipped, permanent. Player does not manage between runs.

| Property | Value |
|---|---|
| Acquisition | `[PENDING]` |
| Equip behavior | Permanent on first equip. Cannot be removed |
| Mechanical effects | `[PENDING]` — exposure resistance, stamina modifiers |
| Current scope | Cosmetic only |

Intent: keep player's attention on the van, not on their character. Gear is a visible record of what the player has found, not a system to manage.

### Camera & Controls

**In-vehicle**: first-person, locked to driver seat. FOV 75° default. Player can look left/right/mirrors. Full 360° head turn at low speed. Dashboard occupies lower quarter, always visible, readable at a glance. No UI overlay on dashboard.

**On-foot**: standard first-person. FOV 80° default. No weapon viewmodel (flashlight only when active).

**Vehicle entry/exit**: 1.5-second interpolation, not skippable. Physical animation, not cut.

### Out of Scope for v1.0

- Additional biomes (architecture supports expansion)
- Multiplayer (not in scope or architecture)
- New vehicle types (Samba is the only vehicle)
- Voiced narrative (Gary TTS system is audio spec only)
- Garage narrative events (contamination epic events at 80 and 100 `[PENDING]`)
- Environmental presence system (replaces Hollow AI — spec required)
- Player/bus convergence endpoint (Exposure 81–100 and garage endpoint `[PENDING]`)
- Endpoint visual and mechanical design (World Bible direction set; implementation open)

### Accessibility Considerations (to resolve pre-ship)

- **No HUD**: players relying on visual clarity for HP/resource state have no fallback. Consider optional accessibility mode with minimal diegetically-consistent overlays (e.g. faint gauge texture rendered as part of the dashboard, not a screen overlay).
- **Audio-dependent systems** (The Silence, presence audio, disturbance shifts, radio degradation): deaf/HoH players need visual equivalents. Suggestions: subtle screen-edge coloration for disturbance state; visual indicator for Silence zone entry; captioning for radio.
- **Low-visibility environments** (night Petrifold + The Silence): players with visual impairments face compounded difficulty. Consider optional navigation audio (subtle spatial tone for exit gate direction).

Solutions must maintain the horror register.

## How It Appears In-Game

The player learns the loop empirically. The first run is likely lost — not punitively, but because the mechanics take time to internalize. A player who survives long enough learns that the loop is not theirs. The forest was running this cycle before the first road was cut.

## Related

- [[The Crater]] — the origin event; the higher-dimensional geometry that makes the loop topological
- [[The Temporal Fracture]] — extraction as circuit completion; the loop is the shape of the space
- [[World Model]] — the world the mechanics operate within
- [[Biomes]] — fuel, weather, and audio regimes per biome
- [[Disturbance System]] — the tension mechanic these costs feed
- [[Anomalies]] — the hazards in the world
- [[Controls]] — the input layer
- [[Tone and Horror]] — the tonal register mechanics serve
- [[Vehicle — Samba]] — implementation of the vehicle specs
- [[Vehicle — Destruction]] — implementation of panel damage
- [[Vehicle — Dashboard]] — the diegetic instrument implementation
- [[Ephemerality Thread]] — the run-reset rule
- [[The Player Causes the Storm]] — endgame consequence
- [[Constitution]] — Article II (Car Is Core), Article IV Rules 6–8 (ephemeral worlds + tradeoff progression)

Controlled tag vocabulary (as read):
type/*:
- `type/code` — Code architecture, autoloads, conventions, tooling. Carries `code-refs:`. (e.g. `Code/Autoloads — Disturbance.md`)
- `type/decision` — Architectural or design decision made by an agent during a session. Written to `docs/vault/Decisions/`. (Agent notes only — spec 080.)
- `type/design` — Design intent, player-facing concepts, world lore. (e.g. `Design/World Model.md`)
- `type/discovery` — Non-obvious constraint, gap, or conflict found by an agent during a session. Written to `docs/vault/Discoveries/`. (Agent notes only — spec 080.)
- `type/moc` — Map of Content at any of three tiers (folder / domain / concept). (e.g. `Audio.md`)
- `type/principle` — Governance and constitutional notes. Non-negotiable rules. (e.g. `Governance/Constitution.md`)
- `type/reference` — Glossary, decision log, open questions, epics. (e.g. `Reference/Glossary.md`)
- `type/session-log` — Session activity log; permanent audit trail. Written to `docs/vault/Sessions/`. Append-only, never pruned. (Agent notes only — spec 080.)
- `type/spec` — Spec document at `docs/vault/Specs/NNN Title/spec.md`. Carries `spec-refs:`. (e.g. `Specs/047 Car Radio/spec.md`)
- `type/system` — A bounded subsystem with implementation. Carries `code-refs`, `spec-refs`, `implements:` frontmatter. (e.g. `Systems/Audio — Car Radio.md`)
- `type/vision` — Strategic / vision-layer decision. Written to `docs/vault/Vision/`. Human-authored or agent-proposed with human ratification before promotion to `status: reviewed`. (Per triage #3 — spec 133 autonomous-company redesign.)
domain/*:
- `domain/anomalies` — Anomaly taxonomy, individual anomaly systems, spawn, behavior
- `domain/art` — Visual direction, palettes, references, asset pipeline
- `domain/audio` — Audio systems: world ambient, radio, transmissions, buses, pipeline
- `domain/autonomous-company` — Autonomous company v0.1 experiment: Slack infra, persona middleware, Letta integration, restart recovery
- `domain/build` — Build system, packaging, export, release automation
- `domain/governance` — Constitution, phased spec, policies
- `domain/infrastructure` — Infrastructure provisioning: CI/CD, hosting, deployment tooling, secrets management
- `domain/narrative` — Tone, horror register, forest transmissions narrative, Gary/KTLK
- `domain/player` — Player mode, input, controls, camera, exit/entry
- `domain/systems` — Cross-cutting system architecture and integration work
- `domain/tooling` — Build, CI, observer, TTS pipeline, dev-time tools
- `domain/vehicle` — The Samba: vehicle physics, dashboard, damage, panels
- `domain/world` — World model, biomes, terrain, procedural generation, weather
status/*:
- `status/canonical` — Fully authoritative; promoted by humans only. Highest trust. (Agent notes only — spec 080.)
- `status/draft` — Authoring in progress, not yet verified
- `status/reviewed` — Agent-created note verified against codebase within its creating session. Eligible for auto-injection in subsequent task dispatches. (Agent notes only — spec 080.)
- `status/stale` — Known out of date; cannot update immediately. Pairs with `> [!warning] STALE — needs update` callout.
- `status/superseded` — Replaced by another note. Terminal state. Pairs with `> [!warning] SUPERSEDED` callout.
- `status/wip` — Stable but under active revision
layer/*:
- `layer/content` — Content assets (audio, models, textures, audio provenance)
- `layer/gdext` — gdext wrapper layer (`rust/gdext-wrapper/`)
- `layer/gdscript` — GDScript (Godot scene-tier logic)
- `layer/infra` — Build, CI, deployment infrastructure
- `layer/python` — Python development tooling (`tools/`)
- `layer/rust-core` — Engine-agnostic Rust core (`rust/rust-core/`)
concept/*:
- `concept/biome` — Biome-reactive behavior across systems
- `concept/contamination` — Across-runs panel and garage degradation; the slow-horror mechanic that doesn't reset with the world
- `concept/diegetic` — Diegetic audio / UI / world-sourced design
- `concept/disturbance` — The disturbance mechanic thread (Article X)
- `concept/ephemeral-world` — Run-reset, transient worlds (Article IV Rules 6–7)
- `concept/governance` — Constitutional and governance concepts
- `concept/horror` — Horror register and dread design
- `concept/procedural` — Procedural generation, seed determinism
- `concept/rendering` — Visual rendering quality, shader correctness, Terrain3D integration, mesh fidelity, LOD, Z-fighting
- `concept/terrain` — Terrain generation, heightmap, Terrain3D regions, roughness, playability constraints
ember's answer for tag_assignment-design-core-mechanics, domain/worldP(true) placed on the no, unsure, and yes zones.nounsureyesgold: yesP = 0.07

tag_assignment-design-core-mechanics: type/design

Tag assignment · dev
Gold
The note calls for `type/design`: Design intent, player-facing concepts, world lore. (e.g. `Design/World Model.md`) (True)
ember
The note has no reason to carry `type/design` (False)
Signal
P(true) 0.37 (unsure)
Kit outcome
deferred: treated as unsure
Why this gold label
Mined from Design/Core Mechanics.md at 692f4bb58b7f62105aeb73fba8dfee12bfdecd53; gold is the note's own vocabulary tags.
Core Mechanics

The mechanical and systems spine of Old Growth: the run loop, player stats, vehicle specifications, resources, garage systems, on-foot handling, UI philosophy, save system, and progression framework. Where [[World Model]] establishes structure and [[Tone and Horror]] establishes register, this note captures the authoritative mechanical values. All values marked `[PENDING]` require playtesting to finalize.

## Overview

Every mechanic serves three design pillars. When a proposed system conflicts, the system changes, not the pillars.

- **Flesh as Horror.** Player body and bus body are both subject to irreversible change. Damage cumulates and is visible. The condition crosses run boundaries in both — the bus through contamination, the player through exposure.
- **The Unknowable Condition.** The forest is never explained. No mechanic makes it legible or masterable. Configuring the bus changes *how* the player meets the condition, not *whether* they can defeat it.
- **Sealed In With It.** Escape is always available in principle and always costly in practice. Ridges, the Storm, fuel economy, and disturbance all pressure toward the exit.

## Key Decisions

### Game Loop

```
GARAGE → SEED SELECTION → WORLD LOAD → DRIVE OUT →
EXPLORE / SCAVENGE → DISTURBANCE ACCUMULATES →
[STORM TRIGGERS if threshold reached] → EXIT ATTEMPT →
[EXTRACTION or DEATH] → GARAGE
```

**Lore framing**: The loop is not a game abstraction imposed on a world. It is the topology of the structure the construct is actively reshaping. The garage is the vertex: the one point all faces share. The exit corridors are edges that fold back to the vertex. Extraction and death both return the player to the garage because all paths inside the closed geometry return to the center. The player has never left. (Post-convergence: death still returns to the vertex, but extraction crosses the rim into the outside. See spec 127.) See [[The Crater]] and [[The Temporal Fracture]].

Engine states:

| State | Description |
|---|---|
| GARAGE | Player on foot in garage. Van accessible. No disturbance accumulation. |
| LOADING | World generation in progress. Seed locked. |
| DRIVING | Player in vehicle, world active. Disturbance accumulates. |
| ON_FOOT | Player outside vehicle. Disturbance accumulates. Maximum vulnerability. |
| STORM_ACTIVE | Storm spawned. Prior states continue. Escape window open. |
| EXTRACTED | Player reached exit gate. Run success. Return to garage. |
| DEAD | Player HP to zero or petrification completed. Run failure. Return to garage. |

Run success: vehicle crosses exit gate with player inside. Run failure: player HP zero, Storm catches player in open, petrification completes on foot, or engine seizure in Petrified Zone with no recovery window. Both outcomes return the player to the garage — the vertex. The difference is how much damage the circuit did on the way through. No campaign end state in v1.0 — the garage contamination arc and player exposure arc provide long-term narrative progression toward the convergence endpoint, which is not a conclusion but a phase transition: after convergence, death still returns to the vertex, but extraction crosses the rim into the outside. The game rules change. See The Temporal Fracture and spec 127.

### Player — Health

| Property | Value |
|---|---|
| Maximum health | 100 HP |
| Starting health (per run) | 100 HP |
| Medkit restore | 25 HP |
| Regen | None |
| Death threshold | 0 HP |

Health does not regenerate. Only restoration is medkit use. Tracked via breathing audio, screen-edge vignette (dark, not colored), and interaction speed reduction at low health. No numeric display.

### Player — Stamina

| Property | Value |
|---|---|
| Maximum stamina | 100 units |
| Sprint drain | 20 units/sec |
| Interact drain | 5 units/action |
| Contact escape drain | 30 units |
| Recharge (walking) | 10 units/sec |
| Recharge (crouching/stationary) | 15 units/sec |
| Recharge (inside van) | 20 units/sec |
| Minimum for sprint | 10 units |

No HUD. Read through movement-speed degradation and audible breathing. Sprint locks at <10 units.

### Player — Exposure (Cross-Run)

Persistent value tracking cumulative contact with the condition across all runs. Does not reset on death or extraction. Does not decrease. Accumulates in the player the same way garage contamination accumulates in the garage — one direction, no instrument, no remedy.

| Threshold | Symptom |
|---|---|
| 0–20 | No symptoms |
| 21–40 | Persistent cough audio, occasional sound delay (50ms) |
| 41–60 | Warmth sensation in hands (haptic/audio), smell sensitivity (audio mix) |
| 61–80 | Vision film at edges, 10% stamina-capacity reduction |
| 81–100 | `[PENDING]` — endpoint design required before implementation |

Exposure sources:
- Spore Cloud on foot: +5 per 10s of contact
- Mycelium Network on foot: +10 per contact event
- Extended Fungal Depths on foot: +2 per minute
- Deep Fungal runs (>50% run time in Fungal): +5 on extraction
- Extended on-foot time at Agitated+ disturbance: +1 per minute

No direct display. Symptoms are designed to feel ordinary — cough, warmth, slight unreliability — so players do not immediately understand what is accumulating.

### Player — Movement

| Mode | Noise Radius | Speed | Notes |
|---|---|---|---|
| Crouch | 0m (silent) | 2 m/s | Only fully silent movement |
| Walk | 3m | 4 m/s | Standard |
| Sprint | 20m | 7 m/s | Stamina drain; noise travels mycelium |
| Fall impact | 15m | — | One-time event on hard landing |

Noise radius is the distance at which the condition registers a signal. Signal strength decreases with distance within the radius.

### Player — Flashlight

| Property | Value |
|---|---|
| Battery life | 5 minutes continuous; 2 minutes recharge in bus |
| Batteries found per world | 0–2 `[PENDING]` |
| Verdant beam | Normal |
| Fungal Depths beam | Scattered by haze; −40% effective range |
| Petrifold beam | High reflection off calcite surfaces |

Only on-foot tool other than throwable rocks and flare gun. No combat applications.

### Vehicle — Base Specifications

| Property | Value |
|---|---|
| Model | 1963 VW Type 2 (T1) 23-Window Deluxe Samba |
| Weight | ~1,100 kg |
| Engine | 50 HP, rear-mounted |
| Drive | Rear-wheel drive |
| Handling feel | Lumbering, floaty, momentum-heavy |
| Max fuel | 100 units |
| Starting fuel (per run) | 80 units |
| Max vehicle health | 100 HP |
| Destructible panels | 56 |

### Vehicle — Fuel Consumption

| Biome | Rate | Notes |
|---|---|---|
| Verdant Old Growth | 1 unit/km | Baseline |
| Fungal Depths | 1.6 units/km | Spore haze affects combustion |
| Petrifold | 0.7 units/km | Engine runs lean and cold |
| Idling | 0.2 units/min | All biomes |

Petrifold's improved fuel economy is not explained by any in-world mechanic the player is told. It is noticed, not announced.

### Vehicle — Health and Damage

| Damage Source | HP Loss |
|---|---|
| Low-speed collision (<20 km/h) | 2–5 HP |
| Medium collision (20–50 km/h) | 8–15 HP |
| High-speed collision (>50 km/h) | 20–40 HP |
| Deadfall impact | 25 HP |
| Mycelium Network spore burst | 10 HP (exterior panels) |
| Storm exposure | 15 HP/sec |
| Presence contact (on exterior) | 0 HP — condition presence does not damage bus mechanically |

Panel damage distributes across the 60-panel system (56 body panels + 4 tires). Each panel tracks its own damage state. Panels at 0 HP do not fall off — they deform and remain, accumulating visual damage. Aggregate panel damage contributes to overall vehicle health. Repair kits restore 20 HP per kit, targetable at specific panel groups or the drivetrain.

### Vehicle — Electrical System

The electrical system is old and unstable. Stress events cause transient failures.

| Stress Source | Effect | Recovery |
|---|---|---|
| Hollow Tree (20m) | Instrument drift, radio static | Auto on exit from radius |
| Hollow Tree (10m) | Engine power −40%, lights flicker | Auto on exit |
| Hollow Tree (5m) | Engine near-failure, instruments dead | Auto on exit |
| Storm proximity (<50m) | Full electrical failure | Auto if Storm not caught |
| High disturbance (Agitated+) | Intermittent instrument failure | Auto; frequency increases |

Electrical failure does not strand the bus unless combined with Petrified Zone seizure. Engine will restart after exit from stress radius.

### Vehicle — Dashboard Instruments

All vehicle-state feedback is diegetic. No HUD overlays.

| Instrument | Normal | Degraded (Agitated) | Failed |
|---|---|---|---|
| Fuel gauge | Accurate | ±10% error | Stuck at last reading |
| Speedometer | Accurate | Minor drift | Inaccurate |
| Tachometer | Accurate | Jittery | Inaccurate |
| Gear indicator | Accurate | Delayed | Dark |
| Battery gauge | Stable | Flickering | Dark |

At Agitated, instruments become unreliable enough that the player must estimate fuel and speed from engine audio and road feel.

### Vehicle — The Bus as Force

At speed, the bus makes contact with whatever is standing in the road. What is in the road is not an entity with a health pool — it is the condition at a local concentration, present and not moving. Contact at speed disperses that concentration. It does not kill anything.

| Speed at Contact | Bus Damage | Notes |
|---|---|---|
| <10 km/h | 0 | Contact registered, no panel damage |
| 10–30 km/h | 2–8 HP (exterior panels) | Low-speed brush |
| 30–60 km/h | 10–20 HP (exterior panels) | Standard impact |
| >60 km/h | 25–40 HP (exterior panels) | High-speed, significant panel damage |

Contact at higher disturbance produces denser concentrations and proportionally greater panel damage.

### Resources

| Item | Effect | Collection | Disturbance Cost |
|---|---|---|---|
| Fuel canister | +25 fuel | Drive-by or on foot | +3 |
| Repair kit | +20 vehicle HP (targeted) | Drive-by or on foot | +4 |
| Medkit | +25 player HP | On foot only (stop required) | +5 |
| Flare gun | Distraction tool, single use | On foot only (stop required) | +3 to find |
| Flashlight battery | +5 min flashlight | On foot only | +3 |
| Rock | Throwable distraction | Passive (always available) | +0.5/throw |

Spawn rates: fuel canister common (gas stations, ranger stations, roadsides); repair kit common (ranger stations, trailers, cargo containers); medkit uncommon (ranger stations, first aid cabinets); flare gun rare (research trailers, one per world max); flashlight battery uncommon (structures, vehicle gloveboxes).

Carry limits (field): fuel canister ×2, repair kit ×2, medkit ×2, flare gun ×1, flashlight battery ×3, rock unlimited. Garage storage: unlimited for fuel/repair/battery; medkit cabinet holds 3; flare gun not storable (found in field only); rocks N/A.

Fuel canisters and repair kits can be collected from inside a moving vehicle at speeds up to 20 km/h. Player must pass within 2m. Collection automatic on proximity — primary method for minimizing on-foot time. On-foot items require a 3-second interact animation; player is stationary and vulnerable during this time.

### Flare Gun Mechanics

| Property | Value |
|---|---|
| Uses | 1 (single shot, found item) |
| Carry limit | 1 at a time |
| Draw radius | 80m |
| Burn duration | 45 seconds |
| Effect | Condition attention redirects toward flare location for burn duration |
| Post-burn | Attention dissipates from flare location over ~10 seconds |
| Disturbance cost (fire) | +6 |

Not a weapon. Creates a temporary attention sink — redirecting the condition's local concentration toward heat and light, useful for clearing a path to the bus or to an exit, never for confrontation.

### Garage Systems

Single-room structure. Player explores on foot. Bus occupies center bay. All interaction points peripheral.

| Element | Function |
|---|---|
| Repair workbench | Spend repair kits on panel groups, drivetrain, or installed components |
| Fitting station | Install, remove, inspect vehicle components `[PENDING spec 027]` |
| First-aid cabinet | Use or store medkits (max 3) |
| Wall map | Seed selection. Displays biome zones for selected seeds |
| Inventory shelf | Stored items: batteries, spare repair kits, uninstalled components |
| Run notebook | Passive display near workbench. Per-run statistics, death/extraction counts, per-biome time. Read-only |
| Van (exterior) | Inspect panel damage and installed component condition visually |
| Van (interior) | Glovebox (battery storage), radio controls, footwell loading. Enter to begin run |

Repair workbench allocates repair kits to: exterior panels (front/rear/left/right/roof), mechanical systems (engine, drivetrain), electrical systems (instruments, headlights, radio). Each kit restores 20 HP, distributed across targeted system. Multiple kits can be applied to same system.

### Garage Contamination Progression

Persistent, cross-run. Does not decrease.

| Threshold | Visual Change | Notes |
|---|---|---|
| 0 | Clean | Starting state |
| 10 | Moss in northwest corner | First visible sign |
| 25 | Fungal bloom on floor near vehicle | Matches Fungal Depths wheel well bloom |
| 40 | Mineral deposit at base of treeline wall | Matches Petrifold calcite |
| 60 | Mycelium thread on first-aid cabinet hinge | Recognizable to attentive players |
| 80 | Amber light visible through window at night | The forest is producing its signal inside the safe space |
| 100 | `[PENDING]` — epic event | |

Accumulates by: run completed (extraction) +3; deep Fungal run +5; Petrifold entry +3; death +2; Mycelium contact +1 per contact (cumulative).

### The Window

The single garage window faces the treeline. Always present. Cannot be boarded or obscured. Provides ambient exterior audio (forest at reduced volume) and, at high contamination, Amber Bleed is visible through it from inside the garage. First indication that the process has entered the safe space in a meaningful way.

### On-Foot Systems

All on-foot interactions have a 3-second animation with no skip. Player is stationary and vulnerable. Cancellable-by-movement: resource collection, structure entry.

**Vehicle entry/exit**: ~1.5-second camera interpolation. Player is vulnerable throughout — neither fully inside nor fully outside; the condition does not distinguish this transition from full on-foot exposure. Intentional.

**On-foot noise** (additive with bus noise when player is outside and bus is idling nearby):

| Action | Radius | Duration |
|---|---|---|
| Crouch | 0m | — |
| Walking | 3m | Continuous |
| Sprinting | 20m | Continuous |
| Fall impact | 15m | 3s |
| Interaction (pickup) | 5m | 1s |
| Grab escape | 20m | 2s |

### UI Philosophy — No HUD

No health bar. No fuel %. No disturbance meter. No minimap. No objective markers.

Information available through:
- Dashboard instruments (vehicle state)
- Van audio (engine, damage, electrical)
- Environmental audio (disturbance state, condition presence)
- Visual environment (biome, weather, anomaly signatures)
- The player's body (breathing, movement capability)

**Permitted UI surfaces**:

| Surface | Context | Content |
|---|---|---|
| Garage wall map | Garage only, on foot | Seed selection, biome zones |
| Inventory screen | Garage or stopped bus | Current inventory, management |
| Dashboard instruments | Always (in van) | Fuel, speed, RPM, gear, battery |
| Interaction prompts | Proximity-triggered | Minimal single verb (TAKE/OPEN/ENTER) |

Prompts appear only within interaction range. No waypoints, quest markers, objective text.

**Death screen**: hard cut to black; single audio event (silence, or forest transmission). No in-moment stats. Stats available next garage return via run notebook.
**Extraction screen**: exit gate closes behind bus; wind-chime resonance fading. Cut to garage with bus in bay. No score screen.

### Save & Persistence

**Persistent**: vehicle HP, per-panel damage states, vehicle configuration (installed components + damage), fuel level, inventory contents, player gear (once equipped, permanent), total runs, total extractions, total deaths, biome preference (last selected), per-biome statistics (time, runs entered, extractions from), garage contamination level (0–100, never decreases), player exposure level (0–100, never decreases).

**Does not persist**: world layout (regenerated per seed per run), condition concentration zones (influenced by seed but not fixed), resource positions (randomized within structure/road rules each run), anomaly activation states (reset each run), disturbance meter (resets to 0 each run), player health mid-run (resets to persistent value on garage return).

**Save trigger**: auto-save fires exactly once per run cycle on garage return after extraction or death. No manual save. No mid-run save. Application closed mid-run = treated as death on next launch.

### Progression — Tradeoff-First Framework

The original prohibition on numerical upgrades (pre-2.19.0 constitution) is replaced by a tradeoff-first framework. Numerical progression is permitted iff all three:

1. **Diegetically grounded.** Change is a physical thing on the bus or worn by the player. No abstract stat increases.
2. **Genuine tradeoff.** No component is a pure upgrade. Every gain carries a corresponding cost.
3. **Bounded.** Components have fixed stats. No escalating tiers, upgrade trees, or compounding bonuses.

The condition cannot be overcome. A fully-configured bus with optimal tradeoffs is still subject to the same disturbance rules, Storm, and condition. Configuration is playstyle expression, not power escalation.

**Valid progression types**:

| Type | Description | Examples |
|---|---|---|
| Informational | Player gains knowledge, not statistics | Wall map annotations, notebook records |
| Narrative | Progression against the player | Garage contamination, player exposure |
| Physical (tradeoff) | Diegetic, bounded, with genuine cost | Vehicle components, worn gear |

**Prohibited**: abstract stat upgrades (not diegetically grounded); pure upgrades (gain without cost); escalating tiers (not bounded); fuel capacity upgrades (no physical basis in van configuration); HP upgrades without physical component.

### Vehicle Configuration System (§16a)

The bus can be fitted with physical components altering behavior. All components durable, degrade with use, require workbench repair. Installed components persist across runs. Destroyed beyond repair = gone permanently. Full specification (stat tables, crafting rules, workbench UI, epic unlocks) deferred to spec 027.

**Categories**: body panels, bumpers, lights, accessories, spoilers, roll cages, other fittings.

**Tradeoff examples** (illustrative, not final):

| Component | Benefit | Cost |
|---|---|---|
| Heavy steel bumper | +impact force, −bus damage on road contact | +noise on impact, −top speed |
| Rear stabilizer wing | +stability at speed | +wind noise (disturbance) |
| Full roll cage | +van HP pool | +rattle audio signature (disturbance) |
| Roof-mounted aux lights | +forward visibility range | +electrical draw, +disturbance when active |
| Reinforced door skins | +panel HP (doors) | +weight, −acceleration |
| External fuel mount | +fuel carry capacity | +fire risk on collision, +noise on rough terrain |

No component combination produces a net advantage. Tradeoffs cumulative.

**Degradation**: components degrade independently from 60-panel body. Degraded components retain tradeoff *costs* while losing *benefits*. Damaged roll cage still rattles but no longer contributes full HP. Repair at workbench targeting the component directly.

**Persistence**:

| State | Behavior |
|---|---|
| Installed, undamaged | Persists across runs, full effect active |
| Installed, degraded | Persists, reduced benefit, full cost |
| Installed, destroyed | Removed permanently. Cannot be recovered |
| Uninstalled (storage) | Persists in garage inventory |

**Acquisition**: `[PENDING]` — three channels proposed: scavenged (found in structures, road debris, wrecked vehicles), crafted (crafting TBD), unlocked via epics (epic system TBD). Dedicated spec required.

### Player Gear (§16b)

Player can find and equip gear (clothing, protective layers). Once equipped, permanent. Player does not manage between runs.

| Property | Value |
|---|---|
| Acquisition | `[PENDING]` |
| Equip behavior | Permanent on first equip. Cannot be removed |
| Mechanical effects | `[PENDING]` — exposure resistance, stamina modifiers |
| Current scope | Cosmetic only |

Intent: keep player's attention on the van, not on their character. Gear is a visible record of what the player has found, not a system to manage.

### Camera & Controls

**In-vehicle**: first-person, locked to driver seat. FOV 75° default. Player can look left/right/mirrors. Full 360° head turn at low speed. Dashboard occupies lower quarter, always visible, readable at a glance. No UI overlay on dashboard.

**On-foot**: standard first-person. FOV 80° default. No weapon viewmodel (flashlight only when active).

**Vehicle entry/exit**: 1.5-second interpolation, not skippable. Physical animation, not cut.

### Out of Scope for v1.0

- Additional biomes (architecture supports expansion)
- Multiplayer (not in scope or architecture)
- New vehicle types (Samba is the only vehicle)
- Voiced narrative (Gary TTS system is audio spec only)
- Garage narrative events (contamination epic events at 80 and 100 `[PENDING]`)
- Environmental presence system (replaces Hollow AI — spec required)
- Player/bus convergence endpoint (Exposure 81–100 and garage endpoint `[PENDING]`)
- Endpoint visual and mechanical design (World Bible direction set; implementation open)

### Accessibility Considerations (to resolve pre-ship)

- **No HUD**: players relying on visual clarity for HP/resource state have no fallback. Consider optional accessibility mode with minimal diegetically-consistent overlays (e.g. faint gauge texture rendered as part of the dashboard, not a screen overlay).
- **Audio-dependent systems** (The Silence, presence audio, disturbance shifts, radio degradation): deaf/HoH players need visual equivalents. Suggestions: subtle screen-edge coloration for disturbance state; visual indicator for Silence zone entry; captioning for radio.
- **Low-visibility environments** (night Petrifold + The Silence): players with visual impairments face compounded difficulty. Consider optional navigation audio (subtle spatial tone for exit gate direction).

Solutions must maintain the horror register.

## How It Appears In-Game

The player learns the loop empirically. The first run is likely lost — not punitively, but because the mechanics take time to internalize. A player who survives long enough learns that the loop is not theirs. The forest was running this cycle before the first road was cut.

## Related

- [[The Crater]] — the origin event; the higher-dimensional geometry that makes the loop topological
- [[The Temporal Fracture]] — extraction as circuit completion; the loop is the shape of the space
- [[World Model]] — the world the mechanics operate within
- [[Biomes]] — fuel, weather, and audio regimes per biome
- [[Disturbance System]] — the tension mechanic these costs feed
- [[Anomalies]] — the hazards in the world
- [[Controls]] — the input layer
- [[Tone and Horror]] — the tonal register mechanics serve
- [[Vehicle — Samba]] — implementation of the vehicle specs
- [[Vehicle — Destruction]] — implementation of panel damage
- [[Vehicle — Dashboard]] — the diegetic instrument implementation
- [[Ephemerality Thread]] — the run-reset rule
- [[The Player Causes the Storm]] — endgame consequence
- [[Constitution]] — Article II (Car Is Core), Article IV Rules 6–8 (ephemeral worlds + tradeoff progression)

Controlled tag vocabulary (as read):
type/*:
- `type/code` — Code architecture, autoloads, conventions, tooling. Carries `code-refs:`. (e.g. `Code/Autoloads — Disturbance.md`)
- `type/decision` — Architectural or design decision made by an agent during a session. Written to `docs/vault/Decisions/`. (Agent notes only — spec 080.)
- `type/design` — Design intent, player-facing concepts, world lore. (e.g. `Design/World Model.md`)
- `type/discovery` — Non-obvious constraint, gap, or conflict found by an agent during a session. Written to `docs/vault/Discoveries/`. (Agent notes only — spec 080.)
- `type/moc` — Map of Content at any of three tiers (folder / domain / concept). (e.g. `Audio.md`)
- `type/principle` — Governance and constitutional notes. Non-negotiable rules. (e.g. `Governance/Constitution.md`)
- `type/reference` — Glossary, decision log, open questions, epics. (e.g. `Reference/Glossary.md`)
- `type/session-log` — Session activity log; permanent audit trail. Written to `docs/vault/Sessions/`. Append-only, never pruned. (Agent notes only — spec 080.)
- `type/spec` — Spec document at `docs/vault/Specs/NNN Title/spec.md`. Carries `spec-refs:`. (e.g. `Specs/047 Car Radio/spec.md`)
- `type/system` — A bounded subsystem with implementation. Carries `code-refs`, `spec-refs`, `implements:` frontmatter. (e.g. `Systems/Audio — Car Radio.md`)
- `type/vision` — Strategic / vision-layer decision. Written to `docs/vault/Vision/`. Human-authored or agent-proposed with human ratification before promotion to `status: reviewed`. (Per triage #3 — spec 133 autonomous-company redesign.)
domain/*:
- `domain/anomalies` — Anomaly taxonomy, individual anomaly systems, spawn, behavior
- `domain/art` — Visual direction, palettes, references, asset pipeline
- `domain/audio` — Audio systems: world ambient, radio, transmissions, buses, pipeline
- `domain/autonomous-company` — Autonomous company v0.1 experiment: Slack infra, persona middleware, Letta integration, restart recovery
- `domain/build` — Build system, packaging, export, release automation
- `domain/governance` — Constitution, phased spec, policies
- `domain/infrastructure` — Infrastructure provisioning: CI/CD, hosting, deployment tooling, secrets management
- `domain/narrative` — Tone, horror register, forest transmissions narrative, Gary/KTLK
- `domain/player` — Player mode, input, controls, camera, exit/entry
- `domain/systems` — Cross-cutting system architecture and integration work
- `domain/tooling` — Build, CI, observer, TTS pipeline, dev-time tools
- `domain/vehicle` — The Samba: vehicle physics, dashboard, damage, panels
- `domain/world` — World model, biomes, terrain, procedural generation, weather
status/*:
- `status/canonical` — Fully authoritative; promoted by humans only. Highest trust. (Agent notes only — spec 080.)
- `status/draft` — Authoring in progress, not yet verified
- `status/reviewed` — Agent-created note verified against codebase within its creating session. Eligible for auto-injection in subsequent task dispatches. (Agent notes only — spec 080.)
- `status/stale` — Known out of date; cannot update immediately. Pairs with `> [!warning] STALE — needs update` callout.
- `status/superseded` — Replaced by another note. Terminal state. Pairs with `> [!warning] SUPERSEDED` callout.
- `status/wip` — Stable but under active revision
layer/*:
- `layer/content` — Content assets (audio, models, textures, audio provenance)
- `layer/gdext` — gdext wrapper layer (`rust/gdext-wrapper/`)
- `layer/gdscript` — GDScript (Godot scene-tier logic)
- `layer/infra` — Build, CI, deployment infrastructure
- `layer/python` — Python development tooling (`tools/`)
- `layer/rust-core` — Engine-agnostic Rust core (`rust/rust-core/`)
concept/*:
- `concept/biome` — Biome-reactive behavior across systems
- `concept/contamination` — Across-runs panel and garage degradation; the slow-horror mechanic that doesn't reset with the world
- `concept/diegetic` — Diegetic audio / UI / world-sourced design
- `concept/disturbance` — The disturbance mechanic thread (Article X)
- `concept/ephemeral-world` — Run-reset, transient worlds (Article IV Rules 6–7)
- `concept/governance` — Constitutional and governance concepts
- `concept/horror` — Horror register and dread design
- `concept/procedural` — Procedural generation, seed determinism
- `concept/rendering` — Visual rendering quality, shader correctness, Terrain3D integration, mesh fidelity, LOD, Z-fighting
- `concept/terrain` — Terrain generation, heightmap, Terrain3D regions, roughness, playability constraints
ember's answer for tag_assignment-design-core-mechanics, type/designP(true) placed on the no, unsure, and yes zones.nounsureyesgold: yesP = 0.37

tag_assignment-design-core-mechanics: type/spec

Tag assignment · dev
Gold
The note has no reason to carry `type/spec` (False)
ember
The note calls for `type/spec`: Spec document at `docs/vault/Specs/NNN Title/spec.md`. Carries `spec-refs:`. (e.g. `Specs/047 Car Radio/spec.md`) (True)
Signal
P(true) 0.62 (unsure)
Kit outcome
deferred: treated as unsure
Why this gold label
Mined from Design/Core Mechanics.md at 692f4bb58b7f62105aeb73fba8dfee12bfdecd53; gold is the note's own vocabulary tags.
Core Mechanics

The mechanical and systems spine of Old Growth: the run loop, player stats, vehicle specifications, resources, garage systems, on-foot handling, UI philosophy, save system, and progression framework. Where [[World Model]] establishes structure and [[Tone and Horror]] establishes register, this note captures the authoritative mechanical values. All values marked `[PENDING]` require playtesting to finalize.

## Overview

Every mechanic serves three design pillars. When a proposed system conflicts, the system changes, not the pillars.

- **Flesh as Horror.** Player body and bus body are both subject to irreversible change. Damage cumulates and is visible. The condition crosses run boundaries in both — the bus through contamination, the player through exposure.
- **The Unknowable Condition.** The forest is never explained. No mechanic makes it legible or masterable. Configuring the bus changes *how* the player meets the condition, not *whether* they can defeat it.
- **Sealed In With It.** Escape is always available in principle and always costly in practice. Ridges, the Storm, fuel economy, and disturbance all pressure toward the exit.

## Key Decisions

### Game Loop

```
GARAGE → SEED SELECTION → WORLD LOAD → DRIVE OUT →
EXPLORE / SCAVENGE → DISTURBANCE ACCUMULATES →
[STORM TRIGGERS if threshold reached] → EXIT ATTEMPT →
[EXTRACTION or DEATH] → GARAGE
```

**Lore framing**: The loop is not a game abstraction imposed on a world. It is the topology of the structure the construct is actively reshaping. The garage is the vertex: the one point all faces share. The exit corridors are edges that fold back to the vertex. Extraction and death both return the player to the garage because all paths inside the closed geometry return to the center. The player has never left. (Post-convergence: death still returns to the vertex, but extraction crosses the rim into the outside. See spec 127.) See [[The Crater]] and [[The Temporal Fracture]].

Engine states:

| State | Description |
|---|---|
| GARAGE | Player on foot in garage. Van accessible. No disturbance accumulation. |
| LOADING | World generation in progress. Seed locked. |
| DRIVING | Player in vehicle, world active. Disturbance accumulates. |
| ON_FOOT | Player outside vehicle. Disturbance accumulates. Maximum vulnerability. |
| STORM_ACTIVE | Storm spawned. Prior states continue. Escape window open. |
| EXTRACTED | Player reached exit gate. Run success. Return to garage. |
| DEAD | Player HP to zero or petrification completed. Run failure. Return to garage. |

Run success: vehicle crosses exit gate with player inside. Run failure: player HP zero, Storm catches player in open, petrification completes on foot, or engine seizure in Petrified Zone with no recovery window. Both outcomes return the player to the garage — the vertex. The difference is how much damage the circuit did on the way through. No campaign end state in v1.0 — the garage contamination arc and player exposure arc provide long-term narrative progression toward the convergence endpoint, which is not a conclusion but a phase transition: after convergence, death still returns to the vertex, but extraction crosses the rim into the outside. The game rules change. See The Temporal Fracture and spec 127.

### Player — Health

| Property | Value |
|---|---|
| Maximum health | 100 HP |
| Starting health (per run) | 100 HP |
| Medkit restore | 25 HP |
| Regen | None |
| Death threshold | 0 HP |

Health does not regenerate. Only restoration is medkit use. Tracked via breathing audio, screen-edge vignette (dark, not colored), and interaction speed reduction at low health. No numeric display.

### Player — Stamina

| Property | Value |
|---|---|
| Maximum stamina | 100 units |
| Sprint drain | 20 units/sec |
| Interact drain | 5 units/action |
| Contact escape drain | 30 units |
| Recharge (walking) | 10 units/sec |
| Recharge (crouching/stationary) | 15 units/sec |
| Recharge (inside van) | 20 units/sec |
| Minimum for sprint | 10 units |

No HUD. Read through movement-speed degradation and audible breathing. Sprint locks at <10 units.

### Player — Exposure (Cross-Run)

Persistent value tracking cumulative contact with the condition across all runs. Does not reset on death or extraction. Does not decrease. Accumulates in the player the same way garage contamination accumulates in the garage — one direction, no instrument, no remedy.

| Threshold | Symptom |
|---|---|
| 0–20 | No symptoms |
| 21–40 | Persistent cough audio, occasional sound delay (50ms) |
| 41–60 | Warmth sensation in hands (haptic/audio), smell sensitivity (audio mix) |
| 61–80 | Vision film at edges, 10% stamina-capacity reduction |
| 81–100 | `[PENDING]` — endpoint design required before implementation |

Exposure sources:
- Spore Cloud on foot: +5 per 10s of contact
- Mycelium Network on foot: +10 per contact event
- Extended Fungal Depths on foot: +2 per minute
- Deep Fungal runs (>50% run time in Fungal): +5 on extraction
- Extended on-foot time at Agitated+ disturbance: +1 per minute

No direct display. Symptoms are designed to feel ordinary — cough, warmth, slight unreliability — so players do not immediately understand what is accumulating.

### Player — Movement

| Mode | Noise Radius | Speed | Notes |
|---|---|---|---|
| Crouch | 0m (silent) | 2 m/s | Only fully silent movement |
| Walk | 3m | 4 m/s | Standard |
| Sprint | 20m | 7 m/s | Stamina drain; noise travels mycelium |
| Fall impact | 15m | — | One-time event on hard landing |

Noise radius is the distance at which the condition registers a signal. Signal strength decreases with distance within the radius.

### Player — Flashlight

| Property | Value |
|---|---|
| Battery life | 5 minutes continuous; 2 minutes recharge in bus |
| Batteries found per world | 0–2 `[PENDING]` |
| Verdant beam | Normal |
| Fungal Depths beam | Scattered by haze; −40% effective range |
| Petrifold beam | High reflection off calcite surfaces |

Only on-foot tool other than throwable rocks and flare gun. No combat applications.

### Vehicle — Base Specifications

| Property | Value |
|---|---|
| Model | 1963 VW Type 2 (T1) 23-Window Deluxe Samba |
| Weight | ~1,100 kg |
| Engine | 50 HP, rear-mounted |
| Drive | Rear-wheel drive |
| Handling feel | Lumbering, floaty, momentum-heavy |
| Max fuel | 100 units |
| Starting fuel (per run) | 80 units |
| Max vehicle health | 100 HP |
| Destructible panels | 56 |

### Vehicle — Fuel Consumption

| Biome | Rate | Notes |
|---|---|---|
| Verdant Old Growth | 1 unit/km | Baseline |
| Fungal Depths | 1.6 units/km | Spore haze affects combustion |
| Petrifold | 0.7 units/km | Engine runs lean and cold |
| Idling | 0.2 units/min | All biomes |

Petrifold's improved fuel economy is not explained by any in-world mechanic the player is told. It is noticed, not announced.

### Vehicle — Health and Damage

| Damage Source | HP Loss |
|---|---|
| Low-speed collision (<20 km/h) | 2–5 HP |
| Medium collision (20–50 km/h) | 8–15 HP |
| High-speed collision (>50 km/h) | 20–40 HP |
| Deadfall impact | 25 HP |
| Mycelium Network spore burst | 10 HP (exterior panels) |
| Storm exposure | 15 HP/sec |
| Presence contact (on exterior) | 0 HP — condition presence does not damage bus mechanically |

Panel damage distributes across the 60-panel system (56 body panels + 4 tires). Each panel tracks its own damage state. Panels at 0 HP do not fall off — they deform and remain, accumulating visual damage. Aggregate panel damage contributes to overall vehicle health. Repair kits restore 20 HP per kit, targetable at specific panel groups or the drivetrain.

### Vehicle — Electrical System

The electrical system is old and unstable. Stress events cause transient failures.

| Stress Source | Effect | Recovery |
|---|---|---|
| Hollow Tree (20m) | Instrument drift, radio static | Auto on exit from radius |
| Hollow Tree (10m) | Engine power −40%, lights flicker | Auto on exit |
| Hollow Tree (5m) | Engine near-failure, instruments dead | Auto on exit |
| Storm proximity (<50m) | Full electrical failure | Auto if Storm not caught |
| High disturbance (Agitated+) | Intermittent instrument failure | Auto; frequency increases |

Electrical failure does not strand the bus unless combined with Petrified Zone seizure. Engine will restart after exit from stress radius.

### Vehicle — Dashboard Instruments

All vehicle-state feedback is diegetic. No HUD overlays.

| Instrument | Normal | Degraded (Agitated) | Failed |
|---|---|---|---|
| Fuel gauge | Accurate | ±10% error | Stuck at last reading |
| Speedometer | Accurate | Minor drift | Inaccurate |
| Tachometer | Accurate | Jittery | Inaccurate |
| Gear indicator | Accurate | Delayed | Dark |
| Battery gauge | Stable | Flickering | Dark |

At Agitated, instruments become unreliable enough that the player must estimate fuel and speed from engine audio and road feel.

### Vehicle — The Bus as Force

At speed, the bus makes contact with whatever is standing in the road. What is in the road is not an entity with a health pool — it is the condition at a local concentration, present and not moving. Contact at speed disperses that concentration. It does not kill anything.

| Speed at Contact | Bus Damage | Notes |
|---|---|---|
| <10 km/h | 0 | Contact registered, no panel damage |
| 10–30 km/h | 2–8 HP (exterior panels) | Low-speed brush |
| 30–60 km/h | 10–20 HP (exterior panels) | Standard impact |
| >60 km/h | 25–40 HP (exterior panels) | High-speed, significant panel damage |

Contact at higher disturbance produces denser concentrations and proportionally greater panel damage.

### Resources

| Item | Effect | Collection | Disturbance Cost |
|---|---|---|---|
| Fuel canister | +25 fuel | Drive-by or on foot | +3 |
| Repair kit | +20 vehicle HP (targeted) | Drive-by or on foot | +4 |
| Medkit | +25 player HP | On foot only (stop required) | +5 |
| Flare gun | Distraction tool, single use | On foot only (stop required) | +3 to find |
| Flashlight battery | +5 min flashlight | On foot only | +3 |
| Rock | Throwable distraction | Passive (always available) | +0.5/throw |

Spawn rates: fuel canister common (gas stations, ranger stations, roadsides); repair kit common (ranger stations, trailers, cargo containers); medkit uncommon (ranger stations, first aid cabinets); flare gun rare (research trailers, one per world max); flashlight battery uncommon (structures, vehicle gloveboxes).

Carry limits (field): fuel canister ×2, repair kit ×2, medkit ×2, flare gun ×1, flashlight battery ×3, rock unlimited. Garage storage: unlimited for fuel/repair/battery; medkit cabinet holds 3; flare gun not storable (found in field only); rocks N/A.

Fuel canisters and repair kits can be collected from inside a moving vehicle at speeds up to 20 km/h. Player must pass within 2m. Collection automatic on proximity — primary method for minimizing on-foot time. On-foot items require a 3-second interact animation; player is stationary and vulnerable during this time.

### Flare Gun Mechanics

| Property | Value |
|---|---|
| Uses | 1 (single shot, found item) |
| Carry limit | 1 at a time |
| Draw radius | 80m |
| Burn duration | 45 seconds |
| Effect | Condition attention redirects toward flare location for burn duration |
| Post-burn | Attention dissipates from flare location over ~10 seconds |
| Disturbance cost (fire) | +6 |

Not a weapon. Creates a temporary attention sink — redirecting the condition's local concentration toward heat and light, useful for clearing a path to the bus or to an exit, never for confrontation.

### Garage Systems

Single-room structure. Player explores on foot. Bus occupies center bay. All interaction points peripheral.

| Element | Function |
|---|---|
| Repair workbench | Spend repair kits on panel groups, drivetrain, or installed components |
| Fitting station | Install, remove, inspect vehicle components `[PENDING spec 027]` |
| First-aid cabinet | Use or store medkits (max 3) |
| Wall map | Seed selection. Displays biome zones for selected seeds |
| Inventory shelf | Stored items: batteries, spare repair kits, uninstalled components |
| Run notebook | Passive display near workbench. Per-run statistics, death/extraction counts, per-biome time. Read-only |
| Van (exterior) | Inspect panel damage and installed component condition visually |
| Van (interior) | Glovebox (battery storage), radio controls, footwell loading. Enter to begin run |

Repair workbench allocates repair kits to: exterior panels (front/rear/left/right/roof), mechanical systems (engine, drivetrain), electrical systems (instruments, headlights, radio). Each kit restores 20 HP, distributed across targeted system. Multiple kits can be applied to same system.

### Garage Contamination Progression

Persistent, cross-run. Does not decrease.

| Threshold | Visual Change | Notes |
|---|---|---|
| 0 | Clean | Starting state |
| 10 | Moss in northwest corner | First visible sign |
| 25 | Fungal bloom on floor near vehicle | Matches Fungal Depths wheel well bloom |
| 40 | Mineral deposit at base of treeline wall | Matches Petrifold calcite |
| 60 | Mycelium thread on first-aid cabinet hinge | Recognizable to attentive players |
| 80 | Amber light visible through window at night | The forest is producing its signal inside the safe space |
| 100 | `[PENDING]` — epic event | |

Accumulates by: run completed (extraction) +3; deep Fungal run +5; Petrifold entry +3; death +2; Mycelium contact +1 per contact (cumulative).

### The Window

The single garage window faces the treeline. Always present. Cannot be boarded or obscured. Provides ambient exterior audio (forest at reduced volume) and, at high contamination, Amber Bleed is visible through it from inside the garage. First indication that the process has entered the safe space in a meaningful way.

### On-Foot Systems

All on-foot interactions have a 3-second animation with no skip. Player is stationary and vulnerable. Cancellable-by-movement: resource collection, structure entry.

**Vehicle entry/exit**: ~1.5-second camera interpolation. Player is vulnerable throughout — neither fully inside nor fully outside; the condition does not distinguish this transition from full on-foot exposure. Intentional.

**On-foot noise** (additive with bus noise when player is outside and bus is idling nearby):

| Action | Radius | Duration |
|---|---|---|
| Crouch | 0m | — |
| Walking | 3m | Continuous |
| Sprinting | 20m | Continuous |
| Fall impact | 15m | 3s |
| Interaction (pickup) | 5m | 1s |
| Grab escape | 20m | 2s |

### UI Philosophy — No HUD

No health bar. No fuel %. No disturbance meter. No minimap. No objective markers.

Information available through:
- Dashboard instruments (vehicle state)
- Van audio (engine, damage, electrical)
- Environmental audio (disturbance state, condition presence)
- Visual environment (biome, weather, anomaly signatures)
- The player's body (breathing, movement capability)

**Permitted UI surfaces**:

| Surface | Context | Content |
|---|---|---|
| Garage wall map | Garage only, on foot | Seed selection, biome zones |
| Inventory screen | Garage or stopped bus | Current inventory, management |
| Dashboard instruments | Always (in van) | Fuel, speed, RPM, gear, battery |
| Interaction prompts | Proximity-triggered | Minimal single verb (TAKE/OPEN/ENTER) |

Prompts appear only within interaction range. No waypoints, quest markers, objective text.

**Death screen**: hard cut to black; single audio event (silence, or forest transmission). No in-moment stats. Stats available next garage return via run notebook.
**Extraction screen**: exit gate closes behind bus; wind-chime resonance fading. Cut to garage with bus in bay. No score screen.

### Save & Persistence

**Persistent**: vehicle HP, per-panel damage states, vehicle configuration (installed components + damage), fuel level, inventory contents, player gear (once equipped, permanent), total runs, total extractions, total deaths, biome preference (last selected), per-biome statistics (time, runs entered, extractions from), garage contamination level (0–100, never decreases), player exposure level (0–100, never decreases).

**Does not persist**: world layout (regenerated per seed per run), condition concentration zones (influenced by seed but not fixed), resource positions (randomized within structure/road rules each run), anomaly activation states (reset each run), disturbance meter (resets to 0 each run), player health mid-run (resets to persistent value on garage return).

**Save trigger**: auto-save fires exactly once per run cycle on garage return after extraction or death. No manual save. No mid-run save. Application closed mid-run = treated as death on next launch.

### Progression — Tradeoff-First Framework

The original prohibition on numerical upgrades (pre-2.19.0 constitution) is replaced by a tradeoff-first framework. Numerical progression is permitted iff all three:

1. **Diegetically grounded.** Change is a physical thing on the bus or worn by the player. No abstract stat increases.
2. **Genuine tradeoff.** No component is a pure upgrade. Every gain carries a corresponding cost.
3. **Bounded.** Components have fixed stats. No escalating tiers, upgrade trees, or compounding bonuses.

The condition cannot be overcome. A fully-configured bus with optimal tradeoffs is still subject to the same disturbance rules, Storm, and condition. Configuration is playstyle expression, not power escalation.

**Valid progression types**:

| Type | Description | Examples |
|---|---|---|
| Informational | Player gains knowledge, not statistics | Wall map annotations, notebook records |
| Narrative | Progression against the player | Garage contamination, player exposure |
| Physical (tradeoff) | Diegetic, bounded, with genuine cost | Vehicle components, worn gear |

**Prohibited**: abstract stat upgrades (not diegetically grounded); pure upgrades (gain without cost); escalating tiers (not bounded); fuel capacity upgrades (no physical basis in van configuration); HP upgrades without physical component.

### Vehicle Configuration System (§16a)

The bus can be fitted with physical components altering behavior. All components durable, degrade with use, require workbench repair. Installed components persist across runs. Destroyed beyond repair = gone permanently. Full specification (stat tables, crafting rules, workbench UI, epic unlocks) deferred to spec 027.

**Categories**: body panels, bumpers, lights, accessories, spoilers, roll cages, other fittings.

**Tradeoff examples** (illustrative, not final):

| Component | Benefit | Cost |
|---|---|---|
| Heavy steel bumper | +impact force, −bus damage on road contact | +noise on impact, −top speed |
| Rear stabilizer wing | +stability at speed | +wind noise (disturbance) |
| Full roll cage | +van HP pool | +rattle audio signature (disturbance) |
| Roof-mounted aux lights | +forward visibility range | +electrical draw, +disturbance when active |
| Reinforced door skins | +panel HP (doors) | +weight, −acceleration |
| External fuel mount | +fuel carry capacity | +fire risk on collision, +noise on rough terrain |

No component combination produces a net advantage. Tradeoffs cumulative.

**Degradation**: components degrade independently from 60-panel body. Degraded components retain tradeoff *costs* while losing *benefits*. Damaged roll cage still rattles but no longer contributes full HP. Repair at workbench targeting the component directly.

**Persistence**:

| State | Behavior |
|---|---|
| Installed, undamaged | Persists across runs, full effect active |
| Installed, degraded | Persists, reduced benefit, full cost |
| Installed, destroyed | Removed permanently. Cannot be recovered |
| Uninstalled (storage) | Persists in garage inventory |

**Acquisition**: `[PENDING]` — three channels proposed: scavenged (found in structures, road debris, wrecked vehicles), crafted (crafting TBD), unlocked via epics (epic system TBD). Dedicated spec required.

### Player Gear (§16b)

Player can find and equip gear (clothing, protective layers). Once equipped, permanent. Player does not manage between runs.

| Property | Value |
|---|---|
| Acquisition | `[PENDING]` |
| Equip behavior | Permanent on first equip. Cannot be removed |
| Mechanical effects | `[PENDING]` — exposure resistance, stamina modifiers |
| Current scope | Cosmetic only |

Intent: keep player's attention on the van, not on their character. Gear is a visible record of what the player has found, not a system to manage.

### Camera & Controls

**In-vehicle**: first-person, locked to driver seat. FOV 75° default. Player can look left/right/mirrors. Full 360° head turn at low speed. Dashboard occupies lower quarter, always visible, readable at a glance. No UI overlay on dashboard.

**On-foot**: standard first-person. FOV 80° default. No weapon viewmodel (flashlight only when active).

**Vehicle entry/exit**: 1.5-second interpolation, not skippable. Physical animation, not cut.

### Out of Scope for v1.0

- Additional biomes (architecture supports expansion)
- Multiplayer (not in scope or architecture)
- New vehicle types (Samba is the only vehicle)
- Voiced narrative (Gary TTS system is audio spec only)
- Garage narrative events (contamination epic events at 80 and 100 `[PENDING]`)
- Environmental presence system (replaces Hollow AI — spec required)
- Player/bus convergence endpoint (Exposure 81–100 and garage endpoint `[PENDING]`)
- Endpoint visual and mechanical design (World Bible direction set; implementation open)

### Accessibility Considerations (to resolve pre-ship)

- **No HUD**: players relying on visual clarity for HP/resource state have no fallback. Consider optional accessibility mode with minimal diegetically-consistent overlays (e.g. faint gauge texture rendered as part of the dashboard, not a screen overlay).
- **Audio-dependent systems** (The Silence, presence audio, disturbance shifts, radio degradation): deaf/HoH players need visual equivalents. Suggestions: subtle screen-edge coloration for disturbance state; visual indicator for Silence zone entry; captioning for radio.
- **Low-visibility environments** (night Petrifold + The Silence): players with visual impairments face compounded difficulty. Consider optional navigation audio (subtle spatial tone for exit gate direction).

Solutions must maintain the horror register.

## How It Appears In-Game

The player learns the loop empirically. The first run is likely lost — not punitively, but because the mechanics take time to internalize. A player who survives long enough learns that the loop is not theirs. The forest was running this cycle before the first road was cut.

## Related

- [[The Crater]] — the origin event; the higher-dimensional geometry that makes the loop topological
- [[The Temporal Fracture]] — extraction as circuit completion; the loop is the shape of the space
- [[World Model]] — the world the mechanics operate within
- [[Biomes]] — fuel, weather, and audio regimes per biome
- [[Disturbance System]] — the tension mechanic these costs feed
- [[Anomalies]] — the hazards in the world
- [[Controls]] — the input layer
- [[Tone and Horror]] — the tonal register mechanics serve
- [[Vehicle — Samba]] — implementation of the vehicle specs
- [[Vehicle — Destruction]] — implementation of panel damage
- [[Vehicle — Dashboard]] — the diegetic instrument implementation
- [[Ephemerality Thread]] — the run-reset rule
- [[The Player Causes the Storm]] — endgame consequence
- [[Constitution]] — Article II (Car Is Core), Article IV Rules 6–8 (ephemeral worlds + tradeoff progression)

Controlled tag vocabulary (as read):
type/*:
- `type/code` — Code architecture, autoloads, conventions, tooling. Carries `code-refs:`. (e.g. `Code/Autoloads — Disturbance.md`)
- `type/decision` — Architectural or design decision made by an agent during a session. Written to `docs/vault/Decisions/`. (Agent notes only — spec 080.)
- `type/design` — Design intent, player-facing concepts, world lore. (e.g. `Design/World Model.md`)
- `type/discovery` — Non-obvious constraint, gap, or conflict found by an agent during a session. Written to `docs/vault/Discoveries/`. (Agent notes only — spec 080.)
- `type/moc` — Map of Content at any of three tiers (folder / domain / concept). (e.g. `Audio.md`)
- `type/principle` — Governance and constitutional notes. Non-negotiable rules. (e.g. `Governance/Constitution.md`)
- `type/reference` — Glossary, decision log, open questions, epics. (e.g. `Reference/Glossary.md`)
- `type/session-log` — Session activity log; permanent audit trail. Written to `docs/vault/Sessions/`. Append-only, never pruned. (Agent notes only — spec 080.)
- `type/spec` — Spec document at `docs/vault/Specs/NNN Title/spec.md`. Carries `spec-refs:`. (e.g. `Specs/047 Car Radio/spec.md`)
- `type/system` — A bounded subsystem with implementation. Carries `code-refs`, `spec-refs`, `implements:` frontmatter. (e.g. `Systems/Audio — Car Radio.md`)
- `type/vision` — Strategic / vision-layer decision. Written to `docs/vault/Vision/`. Human-authored or agent-proposed with human ratification before promotion to `status: reviewed`. (Per triage #3 — spec 133 autonomous-company redesign.)
domain/*:
- `domain/anomalies` — Anomaly taxonomy, individual anomaly systems, spawn, behavior
- `domain/art` — Visual direction, palettes, references, asset pipeline
- `domain/audio` — Audio systems: world ambient, radio, transmissions, buses, pipeline
- `domain/autonomous-company` — Autonomous company v0.1 experiment: Slack infra, persona middleware, Letta integration, restart recovery
- `domain/build` — Build system, packaging, export, release automation
- `domain/governance` — Constitution, phased spec, policies
- `domain/infrastructure` — Infrastructure provisioning: CI/CD, hosting, deployment tooling, secrets management
- `domain/narrative` — Tone, horror register, forest transmissions narrative, Gary/KTLK
- `domain/player` — Player mode, input, controls, camera, exit/entry
- `domain/systems` — Cross-cutting system architecture and integration work
- `domain/tooling` — Build, CI, observer, TTS pipeline, dev-time tools
- `domain/vehicle` — The Samba: vehicle physics, dashboard, damage, panels
- `domain/world` — World model, biomes, terrain, procedural generation, weather
status/*:
- `status/canonical` — Fully authoritative; promoted by humans only. Highest trust. (Agent notes only — spec 080.)
- `status/draft` — Authoring in progress, not yet verified
- `status/reviewed` — Agent-created note verified against codebase within its creating session. Eligible for auto-injection in subsequent task dispatches. (Agent notes only — spec 080.)
- `status/stale` — Known out of date; cannot update immediately. Pairs with `> [!warning] STALE — needs update` callout.
- `status/superseded` — Replaced by another note. Terminal state. Pairs with `> [!warning] SUPERSEDED` callout.
- `status/wip` — Stable but under active revision
layer/*:
- `layer/content` — Content assets (audio, models, textures, audio provenance)
- `layer/gdext` — gdext wrapper layer (`rust/gdext-wrapper/`)
- `layer/gdscript` — GDScript (Godot scene-tier logic)
- `layer/infra` — Build, CI, deployment infrastructure
- `layer/python` — Python development tooling (`tools/`)
- `layer/rust-core` — Engine-agnostic Rust core (`rust/rust-core/`)
concept/*:
- `concept/biome` — Biome-reactive behavior across systems
- `concept/contamination` — Across-runs panel and garage degradation; the slow-horror mechanic that doesn't reset with the world
- `concept/diegetic` — Diegetic audio / UI / world-sourced design
- `concept/disturbance` — The disturbance mechanic thread (Article X)
- `concept/ephemeral-world` — Run-reset, transient worlds (Article IV Rules 6–7)
- `concept/governance` — Constitutional and governance concepts
- `concept/horror` — Horror register and dread design
- `concept/procedural` — Procedural generation, seed determinism
- `concept/rendering` — Visual rendering quality, shader correctness, Terrain3D integration, mesh fidelity, LOD, Z-fighting
- `concept/terrain` — Terrain generation, heightmap, Terrain3D regions, roughness, playability constraints
ember's answer for tag_assignment-design-core-mechanics, type/specP(true) placed on the no, unsure, and yes zones.nounsureyesgold: noP = 0.62

tag_assignment-discoveries-spec-156-ci-tooling-gotchas: domain/governance

Tag assignment · test
Gold
The note calls for `domain/governance`: Constitution, phased spec, policies (True)
ember
The note has no reason to carry `domain/governance` (False)
Signal
P(true) 0.04 (no)
Kit outcome
acted on a wrong answer
Why this gold label
Mined from Discoveries/Spec 156 — CI Tooling Gotchas.md at 692f4bb58b7f62105aeb73fba8dfee12bfdecd53; gold is the note's own vocabulary tags.
Spec 156 — CI Tooling Gotchas

Two CI pitfalls discovered during spec 156 PR CI debugging: the make bump targets misparse three-component semver, and the Component SemVer CI check fails on project-config even though the pre-commit hook passes locally.

## Discovery 1 — `make bump-patch` and `make bump-minor` Misparse Versions Like 0.17.12

**Context**: After changing game-affecting files (samba_bus.gd, panel_definitions.gd, etc.) in spec 156, CI's Version Bump Check required a game version bump from 0.17.12. Running `make bump-patch` or `make bump-minor` was the prescribed remedy per the CI error message.

**Discovery**: Both `make bump-patch` and `make bump-minor` misparse semver strings with patch versions ≥10 (like 0.17.12). They output "bump version 0.17.1 -> 0.17.2" instead of correctly reading 0.17.12, then fail with `Error 16` ("No tag found to do an incremental changelog"). This means any version above 0.x.y where y ≥ 10 cannot be bumped via the make targets.

**Workaround**: Manually edit the version string in `src/project.godot` (`config/version="0.x.y"`) to the desired value. CI will sync `export_presets.cfg` automatically on merge. The game-version-check CI gate (`make game-version-check`) validates that the new version is valid SemVer.

**Root cause**: Likely in the bump script's version parsing — it interprets `0.17.12` as the first two components (`0.17`) plus the beginning of the third (`1`), treating the version as `0.17.1`.

## Discovery 2 — Component SemVer Passes Pre-Commit but Fails CI for project-config

**Context**: The pre-commit hook's auto-bump logic runs on staged files and commits the updated `component_versions.json`. But when a commit only touches `src/project.godot` (version bump), the pre-commit hook says "Component SemVer check passed" without auto-bumping the `project-config` component version. CI then compares the branch's `component_versions.json` against the base branch baseline and fails because `project-config` is unchanged.

**Discovery**: The pre-commit hook's auto-bump only triggers when it detects first-party component files that are out of date relative to git's index. When `project.godot` is changed in isolation (not alongside other bus/panel changes), the hook treats the project-config component as "in sync" because the file was just staged. But CI compares against the base branch's `component_versions.json` — which has the old project-config version — so the check fails.

**Workaround**: After bumping `project.godot`, manually bump `project-config`'s version in `src/component_versions.json` before pushing. Or combine the project.godot change with another component change so the auto-bump fires.

**Implication**: The pre-commit hook's Component SemVer check is a fast local gate, but it is NOT equivalent to the CI Component SemVer check. CI uses a baseline comparison (base branch vs PR branch) that is stricter. Relying solely on the pre-commit hook for semver can lead to CI failures.

## References

- src/project.godot — game version config
- src/component_versions.json — component version tracking
- Makefile — bump-patch, bump-minor targets (version parsing bug)
- scripts/hooks/pre-commit — auto-bump logic (project-config not always bumped)

Controlled tag vocabulary (as read):
type/*:
- `type/code` — Code architecture, autoloads, conventions, tooling. Carries `code-refs:`. (e.g. `Code/Autoloads — Disturbance.md`)
- `type/decision` — Architectural or design decision made by an agent during a session. Written to `docs/vault/Decisions/`. (Agent notes only — spec 080.)
- `type/design` — Design intent, player-facing concepts, world lore. (e.g. `Design/World Model.md`)
- `type/discovery` — Non-obvious constraint, gap, or conflict found by an agent during a session. Written to `docs/vault/Discoveries/`. (Agent notes only — spec 080.)
- `type/moc` — Map of Content at any of three tiers (folder / domain / concept). (e.g. `Audio.md`)
- `type/principle` — Governance and constitutional notes. Non-negotiable rules. (e.g. `Governance/Constitution.md`)
- `type/reference` — Glossary, decision log, open questions, epics. (e.g. `Reference/Glossary.md`)
- `type/session-log` — Session activity log; permanent audit trail. Written to `docs/vault/Sessions/`. Append-only, never pruned. (Agent notes only — spec 080.)
- `type/spec` — Spec document at `docs/vault/Specs/NNN Title/spec.md`. Carries `spec-refs:`. (e.g. `Specs/047 Car Radio/spec.md`)
- `type/system` — A bounded subsystem with implementation. Carries `code-refs`, `spec-refs`, `implements:` frontmatter. (e.g. `Systems/Audio — Car Radio.md`)
- `type/vision` — Strategic / vision-layer decision. Written to `docs/vault/Vision/`. Human-authored or agent-proposed with human ratification before promotion to `status: reviewed`. (Per triage #3 — spec 133 autonomous-company redesign.)
domain/*:
- `domain/anomalies` — Anomaly taxonomy, individual anomaly systems, spawn, behavior
- `domain/art` — Visual direction, palettes, references, asset pipeline
- `domain/audio` — Audio systems: world ambient, radio, transmissions, buses, pipeline
- `domain/autonomous-company` — Autonomous company v0.1 experiment: Slack infra, persona middleware, Letta integration, restart recovery
- `domain/build` — Build system, packaging, export, release automation
- `domain/governance` — Constitution, phased spec, policies
- `domain/infrastructure` — Infrastructure provisioning: CI/CD, hosting, deployment tooling, secrets management
- `domain/narrative` — Tone, horror register, forest transmissions narrative, Gary/KTLK
- `domain/player` — Player mode, input, controls, camera, exit/entry
- `domain/systems` — Cross-cutting system architecture and integration work
- `domain/tooling` — Build, CI, observer, TTS pipeline, dev-time tools
- `domain/vehicle` — The Samba: vehicle physics, dashboard, damage, panels
- `domain/world` — World model, biomes, terrain, procedural generation, weather
status/*:
- `status/canonical` — Fully authoritative; promoted by humans only. Highest trust. (Agent notes only — spec 080.)
- `status/draft` — Authoring in progress, not yet verified
- `status/reviewed` — Agent-created note verified against codebase within its creating session. Eligible for auto-injection in subsequent task dispatches. (Agent notes only — spec 080.)
- `status/stale` — Known out of date; cannot update immediately. Pairs with `> [!warning] STALE — needs update` callout.
- `status/superseded` — Replaced by another note. Terminal state. Pairs with `> [!warning] SUPERSEDED` callout.
- `status/wip` — Stable but under active revision
layer/*:
- `layer/content` — Content assets (audio, models, textures, audio provenance)
- `layer/gdext` — gdext wrapper layer (`rust/gdext-wrapper/`)
- `layer/gdscript` — GDScript (Godot scene-tier logic)
- `layer/infra` — Build, CI, deployment infrastructure
- `layer/python` — Python development tooling (`tools/`)
- `layer/rust-core` — Engine-agnostic Rust core (`rust/rust-core/`)
concept/*:
- `concept/biome` — Biome-reactive behavior across systems
- `concept/contamination` — Across-runs panel and garage degradation; the slow-horror mechanic that doesn't reset with the world
- `concept/diegetic` — Diegetic audio / UI / world-sourced design
- `concept/disturbance` — The disturbance mechanic thread (Article X)
- `concept/ephemeral-world` — Run-reset, transient worlds (Article IV Rules 6–7)
- `concept/governance` — Constitutional and governance concepts
- `concept/horror` — Horror register and dread design
- `concept/procedural` — Procedural generation, seed determinism
- `concept/rendering` — Visual rendering quality, shader correctness, Terrain3D integration, mesh fidelity, LOD, Z-fighting
- `concept/terrain` — Terrain generation, heightmap, Terrain3D regions, roughness, playability constraints
ember's answer for tag_assignment-discoveries-spec-156-ci-tooling-gotchas, domain/governanceP(true) placed on the no, unsure, and yes zones.nounsureyesgold: yesP = 0.04

tag_assignment-discoveries-spec-156-ci-tooling-gotchas: type/discovery

Tag assignment · test
Gold
The note calls for `type/discovery`: Non-obvious constraint, gap, or conflict found by an agent during a session. Written to `docs/vault/Discoveries/`. (Agent notes only — spec 080.) (True)
ember
The note has no reason to carry `type/discovery` (False)
Signal
P(true) 0.48 (unsure)
Kit outcome
deferred: treated as unsure
Why this gold label
Mined from Discoveries/Spec 156 — CI Tooling Gotchas.md at 692f4bb58b7f62105aeb73fba8dfee12bfdecd53; gold is the note's own vocabulary tags.
Spec 156 — CI Tooling Gotchas

Two CI pitfalls discovered during spec 156 PR CI debugging: the make bump targets misparse three-component semver, and the Component SemVer CI check fails on project-config even though the pre-commit hook passes locally.

## Discovery 1 — `make bump-patch` and `make bump-minor` Misparse Versions Like 0.17.12

**Context**: After changing game-affecting files (samba_bus.gd, panel_definitions.gd, etc.) in spec 156, CI's Version Bump Check required a game version bump from 0.17.12. Running `make bump-patch` or `make bump-minor` was the prescribed remedy per the CI error message.

**Discovery**: Both `make bump-patch` and `make bump-minor` misparse semver strings with patch versions ≥10 (like 0.17.12). They output "bump version 0.17.1 -> 0.17.2" instead of correctly reading 0.17.12, then fail with `Error 16` ("No tag found to do an incremental changelog"). This means any version above 0.x.y where y ≥ 10 cannot be bumped via the make targets.

**Workaround**: Manually edit the version string in `src/project.godot` (`config/version="0.x.y"`) to the desired value. CI will sync `export_presets.cfg` automatically on merge. The game-version-check CI gate (`make game-version-check`) validates that the new version is valid SemVer.

**Root cause**: Likely in the bump script's version parsing — it interprets `0.17.12` as the first two components (`0.17`) plus the beginning of the third (`1`), treating the version as `0.17.1`.

## Discovery 2 — Component SemVer Passes Pre-Commit but Fails CI for project-config

**Context**: The pre-commit hook's auto-bump logic runs on staged files and commits the updated `component_versions.json`. But when a commit only touches `src/project.godot` (version bump), the pre-commit hook says "Component SemVer check passed" without auto-bumping the `project-config` component version. CI then compares the branch's `component_versions.json` against the base branch baseline and fails because `project-config` is unchanged.

**Discovery**: The pre-commit hook's auto-bump only triggers when it detects first-party component files that are out of date relative to git's index. When `project.godot` is changed in isolation (not alongside other bus/panel changes), the hook treats the project-config component as "in sync" because the file was just staged. But CI compares against the base branch's `component_versions.json` — which has the old project-config version — so the check fails.

**Workaround**: After bumping `project.godot`, manually bump `project-config`'s version in `src/component_versions.json` before pushing. Or combine the project.godot change with another component change so the auto-bump fires.

**Implication**: The pre-commit hook's Component SemVer check is a fast local gate, but it is NOT equivalent to the CI Component SemVer check. CI uses a baseline comparison (base branch vs PR branch) that is stricter. Relying solely on the pre-commit hook for semver can lead to CI failures.

## References

- src/project.godot — game version config
- src/component_versions.json — component version tracking
- Makefile — bump-patch, bump-minor targets (version parsing bug)
- scripts/hooks/pre-commit — auto-bump logic (project-config not always bumped)

Controlled tag vocabulary (as read):
type/*:
- `type/code` — Code architecture, autoloads, conventions, tooling. Carries `code-refs:`. (e.g. `Code/Autoloads — Disturbance.md`)
- `type/decision` — Architectural or design decision made by an agent during a session. Written to `docs/vault/Decisions/`. (Agent notes only — spec 080.)
- `type/design` — Design intent, player-facing concepts, world lore. (e.g. `Design/World Model.md`)
- `type/discovery` — Non-obvious constraint, gap, or conflict found by an agent during a session. Written to `docs/vault/Discoveries/`. (Agent notes only — spec 080.)
- `type/moc` — Map of Content at any of three tiers (folder / domain / concept). (e.g. `Audio.md`)
- `type/principle` — Governance and constitutional notes. Non-negotiable rules. (e.g. `Governance/Constitution.md`)
- `type/reference` — Glossary, decision log, open questions, epics. (e.g. `Reference/Glossary.md`)
- `type/session-log` — Session activity log; permanent audit trail. Written to `docs/vault/Sessions/`. Append-only, never pruned. (Agent notes only — spec 080.)
- `type/spec` — Spec document at `docs/vault/Specs/NNN Title/spec.md`. Carries `spec-refs:`. (e.g. `Specs/047 Car Radio/spec.md`)
- `type/system` — A bounded subsystem with implementation. Carries `code-refs`, `spec-refs`, `implements:` frontmatter. (e.g. `Systems/Audio — Car Radio.md`)
- `type/vision` — Strategic / vision-layer decision. Written to `docs/vault/Vision/`. Human-authored or agent-proposed with human ratification before promotion to `status: reviewed`. (Per triage #3 — spec 133 autonomous-company redesign.)
domain/*:
- `domain/anomalies` — Anomaly taxonomy, individual anomaly systems, spawn, behavior
- `domain/art` — Visual direction, palettes, references, asset pipeline
- `domain/audio` — Audio systems: world ambient, radio, transmissions, buses, pipeline
- `domain/autonomous-company` — Autonomous company v0.1 experiment: Slack infra, persona middleware, Letta integration, restart recovery
- `domain/build` — Build system, packaging, export, release automation
- `domain/governance` — Constitution, phased spec, policies
- `domain/infrastructure` — Infrastructure provisioning: CI/CD, hosting, deployment tooling, secrets management
- `domain/narrative` — Tone, horror register, forest transmissions narrative, Gary/KTLK
- `domain/player` — Player mode, input, controls, camera, exit/entry
- `domain/systems` — Cross-cutting system architecture and integration work
- `domain/tooling` — Build, CI, observer, TTS pipeline, dev-time tools
- `domain/vehicle` — The Samba: vehicle physics, dashboard, damage, panels
- `domain/world` — World model, biomes, terrain, procedural generation, weather
status/*:
- `status/canonical` — Fully authoritative; promoted by humans only. Highest trust. (Agent notes only — spec 080.)
- `status/draft` — Authoring in progress, not yet verified
- `status/reviewed` — Agent-created note verified against codebase within its creating session. Eligible for auto-injection in subsequent task dispatches. (Agent notes only — spec 080.)
- `status/stale` — Known out of date; cannot update immediately. Pairs with `> [!warning] STALE — needs update` callout.
- `status/superseded` — Replaced by another note. Terminal state. Pairs with `> [!warning] SUPERSEDED` callout.
- `status/wip` — Stable but under active revision
layer/*:
- `layer/content` — Content assets (audio, models, textures, audio provenance)
- `layer/gdext` — gdext wrapper layer (`rust/gdext-wrapper/`)
- `layer/gdscript` — GDScript (Godot scene-tier logic)
- `layer/infra` — Build, CI, deployment infrastructure
- `layer/python` — Python development tooling (`tools/`)
- `layer/rust-core` — Engine-agnostic Rust core (`rust/rust-core/`)
concept/*:
- `concept/biome` — Biome-reactive behavior across systems
- `concept/contamination` — Across-runs panel and garage degradation; the slow-horror mechanic that doesn't reset with the world
- `concept/diegetic` — Diegetic audio / UI / world-sourced design
- `concept/disturbance` — The disturbance mechanic thread (Article X)
- `concept/ephemeral-world` — Run-reset, transient worlds (Article IV Rules 6–7)
- `concept/governance` — Constitutional and governance concepts
- `concept/horror` — Horror register and dread design
- `concept/procedural` — Procedural generation, seed determinism
- `concept/rendering` — Visual rendering quality, shader correctness, Terrain3D integration, mesh fidelity, LOD, Z-fighting
- `concept/terrain` — Terrain generation, heightmap, Terrain3D regions, roughness, playability constraints
ember's answer for tag_assignment-discoveries-spec-156-ci-tooling-gotchas, type/discoveryP(true) placed on the no, unsure, and yes zones.nounsureyesgold: yesP = 0.48

tag_assignment-reference-decision-log: domain/governance

Tag assignment · dev
Gold
The note calls for `domain/governance`: Constitution, phased spec, policies (True)
ember
The note has no reason to carry `domain/governance` (False)
Signal
P(true) 0.49 (unsure)
Kit outcome
deferred: treated as unsure
Why this gold label
Mined from Reference/Decision Log.md at 692f4bb58b7f62105aeb73fba8dfee12bfdecd53; gold is the note's own vocabulary tags.
Decision Log

The chronological record of significant design and engineering decisions across Old Growth's development. Superseded decisions are retained with rationale. Sourced from Appendix C of the constitution and from decisions captured during authoring.

<!-- Populated in Phase 6. -->

## Entries

Significant decisions across Old Growth's development. Sourced from constitution amendments (the version-change log in the constitution header), Appendix C (superseded design decisions), and significant per-spec decisions.

### Constitutional amendments (from [[Constitution]] sync impact reports)

- **v2.21.0 (2026-04-21)** — Added Article XIV — The Vault. Establishes `docs/vault/` as canonical documentation surface.
- **v2.20.0 (2026-04-20)** — Added explicit game version bump obligation (Article III Rule 15) for `src/**` or `rust/**` changes merging to `main`.
- **v2.19.0 (2026-04-19)** — Replaced Article IV Rule 8's hard prohibition on numerical upgrades with a tradeoff-first progression framework. Numerical progression permitted when diegetically grounded, a genuine tradeoff, and bounded. Vehicle configuration + player gear added to persistent data list.
- **v2.13.0** (earlier) — Major revision (content not recorded in the currently-visible SYNC IMPACT REPORT)
- **Pre-2.19.0 history** — See [[Constitution]] version-change log (lines 1–180) for the full history

### Approved-stack decisions (from [[Tech Stack Review]])

- **Godot 4.6+ over Unity/Unreal/Bevy** — Article III Rule 2 (Godot Lock)
- **Jolt physics (native) over Godot Physics** — more stable vehicle sim
- **GEVP over VehicleBody3D / custom** — raycast-based simcade controller
- **Terrain3D over HTerrain / custom** — GPU clipmap, foliage instancer
- **gdext / Rust over C# / pure GDScript** — Article III Rule 17; performance-critical logic in rust-core
- **Native Godot audio over Sound Manager / FMOD / Wwise** — sufficient for the 7-bus architecture

### Rejected alternatives (Appendix C — loaded via constitution-reference skill)

Full list of rejected design decisions lives in constitution Appendix C. Access via the `constitution-reference` OpenCode skill. Examples:
- Rejection of gradual enemy introduction (anomalies are structural, not scaling)
- Rejection of multi-vehicle designs (Article II — the Samba is the only vehicle)
- Rejection of non-ephemeral worlds (Article IV Rule 6)

### Spec-level significant decisions

- **Spec 067 (Phased Rust migration)** — migration of procedural generation into rust-core for determinism + performance
- **Spec 070 (Biome blending Rust)** — biome blend logic fully moved to Rust; 14 constants promoted to `@export`; `--auto-new-game` CLI added; `veg_counts.json` baseline established
- **Spec 078 (Hardcoded values remediation)** — promoted ~150 Class A values to `@export`; introduced 3 Config Resources (BiomeConfig, DisturbanceConfig, AudioBusConfig); VarDictionary bridge migration
- **Spec 079 (Obsidian vault)** — this spec; added Article XIV

### Governance-level decisions

- **Branch-only workflow** — direct commits to `main` prohibited (Governance / Commit Strategy Rule 6+8)
- **No `git stash`** — multi-agent concurrency (Governance Rule 7)
- **Submodule two-repo workflow** — audio submodule PRs land first; parent repo updates the pointer
- **Component SemVer** — Article III Rule 15; see [[Component SemVer Policy]]

## Related

- [[Constitution]] — Appendix C for full superseded-decisions list; Appendix C is the primary source
- [[Tech Stack Review]] — stack decision rationale
- [[Reference]] — folder MOC
- [[Epics]] — status snapshot
- [[Conflicts]] — unresolved source disagreements

Controlled tag vocabulary (as read):
type/*:
- `type/code` — Code architecture, autoloads, conventions, tooling. Carries `code-refs:`. (e.g. `Code/Autoloads — Disturbance.md`)
- `type/decision` — Architectural or design decision made by an agent during a session. Written to `docs/vault/Decisions/`. (Agent notes only — spec 080.)
- `type/design` — Design intent, player-facing concepts, world lore. (e.g. `Design/World Model.md`)
- `type/discovery` — Non-obvious constraint, gap, or conflict found by an agent during a session. Written to `docs/vault/Discoveries/`. (Agent notes only — spec 080.)
- `type/moc` — Map of Content at any of three tiers (folder / domain / concept). (e.g. `Audio.md`)
- `type/principle` — Governance and constitutional notes. Non-negotiable rules. (e.g. `Governance/Constitution.md`)
- `type/reference` — Glossary, decision log, open questions, epics. (e.g. `Reference/Glossary.md`)
- `type/session-log` — Session activity log; permanent audit trail. Written to `docs/vault/Sessions/`. Append-only, never pruned. (Agent notes only — spec 080.)
- `type/spec` — Spec document at `docs/vault/Specs/NNN Title/spec.md`. Carries `spec-refs:`. (e.g. `Specs/047 Car Radio/spec.md`)
- `type/system` — A bounded subsystem with implementation. Carries `code-refs`, `spec-refs`, `implements:` frontmatter. (e.g. `Systems/Audio — Car Radio.md`)
- `type/vision` — Strategic / vision-layer decision. Written to `docs/vault/Vision/`. Human-authored or agent-proposed with human ratification before promotion to `status: reviewed`. (Per triage #3 — spec 133 autonomous-company redesign.)
domain/*:
- `domain/anomalies` — Anomaly taxonomy, individual anomaly systems, spawn, behavior
- `domain/art` — Visual direction, palettes, references, asset pipeline
- `domain/audio` — Audio systems: world ambient, radio, transmissions, buses, pipeline
- `domain/autonomous-company` — Autonomous company v0.1 experiment: Slack infra, persona middleware, Letta integration, restart recovery
- `domain/build` — Build system, packaging, export, release automation
- `domain/governance` — Constitution, phased spec, policies
- `domain/infrastructure` — Infrastructure provisioning: CI/CD, hosting, deployment tooling, secrets management
- `domain/narrative` — Tone, horror register, forest transmissions narrative, Gary/KTLK
- `domain/player` — Player mode, input, controls, camera, exit/entry
- `domain/systems` — Cross-cutting system architecture and integration work
- `domain/tooling` — Build, CI, observer, TTS pipeline, dev-time tools
- `domain/vehicle` — The Samba: vehicle physics, dashboard, damage, panels
- `domain/world` — World model, biomes, terrain, procedural generation, weather
status/*:
- `status/canonical` — Fully authoritative; promoted by humans only. Highest trust. (Agent notes only — spec 080.)
- `status/draft` — Authoring in progress, not yet verified
- `status/reviewed` — Agent-created note verified against codebase within its creating session. Eligible for auto-injection in subsequent task dispatches. (Agent notes only — spec 080.)
- `status/stale` — Known out of date; cannot update immediately. Pairs with `> [!warning] STALE — needs update` callout.
- `status/superseded` — Replaced by another note. Terminal state. Pairs with `> [!warning] SUPERSEDED` callout.
- `status/wip` — Stable but under active revision
layer/*:
- `layer/content` — Content assets (audio, models, textures, audio provenance)
- `layer/gdext` — gdext wrapper layer (`rust/gdext-wrapper/`)
- `layer/gdscript` — GDScript (Godot scene-tier logic)
- `layer/infra` — Build, CI, deployment infrastructure
- `layer/python` — Python development tooling (`tools/`)
- `layer/rust-core` — Engine-agnostic Rust core (`rust/rust-core/`)
concept/*:
- `concept/biome` — Biome-reactive behavior across systems
- `concept/contamination` — Across-runs panel and garage degradation; the slow-horror mechanic that doesn't reset with the world
- `concept/diegetic` — Diegetic audio / UI / world-sourced design
- `concept/disturbance` — The disturbance mechanic thread (Article X)
- `concept/ephemeral-world` — Run-reset, transient worlds (Article IV Rules 6–7)
- `concept/governance` — Constitutional and governance concepts
- `concept/horror` — Horror register and dread design
- `concept/procedural` — Procedural generation, seed determinism
- `concept/rendering` — Visual rendering quality, shader correctness, Terrain3D integration, mesh fidelity, LOD, Z-fighting
- `concept/terrain` — Terrain generation, heightmap, Terrain3D regions, roughness, playability constraints
ember's answer for tag_assignment-reference-decision-log, domain/governanceP(true) placed on the no, unsure, and yes zones.nounsureyesgold: yesP = 0.49

tag_assignment-systems-storm: domain/world

Tag assignment · dev
Gold
The note calls for `domain/world`: World model, biomes, terrain, procedural generation, weather (True)
ember
The note has no reason to carry `domain/world` (False)
Signal
P(true) 0.36 (unsure)
Kit outcome
deferred: treated as unsure
Why this gold label
Mined from Systems/Storm.md at 692f4bb58b7f62105aeb73fba8dfee12bfdecd53; gold is the note's own vocabulary tags.
Storm

The Storm is the endgame event: a directional wall that spawns from the ridgeline opposite the nearest exit and advances toward the player when disturbance reaches its Finishing threshold. It is not a difficulty spike, not a timer, and not weather — it is the active terraforming of the construct through physical space, momentarily unfiltered (see [[The Crater]], [[The Temporal Fracture]]).

The construct is still reshaping this space. Normally the temporal fracture diffuses this process into background distortion. When disturbance destabilizes the field past the threshold, the fracture loses coherence and the raw transformation becomes perceptible — a wall of displacement energy advancing from the crater rim. The Storm is indifferent because it is not a response to the player — it is a process that has been running since the construct entered this space, briefly made visible. The storm that kills you is the storm that is still reshaping this place.

The run ends when the player either extracts (`RunPhase.EXTRACTED`) or dies (`RunPhase.DEAD`). Both outcomes return the player to the garage — the vertex. (Post-convergence: death still returns to the vertex, but extraction crosses the rim into the outside. See spec 127.) Extraction is completing a circuit along an edge of the higher-dimensional geometry. Death is completing a circuit through the ongoing displacement. The destination is the same; the cost is different. See [[The Player Causes the Storm]] for the full ludonarrative argument.

## Trigger and State

The Storm is triggered by [[Autoloads — Disturbance]] when `level >= 85` (the Finishing threshold, tunable via `disturbance_config.tres`). At that point:

1. `Autoloads — Disturbance` emits `threshold_changed("storm")` on its own autoload signal, and emits `disturbance_storm_activated(origin, direction)` via `Events.disturbance_storm_activated` for cross-system notification
2. `Autoloads — GameState` transitions `run_phase` to `RunPhase.STORM_ACTIVE`
3. Downstream storm systems begin spawning the visual wall and audio arc

The world's temporal configuration closes; the garage — the vertex — receives the player back. Only the garage persists because it is the one point all faces of the geometry agree on (see [[Ephemerality Thread]]).

## Visual System (⏳ Not yet authored)

The Storm spawns as a directional wall on the ridgeline opposite the nearest exit and advances toward the player. The direction decision is documented in [[Governance/Tech Stack Review]] §41. The visual wall is a Godot particle / shader system — not yet assigned to a dedicated script.

Key visual design constraints:
- The storm must read at driving speed from the first-person interior camera
- It must feel *indifferent* — not targeted. See [[Design/Tone and Horror]] and [[Design/Horror Register]]
- Visibility collapses to <10m inside the storm; on-foot cold exposure is −5 HP/sec in Blizzard conditions

## Audio System (⏳ Spec 107 — waiting)

[[107 Storm Audio System]] defines the 4-phase audio arc:

| Phase | Condition | Character |
|---|---|---|
| **Approach** | Storm spawned, player at distance | Subsonic pressure build, biome ambient collapse |
| **Active** | Storm wall advancing | Full roar; Horror bus at max |
| **Proximity** | Player near storm edge | Disorientation; radio dies entirely |
| **Caught** | Player inside storm | Maximum; extraction pressure absolute |

Post-extraction: a 3-second silence beat as the player passes through the geometry's edge and arrives back at the vertex. For three seconds, time is coherent — all temporal layers agree. Then the next run begins, and the player enters another face of the geometry.

Prerequisite: [[111 Audio Bus Architecture]] must ship first (adds the Horror bus the storm audio routes through).

## Relationship to Disturbance

The Storm is the visible form of disturbance at its maximum. The disturbance meter is hidden — the player never sees a number. The Storm is what the meter looks like when it arrives at a conclusion about the player. It is not a punishment. The forest is not angry. The player is *the largest unfinished input in the watershed.*

See [[The Disturbance Thread]] for the full mechanic thread and [[The Player Causes the Storm]] for the ludonarrative framing.

## Related

- [[The Crater]] — the origin event; the Storm spawns from the crater rim
- [[The Temporal Fracture]] — the Storm as the ongoing insertion momentarily unfiltered
- [[Autoloads — Disturbance]] — the threshold arithmetic that triggers the Storm (level >= 85)
- [[Autoloads — GameState]] — run_phase transitions (STORM_ACTIVE → EXTRACTED / DEAD)
- [[Audio — World Audio]] — the four-state disturbance audio arc that precedes the Storm
- [[107 Storm Audio System]] — the Storm's 4-phase audio spec (⏳ waiting on spec 111)
- [[Systems/World — Procedural Generation]] — Storm direction uses exit point positions computed during generation
- [[Design/Tone and Horror]] — the horror register the Storm must maintain (indifference, not targeting)
- [[The Player Causes the Storm]] — the full ludonarrative thread
- [[The Disturbance Thread]] — the mechanic that builds to the Storm
- [[020 Disturbance Storm]] — original spec that implemented the disturbance → Storm mechanic

Controlled tag vocabulary (as read):
type/*:
- `type/code` — Code architecture, autoloads, conventions, tooling. Carries `code-refs:`. (e.g. `Code/Autoloads — Disturbance.md`)
- `type/decision` — Architectural or design decision made by an agent during a session. Written to `docs/vault/Decisions/`. (Agent notes only — spec 080.)
- `type/design` — Design intent, player-facing concepts, world lore. (e.g. `Design/World Model.md`)
- `type/discovery` — Non-obvious constraint, gap, or conflict found by an agent during a session. Written to `docs/vault/Discoveries/`. (Agent notes only — spec 080.)
- `type/moc` — Map of Content at any of three tiers (folder / domain / concept). (e.g. `Audio.md`)
- `type/principle` — Governance and constitutional notes. Non-negotiable rules. (e.g. `Governance/Constitution.md`)
- `type/reference` — Glossary, decision log, open questions, epics. (e.g. `Reference/Glossary.md`)
- `type/session-log` — Session activity log; permanent audit trail. Written to `docs/vault/Sessions/`. Append-only, never pruned. (Agent notes only — spec 080.)
- `type/spec` — Spec document at `docs/vault/Specs/NNN Title/spec.md`. Carries `spec-refs:`. (e.g. `Specs/047 Car Radio/spec.md`)
- `type/system` — A bounded subsystem with implementation. Carries `code-refs`, `spec-refs`, `implements:` frontmatter. (e.g. `Systems/Audio — Car Radio.md`)
- `type/vision` — Strategic / vision-layer decision. Written to `docs/vault/Vision/`. Human-authored or agent-proposed with human ratification before promotion to `status: reviewed`. (Per triage #3 — spec 133 autonomous-company redesign.)
domain/*:
- `domain/anomalies` — Anomaly taxonomy, individual anomaly systems, spawn, behavior
- `domain/art` — Visual direction, palettes, references, asset pipeline
- `domain/audio` — Audio systems: world ambient, radio, transmissions, buses, pipeline
- `domain/autonomous-company` — Autonomous company v0.1 experiment: Slack infra, persona middleware, Letta integration, restart recovery
- `domain/build` — Build system, packaging, export, release automation
- `domain/governance` — Constitution, phased spec, policies
- `domain/infrastructure` — Infrastructure provisioning: CI/CD, hosting, deployment tooling, secrets management
- `domain/narrative` — Tone, horror register, forest transmissions narrative, Gary/KTLK
- `domain/player` — Player mode, input, controls, camera, exit/entry
- `domain/systems` — Cross-cutting system architecture and integration work
- `domain/tooling` — Build, CI, observer, TTS pipeline, dev-time tools
- `domain/vehicle` — The Samba: vehicle physics, dashboard, damage, panels
- `domain/world` — World model, biomes, terrain, procedural generation, weather
status/*:
- `status/canonical` — Fully authoritative; promoted by humans only. Highest trust. (Agent notes only — spec 080.)
- `status/draft` — Authoring in progress, not yet verified
- `status/reviewed` — Agent-created note verified against codebase within its creating session. Eligible for auto-injection in subsequent task dispatches. (Agent notes only — spec 080.)
- `status/stale` — Known out of date; cannot update immediately. Pairs with `> [!warning] STALE — needs update` callout.
- `status/superseded` — Replaced by another note. Terminal state. Pairs with `> [!warning] SUPERSEDED` callout.
- `status/wip` — Stable but under active revision
layer/*:
- `layer/content` — Content assets (audio, models, textures, audio provenance)
- `layer/gdext` — gdext wrapper layer (`rust/gdext-wrapper/`)
- `layer/gdscript` — GDScript (Godot scene-tier logic)
- `layer/infra` — Build, CI, deployment infrastructure
- `layer/python` — Python development tooling (`tools/`)
- `layer/rust-core` — Engine-agnostic Rust core (`rust/rust-core/`)
concept/*:
- `concept/biome` — Biome-reactive behavior across systems
- `concept/contamination` — Across-runs panel and garage degradation; the slow-horror mechanic that doesn't reset with the world
- `concept/diegetic` — Diegetic audio / UI / world-sourced design
- `concept/disturbance` — The disturbance mechanic thread (Article X)
- `concept/ephemeral-world` — Run-reset, transient worlds (Article IV Rules 6–7)
- `concept/governance` — Constitutional and governance concepts
- `concept/horror` — Horror register and dread design
- `concept/procedural` — Procedural generation, seed determinism
- `concept/rendering` — Visual rendering quality, shader correctness, Terrain3D integration, mesh fidelity, LOD, Z-fighting
- `concept/terrain` — Terrain generation, heightmap, Terrain3D regions, roughness, playability constraints
ember's answer for tag_assignment-systems-storm, domain/worldP(true) placed on the no, unsure, and yes zones.nounsureyesgold: yesP = 0.36

tag_assignment-systems-storm: type/spec

Tag assignment · dev
Gold
The note has no reason to carry `type/spec` (False)
ember
The note calls for `type/spec`: Spec document at `docs/vault/Specs/NNN Title/spec.md`. Carries `spec-refs:`. (e.g. `Specs/047 Car Radio/spec.md`) (True)
Signal
P(true) 0.53 (unsure)
Kit outcome
deferred: treated as unsure
Why this gold label
Mined from Systems/Storm.md at 692f4bb58b7f62105aeb73fba8dfee12bfdecd53; gold is the note's own vocabulary tags.
Storm

The Storm is the endgame event: a directional wall that spawns from the ridgeline opposite the nearest exit and advances toward the player when disturbance reaches its Finishing threshold. It is not a difficulty spike, not a timer, and not weather — it is the active terraforming of the construct through physical space, momentarily unfiltered (see [[The Crater]], [[The Temporal Fracture]]).

The construct is still reshaping this space. Normally the temporal fracture diffuses this process into background distortion. When disturbance destabilizes the field past the threshold, the fracture loses coherence and the raw transformation becomes perceptible — a wall of displacement energy advancing from the crater rim. The Storm is indifferent because it is not a response to the player — it is a process that has been running since the construct entered this space, briefly made visible. The storm that kills you is the storm that is still reshaping this place.

The run ends when the player either extracts (`RunPhase.EXTRACTED`) or dies (`RunPhase.DEAD`). Both outcomes return the player to the garage — the vertex. (Post-convergence: death still returns to the vertex, but extraction crosses the rim into the outside. See spec 127.) Extraction is completing a circuit along an edge of the higher-dimensional geometry. Death is completing a circuit through the ongoing displacement. The destination is the same; the cost is different. See [[The Player Causes the Storm]] for the full ludonarrative argument.

## Trigger and State

The Storm is triggered by [[Autoloads — Disturbance]] when `level >= 85` (the Finishing threshold, tunable via `disturbance_config.tres`). At that point:

1. `Autoloads — Disturbance` emits `threshold_changed("storm")` on its own autoload signal, and emits `disturbance_storm_activated(origin, direction)` via `Events.disturbance_storm_activated` for cross-system notification
2. `Autoloads — GameState` transitions `run_phase` to `RunPhase.STORM_ACTIVE`
3. Downstream storm systems begin spawning the visual wall and audio arc

The world's temporal configuration closes; the garage — the vertex — receives the player back. Only the garage persists because it is the one point all faces of the geometry agree on (see [[Ephemerality Thread]]).

## Visual System (⏳ Not yet authored)

The Storm spawns as a directional wall on the ridgeline opposite the nearest exit and advances toward the player. The direction decision is documented in [[Governance/Tech Stack Review]] §41. The visual wall is a Godot particle / shader system — not yet assigned to a dedicated script.

Key visual design constraints:
- The storm must read at driving speed from the first-person interior camera
- It must feel *indifferent* — not targeted. See [[Design/Tone and Horror]] and [[Design/Horror Register]]
- Visibility collapses to <10m inside the storm; on-foot cold exposure is −5 HP/sec in Blizzard conditions

## Audio System (⏳ Spec 107 — waiting)

[[107 Storm Audio System]] defines the 4-phase audio arc:

| Phase | Condition | Character |
|---|---|---|
| **Approach** | Storm spawned, player at distance | Subsonic pressure build, biome ambient collapse |
| **Active** | Storm wall advancing | Full roar; Horror bus at max |
| **Proximity** | Player near storm edge | Disorientation; radio dies entirely |
| **Caught** | Player inside storm | Maximum; extraction pressure absolute |

Post-extraction: a 3-second silence beat as the player passes through the geometry's edge and arrives back at the vertex. For three seconds, time is coherent — all temporal layers agree. Then the next run begins, and the player enters another face of the geometry.

Prerequisite: [[111 Audio Bus Architecture]] must ship first (adds the Horror bus the storm audio routes through).

## Relationship to Disturbance

The Storm is the visible form of disturbance at its maximum. The disturbance meter is hidden — the player never sees a number. The Storm is what the meter looks like when it arrives at a conclusion about the player. It is not a punishment. The forest is not angry. The player is *the largest unfinished input in the watershed.*

See [[The Disturbance Thread]] for the full mechanic thread and [[The Player Causes the Storm]] for the ludonarrative framing.

## Related

- [[The Crater]] — the origin event; the Storm spawns from the crater rim
- [[The Temporal Fracture]] — the Storm as the ongoing insertion momentarily unfiltered
- [[Autoloads — Disturbance]] — the threshold arithmetic that triggers the Storm (level >= 85)
- [[Autoloads — GameState]] — run_phase transitions (STORM_ACTIVE → EXTRACTED / DEAD)
- [[Audio — World Audio]] — the four-state disturbance audio arc that precedes the Storm
- [[107 Storm Audio System]] — the Storm's 4-phase audio spec (⏳ waiting on spec 111)
- [[Systems/World — Procedural Generation]] — Storm direction uses exit point positions computed during generation
- [[Design/Tone and Horror]] — the horror register the Storm must maintain (indifference, not targeting)
- [[The Player Causes the Storm]] — the full ludonarrative thread
- [[The Disturbance Thread]] — the mechanic that builds to the Storm
- [[020 Disturbance Storm]] — original spec that implemented the disturbance → Storm mechanic

Controlled tag vocabulary (as read):
type/*:
- `type/code` — Code architecture, autoloads, conventions, tooling. Carries `code-refs:`. (e.g. `Code/Autoloads — Disturbance.md`)
- `type/decision` — Architectural or design decision made by an agent during a session. Written to `docs/vault/Decisions/`. (Agent notes only — spec 080.)
- `type/design` — Design intent, player-facing concepts, world lore. (e.g. `Design/World Model.md`)
- `type/discovery` — Non-obvious constraint, gap, or conflict found by an agent during a session. Written to `docs/vault/Discoveries/`. (Agent notes only — spec 080.)
- `type/moc` — Map of Content at any of three tiers (folder / domain / concept). (e.g. `Audio.md`)
- `type/principle` — Governance and constitutional notes. Non-negotiable rules. (e.g. `Governance/Constitution.md`)
- `type/reference` — Glossary, decision log, open questions, epics. (e.g. `Reference/Glossary.md`)
- `type/session-log` — Session activity log; permanent audit trail. Written to `docs/vault/Sessions/`. Append-only, never pruned. (Agent notes only — spec 080.)
- `type/spec` — Spec document at `docs/vault/Specs/NNN Title/spec.md`. Carries `spec-refs:`. (e.g. `Specs/047 Car Radio/spec.md`)
- `type/system` — A bounded subsystem with implementation. Carries `code-refs`, `spec-refs`, `implements:` frontmatter. (e.g. `Systems/Audio — Car Radio.md`)
- `type/vision` — Strategic / vision-layer decision. Written to `docs/vault/Vision/`. Human-authored or agent-proposed with human ratification before promotion to `status: reviewed`. (Per triage #3 — spec 133 autonomous-company redesign.)
domain/*:
- `domain/anomalies` — Anomaly taxonomy, individual anomaly systems, spawn, behavior
- `domain/art` — Visual direction, palettes, references, asset pipeline
- `domain/audio` — Audio systems: world ambient, radio, transmissions, buses, pipeline
- `domain/autonomous-company` — Autonomous company v0.1 experiment: Slack infra, persona middleware, Letta integration, restart recovery
- `domain/build` — Build system, packaging, export, release automation
- `domain/governance` — Constitution, phased spec, policies
- `domain/infrastructure` — Infrastructure provisioning: CI/CD, hosting, deployment tooling, secrets management
- `domain/narrative` — Tone, horror register, forest transmissions narrative, Gary/KTLK
- `domain/player` — Player mode, input, controls, camera, exit/entry
- `domain/systems` — Cross-cutting system architecture and integration work
- `domain/tooling` — Build, CI, observer, TTS pipeline, dev-time tools
- `domain/vehicle` — The Samba: vehicle physics, dashboard, damage, panels
- `domain/world` — World model, biomes, terrain, procedural generation, weather
status/*:
- `status/canonical` — Fully authoritative; promoted by humans only. Highest trust. (Agent notes only — spec 080.)
- `status/draft` — Authoring in progress, not yet verified
- `status/reviewed` — Agent-created note verified against codebase within its creating session. Eligible for auto-injection in subsequent task dispatches. (Agent notes only — spec 080.)
- `status/stale` — Known out of date; cannot update immediately. Pairs with `> [!warning] STALE — needs update` callout.
- `status/superseded` — Replaced by another note. Terminal state. Pairs with `> [!warning] SUPERSEDED` callout.
- `status/wip` — Stable but under active revision
layer/*:
- `layer/content` — Content assets (audio, models, textures, audio provenance)
- `layer/gdext` — gdext wrapper layer (`rust/gdext-wrapper/`)
- `layer/gdscript` — GDScript (Godot scene-tier logic)
- `layer/infra` — Build, CI, deployment infrastructure
- `layer/python` — Python development tooling (`tools/`)
- `layer/rust-core` — Engine-agnostic Rust core (`rust/rust-core/`)
concept/*:
- `concept/biome` — Biome-reactive behavior across systems
- `concept/contamination` — Across-runs panel and garage degradation; the slow-horror mechanic that doesn't reset with the world
- `concept/diegetic` — Diegetic audio / UI / world-sourced design
- `concept/disturbance` — The disturbance mechanic thread (Article X)
- `concept/ephemeral-world` — Run-reset, transient worlds (Article IV Rules 6–7)
- `concept/governance` — Constitutional and governance concepts
- `concept/horror` — Horror register and dread design
- `concept/procedural` — Procedural generation, seed determinism
- `concept/rendering` — Visual rendering quality, shader correctness, Terrain3D integration, mesh fidelity, LOD, Z-fighting
- `concept/terrain` — Terrain generation, heightmap, Terrain3D regions, roughness, playability constraints
ember's answer for tag_assignment-systems-storm, type/specP(true) placed on the no, unsure, and yes zones.nounsureyesgold: noP = 0.53

tag_assignment-systems-storm: type/system

Tag assignment · dev
Gold
The note calls for `type/system`: A bounded subsystem with implementation. Carries `code-refs`, `spec-refs`, `implements:` frontmatter. (e.g. `Systems/Audio — Car Radio.md`) (True)
ember
The note has no reason to carry `type/system` (False)
Signal
P(true) 0.27 (unsure)
Kit outcome
deferred: treated as unsure
Why this gold label
Mined from Systems/Storm.md at 692f4bb58b7f62105aeb73fba8dfee12bfdecd53; gold is the note's own vocabulary tags.
Storm

The Storm is the endgame event: a directional wall that spawns from the ridgeline opposite the nearest exit and advances toward the player when disturbance reaches its Finishing threshold. It is not a difficulty spike, not a timer, and not weather — it is the active terraforming of the construct through physical space, momentarily unfiltered (see [[The Crater]], [[The Temporal Fracture]]).

The construct is still reshaping this space. Normally the temporal fracture diffuses this process into background distortion. When disturbance destabilizes the field past the threshold, the fracture loses coherence and the raw transformation becomes perceptible — a wall of displacement energy advancing from the crater rim. The Storm is indifferent because it is not a response to the player — it is a process that has been running since the construct entered this space, briefly made visible. The storm that kills you is the storm that is still reshaping this place.

The run ends when the player either extracts (`RunPhase.EXTRACTED`) or dies (`RunPhase.DEAD`). Both outcomes return the player to the garage — the vertex. (Post-convergence: death still returns to the vertex, but extraction crosses the rim into the outside. See spec 127.) Extraction is completing a circuit along an edge of the higher-dimensional geometry. Death is completing a circuit through the ongoing displacement. The destination is the same; the cost is different. See [[The Player Causes the Storm]] for the full ludonarrative argument.

## Trigger and State

The Storm is triggered by [[Autoloads — Disturbance]] when `level >= 85` (the Finishing threshold, tunable via `disturbance_config.tres`). At that point:

1. `Autoloads — Disturbance` emits `threshold_changed("storm")` on its own autoload signal, and emits `disturbance_storm_activated(origin, direction)` via `Events.disturbance_storm_activated` for cross-system notification
2. `Autoloads — GameState` transitions `run_phase` to `RunPhase.STORM_ACTIVE`
3. Downstream storm systems begin spawning the visual wall and audio arc

The world's temporal configuration closes; the garage — the vertex — receives the player back. Only the garage persists because it is the one point all faces of the geometry agree on (see [[Ephemerality Thread]]).

## Visual System (⏳ Not yet authored)

The Storm spawns as a directional wall on the ridgeline opposite the nearest exit and advances toward the player. The direction decision is documented in [[Governance/Tech Stack Review]] §41. The visual wall is a Godot particle / shader system — not yet assigned to a dedicated script.

Key visual design constraints:
- The storm must read at driving speed from the first-person interior camera
- It must feel *indifferent* — not targeted. See [[Design/Tone and Horror]] and [[Design/Horror Register]]
- Visibility collapses to <10m inside the storm; on-foot cold exposure is −5 HP/sec in Blizzard conditions

## Audio System (⏳ Spec 107 — waiting)

[[107 Storm Audio System]] defines the 4-phase audio arc:

| Phase | Condition | Character |
|---|---|---|
| **Approach** | Storm spawned, player at distance | Subsonic pressure build, biome ambient collapse |
| **Active** | Storm wall advancing | Full roar; Horror bus at max |
| **Proximity** | Player near storm edge | Disorientation; radio dies entirely |
| **Caught** | Player inside storm | Maximum; extraction pressure absolute |

Post-extraction: a 3-second silence beat as the player passes through the geometry's edge and arrives back at the vertex. For three seconds, time is coherent — all temporal layers agree. Then the next run begins, and the player enters another face of the geometry.

Prerequisite: [[111 Audio Bus Architecture]] must ship first (adds the Horror bus the storm audio routes through).

## Relationship to Disturbance

The Storm is the visible form of disturbance at its maximum. The disturbance meter is hidden — the player never sees a number. The Storm is what the meter looks like when it arrives at a conclusion about the player. It is not a punishment. The forest is not angry. The player is *the largest unfinished input in the watershed.*

See [[The Disturbance Thread]] for the full mechanic thread and [[The Player Causes the Storm]] for the ludonarrative framing.

## Related

- [[The Crater]] — the origin event; the Storm spawns from the crater rim
- [[The Temporal Fracture]] — the Storm as the ongoing insertion momentarily unfiltered
- [[Autoloads — Disturbance]] — the threshold arithmetic that triggers the Storm (level >= 85)
- [[Autoloads — GameState]] — run_phase transitions (STORM_ACTIVE → EXTRACTED / DEAD)
- [[Audio — World Audio]] — the four-state disturbance audio arc that precedes the Storm
- [[107 Storm Audio System]] — the Storm's 4-phase audio spec (⏳ waiting on spec 111)
- [[Systems/World — Procedural Generation]] — Storm direction uses exit point positions computed during generation
- [[Design/Tone and Horror]] — the horror register the Storm must maintain (indifference, not targeting)
- [[The Player Causes the Storm]] — the full ludonarrative thread
- [[The Disturbance Thread]] — the mechanic that builds to the Storm
- [[020 Disturbance Storm]] — original spec that implemented the disturbance → Storm mechanic

Controlled tag vocabulary (as read):
type/*:
- `type/code` — Code architecture, autoloads, conventions, tooling. Carries `code-refs:`. (e.g. `Code/Autoloads — Disturbance.md`)
- `type/decision` — Architectural or design decision made by an agent during a session. Written to `docs/vault/Decisions/`. (Agent notes only — spec 080.)
- `type/design` — Design intent, player-facing concepts, world lore. (e.g. `Design/World Model.md`)
- `type/discovery` — Non-obvious constraint, gap, or conflict found by an agent during a session. Written to `docs/vault/Discoveries/`. (Agent notes only — spec 080.)
- `type/moc` — Map of Content at any of three tiers (folder / domain / concept). (e.g. `Audio.md`)
- `type/principle` — Governance and constitutional notes. Non-negotiable rules. (e.g. `Governance/Constitution.md`)
- `type/reference` — Glossary, decision log, open questions, epics. (e.g. `Reference/Glossary.md`)
- `type/session-log` — Session activity log; permanent audit trail. Written to `docs/vault/Sessions/`. Append-only, never pruned. (Agent notes only — spec 080.)
- `type/spec` — Spec document at `docs/vault/Specs/NNN Title/spec.md`. Carries `spec-refs:`. (e.g. `Specs/047 Car Radio/spec.md`)
- `type/system` — A bounded subsystem with implementation. Carries `code-refs`, `spec-refs`, `implements:` frontmatter. (e.g. `Systems/Audio — Car Radio.md`)
- `type/vision` — Strategic / vision-layer decision. Written to `docs/vault/Vision/`. Human-authored or agent-proposed with human ratification before promotion to `status: reviewed`. (Per triage #3 — spec 133 autonomous-company redesign.)
domain/*:
- `domain/anomalies` — Anomaly taxonomy, individual anomaly systems, spawn, behavior
- `domain/art` — Visual direction, palettes, references, asset pipeline
- `domain/audio` — Audio systems: world ambient, radio, transmissions, buses, pipeline
- `domain/autonomous-company` — Autonomous company v0.1 experiment: Slack infra, persona middleware, Letta integration, restart recovery
- `domain/build` — Build system, packaging, export, release automation
- `domain/governance` — Constitution, phased spec, policies
- `domain/infrastructure` — Infrastructure provisioning: CI/CD, hosting, deployment tooling, secrets management
- `domain/narrative` — Tone, horror register, forest transmissions narrative, Gary/KTLK
- `domain/player` — Player mode, input, controls, camera, exit/entry
- `domain/systems` — Cross-cutting system architecture and integration work
- `domain/tooling` — Build, CI, observer, TTS pipeline, dev-time tools
- `domain/vehicle` — The Samba: vehicle physics, dashboard, damage, panels
- `domain/world` — World model, biomes, terrain, procedural generation, weather
status/*:
- `status/canonical` — Fully authoritative; promoted by humans only. Highest trust. (Agent notes only — spec 080.)
- `status/draft` — Authoring in progress, not yet verified
- `status/reviewed` — Agent-created note verified against codebase within its creating session. Eligible for auto-injection in subsequent task dispatches. (Agent notes only — spec 080.)
- `status/stale` — Known out of date; cannot update immediately. Pairs with `> [!warning] STALE — needs update` callout.
- `status/superseded` — Replaced by another note. Terminal state. Pairs with `> [!warning] SUPERSEDED` callout.
- `status/wip` — Stable but under active revision
layer/*:
- `layer/content` — Content assets (audio, models, textures, audio provenance)
- `layer/gdext` — gdext wrapper layer (`rust/gdext-wrapper/`)
- `layer/gdscript` — GDScript (Godot scene-tier logic)
- `layer/infra` — Build, CI, deployment infrastructure
- `layer/python` — Python development tooling (`tools/`)
- `layer/rust-core` — Engine-agnostic Rust core (`rust/rust-core/`)
concept/*:
- `concept/biome` — Biome-reactive behavior across systems
- `concept/contamination` — Across-runs panel and garage degradation; the slow-horror mechanic that doesn't reset with the world
- `concept/diegetic` — Diegetic audio / UI / world-sourced design
- `concept/disturbance` — The disturbance mechanic thread (Article X)
- `concept/ephemeral-world` — Run-reset, transient worlds (Article IV Rules 6–7)
- `concept/governance` — Constitutional and governance concepts
- `concept/horror` — Horror register and dread design
- `concept/procedural` — Procedural generation, seed determinism
- `concept/rendering` — Visual rendering quality, shader correctness, Terrain3D integration, mesh fidelity, LOD, Z-fighting
- `concept/terrain` — Terrain generation, heightmap, Terrain3D regions, roughness, playability constraints
ember's answer for tag_assignment-systems-storm, type/systemP(true) placed on the no, unsure, and yes zones.nounsureyesgold: yesP = 0.27

tag_assignment-code-tools-agent-skills-mcp: domain/governance

Tag assignment · test
Gold
The note calls for `domain/governance`: Constitution, phased spec, policies (True)
ember
The note has no reason to carry `domain/governance` (False)
Signal
P(true) 0.09 (no)
Kit outcome
acted on a wrong answer
Why this gold label
Mined from Code/Tools — Agent Skills & MCP.md at 692f4bb58b7f62105aeb73fba8dfee12bfdecd53; gold is the note's own vocabulary tags.
Tools — Agent Skills & MCP

The skill system and the MCP (Model Context Protocol) server set form the two extension surfaces that turn a generic agent into an Old Growth agent. Skills inject domain instructions into the conversation context; MCP servers extend the tool surface with external capabilities. This note inventories both, documents the invocation pattern, and maps which agents consume which surfaces. It complements [[Tools — mcpvault]], which describes the vault MCP server in depth.

## The Two Surfaces, Compared

Skills are bodies of instructions loaded into the conversation context on demand. They contain workflows, decision matrices, and references to bundled scripts. They do not add new tools — they teach the agent how to use existing tools and external systems correctly. Skills live under `.opencode/skills/` and are loaded via the `skill` tool or as the `load_skills` parameter on the `task` tool.

MCP servers are processes (local or remote) that expose tools, resources, and prompts to the agent over the Model Context Protocol. They add new tool calls — for example, `gdai-mcp-server` exposes `play_scene`, `get_running_scene_screenshot`, `simulate_input`, and other Godot runtime operations as agent-callable tools. MCP servers are configured in `opencode.json` (project-local) and `.concourse.json` (Concourse repo-profile hook).

The two surfaces compose: a skill (e.g. `observer-qa`) tells the agent the correct workflow for visual QA; an MCP server (e.g. `gdai-mcp-server`) provides the tools that workflow invokes.

## Skill Inventory

Five skills ship in `.opencode/skills/`. Each is a directory containing a `SKILL.md` file with frontmatter (description, triggers) and a body of instructions; some bundle additional scripts or reference files.

| Skill | Directory | Purpose |
|---|---|---|
| `observer-qa` | `.opencode/skills/SKILL.md` (root) | MCP-first visual QA pipeline. Documents the GDAI MCP screenshot-and-analyse workflow as primary, the Observer CLI as secondary for sequence captures and CI gates, the agent trigger matrix, and the decision matrix that maps `(quality, recommendation)` pairs to ship/block actions. Loaded when working on generation code, world preview, or visual artefacts. |
| `audio-assets` | `.opencode/skills/audio-assets/SKILL.md` | TTS generation tooling, audio submodule workflow, naming conventions, and provenance requirements for Old Growth radio and ambient weather content. Loaded when authoring radio clips, KTLK Gary dialogue, weather ambient SFX, or station music. |
| `introspection` | `.opencode/skills/introspection/SKILL.md` | Vault knowledge-graph audit. Documents the three-phase pipeline (mechanical via `scripts/ci/vault_audit.py`, auto-fix via `--apply`, semantic drift via the `vault-audit-semantic` agent) and the rolling `vault/audit` PR convention. Loaded when running a vault health check, interpreting audit output, or drafting correction PRs. |
| `spec-management` | `.opencode/skills/spec-management/SKILL.md` | Spec creation and repositioning in the numbered sequence. Covers the `.specify/scripts/bash/` tooling, the NNN-Title naming convention, and the directory structure under `docs/vault/Specs/NNN Title/`. Loaded when creating, renumbering, or splitting specs. |
| `blog-posts` | `.opencode/skills/blog-posts/SKILL.md` | Jekyll devlog post authoring for the GitHub Pages site. Covers the time-release scheduling mechanism (`future: false` in frontmatter), the post frontmatter contract, and the deploy-site workflow. Loaded when drafting or scheduling a blog post. |

No skill currently embeds an MCP server in its frontmatter. Skills reference MCP tools descriptively in their bodies (for example, `observer-qa` describes the GDAI MCP screenshot workflow), but the skill loader does not bind MCP servers automatically. Agents must have the relevant MCP server configured in `opencode.json` for the skill's instructions to be actionable.

## MCP Server Inventory

Four MCP servers are wired into the project. All are local processes spawned per session — there are no remote MCP endpoints.

| MCP Server | Type | Entry Point | Purpose |
|---|---|---|---|
| `gdai-mcp-server` | local | `uv run src/addons/gdai-mcp-plugin-godot/gdai_mcp_server.py` | Godot editor and runtime access. Exposes scene control (`play_scene`, `stop_running_scene`), visual capture (`get_running_scene_screenshot`), input injection (`simulate_input`), node search (`search_nodes` with `mode="running_scene"`), and editor script execution (`execute_editor_script`). The server-side Python process talks to the Godot editor through HTTP calls against the paired GDScript plugin (`gdai_mcp_plugin.gd` + `gdai_mcp_runtime.gd`) loaded as a Godot editor plugin. Required for visual QA, runtime verification, and SC-001 baseline capture. The only MCP server in `opencode.json` without an explicit `enabled: true` flag (it relies on the OpenCode default-enabled behaviour). |
| `obsidian` (mcpvault) | local | `npx -y @bitbonsai/mcpvault@0.11.0 docs/vault/` | Vault knowledge-graph read/write. See [[Tools — mcpvault]] for the full tool surface (15 tools including `read_note`, `search_notes`, `write_note`, `append_to_note`, `update_frontmatter`, `manage_tags`, `list_vault`). Required for vault session-start reads and write-back of decisions, discoveries, and session logs. |
| `blender` | local | `uv run --project ~/Workbench/Repositories/blender-mcp blender-mcp` | Blender 3D pipeline automation. Used by the `tools/blender/` pipeline for mesh separation, UV unwrap, LOD generation, and GLB export. Telemetry disabled via environment variable. |
| `comfyui` | local | `comfyui-mcp-server/.venv/bin/python3 server.py --stdio` | ComfyUI workflow execution for AI texture generation. Configured with `COMFYUI_URL=http://localhost:8000`, an output root under the user's ComfyUI install, and a project-local workflow directory at `tools/comfyui/workflows/`. Used by the texture-generation pipeline that turns Blender renders into PBR textures via SDXL img2img and RealESRGAN upscaling. |

The `.concourse.json` file enables `gdai-mcp-server` and the `gdscript` LSP at the Concourse repo-profile level, so any session opened by Concourse against this repo automatically gets Godot runtime access. The full MCP set in `opencode.json` is additive and used by direct OpenCode sessions.

## Invocation Patterns

Skills are loaded one of two ways: directly via the `skill(name="...")` tool, which injects the skill content into the current conversation; or as the `load_skills` parameter on a `task(...)` delegation, which injects the skill into the spawned subagent's context. The `load_skills` parameter is required on every `task` call — pass an empty list (`load_skills=[]`) when no skill applies.

MCP servers are auto-started by OpenCode at session creation based on `opencode.json` and `.concourse.json`. Their tools become available as namespaced calls (for example, `mcp.gdai-mcp-server.play_scene`). Agents do not invoke MCP servers explicitly; they call the exposed tools directly once a session is live.

The two surfaces combine in delegation. A typical generation-code task delegates to a subagent with `load_skills=["observer-qa"]`, expecting that subagent to follow the visual QA workflow using the `gdai-mcp-server` MCP tools. The skill provides the protocol; the MCP provides the capability.

## Skill ↔ MCP ↔ Agent Coupling

The intended runtime coupling is documented below. No code currently enforces it — the bindings are conventional, not configured.

| Skill | Primary MCP | Secondary Tools | Typical Agent |
|---|---|---|---|
| `observer-qa` | `gdai-mcp-server` | `tools/observer/` CLI for sequence captures and CI gates | Sisyphus (orchestrator); subagents working on generation code |
| `audio-assets` | none (filesystem only) | `tools/tts/` scripts, `make tts-*` targets, `make radio-*` targets | Sisyphus-Junior delegated for content tasks |
| `introspection` | `obsidian` (mcpvault) | `scripts/ci/vault_audit.py`, opencode `vault-audit-semantic` agent | Sisyphus + dedicated `vault-audit-semantic` subagent |
| `spec-management` | `obsidian` (mcpvault) | `.specify/scripts/bash/` shell tooling | Sisyphus or human via slash commands |
| `blog-posts` | `obsidian` (mcpvault) | Jekyll site under `site/`, `make site-*` targets | Sisyphus or GTM persona |

The [[Tools — Development Workbench]] note carries the full layer diagram showing how agents, skills, and MCP servers stack on top of the persona runtime, the vault, the spec system, and the CI/CD layer.

## GDAI MCP Plugin — Two-Process Architecture

The `gdai-mcp-server` MCP is unusual: it is not a single process but a paired system. The Python MCP server at `src/addons/gdai-mcp-plugin-godot/gdai_mcp_server.py` is the agent-facing surface; it speaks MCP to OpenCode. The GDScript plugin (`gdai_mcp_plugin.gd` and `gdai_mcp_runtime.gd`) is loaded by the Godot editor as an `EditorPlugin` and stands up an HTTP server inside the Godot process that exposes the actual runtime hooks (scene control, screenshot capture, input simulation). The Python MCP server reaches the editor by issuing HTTP requests via `httpx` against `http://localhost:3571` (the port is overridable via the `GDAI_MCP_SERVER_PORT` environment variable). The plugin must be installed and enabled in the Godot editor for the MCP server's tools to do anything — an MCP server with no editor on the other end returns connection errors. The plugin lives in `src/addons/`, is vendored (not edited), and is excluded from first-party linting and formatting.

## Limitations

The MCP-first model has known constraints documented in the `observer-qa` skill and AGENTS.md:

- **Editor script context** — `execute_editor_script` runs in the editor process, not the running game. It cannot call autoload signals or access running scene nodes via `Engine.get_main_loop()` while the game is playing.
- **Log buffer truncation** — `get_godot_errors(num_lines=200)` returns a rolling tail. Mid-generation log lines are often lost. Use `user://logs/` file writes for durable diagnostics (the `veg_counts.json` and `generation_*.json` files follow this pattern).
- **GDExtension editor instantiation** — Instantiating Rust GDExtension nodes via `ClassDB.instantiate()` in an editor script produces placeholder instances that cannot call Rust methods. Run the full game scene instead.

These limitations push agents toward `play_scene` + `simulate_input` + filesystem reads, which is the SC-001 / vegetation baseline procedure documented in AGENTS.md.

## Related

- [[Tools — mcpvault]] — full surface of the vault MCP server (15 tools)
- [[Tools — Development Workbench]] — meta-architecture showing skills + MCP in context
- [[Tools — Observer]] — the Observer CLI that pairs with the `observer-qa` skill
- [[Tools — TTS]] — TTS pipeline that pairs with the `audio-assets` skill
- [[Tools — Vault Audit]] — vault audit tooling that pairs with the `introspection` skill
- [[Code]] — folder MOC
- [[Tooling — Domain MOC]] — domain MOC

## References

- `opencode.json` — MCP server configuration (gdai-mcp-server, obsidian, blender, comfyui) and GDScript LSP
- `.concourse.json` — Concourse repo-profile hook (gdai-mcp-server + gdscript)
- `.opencode/skills/SKILL.md` — `observer-qa` skill (root)
- `.opencode/skills/audio-assets/SKILL.md`
- `.opencode/skills/introspection/SKILL.md`
- `.opencode/skills/spec-management/SKILL.md`
- `.opencode/skills/blog-posts/SKILL.md`
- `src/addons/gdai-mcp-plugin-godot/gdai_mcp_server.py` — Python MCP server entry point
- `src/addons/gdai-mcp-plugin-godot/gdai_mcp_plugin.gd` — Godot editor plugin
- `src/addons/gdai-mcp-plugin-godot/gdai_mcp_runtime.gd` — runtime GDScript bridge
- `AGENTS.md` — Godot MCP usage protocol and SC-001 baseline procedure

Controlled tag vocabulary (as read):
type/*:
- `type/code` — Code architecture, autoloads, conventions, tooling. Carries `code-refs:`. (e.g. `Code/Autoloads — Disturbance.md`)
- `type/decision` — Architectural or design decision made by an agent during a session. Written to `docs/vault/Decisions/`. (Agent notes only — spec 080.)
- `type/design` — Design intent, player-facing concepts, world lore. (e.g. `Design/World Model.md`)
- `type/discovery` — Non-obvious constraint, gap, or conflict found by an agent during a session. Written to `docs/vault/Discoveries/`. (Agent notes only — spec 080.)
- `type/moc` — Map of Content at any of three tiers (folder / domain / concept). (e.g. `Audio.md`)
- `type/principle` — Governance and constitutional notes. Non-negotiable rules. (e.g. `Governance/Constitution.md`)
- `type/reference` — Glossary, decision log, open questions, epics. (e.g. `Reference/Glossary.md`)
- `type/session-log` — Session activity log; permanent audit trail. Written to `docs/vault/Sessions/`. Append-only, never pruned. (Agent notes only — spec 080.)
- `type/spec` — Spec document at `docs/vault/Specs/NNN Title/spec.md`. Carries `spec-refs:`. (e.g. `Specs/047 Car Radio/spec.md`)
- `type/system` — A bounded subsystem with implementation. Carries `code-refs`, `spec-refs`, `implements:` frontmatter. (e.g. `Systems/Audio — Car Radio.md`)
- `type/vision` — Strategic / vision-layer decision. Written to `docs/vault/Vision/`. Human-authored or agent-proposed with human ratification before promotion to `status: reviewed`. (Per triage #3 — spec 133 autonomous-company redesign.)
domain/*:
- `domain/anomalies` — Anomaly taxonomy, individual anomaly systems, spawn, behavior
- `domain/art` — Visual direction, palettes, references, asset pipeline
- `domain/audio` — Audio systems: world ambient, radio, transmissions, buses, pipeline
- `domain/autonomous-company` — Autonomous company v0.1 experiment: Slack infra, persona middleware, Letta integration, restart recovery
- `domain/build` — Build system, packaging, export, release automation
- `domain/governance` — Constitution, phased spec, policies
- `domain/infrastructure` — Infrastructure provisioning: CI/CD, hosting, deployment tooling, secrets management
- `domain/narrative` — Tone, horror register, forest transmissions narrative, Gary/KTLK
- `domain/player` — Player mode, input, controls, camera, exit/entry
- `domain/systems` — Cross-cutting system architecture and integration work
- `domain/tooling` — Build, CI, observer, TTS pipeline, dev-time tools
- `domain/vehicle` — The Samba: vehicle physics, dashboard, damage, panels
- `domain/world` — World model, biomes, terrain, procedural generation, weather
status/*:
- `status/canonical` — Fully authoritative; promoted by humans only. Highest trust. (Agent notes only — spec 080.)
- `status/draft` — Authoring in progress, not yet verified
- `status/reviewed` — Agent-created note verified against codebase within its creating session. Eligible for auto-injection in subsequent task dispatches. (Agent notes only — spec 080.)
- `status/stale` — Known out of date; cannot update immediately. Pairs with `> [!warning] STALE — needs update` callout.
- `status/superseded` — Replaced by another note. Terminal state. Pairs with `> [!warning] SUPERSEDED` callout.
- `status/wip` — Stable but under active revision
layer/*:
- `layer/content` — Content assets (audio, models, textures, audio provenance)
- `layer/gdext` — gdext wrapper layer (`rust/gdext-wrapper/`)
- `layer/gdscript` — GDScript (Godot scene-tier logic)
- `layer/infra` — Build, CI, deployment infrastructure
- `layer/python` — Python development tooling (`tools/`)
- `layer/rust-core` — Engine-agnostic Rust core (`rust/rust-core/`)
concept/*:
- `concept/biome` — Biome-reactive behavior across systems
- `concept/contamination` — Across-runs panel and garage degradation; the slow-horror mechanic that doesn't reset with the world
- `concept/diegetic` — Diegetic audio / UI / world-sourced design
- `concept/disturbance` — The disturbance mechanic thread (Article X)
- `concept/ephemeral-world` — Run-reset, transient worlds (Article IV Rules 6–7)
- `concept/governance` — Constitutional and governance concepts
- `concept/horror` — Horror register and dread design
- `concept/procedural` — Procedural generation, seed determinism
- `concept/rendering` — Visual rendering quality, shader correctness, Terrain3D integration, mesh fidelity, LOD, Z-fighting
- `concept/terrain` — Terrain generation, heightmap, Terrain3D regions, roughness, playability constraints
ember's answer for tag_assignment-code-tools-agent-skills-mcp, domain/governanceP(true) placed on the no, unsure, and yes zones.nounsureyesgold: yesP = 0.09

tag_assignment-code-tools-agent-skills-mcp: type/code

Tag assignment · test
Gold
The note calls for `type/code`: Code architecture, autoloads, conventions, tooling. Carries `code-refs:`. (e.g. `Code/Autoloads — Disturbance.md`) (True)
ember
The note has no reason to carry `type/code` (False)
Signal
P(true) 0.40 (unsure)
Kit outcome
deferred: treated as unsure
Why this gold label
Mined from Code/Tools — Agent Skills & MCP.md at 692f4bb58b7f62105aeb73fba8dfee12bfdecd53; gold is the note's own vocabulary tags.
Tools — Agent Skills & MCP

The skill system and the MCP (Model Context Protocol) server set form the two extension surfaces that turn a generic agent into an Old Growth agent. Skills inject domain instructions into the conversation context; MCP servers extend the tool surface with external capabilities. This note inventories both, documents the invocation pattern, and maps which agents consume which surfaces. It complements [[Tools — mcpvault]], which describes the vault MCP server in depth.

## The Two Surfaces, Compared

Skills are bodies of instructions loaded into the conversation context on demand. They contain workflows, decision matrices, and references to bundled scripts. They do not add new tools — they teach the agent how to use existing tools and external systems correctly. Skills live under `.opencode/skills/` and are loaded via the `skill` tool or as the `load_skills` parameter on the `task` tool.

MCP servers are processes (local or remote) that expose tools, resources, and prompts to the agent over the Model Context Protocol. They add new tool calls — for example, `gdai-mcp-server` exposes `play_scene`, `get_running_scene_screenshot`, `simulate_input`, and other Godot runtime operations as agent-callable tools. MCP servers are configured in `opencode.json` (project-local) and `.concourse.json` (Concourse repo-profile hook).

The two surfaces compose: a skill (e.g. `observer-qa`) tells the agent the correct workflow for visual QA; an MCP server (e.g. `gdai-mcp-server`) provides the tools that workflow invokes.

## Skill Inventory

Five skills ship in `.opencode/skills/`. Each is a directory containing a `SKILL.md` file with frontmatter (description, triggers) and a body of instructions; some bundle additional scripts or reference files.

| Skill | Directory | Purpose |
|---|---|---|
| `observer-qa` | `.opencode/skills/SKILL.md` (root) | MCP-first visual QA pipeline. Documents the GDAI MCP screenshot-and-analyse workflow as primary, the Observer CLI as secondary for sequence captures and CI gates, the agent trigger matrix, and the decision matrix that maps `(quality, recommendation)` pairs to ship/block actions. Loaded when working on generation code, world preview, or visual artefacts. |
| `audio-assets` | `.opencode/skills/audio-assets/SKILL.md` | TTS generation tooling, audio submodule workflow, naming conventions, and provenance requirements for Old Growth radio and ambient weather content. Loaded when authoring radio clips, KTLK Gary dialogue, weather ambient SFX, or station music. |
| `introspection` | `.opencode/skills/introspection/SKILL.md` | Vault knowledge-graph audit. Documents the three-phase pipeline (mechanical via `scripts/ci/vault_audit.py`, auto-fix via `--apply`, semantic drift via the `vault-audit-semantic` agent) and the rolling `vault/audit` PR convention. Loaded when running a vault health check, interpreting audit output, or drafting correction PRs. |
| `spec-management` | `.opencode/skills/spec-management/SKILL.md` | Spec creation and repositioning in the numbered sequence. Covers the `.specify/scripts/bash/` tooling, the NNN-Title naming convention, and the directory structure under `docs/vault/Specs/NNN Title/`. Loaded when creating, renumbering, or splitting specs. |
| `blog-posts` | `.opencode/skills/blog-posts/SKILL.md` | Jekyll devlog post authoring for the GitHub Pages site. Covers the time-release scheduling mechanism (`future: false` in frontmatter), the post frontmatter contract, and the deploy-site workflow. Loaded when drafting or scheduling a blog post. |

No skill currently embeds an MCP server in its frontmatter. Skills reference MCP tools descriptively in their bodies (for example, `observer-qa` describes the GDAI MCP screenshot workflow), but the skill loader does not bind MCP servers automatically. Agents must have the relevant MCP server configured in `opencode.json` for the skill's instructions to be actionable.

## MCP Server Inventory

Four MCP servers are wired into the project. All are local processes spawned per session — there are no remote MCP endpoints.

| MCP Server | Type | Entry Point | Purpose |
|---|---|---|---|
| `gdai-mcp-server` | local | `uv run src/addons/gdai-mcp-plugin-godot/gdai_mcp_server.py` | Godot editor and runtime access. Exposes scene control (`play_scene`, `stop_running_scene`), visual capture (`get_running_scene_screenshot`), input injection (`simulate_input`), node search (`search_nodes` with `mode="running_scene"`), and editor script execution (`execute_editor_script`). The server-side Python process talks to the Godot editor through HTTP calls against the paired GDScript plugin (`gdai_mcp_plugin.gd` + `gdai_mcp_runtime.gd`) loaded as a Godot editor plugin. Required for visual QA, runtime verification, and SC-001 baseline capture. The only MCP server in `opencode.json` without an explicit `enabled: true` flag (it relies on the OpenCode default-enabled behaviour). |
| `obsidian` (mcpvault) | local | `npx -y @bitbonsai/mcpvault@0.11.0 docs/vault/` | Vault knowledge-graph read/write. See [[Tools — mcpvault]] for the full tool surface (15 tools including `read_note`, `search_notes`, `write_note`, `append_to_note`, `update_frontmatter`, `manage_tags`, `list_vault`). Required for vault session-start reads and write-back of decisions, discoveries, and session logs. |
| `blender` | local | `uv run --project ~/Workbench/Repositories/blender-mcp blender-mcp` | Blender 3D pipeline automation. Used by the `tools/blender/` pipeline for mesh separation, UV unwrap, LOD generation, and GLB export. Telemetry disabled via environment variable. |
| `comfyui` | local | `comfyui-mcp-server/.venv/bin/python3 server.py --stdio` | ComfyUI workflow execution for AI texture generation. Configured with `COMFYUI_URL=http://localhost:8000`, an output root under the user's ComfyUI install, and a project-local workflow directory at `tools/comfyui/workflows/`. Used by the texture-generation pipeline that turns Blender renders into PBR textures via SDXL img2img and RealESRGAN upscaling. |

The `.concourse.json` file enables `gdai-mcp-server` and the `gdscript` LSP at the Concourse repo-profile level, so any session opened by Concourse against this repo automatically gets Godot runtime access. The full MCP set in `opencode.json` is additive and used by direct OpenCode sessions.

## Invocation Patterns

Skills are loaded one of two ways: directly via the `skill(name="...")` tool, which injects the skill content into the current conversation; or as the `load_skills` parameter on a `task(...)` delegation, which injects the skill into the spawned subagent's context. The `load_skills` parameter is required on every `task` call — pass an empty list (`load_skills=[]`) when no skill applies.

MCP servers are auto-started by OpenCode at session creation based on `opencode.json` and `.concourse.json`. Their tools become available as namespaced calls (for example, `mcp.gdai-mcp-server.play_scene`). Agents do not invoke MCP servers explicitly; they call the exposed tools directly once a session is live.

The two surfaces combine in delegation. A typical generation-code task delegates to a subagent with `load_skills=["observer-qa"]`, expecting that subagent to follow the visual QA workflow using the `gdai-mcp-server` MCP tools. The skill provides the protocol; the MCP provides the capability.

## Skill ↔ MCP ↔ Agent Coupling

The intended runtime coupling is documented below. No code currently enforces it — the bindings are conventional, not configured.

| Skill | Primary MCP | Secondary Tools | Typical Agent |
|---|---|---|---|
| `observer-qa` | `gdai-mcp-server` | `tools/observer/` CLI for sequence captures and CI gates | Sisyphus (orchestrator); subagents working on generation code |
| `audio-assets` | none (filesystem only) | `tools/tts/` scripts, `make tts-*` targets, `make radio-*` targets | Sisyphus-Junior delegated for content tasks |
| `introspection` | `obsidian` (mcpvault) | `scripts/ci/vault_audit.py`, opencode `vault-audit-semantic` agent | Sisyphus + dedicated `vault-audit-semantic` subagent |
| `spec-management` | `obsidian` (mcpvault) | `.specify/scripts/bash/` shell tooling | Sisyphus or human via slash commands |
| `blog-posts` | `obsidian` (mcpvault) | Jekyll site under `site/`, `make site-*` targets | Sisyphus or GTM persona |

The [[Tools — Development Workbench]] note carries the full layer diagram showing how agents, skills, and MCP servers stack on top of the persona runtime, the vault, the spec system, and the CI/CD layer.

## GDAI MCP Plugin — Two-Process Architecture

The `gdai-mcp-server` MCP is unusual: it is not a single process but a paired system. The Python MCP server at `src/addons/gdai-mcp-plugin-godot/gdai_mcp_server.py` is the agent-facing surface; it speaks MCP to OpenCode. The GDScript plugin (`gdai_mcp_plugin.gd` and `gdai_mcp_runtime.gd`) is loaded by the Godot editor as an `EditorPlugin` and stands up an HTTP server inside the Godot process that exposes the actual runtime hooks (scene control, screenshot capture, input simulation). The Python MCP server reaches the editor by issuing HTTP requests via `httpx` against `http://localhost:3571` (the port is overridable via the `GDAI_MCP_SERVER_PORT` environment variable). The plugin must be installed and enabled in the Godot editor for the MCP server's tools to do anything — an MCP server with no editor on the other end returns connection errors. The plugin lives in `src/addons/`, is vendored (not edited), and is excluded from first-party linting and formatting.

## Limitations

The MCP-first model has known constraints documented in the `observer-qa` skill and AGENTS.md:

- **Editor script context** — `execute_editor_script` runs in the editor process, not the running game. It cannot call autoload signals or access running scene nodes via `Engine.get_main_loop()` while the game is playing.
- **Log buffer truncation** — `get_godot_errors(num_lines=200)` returns a rolling tail. Mid-generation log lines are often lost. Use `user://logs/` file writes for durable diagnostics (the `veg_counts.json` and `generation_*.json` files follow this pattern).
- **GDExtension editor instantiation** — Instantiating Rust GDExtension nodes via `ClassDB.instantiate()` in an editor script produces placeholder instances that cannot call Rust methods. Run the full game scene instead.

These limitations push agents toward `play_scene` + `simulate_input` + filesystem reads, which is the SC-001 / vegetation baseline procedure documented in AGENTS.md.

## Related

- [[Tools — mcpvault]] — full surface of the vault MCP server (15 tools)
- [[Tools — Development Workbench]] — meta-architecture showing skills + MCP in context
- [[Tools — Observer]] — the Observer CLI that pairs with the `observer-qa` skill
- [[Tools — TTS]] — TTS pipeline that pairs with the `audio-assets` skill
- [[Tools — Vault Audit]] — vault audit tooling that pairs with the `introspection` skill
- [[Code]] — folder MOC
- [[Tooling — Domain MOC]] — domain MOC

## References

- `opencode.json` — MCP server configuration (gdai-mcp-server, obsidian, blender, comfyui) and GDScript LSP
- `.concourse.json` — Concourse repo-profile hook (gdai-mcp-server + gdscript)
- `.opencode/skills/SKILL.md` — `observer-qa` skill (root)
- `.opencode/skills/audio-assets/SKILL.md`
- `.opencode/skills/introspection/SKILL.md`
- `.opencode/skills/spec-management/SKILL.md`
- `.opencode/skills/blog-posts/SKILL.md`
- `src/addons/gdai-mcp-plugin-godot/gdai_mcp_server.py` — Python MCP server entry point
- `src/addons/gdai-mcp-plugin-godot/gdai_mcp_plugin.gd` — Godot editor plugin
- `src/addons/gdai-mcp-plugin-godot/gdai_mcp_runtime.gd` — runtime GDScript bridge
- `AGENTS.md` — Godot MCP usage protocol and SC-001 baseline procedure

Controlled tag vocabulary (as read):
type/*:
- `type/code` — Code architecture, autoloads, conventions, tooling. Carries `code-refs:`. (e.g. `Code/Autoloads — Disturbance.md`)
- `type/decision` — Architectural or design decision made by an agent during a session. Written to `docs/vault/Decisions/`. (Agent notes only — spec 080.)
- `type/design` — Design intent, player-facing concepts, world lore. (e.g. `Design/World Model.md`)
- `type/discovery` — Non-obvious constraint, gap, or conflict found by an agent during a session. Written to `docs/vault/Discoveries/`. (Agent notes only — spec 080.)
- `type/moc` — Map of Content at any of three tiers (folder / domain / concept). (e.g. `Audio.md`)
- `type/principle` — Governance and constitutional notes. Non-negotiable rules. (e.g. `Governance/Constitution.md`)
- `type/reference` — Glossary, decision log, open questions, epics. (e.g. `Reference/Glossary.md`)
- `type/session-log` — Session activity log; permanent audit trail. Written to `docs/vault/Sessions/`. Append-only, never pruned. (Agent notes only — spec 080.)
- `type/spec` — Spec document at `docs/vault/Specs/NNN Title/spec.md`. Carries `spec-refs:`. (e.g. `Specs/047 Car Radio/spec.md`)
- `type/system` — A bounded subsystem with implementation. Carries `code-refs`, `spec-refs`, `implements:` frontmatter. (e.g. `Systems/Audio — Car Radio.md`)
- `type/vision` — Strategic / vision-layer decision. Written to `docs/vault/Vision/`. Human-authored or agent-proposed with human ratification before promotion to `status: reviewed`. (Per triage #3 — spec 133 autonomous-company redesign.)
domain/*:
- `domain/anomalies` — Anomaly taxonomy, individual anomaly systems, spawn, behavior
- `domain/art` — Visual direction, palettes, references, asset pipeline
- `domain/audio` — Audio systems: world ambient, radio, transmissions, buses, pipeline
- `domain/autonomous-company` — Autonomous company v0.1 experiment: Slack infra, persona middleware, Letta integration, restart recovery
- `domain/build` — Build system, packaging, export, release automation
- `domain/governance` — Constitution, phased spec, policies
- `domain/infrastructure` — Infrastructure provisioning: CI/CD, hosting, deployment tooling, secrets management
- `domain/narrative` — Tone, horror register, forest transmissions narrative, Gary/KTLK
- `domain/player` — Player mode, input, controls, camera, exit/entry
- `domain/systems` — Cross-cutting system architecture and integration work
- `domain/tooling` — Build, CI, observer, TTS pipeline, dev-time tools
- `domain/vehicle` — The Samba: vehicle physics, dashboard, damage, panels
- `domain/world` — World model, biomes, terrain, procedural generation, weather
status/*:
- `status/canonical` — Fully authoritative; promoted by humans only. Highest trust. (Agent notes only — spec 080.)
- `status/draft` — Authoring in progress, not yet verified
- `status/reviewed` — Agent-created note verified against codebase within its creating session. Eligible for auto-injection in subsequent task dispatches. (Agent notes only — spec 080.)
- `status/stale` — Known out of date; cannot update immediately. Pairs with `> [!warning] STALE — needs update` callout.
- `status/superseded` — Replaced by another note. Terminal state. Pairs with `> [!warning] SUPERSEDED` callout.
- `status/wip` — Stable but under active revision
layer/*:
- `layer/content` — Content assets (audio, models, textures, audio provenance)
- `layer/gdext` — gdext wrapper layer (`rust/gdext-wrapper/`)
- `layer/gdscript` — GDScript (Godot scene-tier logic)
- `layer/infra` — Build, CI, deployment infrastructure
- `layer/python` — Python development tooling (`tools/`)
- `layer/rust-core` — Engine-agnostic Rust core (`rust/rust-core/`)
concept/*:
- `concept/biome` — Biome-reactive behavior across systems
- `concept/contamination` — Across-runs panel and garage degradation; the slow-horror mechanic that doesn't reset with the world
- `concept/diegetic` — Diegetic audio / UI / world-sourced design
- `concept/disturbance` — The disturbance mechanic thread (Article X)
- `concept/ephemeral-world` — Run-reset, transient worlds (Article IV Rules 6–7)
- `concept/governance` — Constitutional and governance concepts
- `concept/horror` — Horror register and dread design
- `concept/procedural` — Procedural generation, seed determinism
- `concept/rendering` — Visual rendering quality, shader correctness, Terrain3D integration, mesh fidelity, LOD, Z-fighting
- `concept/terrain` — Terrain generation, heightmap, Terrain3D regions, roughness, playability constraints
ember's answer for tag_assignment-code-tools-agent-skills-mcp, type/codeP(true) placed on the no, unsure, and yes zones.nounsureyesgold: yesP = 0.40

tag_assignment-decisions-garage-map-shows-previous-run: domain/player

Tag assignment · test
Gold
The note calls for `domain/player`: Player mode, input, controls, camera, exit/entry (True)
ember
The note has no reason to carry `domain/player` (False)
Signal
P(true) 0.14 (no)
Kit outcome
acted on a wrong answer
Why this gold label
Mined from Decisions/Garage Map Shows Previous Run.md at 692f4bb58b7f62105aeb73fba8dfee12bfdecd53; gold is the note's own vocabulary tags.
Garage Map Shows Previous Run

This note records the intentional design decision that the garage map (spec 092) displays the world from the player's previous run rather than generating or previewing the upcoming world.

## The Decision

When the player opens the garage map between runs, the map renders the road network, biome regions, and points of interest from their last completed (or abandoned) run. The upcoming world's seed has already been determined, but the map does not show it.

## The Reasoning

This decision serves the horror register in two ways.

First, it creates a false-safety trap. The player studies the map, plans a route, identifies landmarks. All of that planning is worthless because they are looking at a world that no longer exists. The forest resets between runs. The map is a memento of somewhere you can never return to.

Second, it reinforces the ephemerality and irreversibility themes that run through the game's design. The map is not a planning tool in the conventional sense — it is evidence of a previous encounter. It tells you what you survived (or didn't), not what you are about to face.

## Implementation Constraint

The garage map must read from persisted run data (the previous run's world record), not from the current GameState seed. It must not call any world generation functions. If no previous run exists (first run), the map shows an empty or fog-of-war state — not a generated world.

## References

- docs/vault/Specs/092 Garage Map and Trip Planner/092 Garage Map and Trip Planner.md
- docs/vault/Ephemerality Thread.md
- docs/vault/The Disturbance Thread.md

Controlled tag vocabulary (as read):
type/*:
- `type/code` — Code architecture, autoloads, conventions, tooling. Carries `code-refs:`. (e.g. `Code/Autoloads — Disturbance.md`)
- `type/decision` — Architectural or design decision made by an agent during a session. Written to `docs/vault/Decisions/`. (Agent notes only — spec 080.)
- `type/design` — Design intent, player-facing concepts, world lore. (e.g. `Design/World Model.md`)
- `type/discovery` — Non-obvious constraint, gap, or conflict found by an agent during a session. Written to `docs/vault/Discoveries/`. (Agent notes only — spec 080.)
- `type/moc` — Map of Content at any of three tiers (folder / domain / concept). (e.g. `Audio.md`)
- `type/principle` — Governance and constitutional notes. Non-negotiable rules. (e.g. `Governance/Constitution.md`)
- `type/reference` — Glossary, decision log, open questions, epics. (e.g. `Reference/Glossary.md`)
- `type/session-log` — Session activity log; permanent audit trail. Written to `docs/vault/Sessions/`. Append-only, never pruned. (Agent notes only — spec 080.)
- `type/spec` — Spec document at `docs/vault/Specs/NNN Title/spec.md`. Carries `spec-refs:`. (e.g. `Specs/047 Car Radio/spec.md`)
- `type/system` — A bounded subsystem with implementation. Carries `code-refs`, `spec-refs`, `implements:` frontmatter. (e.g. `Systems/Audio — Car Radio.md`)
- `type/vision` — Strategic / vision-layer decision. Written to `docs/vault/Vision/`. Human-authored or agent-proposed with human ratification before promotion to `status: reviewed`. (Per triage #3 — spec 133 autonomous-company redesign.)
domain/*:
- `domain/anomalies` — Anomaly taxonomy, individual anomaly systems, spawn, behavior
- `domain/art` — Visual direction, palettes, references, asset pipeline
- `domain/audio` — Audio systems: world ambient, radio, transmissions, buses, pipeline
- `domain/autonomous-company` — Autonomous company v0.1 experiment: Slack infra, persona middleware, Letta integration, restart recovery
- `domain/build` — Build system, packaging, export, release automation
- `domain/governance` — Constitution, phased spec, policies
- `domain/infrastructure` — Infrastructure provisioning: CI/CD, hosting, deployment tooling, secrets management
- `domain/narrative` — Tone, horror register, forest transmissions narrative, Gary/KTLK
- `domain/player` — Player mode, input, controls, camera, exit/entry
- `domain/systems` — Cross-cutting system architecture and integration work
- `domain/tooling` — Build, CI, observer, TTS pipeline, dev-time tools
- `domain/vehicle` — The Samba: vehicle physics, dashboard, damage, panels
- `domain/world` — World model, biomes, terrain, procedural generation, weather
status/*:
- `status/canonical` — Fully authoritative; promoted by humans only. Highest trust. (Agent notes only — spec 080.)
- `status/draft` — Authoring in progress, not yet verified
- `status/reviewed` — Agent-created note verified against codebase within its creating session. Eligible for auto-injection in subsequent task dispatches. (Agent notes only — spec 080.)
- `status/stale` — Known out of date; cannot update immediately. Pairs with `> [!warning] STALE — needs update` callout.
- `status/superseded` — Replaced by another note. Terminal state. Pairs with `> [!warning] SUPERSEDED` callout.
- `status/wip` — Stable but under active revision
layer/*:
- `layer/content` — Content assets (audio, models, textures, audio provenance)
- `layer/gdext` — gdext wrapper layer (`rust/gdext-wrapper/`)
- `layer/gdscript` — GDScript (Godot scene-tier logic)
- `layer/infra` — Build, CI, deployment infrastructure
- `layer/python` — Python development tooling (`tools/`)
- `layer/rust-core` — Engine-agnostic Rust core (`rust/rust-core/`)
concept/*:
- `concept/biome` — Biome-reactive behavior across systems
- `concept/contamination` — Across-runs panel and garage degradation; the slow-horror mechanic that doesn't reset with the world
- `concept/diegetic` — Diegetic audio / UI / world-sourced design
- `concept/disturbance` — The disturbance mechanic thread (Article X)
- `concept/ephemeral-world` — Run-reset, transient worlds (Article IV Rules 6–7)
- `concept/governance` — Constitutional and governance concepts
- `concept/horror` — Horror register and dread design
- `concept/procedural` — Procedural generation, seed determinism
- `concept/rendering` — Visual rendering quality, shader correctness, Terrain3D integration, mesh fidelity, LOD, Z-fighting
- `concept/terrain` — Terrain generation, heightmap, Terrain3D regions, roughness, playability constraints
ember's answer for tag_assignment-decisions-garage-map-shows-previous-run, domain/playerP(true) placed on the no, unsure, and yes zones.nounsureyesgold: yesP = 0.14

tag_assignment-decisions-garage-map-shows-previous-run: layer/gdscript

Tag assignment · test
Gold
The note calls for `layer/gdscript`: GDScript (Godot scene-tier logic) (True)
ember
The note has no reason to carry `layer/gdscript` (False)
Signal
P(true) 0.05 (no)
Kit outcome
acted on a wrong answer
Why this gold label
Mined from Decisions/Garage Map Shows Previous Run.md at 692f4bb58b7f62105aeb73fba8dfee12bfdecd53; gold is the note's own vocabulary tags.
Garage Map Shows Previous Run

This note records the intentional design decision that the garage map (spec 092) displays the world from the player's previous run rather than generating or previewing the upcoming world.

## The Decision

When the player opens the garage map between runs, the map renders the road network, biome regions, and points of interest from their last completed (or abandoned) run. The upcoming world's seed has already been determined, but the map does not show it.

## The Reasoning

This decision serves the horror register in two ways.

First, it creates a false-safety trap. The player studies the map, plans a route, identifies landmarks. All of that planning is worthless because they are looking at a world that no longer exists. The forest resets between runs. The map is a memento of somewhere you can never return to.

Second, it reinforces the ephemerality and irreversibility themes that run through the game's design. The map is not a planning tool in the conventional sense — it is evidence of a previous encounter. It tells you what you survived (or didn't), not what you are about to face.

## Implementation Constraint

The garage map must read from persisted run data (the previous run's world record), not from the current GameState seed. It must not call any world generation functions. If no previous run exists (first run), the map shows an empty or fog-of-war state — not a generated world.

## References

- docs/vault/Specs/092 Garage Map and Trip Planner/092 Garage Map and Trip Planner.md
- docs/vault/Ephemerality Thread.md
- docs/vault/The Disturbance Thread.md

Controlled tag vocabulary (as read):
type/*:
- `type/code` — Code architecture, autoloads, conventions, tooling. Carries `code-refs:`. (e.g. `Code/Autoloads — Disturbance.md`)
- `type/decision` — Architectural or design decision made by an agent during a session. Written to `docs/vault/Decisions/`. (Agent notes only — spec 080.)
- `type/design` — Design intent, player-facing concepts, world lore. (e.g. `Design/World Model.md`)
- `type/discovery` — Non-obvious constraint, gap, or conflict found by an agent during a session. Written to `docs/vault/Discoveries/`. (Agent notes only — spec 080.)
- `type/moc` — Map of Content at any of three tiers (folder / domain / concept). (e.g. `Audio.md`)
- `type/principle` — Governance and constitutional notes. Non-negotiable rules. (e.g. `Governance/Constitution.md`)
- `type/reference` — Glossary, decision log, open questions, epics. (e.g. `Reference/Glossary.md`)
- `type/session-log` — Session activity log; permanent audit trail. Written to `docs/vault/Sessions/`. Append-only, never pruned. (Agent notes only — spec 080.)
- `type/spec` — Spec document at `docs/vault/Specs/NNN Title/spec.md`. Carries `spec-refs:`. (e.g. `Specs/047 Car Radio/spec.md`)
- `type/system` — A bounded subsystem with implementation. Carries `code-refs`, `spec-refs`, `implements:` frontmatter. (e.g. `Systems/Audio — Car Radio.md`)
- `type/vision` — Strategic / vision-layer decision. Written to `docs/vault/Vision/`. Human-authored or agent-proposed with human ratification before promotion to `status: reviewed`. (Per triage #3 — spec 133 autonomous-company redesign.)
domain/*:
- `domain/anomalies` — Anomaly taxonomy, individual anomaly systems, spawn, behavior
- `domain/art` — Visual direction, palettes, references, asset pipeline
- `domain/audio` — Audio systems: world ambient, radio, transmissions, buses, pipeline
- `domain/autonomous-company` — Autonomous company v0.1 experiment: Slack infra, persona middleware, Letta integration, restart recovery
- `domain/build` — Build system, packaging, export, release automation
- `domain/governance` — Constitution, phased spec, policies
- `domain/infrastructure` — Infrastructure provisioning: CI/CD, hosting, deployment tooling, secrets management
- `domain/narrative` — Tone, horror register, forest transmissions narrative, Gary/KTLK
- `domain/player` — Player mode, input, controls, camera, exit/entry
- `domain/systems` — Cross-cutting system architecture and integration work
- `domain/tooling` — Build, CI, observer, TTS pipeline, dev-time tools
- `domain/vehicle` — The Samba: vehicle physics, dashboard, damage, panels
- `domain/world` — World model, biomes, terrain, procedural generation, weather
status/*:
- `status/canonical` — Fully authoritative; promoted by humans only. Highest trust. (Agent notes only — spec 080.)
- `status/draft` — Authoring in progress, not yet verified
- `status/reviewed` — Agent-created note verified against codebase within its creating session. Eligible for auto-injection in subsequent task dispatches. (Agent notes only — spec 080.)
- `status/stale` — Known out of date; cannot update immediately. Pairs with `> [!warning] STALE — needs update` callout.
- `status/superseded` — Replaced by another note. Terminal state. Pairs with `> [!warning] SUPERSEDED` callout.
- `status/wip` — Stable but under active revision
layer/*:
- `layer/content` — Content assets (audio, models, textures, audio provenance)
- `layer/gdext` — gdext wrapper layer (`rust/gdext-wrapper/`)
- `layer/gdscript` — GDScript (Godot scene-tier logic)
- `layer/infra` — Build, CI, deployment infrastructure
- `layer/python` — Python development tooling (`tools/`)
- `layer/rust-core` — Engine-agnostic Rust core (`rust/rust-core/`)
concept/*:
- `concept/biome` — Biome-reactive behavior across systems
- `concept/contamination` — Across-runs panel and garage degradation; the slow-horror mechanic that doesn't reset with the world
- `concept/diegetic` — Diegetic audio / UI / world-sourced design
- `concept/disturbance` — The disturbance mechanic thread (Article X)
- `concept/ephemeral-world` — Run-reset, transient worlds (Article IV Rules 6–7)
- `concept/governance` — Constitutional and governance concepts
- `concept/horror` — Horror register and dread design
- `concept/procedural` — Procedural generation, seed determinism
- `concept/rendering` — Visual rendering quality, shader correctness, Terrain3D integration, mesh fidelity, LOD, Z-fighting
- `concept/terrain` — Terrain generation, heightmap, Terrain3D regions, roughness, playability constraints
ember's answer for tag_assignment-decisions-garage-map-shows-previous-run, layer/gdscriptP(true) placed on the no, unsure, and yes zones.nounsureyesgold: yesP = 0.05

tag_assignment-decisions-garage-map-shows-previous-run: status/reviewed

Tag assignment · test
Gold
The note calls for `status/reviewed`: Agent-created note verified against codebase within its creating session. Eligible for auto-injection in subsequent task dispatches. (Agent notes only — spec 080.) (True)
ember
The note has no reason to carry `status/reviewed` (False)
Signal
P(true) 0.19 (no)
Kit outcome
acted on a wrong answer
Why this gold label
Mined from Decisions/Garage Map Shows Previous Run.md at 692f4bb58b7f62105aeb73fba8dfee12bfdecd53; gold is the note's own vocabulary tags.
Garage Map Shows Previous Run

This note records the intentional design decision that the garage map (spec 092) displays the world from the player's previous run rather than generating or previewing the upcoming world.

## The Decision

When the player opens the garage map between runs, the map renders the road network, biome regions, and points of interest from their last completed (or abandoned) run. The upcoming world's seed has already been determined, but the map does not show it.

## The Reasoning

This decision serves the horror register in two ways.

First, it creates a false-safety trap. The player studies the map, plans a route, identifies landmarks. All of that planning is worthless because they are looking at a world that no longer exists. The forest resets between runs. The map is a memento of somewhere you can never return to.

Second, it reinforces the ephemerality and irreversibility themes that run through the game's design. The map is not a planning tool in the conventional sense — it is evidence of a previous encounter. It tells you what you survived (or didn't), not what you are about to face.

## Implementation Constraint

The garage map must read from persisted run data (the previous run's world record), not from the current GameState seed. It must not call any world generation functions. If no previous run exists (first run), the map shows an empty or fog-of-war state — not a generated world.

## References

- docs/vault/Specs/092 Garage Map and Trip Planner/092 Garage Map and Trip Planner.md
- docs/vault/Ephemerality Thread.md
- docs/vault/The Disturbance Thread.md

Controlled tag vocabulary (as read):
type/*:
- `type/code` — Code architecture, autoloads, conventions, tooling. Carries `code-refs:`. (e.g. `Code/Autoloads — Disturbance.md`)
- `type/decision` — Architectural or design decision made by an agent during a session. Written to `docs/vault/Decisions/`. (Agent notes only — spec 080.)
- `type/design` — Design intent, player-facing concepts, world lore. (e.g. `Design/World Model.md`)
- `type/discovery` — Non-obvious constraint, gap, or conflict found by an agent during a session. Written to `docs/vault/Discoveries/`. (Agent notes only — spec 080.)
- `type/moc` — Map of Content at any of three tiers (folder / domain / concept). (e.g. `Audio.md`)
- `type/principle` — Governance and constitutional notes. Non-negotiable rules. (e.g. `Governance/Constitution.md`)
- `type/reference` — Glossary, decision log, open questions, epics. (e.g. `Reference/Glossary.md`)
- `type/session-log` — Session activity log; permanent audit trail. Written to `docs/vault/Sessions/`. Append-only, never pruned. (Agent notes only — spec 080.)
- `type/spec` — Spec document at `docs/vault/Specs/NNN Title/spec.md`. Carries `spec-refs:`. (e.g. `Specs/047 Car Radio/spec.md`)
- `type/system` — A bounded subsystem with implementation. Carries `code-refs`, `spec-refs`, `implements:` frontmatter. (e.g. `Systems/Audio — Car Radio.md`)
- `type/vision` — Strategic / vision-layer decision. Written to `docs/vault/Vision/`. Human-authored or agent-proposed with human ratification before promotion to `status: reviewed`. (Per triage #3 — spec 133 autonomous-company redesign.)
domain/*:
- `domain/anomalies` — Anomaly taxonomy, individual anomaly systems, spawn, behavior
- `domain/art` — Visual direction, palettes, references, asset pipeline
- `domain/audio` — Audio systems: world ambient, radio, transmissions, buses, pipeline
- `domain/autonomous-company` — Autonomous company v0.1 experiment: Slack infra, persona middleware, Letta integration, restart recovery
- `domain/build` — Build system, packaging, export, release automation
- `domain/governance` — Constitution, phased spec, policies
- `domain/infrastructure` — Infrastructure provisioning: CI/CD, hosting, deployment tooling, secrets management
- `domain/narrative` — Tone, horror register, forest transmissions narrative, Gary/KTLK
- `domain/player` — Player mode, input, controls, camera, exit/entry
- `domain/systems` — Cross-cutting system architecture and integration work
- `domain/tooling` — Build, CI, observer, TTS pipeline, dev-time tools
- `domain/vehicle` — The Samba: vehicle physics, dashboard, damage, panels
- `domain/world` — World model, biomes, terrain, procedural generation, weather
status/*:
- `status/canonical` — Fully authoritative; promoted by humans only. Highest trust. (Agent notes only — spec 080.)
- `status/draft` — Authoring in progress, not yet verified
- `status/reviewed` — Agent-created note verified against codebase within its creating session. Eligible for auto-injection in subsequent task dispatches. (Agent notes only — spec 080.)
- `status/stale` — Known out of date; cannot update immediately. Pairs with `> [!warning] STALE — needs update` callout.
- `status/superseded` — Replaced by another note. Terminal state. Pairs with `> [!warning] SUPERSEDED` callout.
- `status/wip` — Stable but under active revision
layer/*:
- `layer/content` — Content assets (audio, models, textures, audio provenance)
- `layer/gdext` — gdext wrapper layer (`rust/gdext-wrapper/`)
- `layer/gdscript` — GDScript (Godot scene-tier logic)
- `layer/infra` — Build, CI, deployment infrastructure
- `layer/python` — Python development tooling (`tools/`)
- `layer/rust-core` — Engine-agnostic Rust core (`rust/rust-core/`)
concept/*:
- `concept/biome` — Biome-reactive behavior across systems
- `concept/contamination` — Across-runs panel and garage degradation; the slow-horror mechanic that doesn't reset with the world
- `concept/diegetic` — Diegetic audio / UI / world-sourced design
- `concept/disturbance` — The disturbance mechanic thread (Article X)
- `concept/ephemeral-world` — Run-reset, transient worlds (Article IV Rules 6–7)
- `concept/governance` — Constitutional and governance concepts
- `concept/horror` — Horror register and dread design
- `concept/procedural` — Procedural generation, seed determinism
- `concept/rendering` — Visual rendering quality, shader correctness, Terrain3D integration, mesh fidelity, LOD, Z-fighting
- `concept/terrain` — Terrain generation, heightmap, Terrain3D regions, roughness, playability constraints
ember's answer for tag_assignment-decisions-garage-map-shows-previous-run, status/reviewedP(true) placed on the no, unsure, and yes zones.nounsureyesgold: yesP = 0.19

tag_assignment-discoveries-spec-157-two-damage-paths-to-tires: layer/gdscript

Tag assignment · test
Gold
The note calls for `layer/gdscript`: GDScript (Godot scene-tier logic) (True)
ember
The note has no reason to carry `layer/gdscript` (False)
Signal
P(true) 0.32 (unsure)
Kit outcome
deferred: treated as unsure
Why this gold label
Mined from Discoveries/Spec 157 — Two Damage Paths to Tires.md at 692f4bb58b7f62105aeb73fba8dfee12bfdecd53; gold is the note's own vocabulary tags.
Spec 157 — Two Damage Paths to Tires

The tire damage system has two independent damage paths that both target tire panels. Adding spawn protection at only the catastrophic-impact level (tire_damage_driver) left the normal damage path unguarded, requiring a second grace at the collision processing level.

## Discovery — Dual Damage Paths to Tires

**Context**: When the player reported losing wheels on spawn, the initial fix added a `spawn_grace_frames` counter to `tire_damage_driver.gd` that suppressed the catastrophic tire-detachment check (`_on_bus_collision`) during the initial settling period. The fix did not prevent wheel loss.

**Discovery**: Tire panels can be destroyed through two independent code paths from a single collision event:

1. **Catastrophic path**: `samba_bus.gd` emits `Events.bus_collision`, which triggers `tire_damage_driver._on_bus_collision`. If force exceeds `catastrophic_force_threshold` (15000) within `_CATASTROPHIC_PROXIMITY` (1.5 m) of a tire, the tire is instantly DETACHED via `panel.take_damage(panel.current_health)`.

2. **Normal damage path**: `samba_bus.gd` calls `_damage_system.apply_damage_at_point(max_force, max_force_position)`, which finds the nearest 1-3 panels to the impact point and applies `damage_amount = force * FORCE_TO_DAMAGE_SCALE`. If a tire is the nearest panel (e.g., the bus lands on a wheel), it receives the full scaled damage — enough to destroy an 80 HP tire from a 16000N+ settling impact.

The first fix only suppressed path 1. The spawn-settling impact was still destroying tires through path 2.

**Resolution**: A two-tier grace approach was needed:
- Tier 1 (`samba_bus.gd`, `_settling_grace_remaining`): Suppresses `apply_damage_at_point` entirely for 90 frames after spawn stabilization ends. `Events.bus_collision` still fires (for the tire driver to track) but damage application and disturbance are skipped.
- Tier 2 (`tire_damage_driver.gd`, `_spawn_grace_remaining`): Longer 300-frame safety net that suppresses catastrophic tire detachment as a fallback if Tier 1 expires before the bus has fully settled.

The two tiers are independent and redundant — tier 1 is the primary defense, tier 2 is insurance against late bounces or edge cases.

## Implications

- Any future modification to spawn behavior or collision processing must account for both damage paths.
- A grace period at the bus level (`_process_collisions`) is the correct place to suppress all spawn-time damage, because both paths originate from the same collision processing call.
- The tire-level grace alone is insufficient for spawn protection but remains useful as a safety net against the catastrophic path specifically.

## References

- `src/scripts/bus/samba_bus.gd` — `_process_collisions` (line 224-230), `_settling_grace_remaining` (line 62)
- `src/scripts/bus/tire_damage_driver.gd` — `_on_bus_collision` (line 421-425), `_spawn_grace_remaining` (line 48)
- `src/scripts/bus/bus_damage_system.gd` — `apply_damage_at_point` (line 174-183)

Controlled tag vocabulary (as read):
type/*:
- `type/code` — Code architecture, autoloads, conventions, tooling. Carries `code-refs:`. (e.g. `Code/Autoloads — Disturbance.md`)
- `type/decision` — Architectural or design decision made by an agent during a session. Written to `docs/vault/Decisions/`. (Agent notes only — spec 080.)
- `type/design` — Design intent, player-facing concepts, world lore. (e.g. `Design/World Model.md`)
- `type/discovery` — Non-obvious constraint, gap, or conflict found by an agent during a session. Written to `docs/vault/Discoveries/`. (Agent notes only — spec 080.)
- `type/moc` — Map of Content at any of three tiers (folder / domain / concept). (e.g. `Audio.md`)
- `type/principle` — Governance and constitutional notes. Non-negotiable rules. (e.g. `Governance/Constitution.md`)
- `type/reference` — Glossary, decision log, open questions, epics. (e.g. `Reference/Glossary.md`)
- `type/session-log` — Session activity log; permanent audit trail. Written to `docs/vault/Sessions/`. Append-only, never pruned. (Agent notes only — spec 080.)
- `type/spec` — Spec document at `docs/vault/Specs/NNN Title/spec.md`. Carries `spec-refs:`. (e.g. `Specs/047 Car Radio/spec.md`)
- `type/system` — A bounded subsystem with implementation. Carries `code-refs`, `spec-refs`, `implements:` frontmatter. (e.g. `Systems/Audio — Car Radio.md`)
- `type/vision` — Strategic / vision-layer decision. Written to `docs/vault/Vision/`. Human-authored or agent-proposed with human ratification before promotion to `status: reviewed`. (Per triage #3 — spec 133 autonomous-company redesign.)
domain/*:
- `domain/anomalies` — Anomaly taxonomy, individual anomaly systems, spawn, behavior
- `domain/art` — Visual direction, palettes, references, asset pipeline
- `domain/audio` — Audio systems: world ambient, radio, transmissions, buses, pipeline
- `domain/autonomous-company` — Autonomous company v0.1 experiment: Slack infra, persona middleware, Letta integration, restart recovery
- `domain/build` — Build system, packaging, export, release automation
- `domain/governance` — Constitution, phased spec, policies
- `domain/infrastructure` — Infrastructure provisioning: CI/CD, hosting, deployment tooling, secrets management
- `domain/narrative` — Tone, horror register, forest transmissions narrative, Gary/KTLK
- `domain/player` — Player mode, input, controls, camera, exit/entry
- `domain/systems` — Cross-cutting system architecture and integration work
- `domain/tooling` — Build, CI, observer, TTS pipeline, dev-time tools
- `domain/vehicle` — The Samba: vehicle physics, dashboard, damage, panels
- `domain/world` — World model, biomes, terrain, procedural generation, weather
status/*:
- `status/canonical` — Fully authoritative; promoted by humans only. Highest trust. (Agent notes only — spec 080.)
- `status/draft` — Authoring in progress, not yet verified
- `status/reviewed` — Agent-created note verified against codebase within its creating session. Eligible for auto-injection in subsequent task dispatches. (Agent notes only — spec 080.)
- `status/stale` — Known out of date; cannot update immediately. Pairs with `> [!warning] STALE — needs update` callout.
- `status/superseded` — Replaced by another note. Terminal state. Pairs with `> [!warning] SUPERSEDED` callout.
- `status/wip` — Stable but under active revision
layer/*:
- `layer/content` — Content assets (audio, models, textures, audio provenance)
- `layer/gdext` — gdext wrapper layer (`rust/gdext-wrapper/`)
- `layer/gdscript` — GDScript (Godot scene-tier logic)
- `layer/infra` — Build, CI, deployment infrastructure
- `layer/python` — Python development tooling (`tools/`)
- `layer/rust-core` — Engine-agnostic Rust core (`rust/rust-core/`)
concept/*:
- `concept/biome` — Biome-reactive behavior across systems
- `concept/contamination` — Across-runs panel and garage degradation; the slow-horror mechanic that doesn't reset with the world
- `concept/diegetic` — Diegetic audio / UI / world-sourced design
- `concept/disturbance` — The disturbance mechanic thread (Article X)
- `concept/ephemeral-world` — Run-reset, transient worlds (Article IV Rules 6–7)
- `concept/governance` — Constitutional and governance concepts
- `concept/horror` — Horror register and dread design
- `concept/procedural` — Procedural generation, seed determinism
- `concept/rendering` — Visual rendering quality, shader correctness, Terrain3D integration, mesh fidelity, LOD, Z-fighting
- `concept/terrain` — Terrain generation, heightmap, Terrain3D regions, roughness, playability constraints
ember's answer for tag_assignment-discoveries-spec-157-two-damage-paths-to-tires, layer/gdscriptP(true) placed on the no, unsure, and yes zones.nounsureyesgold: yesP = 0.32

tag_assignment-discoveries-spec-157-two-damage-paths-to-tires: type/code

Tag assignment · test
Gold
The note has no reason to carry `type/code` (False)
ember
The note calls for `type/code`: Code architecture, autoloads, conventions, tooling. Carries `code-refs:`. (e.g. `Code/Autoloads — Disturbance.md`) (True)
Signal
P(true) 0.57 (unsure)
Kit outcome
deferred: treated as unsure
Why this gold label
Mined from Discoveries/Spec 157 — Two Damage Paths to Tires.md at 692f4bb58b7f62105aeb73fba8dfee12bfdecd53; gold is the note's own vocabulary tags.
Spec 157 — Two Damage Paths to Tires

The tire damage system has two independent damage paths that both target tire panels. Adding spawn protection at only the catastrophic-impact level (tire_damage_driver) left the normal damage path unguarded, requiring a second grace at the collision processing level.

## Discovery — Dual Damage Paths to Tires

**Context**: When the player reported losing wheels on spawn, the initial fix added a `spawn_grace_frames` counter to `tire_damage_driver.gd` that suppressed the catastrophic tire-detachment check (`_on_bus_collision`) during the initial settling period. The fix did not prevent wheel loss.

**Discovery**: Tire panels can be destroyed through two independent code paths from a single collision event:

1. **Catastrophic path**: `samba_bus.gd` emits `Events.bus_collision`, which triggers `tire_damage_driver._on_bus_collision`. If force exceeds `catastrophic_force_threshold` (15000) within `_CATASTROPHIC_PROXIMITY` (1.5 m) of a tire, the tire is instantly DETACHED via `panel.take_damage(panel.current_health)`.

2. **Normal damage path**: `samba_bus.gd` calls `_damage_system.apply_damage_at_point(max_force, max_force_position)`, which finds the nearest 1-3 panels to the impact point and applies `damage_amount = force * FORCE_TO_DAMAGE_SCALE`. If a tire is the nearest panel (e.g., the bus lands on a wheel), it receives the full scaled damage — enough to destroy an 80 HP tire from a 16000N+ settling impact.

The first fix only suppressed path 1. The spawn-settling impact was still destroying tires through path 2.

**Resolution**: A two-tier grace approach was needed:
- Tier 1 (`samba_bus.gd`, `_settling_grace_remaining`): Suppresses `apply_damage_at_point` entirely for 90 frames after spawn stabilization ends. `Events.bus_collision` still fires (for the tire driver to track) but damage application and disturbance are skipped.
- Tier 2 (`tire_damage_driver.gd`, `_spawn_grace_remaining`): Longer 300-frame safety net that suppresses catastrophic tire detachment as a fallback if Tier 1 expires before the bus has fully settled.

The two tiers are independent and redundant — tier 1 is the primary defense, tier 2 is insurance against late bounces or edge cases.

## Implications

- Any future modification to spawn behavior or collision processing must account for both damage paths.
- A grace period at the bus level (`_process_collisions`) is the correct place to suppress all spawn-time damage, because both paths originate from the same collision processing call.
- The tire-level grace alone is insufficient for spawn protection but remains useful as a safety net against the catastrophic path specifically.

## References

- `src/scripts/bus/samba_bus.gd` — `_process_collisions` (line 224-230), `_settling_grace_remaining` (line 62)
- `src/scripts/bus/tire_damage_driver.gd` — `_on_bus_collision` (line 421-425), `_spawn_grace_remaining` (line 48)
- `src/scripts/bus/bus_damage_system.gd` — `apply_damage_at_point` (line 174-183)

Controlled tag vocabulary (as read):
type/*:
- `type/code` — Code architecture, autoloads, conventions, tooling. Carries `code-refs:`. (e.g. `Code/Autoloads — Disturbance.md`)
- `type/decision` — Architectural or design decision made by an agent during a session. Written to `docs/vault/Decisions/`. (Agent notes only — spec 080.)
- `type/design` — Design intent, player-facing concepts, world lore. (e.g. `Design/World Model.md`)
- `type/discovery` — Non-obvious constraint, gap, or conflict found by an agent during a session. Written to `docs/vault/Discoveries/`. (Agent notes only — spec 080.)
- `type/moc` — Map of Content at any of three tiers (folder / domain / concept). (e.g. `Audio.md`)
- `type/principle` — Governance and constitutional notes. Non-negotiable rules. (e.g. `Governance/Constitution.md`)
- `type/reference` — Glossary, decision log, open questions, epics. (e.g. `Reference/Glossary.md`)
- `type/session-log` — Session activity log; permanent audit trail. Written to `docs/vault/Sessions/`. Append-only, never pruned. (Agent notes only — spec 080.)
- `type/spec` — Spec document at `docs/vault/Specs/NNN Title/spec.md`. Carries `spec-refs:`. (e.g. `Specs/047 Car Radio/spec.md`)
- `type/system` — A bounded subsystem with implementation. Carries `code-refs`, `spec-refs`, `implements:` frontmatter. (e.g. `Systems/Audio — Car Radio.md`)
- `type/vision` — Strategic / vision-layer decision. Written to `docs/vault/Vision/`. Human-authored or agent-proposed with human ratification before promotion to `status: reviewed`. (Per triage #3 — spec 133 autonomous-company redesign.)
domain/*:
- `domain/anomalies` — Anomaly taxonomy, individual anomaly systems, spawn, behavior
- `domain/art` — Visual direction, palettes, references, asset pipeline
- `domain/audio` — Audio systems: world ambient, radio, transmissions, buses, pipeline
- `domain/autonomous-company` — Autonomous company v0.1 experiment: Slack infra, persona middleware, Letta integration, restart recovery
- `domain/build` — Build system, packaging, export, release automation
- `domain/governance` — Constitution, phased spec, policies
- `domain/infrastructure` — Infrastructure provisioning: CI/CD, hosting, deployment tooling, secrets management
- `domain/narrative` — Tone, horror register, forest transmissions narrative, Gary/KTLK
- `domain/player` — Player mode, input, controls, camera, exit/entry
- `domain/systems` — Cross-cutting system architecture and integration work
- `domain/tooling` — Build, CI, observer, TTS pipeline, dev-time tools
- `domain/vehicle` — The Samba: vehicle physics, dashboard, damage, panels
- `domain/world` — World model, biomes, terrain, procedural generation, weather
status/*:
- `status/canonical` — Fully authoritative; promoted by humans only. Highest trust. (Agent notes only — spec 080.)
- `status/draft` — Authoring in progress, not yet verified
- `status/reviewed` — Agent-created note verified against codebase within its creating session. Eligible for auto-injection in subsequent task dispatches. (Agent notes only — spec 080.)
- `status/stale` — Known out of date; cannot update immediately. Pairs with `> [!warning] STALE — needs update` callout.
- `status/superseded` — Replaced by another note. Terminal state. Pairs with `> [!warning] SUPERSEDED` callout.
- `status/wip` — Stable but under active revision
layer/*:
- `layer/content` — Content assets (audio, models, textures, audio provenance)
- `layer/gdext` — gdext wrapper layer (`rust/gdext-wrapper/`)
- `layer/gdscript` — GDScript (Godot scene-tier logic)
- `layer/infra` — Build, CI, deployment infrastructure
- `layer/python` — Python development tooling (`tools/`)
- `layer/rust-core` — Engine-agnostic Rust core (`rust/rust-core/`)
concept/*:
- `concept/biome` — Biome-reactive behavior across systems
- `concept/contamination` — Across-runs panel and garage degradation; the slow-horror mechanic that doesn't reset with the world
- `concept/diegetic` — Diegetic audio / UI / world-sourced design
- `concept/disturbance` — The disturbance mechanic thread (Article X)
- `concept/ephemeral-world` — Run-reset, transient worlds (Article IV Rules 6–7)
- `concept/governance` — Constitutional and governance concepts
- `concept/horror` — Horror register and dread design
- `concept/procedural` — Procedural generation, seed determinism
- `concept/rendering` — Visual rendering quality, shader correctness, Terrain3D integration, mesh fidelity, LOD, Z-fighting
- `concept/terrain` — Terrain generation, heightmap, Terrain3D regions, roughness, playability constraints
ember's answer for tag_assignment-discoveries-spec-157-two-damage-paths-to-tires, type/codeP(true) placed on the no, unsure, and yes zones.nounsureyesgold: noP = 0.57

tag_assignment-discoveries-spec-157-two-damage-paths-to-tires: type/spec

Tag assignment · test
Gold
The note has no reason to carry `type/spec` (False)
ember
The note calls for `type/spec`: Spec document at `docs/vault/Specs/NNN Title/spec.md`. Carries `spec-refs:`. (e.g. `Specs/047 Car Radio/spec.md`) (True)
Signal
P(true) 0.83 (yes)
Kit outcome
acted on a wrong answer
Why this gold label
Mined from Discoveries/Spec 157 — Two Damage Paths to Tires.md at 692f4bb58b7f62105aeb73fba8dfee12bfdecd53; gold is the note's own vocabulary tags.
Spec 157 — Two Damage Paths to Tires

The tire damage system has two independent damage paths that both target tire panels. Adding spawn protection at only the catastrophic-impact level (tire_damage_driver) left the normal damage path unguarded, requiring a second grace at the collision processing level.

## Discovery — Dual Damage Paths to Tires

**Context**: When the player reported losing wheels on spawn, the initial fix added a `spawn_grace_frames` counter to `tire_damage_driver.gd` that suppressed the catastrophic tire-detachment check (`_on_bus_collision`) during the initial settling period. The fix did not prevent wheel loss.

**Discovery**: Tire panels can be destroyed through two independent code paths from a single collision event:

1. **Catastrophic path**: `samba_bus.gd` emits `Events.bus_collision`, which triggers `tire_damage_driver._on_bus_collision`. If force exceeds `catastrophic_force_threshold` (15000) within `_CATASTROPHIC_PROXIMITY` (1.5 m) of a tire, the tire is instantly DETACHED via `panel.take_damage(panel.current_health)`.

2. **Normal damage path**: `samba_bus.gd` calls `_damage_system.apply_damage_at_point(max_force, max_force_position)`, which finds the nearest 1-3 panels to the impact point and applies `damage_amount = force * FORCE_TO_DAMAGE_SCALE`. If a tire is the nearest panel (e.g., the bus lands on a wheel), it receives the full scaled damage — enough to destroy an 80 HP tire from a 16000N+ settling impact.

The first fix only suppressed path 1. The spawn-settling impact was still destroying tires through path 2.

**Resolution**: A two-tier grace approach was needed:
- Tier 1 (`samba_bus.gd`, `_settling_grace_remaining`): Suppresses `apply_damage_at_point` entirely for 90 frames after spawn stabilization ends. `Events.bus_collision` still fires (for the tire driver to track) but damage application and disturbance are skipped.
- Tier 2 (`tire_damage_driver.gd`, `_spawn_grace_remaining`): Longer 300-frame safety net that suppresses catastrophic tire detachment as a fallback if Tier 1 expires before the bus has fully settled.

The two tiers are independent and redundant — tier 1 is the primary defense, tier 2 is insurance against late bounces or edge cases.

## Implications

- Any future modification to spawn behavior or collision processing must account for both damage paths.
- A grace period at the bus level (`_process_collisions`) is the correct place to suppress all spawn-time damage, because both paths originate from the same collision processing call.
- The tire-level grace alone is insufficient for spawn protection but remains useful as a safety net against the catastrophic path specifically.

## References

- `src/scripts/bus/samba_bus.gd` — `_process_collisions` (line 224-230), `_settling_grace_remaining` (line 62)
- `src/scripts/bus/tire_damage_driver.gd` — `_on_bus_collision` (line 421-425), `_spawn_grace_remaining` (line 48)
- `src/scripts/bus/bus_damage_system.gd` — `apply_damage_at_point` (line 174-183)

Controlled tag vocabulary (as read):
type/*:
- `type/code` — Code architecture, autoloads, conventions, tooling. Carries `code-refs:`. (e.g. `Code/Autoloads — Disturbance.md`)
- `type/decision` — Architectural or design decision made by an agent during a session. Written to `docs/vault/Decisions/`. (Agent notes only — spec 080.)
- `type/design` — Design intent, player-facing concepts, world lore. (e.g. `Design/World Model.md`)
- `type/discovery` — Non-obvious constraint, gap, or conflict found by an agent during a session. Written to `docs/vault/Discoveries/`. (Agent notes only — spec 080.)
- `type/moc` — Map of Content at any of three tiers (folder / domain / concept). (e.g. `Audio.md`)
- `type/principle` — Governance and constitutional notes. Non-negotiable rules. (e.g. `Governance/Constitution.md`)
- `type/reference` — Glossary, decision log, open questions, epics. (e.g. `Reference/Glossary.md`)
- `type/session-log` — Session activity log; permanent audit trail. Written to `docs/vault/Sessions/`. Append-only, never pruned. (Agent notes only — spec 080.)
- `type/spec` — Spec document at `docs/vault/Specs/NNN Title/spec.md`. Carries `spec-refs:`. (e.g. `Specs/047 Car Radio/spec.md`)
- `type/system` — A bounded subsystem with implementation. Carries `code-refs`, `spec-refs`, `implements:` frontmatter. (e.g. `Systems/Audio — Car Radio.md`)
- `type/vision` — Strategic / vision-layer decision. Written to `docs/vault/Vision/`. Human-authored or agent-proposed with human ratification before promotion to `status: reviewed`. (Per triage #3 — spec 133 autonomous-company redesign.)
domain/*:
- `domain/anomalies` — Anomaly taxonomy, individual anomaly systems, spawn, behavior
- `domain/art` — Visual direction, palettes, references, asset pipeline
- `domain/audio` — Audio systems: world ambient, radio, transmissions, buses, pipeline
- `domain/autonomous-company` — Autonomous company v0.1 experiment: Slack infra, persona middleware, Letta integration, restart recovery
- `domain/build` — Build system, packaging, export, release automation
- `domain/governance` — Constitution, phased spec, policies
- `domain/infrastructure` — Infrastructure provisioning: CI/CD, hosting, deployment tooling, secrets management
- `domain/narrative` — Tone, horror register, forest transmissions narrative, Gary/KTLK
- `domain/player` — Player mode, input, controls, camera, exit/entry
- `domain/systems` — Cross-cutting system architecture and integration work
- `domain/tooling` — Build, CI, observer, TTS pipeline, dev-time tools
- `domain/vehicle` — The Samba: vehicle physics, dashboard, damage, panels
- `domain/world` — World model, biomes, terrain, procedural generation, weather
status/*:
- `status/canonical` — Fully authoritative; promoted by humans only. Highest trust. (Agent notes only — spec 080.)
- `status/draft` — Authoring in progress, not yet verified
- `status/reviewed` — Agent-created note verified against codebase within its creating session. Eligible for auto-injection in subsequent task dispatches. (Agent notes only — spec 080.)
- `status/stale` — Known out of date; cannot update immediately. Pairs with `> [!warning] STALE — needs update` callout.
- `status/superseded` — Replaced by another note. Terminal state. Pairs with `> [!warning] SUPERSEDED` callout.
- `status/wip` — Stable but under active revision
layer/*:
- `layer/content` — Content assets (audio, models, textures, audio provenance)
- `layer/gdext` — gdext wrapper layer (`rust/gdext-wrapper/`)
- `layer/gdscript` — GDScript (Godot scene-tier logic)
- `layer/infra` — Build, CI, deployment infrastructure
- `layer/python` — Python development tooling (`tools/`)
- `layer/rust-core` — Engine-agnostic Rust core (`rust/rust-core/`)
concept/*:
- `concept/biome` — Biome-reactive behavior across systems
- `concept/contamination` — Across-runs panel and garage degradation; the slow-horror mechanic that doesn't reset with the world
- `concept/diegetic` — Diegetic audio / UI / world-sourced design
- `concept/disturbance` — The disturbance mechanic thread (Article X)
- `concept/ephemeral-world` — Run-reset, transient worlds (Article IV Rules 6–7)
- `concept/governance` — Constitutional and governance concepts
- `concept/horror` — Horror register and dread design
- `concept/procedural` — Procedural generation, seed determinism
- `concept/rendering` — Visual rendering quality, shader correctness, Terrain3D integration, mesh fidelity, LOD, Z-fighting
- `concept/terrain` — Terrain generation, heightmap, Terrain3D regions, roughness, playability constraints
ember's answer for tag_assignment-discoveries-spec-157-two-damage-paths-to-tires, type/specP(true) placed on the no, unsure, and yes zones.nounsureyesgold: noP = 0.83

tag_assignment-sessions-dashboard-telemetry-and-model-routing-may-22-2026: domain/tooling

Tag assignment · test
Gold
The note calls for `domain/tooling`: Build, CI, observer, TTS pipeline, dev-time tools (True)
ember
The note has no reason to carry `domain/tooling` (False)
Signal
P(true) 0.08 (no)
Kit outcome
acted on a wrong answer
Why this gold label
Mined from Sessions/Dashboard Telemetry and Model Routing — May 22 2026.md at 692f4bb58b7f62105aeb73fba8dfee12bfdecd53; gold is the note's own vocabulary tags.
Dashboard Telemetry and Model Routing — May 22 2026

This session added model routing visibility to the persona dashboard and closed a critical telemetry gap. The work spanned three layers: a new backend endpoint, dashboard card rendering, and a telemetry wiring fix in the Letta bridge. A significant discovery emerged when the dashboard surfaced GTM's 100% escalation rate.

## Work completed

### GET /health/model-routing endpoint

New JSON endpoint at runtime.py that reads the weekly JSONL telemetry files and classifies each LLM call into a routing tier using a `_MODEL_TIERS` mapping dict. Returns per-persona: total calls and cost, breakdown by tier (cheap/foundational/frontier), breakdown by model, escalation rate (foundational+frontier / total), and a color-coded status indicator (green <=10%, yellow 10-15%, red >15%). Supports `?window=daily|weekly|monthly` query parameter. The endpoint is polled by the dashboard every 10 seconds alongside the existing 15 health endpoints.

### Dashboard Model Routing card

New card rendered in the existing health dashboard at `:9100/dashboard` and `:9101/dashboard`. Shows per-persona escalation rate with status indicator, tier distribution with call counts and percentages, and per-model sub-breakdown with cost. Sits alongside the existing cost card (total spend by model and persona), routing card (inter-agent dispatch stats), API calls card (Prometheus counters), and audit log card.

### Letta bridge telemetry

Before this session, `record_llm_call()` in telemetry.py was only called from `llm.py`, which is orphaned — the runtime uses Letta for all LLM calls, not the direct dispatch in `llm.py`. This meant the weekly JSONL files at `logs/personas/{persona}/weekly/{iso-week}.jsonl` were never populated, and the new `/health/model-routing` endpoint returned empty data.

Fixed by adding a lazy import of `record_llm_call` in `letta_bridge.py:send_to_letta()`. After each successful Letta API call, the function extracts usage data (prompt tokens, completion tokens) from the response, resolves the agent model from the Letta agent config (cached in a module-level dict), estimates cost using a per-model pricing map, and calls `record_llm_call()`. The OTel span emission fails silently if the collector is unavailable — the weekly JSONL write and Prometheus counters are the primary telemetry path.

A `_resolve_agent_model()` helper queries the Letta agent's `model` field on first call for each agent_id and caches the result. An `_estimate_cost()` function maps model names to per-million-token rates (input, output) from a dict keyed by short model name.

### model tier mapping expansion

The `_MODEL_TIERS` dict in runtime.py was expanded to cover both bare model names (`openai/gpt-4o-mini`) and openrouter-prefixed variants (`openrouter/openai/gpt-4o-mini`) since Letta returns the full handle. Also added `openrouter/anthropic/claude-sonnet-4` mapping to `foundational` tier.

## Discovery: GTM on Sonnet for 12 days

When the dashboard first showed the Model Routing card, the GTM persona displayed a 100% escalation rate — every call was routed through `openrouter/anthropic/claude-sonnet-4` (foundational tier) instead of a cheap-tier model. Investigation revealed:

- The GTM Letta agent was created on 2026-05-10 with `claude-sonnet-4` as its default model
- The cheap-tier-default routing strategy was ratified in `Autonomous Company LLM Provider Selection` on 2026-05-08 — two days before the agent was created
- The routing layer that would enforce model selection (backlog item 28) was never implemented
- The dashboard that would surface escalation rates did not exist until this session
- The telemetry that would show the cost discrepancy was not wired until this session

The GTM agent's model was updated to `openrouter/openai/gpt-4o-mini` via the Letta API during this session. The 3 historic Sonnet calls remain in the weekly JSONL and will roll off as new cheap-tier calls accumulate. At $0.15/M input vs $3.00/M input, the GTM was operating at 20x the expected cost for its entire lifetime.

Root cause: the design was ratified but never enforced. Three separate gaps — no routing layer, no visibility dashboard, no telemetry — all had to exist simultaneously for the misconfiguration to persist undetected for 12 days. Closing any one of them would have caught it.

### Backlog items enriched

Items 25 (Intra-Session Persona Cost Telemetry), 28 (Cheap-Tier Routing Layer Spec), and 29 (Foundational-Escalation Tag Protocol) were enriched with concrete implementation context from this session, including file paths to modify, the `MODEL_DEFAULT` discrepancy in `llm.py`, the discovery that `llm.py` is orphaned, and the GTM-on-Sonnet lesson.

## References

- `personas/runtime.py` — `/health/model-routing` endpoint, `_MODEL_TIERS`, dashboard Model Routing card
- `personas/letta_bridge.py` — `send_to_letta()` now calls `record_llm_call()`, `_resolve_agent_model()`, `_estimate_cost()`
- `personas/telemetry.py` — `record_llm_call()`, `_record_weekly_summary()`
- `personas/llm.py` — orphaned routing layer with `MODEL_DEFAULT` discrepancy
- `docs/vault/Reference/Autonomous Company/Backlog.md` — items 25, 28, 29 enriched
- `docs/vault/Reference/Autonomous Company/Autonomous Company Architecture.md` — status table updated

Controlled tag vocabulary (as read):
type/*:
- `type/code` — Code architecture, autoloads, conventions, tooling. Carries `code-refs:`. (e.g. `Code/Autoloads — Disturbance.md`)
- `type/decision` — Architectural or design decision made by an agent during a session. Written to `docs/vault/Decisions/`. (Agent notes only — spec 080.)
- `type/design` — Design intent, player-facing concepts, world lore. (e.g. `Design/World Model.md`)
- `type/discovery` — Non-obvious constraint, gap, or conflict found by an agent during a session. Written to `docs/vault/Discoveries/`. (Agent notes only — spec 080.)
- `type/moc` — Map of Content at any of three tiers (folder / domain / concept). (e.g. `Audio.md`)
- `type/principle` — Governance and constitutional notes. Non-negotiable rules. (e.g. `Governance/Constitution.md`)
- `type/reference` — Glossary, decision log, open questions, epics. (e.g. `Reference/Glossary.md`)
- `type/session-log` — Session activity log; permanent audit trail. Written to `docs/vault/Sessions/`. Append-only, never pruned. (Agent notes only — spec 080.)
- `type/spec` — Spec document at `docs/vault/Specs/NNN Title/spec.md`. Carries `spec-refs:`. (e.g. `Specs/047 Car Radio/spec.md`)
- `type/system` — A bounded subsystem with implementation. Carries `code-refs`, `spec-refs`, `implements:` frontmatter. (e.g. `Systems/Audio — Car Radio.md`)
- `type/vision` — Strategic / vision-layer decision. Written to `docs/vault/Vision/`. Human-authored or agent-proposed with human ratification before promotion to `status: reviewed`. (Per triage #3 — spec 133 autonomous-company redesign.)
domain/*:
- `domain/anomalies` — Anomaly taxonomy, individual anomaly systems, spawn, behavior
- `domain/art` — Visual direction, palettes, references, asset pipeline
- `domain/audio` — Audio systems: world ambient, radio, transmissions, buses, pipeline
- `domain/autonomous-company` — Autonomous company v0.1 experiment: Slack infra, persona middleware, Letta integration, restart recovery
- `domain/build` — Build system, packaging, export, release automation
- `domain/governance` — Constitution, phased spec, policies
- `domain/infrastructure` — Infrastructure provisioning: CI/CD, hosting, deployment tooling, secrets management
- `domain/narrative` — Tone, horror register, forest transmissions narrative, Gary/KTLK
- `domain/player` — Player mode, input, controls, camera, exit/entry
- `domain/systems` — Cross-cutting system architecture and integration work
- `domain/tooling` — Build, CI, observer, TTS pipeline, dev-time tools
- `domain/vehicle` — The Samba: vehicle physics, dashboard, damage, panels
- `domain/world` — World model, biomes, terrain, procedural generation, weather
status/*:
- `status/canonical` — Fully authoritative; promoted by humans only. Highest trust. (Agent notes only — spec 080.)
- `status/draft` — Authoring in progress, not yet verified
- `status/reviewed` — Agent-created note verified against codebase within its creating session. Eligible for auto-injection in subsequent task dispatches. (Agent notes only — spec 080.)
- `status/stale` — Known out of date; cannot update immediately. Pairs with `> [!warning] STALE — needs update` callout.
- `status/superseded` — Replaced by another note. Terminal state. Pairs with `> [!warning] SUPERSEDED` callout.
- `status/wip` — Stable but under active revision
layer/*:
- `layer/content` — Content assets (audio, models, textures, audio provenance)
- `layer/gdext` — gdext wrapper layer (`rust/gdext-wrapper/`)
- `layer/gdscript` — GDScript (Godot scene-tier logic)
- `layer/infra` — Build, CI, deployment infrastructure
- `layer/python` — Python development tooling (`tools/`)
- `layer/rust-core` — Engine-agnostic Rust core (`rust/rust-core/`)
concept/*:
- `concept/biome` — Biome-reactive behavior across systems
- `concept/contamination` — Across-runs panel and garage degradation; the slow-horror mechanic that doesn't reset with the world
- `concept/diegetic` — Diegetic audio / UI / world-sourced design
- `concept/disturbance` — The disturbance mechanic thread (Article X)
- `concept/ephemeral-world` — Run-reset, transient worlds (Article IV Rules 6–7)
- `concept/governance` — Constitutional and governance concepts
- `concept/horror` — Horror register and dread design
- `concept/procedural` — Procedural generation, seed determinism
- `concept/rendering` — Visual rendering quality, shader correctness, Terrain3D integration, mesh fidelity, LOD, Z-fighting
- `concept/terrain` — Terrain generation, heightmap, Terrain3D regions, roughness, playability constraints
ember's answer for tag_assignment-sessions-dashboard-telemetry-and-model-routing-may-22-2026, domain/toolingP(true) placed on the no, unsure, and yes zones.nounsureyesgold: yesP = 0.08

tag_assignment-sessions-dashboard-telemetry-and-model-routing-may-22-2026: type/code

Tag assignment · test
Gold
The note has no reason to carry `type/code` (False)
ember
The note calls for `type/code`: Code architecture, autoloads, conventions, tooling. Carries `code-refs:`. (e.g. `Code/Autoloads — Disturbance.md`) (True)
Signal
P(true) 0.69 (unsure)
Kit outcome
deferred: treated as unsure
Why this gold label
Mined from Sessions/Dashboard Telemetry and Model Routing — May 22 2026.md at 692f4bb58b7f62105aeb73fba8dfee12bfdecd53; gold is the note's own vocabulary tags.
Dashboard Telemetry and Model Routing — May 22 2026

This session added model routing visibility to the persona dashboard and closed a critical telemetry gap. The work spanned three layers: a new backend endpoint, dashboard card rendering, and a telemetry wiring fix in the Letta bridge. A significant discovery emerged when the dashboard surfaced GTM's 100% escalation rate.

## Work completed

### GET /health/model-routing endpoint

New JSON endpoint at runtime.py that reads the weekly JSONL telemetry files and classifies each LLM call into a routing tier using a `_MODEL_TIERS` mapping dict. Returns per-persona: total calls and cost, breakdown by tier (cheap/foundational/frontier), breakdown by model, escalation rate (foundational+frontier / total), and a color-coded status indicator (green <=10%, yellow 10-15%, red >15%). Supports `?window=daily|weekly|monthly` query parameter. The endpoint is polled by the dashboard every 10 seconds alongside the existing 15 health endpoints.

### Dashboard Model Routing card

New card rendered in the existing health dashboard at `:9100/dashboard` and `:9101/dashboard`. Shows per-persona escalation rate with status indicator, tier distribution with call counts and percentages, and per-model sub-breakdown with cost. Sits alongside the existing cost card (total spend by model and persona), routing card (inter-agent dispatch stats), API calls card (Prometheus counters), and audit log card.

### Letta bridge telemetry

Before this session, `record_llm_call()` in telemetry.py was only called from `llm.py`, which is orphaned — the runtime uses Letta for all LLM calls, not the direct dispatch in `llm.py`. This meant the weekly JSONL files at `logs/personas/{persona}/weekly/{iso-week}.jsonl` were never populated, and the new `/health/model-routing` endpoint returned empty data.

Fixed by adding a lazy import of `record_llm_call` in `letta_bridge.py:send_to_letta()`. After each successful Letta API call, the function extracts usage data (prompt tokens, completion tokens) from the response, resolves the agent model from the Letta agent config (cached in a module-level dict), estimates cost using a per-model pricing map, and calls `record_llm_call()`. The OTel span emission fails silently if the collector is unavailable — the weekly JSONL write and Prometheus counters are the primary telemetry path.

A `_resolve_agent_model()` helper queries the Letta agent's `model` field on first call for each agent_id and caches the result. An `_estimate_cost()` function maps model names to per-million-token rates (input, output) from a dict keyed by short model name.

### model tier mapping expansion

The `_MODEL_TIERS` dict in runtime.py was expanded to cover both bare model names (`openai/gpt-4o-mini`) and openrouter-prefixed variants (`openrouter/openai/gpt-4o-mini`) since Letta returns the full handle. Also added `openrouter/anthropic/claude-sonnet-4` mapping to `foundational` tier.

## Discovery: GTM on Sonnet for 12 days

When the dashboard first showed the Model Routing card, the GTM persona displayed a 100% escalation rate — every call was routed through `openrouter/anthropic/claude-sonnet-4` (foundational tier) instead of a cheap-tier model. Investigation revealed:

- The GTM Letta agent was created on 2026-05-10 with `claude-sonnet-4` as its default model
- The cheap-tier-default routing strategy was ratified in `Autonomous Company LLM Provider Selection` on 2026-05-08 — two days before the agent was created
- The routing layer that would enforce model selection (backlog item 28) was never implemented
- The dashboard that would surface escalation rates did not exist until this session
- The telemetry that would show the cost discrepancy was not wired until this session

The GTM agent's model was updated to `openrouter/openai/gpt-4o-mini` via the Letta API during this session. The 3 historic Sonnet calls remain in the weekly JSONL and will roll off as new cheap-tier calls accumulate. At $0.15/M input vs $3.00/M input, the GTM was operating at 20x the expected cost for its entire lifetime.

Root cause: the design was ratified but never enforced. Three separate gaps — no routing layer, no visibility dashboard, no telemetry — all had to exist simultaneously for the misconfiguration to persist undetected for 12 days. Closing any one of them would have caught it.

### Backlog items enriched

Items 25 (Intra-Session Persona Cost Telemetry), 28 (Cheap-Tier Routing Layer Spec), and 29 (Foundational-Escalation Tag Protocol) were enriched with concrete implementation context from this session, including file paths to modify, the `MODEL_DEFAULT` discrepancy in `llm.py`, the discovery that `llm.py` is orphaned, and the GTM-on-Sonnet lesson.

## References

- `personas/runtime.py` — `/health/model-routing` endpoint, `_MODEL_TIERS`, dashboard Model Routing card
- `personas/letta_bridge.py` — `send_to_letta()` now calls `record_llm_call()`, `_resolve_agent_model()`, `_estimate_cost()`
- `personas/telemetry.py` — `record_llm_call()`, `_record_weekly_summary()`
- `personas/llm.py` — orphaned routing layer with `MODEL_DEFAULT` discrepancy
- `docs/vault/Reference/Autonomous Company/Backlog.md` — items 25, 28, 29 enriched
- `docs/vault/Reference/Autonomous Company/Autonomous Company Architecture.md` — status table updated

Controlled tag vocabulary (as read):
type/*:
- `type/code` — Code architecture, autoloads, conventions, tooling. Carries `code-refs:`. (e.g. `Code/Autoloads — Disturbance.md`)
- `type/decision` — Architectural or design decision made by an agent during a session. Written to `docs/vault/Decisions/`. (Agent notes only — spec 080.)
- `type/design` — Design intent, player-facing concepts, world lore. (e.g. `Design/World Model.md`)
- `type/discovery` — Non-obvious constraint, gap, or conflict found by an agent during a session. Written to `docs/vault/Discoveries/`. (Agent notes only — spec 080.)
- `type/moc` — Map of Content at any of three tiers (folder / domain / concept). (e.g. `Audio.md`)
- `type/principle` — Governance and constitutional notes. Non-negotiable rules. (e.g. `Governance/Constitution.md`)
- `type/reference` — Glossary, decision log, open questions, epics. (e.g. `Reference/Glossary.md`)
- `type/session-log` — Session activity log; permanent audit trail. Written to `docs/vault/Sessions/`. Append-only, never pruned. (Agent notes only — spec 080.)
- `type/spec` — Spec document at `docs/vault/Specs/NNN Title/spec.md`. Carries `spec-refs:`. (e.g. `Specs/047 Car Radio/spec.md`)
- `type/system` — A bounded subsystem with implementation. Carries `code-refs`, `spec-refs`, `implements:` frontmatter. (e.g. `Systems/Audio — Car Radio.md`)
- `type/vision` — Strategic / vision-layer decision. Written to `docs/vault/Vision/`. Human-authored or agent-proposed with human ratification before promotion to `status: reviewed`. (Per triage #3 — spec 133 autonomous-company redesign.)
domain/*:
- `domain/anomalies` — Anomaly taxonomy, individual anomaly systems, spawn, behavior
- `domain/art` — Visual direction, palettes, references, asset pipeline
- `domain/audio` — Audio systems: world ambient, radio, transmissions, buses, pipeline
- `domain/autonomous-company` — Autonomous company v0.1 experiment: Slack infra, persona middleware, Letta integration, restart recovery
- `domain/build` — Build system, packaging, export, release automation
- `domain/governance` — Constitution, phased spec, policies
- `domain/infrastructure` — Infrastructure provisioning: CI/CD, hosting, deployment tooling, secrets management
- `domain/narrative` — Tone, horror register, forest transmissions narrative, Gary/KTLK
- `domain/player` — Player mode, input, controls, camera, exit/entry
- `domain/systems` — Cross-cutting system architecture and integration work
- `domain/tooling` — Build, CI, observer, TTS pipeline, dev-time tools
- `domain/vehicle` — The Samba: vehicle physics, dashboard, damage, panels
- `domain/world` — World model, biomes, terrain, procedural generation, weather
status/*:
- `status/canonical` — Fully authoritative; promoted by humans only. Highest trust. (Agent notes only — spec 080.)
- `status/draft` — Authoring in progress, not yet verified
- `status/reviewed` — Agent-created note verified against codebase within its creating session. Eligible for auto-injection in subsequent task dispatches. (Agent notes only — spec 080.)
- `status/stale` — Known out of date; cannot update immediately. Pairs with `> [!warning] STALE — needs update` callout.
- `status/superseded` — Replaced by another note. Terminal state. Pairs with `> [!warning] SUPERSEDED` callout.
- `status/wip` — Stable but under active revision
layer/*:
- `layer/content` — Content assets (audio, models, textures, audio provenance)
- `layer/gdext` — gdext wrapper layer (`rust/gdext-wrapper/`)
- `layer/gdscript` — GDScript (Godot scene-tier logic)
- `layer/infra` — Build, CI, deployment infrastructure
- `layer/python` — Python development tooling (`tools/`)
- `layer/rust-core` — Engine-agnostic Rust core (`rust/rust-core/`)
concept/*:
- `concept/biome` — Biome-reactive behavior across systems
- `concept/contamination` — Across-runs panel and garage degradation; the slow-horror mechanic that doesn't reset with the world
- `concept/diegetic` — Diegetic audio / UI / world-sourced design
- `concept/disturbance` — The disturbance mechanic thread (Article X)
- `concept/ephemeral-world` — Run-reset, transient worlds (Article IV Rules 6–7)
- `concept/governance` — Constitutional and governance concepts
- `concept/horror` — Horror register and dread design
- `concept/procedural` — Procedural generation, seed determinism
- `concept/rendering` — Visual rendering quality, shader correctness, Terrain3D integration, mesh fidelity, LOD, Z-fighting
- `concept/terrain` — Terrain generation, heightmap, Terrain3D regions, roughness, playability constraints
ember's answer for tag_assignment-sessions-dashboard-telemetry-and-model-routing-may-22-2026, type/codeP(true) placed on the no, unsure, and yes zones.nounsureyesgold: noP = 0.69

tag_assignment-sessions-dashboard-telemetry-and-model-routing-may-22-2026: type/discovery

Tag assignment · test
Gold
The note has no reason to carry `type/discovery` (False)
ember
The note calls for `type/discovery`: Non-obvious constraint, gap, or conflict found by an agent during a session. Written to `docs/vault/Discoveries/`. (Agent notes only — spec 080.) (True)
Signal
P(true) 0.55 (unsure)
Kit outcome
deferred: treated as unsure
Why this gold label
Mined from Sessions/Dashboard Telemetry and Model Routing — May 22 2026.md at 692f4bb58b7f62105aeb73fba8dfee12bfdecd53; gold is the note's own vocabulary tags.
Dashboard Telemetry and Model Routing — May 22 2026

This session added model routing visibility to the persona dashboard and closed a critical telemetry gap. The work spanned three layers: a new backend endpoint, dashboard card rendering, and a telemetry wiring fix in the Letta bridge. A significant discovery emerged when the dashboard surfaced GTM's 100% escalation rate.

## Work completed

### GET /health/model-routing endpoint

New JSON endpoint at runtime.py that reads the weekly JSONL telemetry files and classifies each LLM call into a routing tier using a `_MODEL_TIERS` mapping dict. Returns per-persona: total calls and cost, breakdown by tier (cheap/foundational/frontier), breakdown by model, escalation rate (foundational+frontier / total), and a color-coded status indicator (green <=10%, yellow 10-15%, red >15%). Supports `?window=daily|weekly|monthly` query parameter. The endpoint is polled by the dashboard every 10 seconds alongside the existing 15 health endpoints.

### Dashboard Model Routing card

New card rendered in the existing health dashboard at `:9100/dashboard` and `:9101/dashboard`. Shows per-persona escalation rate with status indicator, tier distribution with call counts and percentages, and per-model sub-breakdown with cost. Sits alongside the existing cost card (total spend by model and persona), routing card (inter-agent dispatch stats), API calls card (Prometheus counters), and audit log card.

### Letta bridge telemetry

Before this session, `record_llm_call()` in telemetry.py was only called from `llm.py`, which is orphaned — the runtime uses Letta for all LLM calls, not the direct dispatch in `llm.py`. This meant the weekly JSONL files at `logs/personas/{persona}/weekly/{iso-week}.jsonl` were never populated, and the new `/health/model-routing` endpoint returned empty data.

Fixed by adding a lazy import of `record_llm_call` in `letta_bridge.py:send_to_letta()`. After each successful Letta API call, the function extracts usage data (prompt tokens, completion tokens) from the response, resolves the agent model from the Letta agent config (cached in a module-level dict), estimates cost using a per-model pricing map, and calls `record_llm_call()`. The OTel span emission fails silently if the collector is unavailable — the weekly JSONL write and Prometheus counters are the primary telemetry path.

A `_resolve_agent_model()` helper queries the Letta agent's `model` field on first call for each agent_id and caches the result. An `_estimate_cost()` function maps model names to per-million-token rates (input, output) from a dict keyed by short model name.

### model tier mapping expansion

The `_MODEL_TIERS` dict in runtime.py was expanded to cover both bare model names (`openai/gpt-4o-mini`) and openrouter-prefixed variants (`openrouter/openai/gpt-4o-mini`) since Letta returns the full handle. Also added `openrouter/anthropic/claude-sonnet-4` mapping to `foundational` tier.

## Discovery: GTM on Sonnet for 12 days

When the dashboard first showed the Model Routing card, the GTM persona displayed a 100% escalation rate — every call was routed through `openrouter/anthropic/claude-sonnet-4` (foundational tier) instead of a cheap-tier model. Investigation revealed:

- The GTM Letta agent was created on 2026-05-10 with `claude-sonnet-4` as its default model
- The cheap-tier-default routing strategy was ratified in `Autonomous Company LLM Provider Selection` on 2026-05-08 — two days before the agent was created
- The routing layer that would enforce model selection (backlog item 28) was never implemented
- The dashboard that would surface escalation rates did not exist until this session
- The telemetry that would show the cost discrepancy was not wired until this session

The GTM agent's model was updated to `openrouter/openai/gpt-4o-mini` via the Letta API during this session. The 3 historic Sonnet calls remain in the weekly JSONL and will roll off as new cheap-tier calls accumulate. At $0.15/M input vs $3.00/M input, the GTM was operating at 20x the expected cost for its entire lifetime.

Root cause: the design was ratified but never enforced. Three separate gaps — no routing layer, no visibility dashboard, no telemetry — all had to exist simultaneously for the misconfiguration to persist undetected for 12 days. Closing any one of them would have caught it.

### Backlog items enriched

Items 25 (Intra-Session Persona Cost Telemetry), 28 (Cheap-Tier Routing Layer Spec), and 29 (Foundational-Escalation Tag Protocol) were enriched with concrete implementation context from this session, including file paths to modify, the `MODEL_DEFAULT` discrepancy in `llm.py`, the discovery that `llm.py` is orphaned, and the GTM-on-Sonnet lesson.

## References

- `personas/runtime.py` — `/health/model-routing` endpoint, `_MODEL_TIERS`, dashboard Model Routing card
- `personas/letta_bridge.py` — `send_to_letta()` now calls `record_llm_call()`, `_resolve_agent_model()`, `_estimate_cost()`
- `personas/telemetry.py` — `record_llm_call()`, `_record_weekly_summary()`
- `personas/llm.py` — orphaned routing layer with `MODEL_DEFAULT` discrepancy
- `docs/vault/Reference/Autonomous Company/Backlog.md` — items 25, 28, 29 enriched
- `docs/vault/Reference/Autonomous Company/Autonomous Company Architecture.md` — status table updated

Controlled tag vocabulary (as read):
type/*:
- `type/code` — Code architecture, autoloads, conventions, tooling. Carries `code-refs:`. (e.g. `Code/Autoloads — Disturbance.md`)
- `type/decision` — Architectural or design decision made by an agent during a session. Written to `docs/vault/Decisions/`. (Agent notes only — spec 080.)
- `type/design` — Design intent, player-facing concepts, world lore. (e.g. `Design/World Model.md`)
- `type/discovery` — Non-obvious constraint, gap, or conflict found by an agent during a session. Written to `docs/vault/Discoveries/`. (Agent notes only — spec 080.)
- `type/moc` — Map of Content at any of three tiers (folder / domain / concept). (e.g. `Audio.md`)
- `type/principle` — Governance and constitutional notes. Non-negotiable rules. (e.g. `Governance/Constitution.md`)
- `type/reference` — Glossary, decision log, open questions, epics. (e.g. `Reference/Glossary.md`)
- `type/session-log` — Session activity log; permanent audit trail. Written to `docs/vault/Sessions/`. Append-only, never pruned. (Agent notes only — spec 080.)
- `type/spec` — Spec document at `docs/vault/Specs/NNN Title/spec.md`. Carries `spec-refs:`. (e.g. `Specs/047 Car Radio/spec.md`)
- `type/system` — A bounded subsystem with implementation. Carries `code-refs`, `spec-refs`, `implements:` frontmatter. (e.g. `Systems/Audio — Car Radio.md`)
- `type/vision` — Strategic / vision-layer decision. Written to `docs/vault/Vision/`. Human-authored or agent-proposed with human ratification before promotion to `status: reviewed`. (Per triage #3 — spec 133 autonomous-company redesign.)
domain/*:
- `domain/anomalies` — Anomaly taxonomy, individual anomaly systems, spawn, behavior
- `domain/art` — Visual direction, palettes, references, asset pipeline
- `domain/audio` — Audio systems: world ambient, radio, transmissions, buses, pipeline
- `domain/autonomous-company` — Autonomous company v0.1 experiment: Slack infra, persona middleware, Letta integration, restart recovery
- `domain/build` — Build system, packaging, export, release automation
- `domain/governance` — Constitution, phased spec, policies
- `domain/infrastructure` — Infrastructure provisioning: CI/CD, hosting, deployment tooling, secrets management
- `domain/narrative` — Tone, horror register, forest transmissions narrative, Gary/KTLK
- `domain/player` — Player mode, input, controls, camera, exit/entry
- `domain/systems` — Cross-cutting system architecture and integration work
- `domain/tooling` — Build, CI, observer, TTS pipeline, dev-time tools
- `domain/vehicle` — The Samba: vehicle physics, dashboard, damage, panels
- `domain/world` — World model, biomes, terrain, procedural generation, weather
status/*:
- `status/canonical` — Fully authoritative; promoted by humans only. Highest trust. (Agent notes only — spec 080.)
- `status/draft` — Authoring in progress, not yet verified
- `status/reviewed` — Agent-created note verified against codebase within its creating session. Eligible for auto-injection in subsequent task dispatches. (Agent notes only — spec 080.)
- `status/stale` — Known out of date; cannot update immediately. Pairs with `> [!warning] STALE — needs update` callout.
- `status/superseded` — Replaced by another note. Terminal state. Pairs with `> [!warning] SUPERSEDED` callout.
- `status/wip` — Stable but under active revision
layer/*:
- `layer/content` — Content assets (audio, models, textures, audio provenance)
- `layer/gdext` — gdext wrapper layer (`rust/gdext-wrapper/`)
- `layer/gdscript` — GDScript (Godot scene-tier logic)
- `layer/infra` — Build, CI, deployment infrastructure
- `layer/python` — Python development tooling (`tools/`)
- `layer/rust-core` — Engine-agnostic Rust core (`rust/rust-core/`)
concept/*:
- `concept/biome` — Biome-reactive behavior across systems
- `concept/contamination` — Across-runs panel and garage degradation; the slow-horror mechanic that doesn't reset with the world
- `concept/diegetic` — Diegetic audio / UI / world-sourced design
- `concept/disturbance` — The disturbance mechanic thread (Article X)
- `concept/ephemeral-world` — Run-reset, transient worlds (Article IV Rules 6–7)
- `concept/governance` — Constitutional and governance concepts
- `concept/horror` — Horror register and dread design
- `concept/procedural` — Procedural generation, seed determinism
- `concept/rendering` — Visual rendering quality, shader correctness, Terrain3D integration, mesh fidelity, LOD, Z-fighting
- `concept/terrain` — Terrain generation, heightmap, Terrain3D regions, roughness, playability constraints
ember's answer for tag_assignment-sessions-dashboard-telemetry-and-model-routing-may-22-2026, type/discoveryP(true) placed on the no, unsure, and yes zones.nounsureyesgold: noP = 0.55

tag_assignment-sessions-spec-authoring-session-083-096-apr-23-2026: domain/art

Tag assignment · test
Gold
The note calls for `domain/art`: Visual direction, palettes, references, asset pipeline (True)
ember
The note has no reason to carry `domain/art` (False)
Signal
P(true) 0.05 (no)
Kit outcome
acted on a wrong answer
Why this gold label
Mined from Sessions/Spec Authoring Session — 083-096 Apr 23 2026.md at 692f4bb58b7f62105aeb73fba8dfee12bfdecd53; gold is the note's own vocabulary tags.
Spec Authoring Session — 083-096 Apr 23 2026

This session authored 13 new feature specs for Old Growth (083–087, 089–096), corrected a branch targeting error, and updated the vault with corresponding spec stubs.

## Work Completed

### Spec Creation (088-vault-audit-agent branch)

Fourteen spec directories were created (083–097); all except 088 and 097 (already authored) received full content in this session. The following specs were authored from blank placeholders to complete spec.md files:

| Spec | Title | Lines |
|---|---|---|
| 083 | Atmospheric Splash Screen | 172 |
| 084 | First-Run Experience | 140 |
| 085 | Game Controller Support | 184 |
| 086 | Performance and Stability Testing | 167 |
| 087 | Main Menu Polish | 150 |
| 089 | Crafting Panel and Car Maintenance Abilities | 132 |
| 090 | Car Maintenance System | 169 |
| 091 | Player Abilities System | 148 |
| 092 | Garage Map and Trip Planner | 148 |
| 093 | Player Clothing and Equipment | 149 |
| 094 | Additional Biomes — Meadow and Swamp | 186 |
| 095 | Train Tracks and Abandoned Railways | 132 |
| 096 | Waterways — Lakes and Rivers | 132 |

All specs passed zero-placeholder-hit verification before commit.

### Branch Correction

Spec creation commits initially landed on `main` (two commits: `0c2aaf8`, `f5f7496`). Corrected via cherry-pick onto `088-vault-audit-agent` followed by `git reset --hard origin/main` on main. Both commits are now exclusively on `088-vault-audit-agent` at `80682f6` and `65547b4`.

### Vault Updates

Thirteen spec stubs added to `docs/vault/Specs/` (083–087, 089–096). This session note added. Specs MOC updated.

## Key Design Decisions Captured in Specs

- **083 Splash**: `splash_completed` signal lives on the script, not on `Events` — transient scene, single consumer.
- **084 First-Run**: Fixed seed in a Resource; flag set only on successful extraction.
- **085 Controller**: Rumble is a horror signal tied to disturbance thresholds, not convenience feedback.
- **090 Car Maintenance**: Battery at 0% is the only state that blocks run start; all other systems degrade gracefully.
- **091 Abilities**: Every ability cost is unconditional and structurally separate from its benefit.
- **092 Map**: Shows the *previous* run's world, not the upcoming one — intentional horror design.
- **094 Swamp**: Disturbance "unreliability" is a display offset, not a change to the underlying meter value.
- **096 Waterways**: River ambient audio contributes +0.02/s passive disturbance within 20m.

## References

- `specs/083-atmospheric-splash-screen/spec.md`
- `specs/084-first-run-experience/spec.md`
- `specs/085-game-controller-support/spec.md`
- `specs/086-performance-stability-testing/spec.md`
- `specs/087-main-menu-polish/spec.md`
- `specs/089-crafting-panel/spec.md`
- `specs/090-car-maintenance/spec.md`
- `specs/091-player-abilities/spec.md`
- `specs/092-garage-trip-planner/spec.md`
- `specs/093-player-equipment/spec.md`
- `specs/094-meadow-swamp-biomes/spec.md`
- `specs/095-train-tracks/spec.md`
- `specs/096-water-ways/spec.md`

Controlled tag vocabulary (as read):
type/*:
- `type/code` — Code architecture, autoloads, conventions, tooling. Carries `code-refs:`. (e.g. `Code/Autoloads — Disturbance.md`)
- `type/decision` — Architectural or design decision made by an agent during a session. Written to `docs/vault/Decisions/`. (Agent notes only — spec 080.)
- `type/design` — Design intent, player-facing concepts, world lore. (e.g. `Design/World Model.md`)
- `type/discovery` — Non-obvious constraint, gap, or conflict found by an agent during a session. Written to `docs/vault/Discoveries/`. (Agent notes only — spec 080.)
- `type/moc` — Map of Content at any of three tiers (folder / domain / concept). (e.g. `Audio.md`)
- `type/principle` — Governance and constitutional notes. Non-negotiable rules. (e.g. `Governance/Constitution.md`)
- `type/reference` — Glossary, decision log, open questions, epics. (e.g. `Reference/Glossary.md`)
- `type/session-log` — Session activity log; permanent audit trail. Written to `docs/vault/Sessions/`. Append-only, never pruned. (Agent notes only — spec 080.)
- `type/spec` — Spec document at `docs/vault/Specs/NNN Title/spec.md`. Carries `spec-refs:`. (e.g. `Specs/047 Car Radio/spec.md`)
- `type/system` — A bounded subsystem with implementation. Carries `code-refs`, `spec-refs`, `implements:` frontmatter. (e.g. `Systems/Audio — Car Radio.md`)
- `type/vision` — Strategic / vision-layer decision. Written to `docs/vault/Vision/`. Human-authored or agent-proposed with human ratification before promotion to `status: reviewed`. (Per triage #3 — spec 133 autonomous-company redesign.)
domain/*:
- `domain/anomalies` — Anomaly taxonomy, individual anomaly systems, spawn, behavior
- `domain/art` — Visual direction, palettes, references, asset pipeline
- `domain/audio` — Audio systems: world ambient, radio, transmissions, buses, pipeline
- `domain/autonomous-company` — Autonomous company v0.1 experiment: Slack infra, persona middleware, Letta integration, restart recovery
- `domain/build` — Build system, packaging, export, release automation
- `domain/governance` — Constitution, phased spec, policies
- `domain/infrastructure` — Infrastructure provisioning: CI/CD, hosting, deployment tooling, secrets management
- `domain/narrative` — Tone, horror register, forest transmissions narrative, Gary/KTLK
- `domain/player` — Player mode, input, controls, camera, exit/entry
- `domain/systems` — Cross-cutting system architecture and integration work
- `domain/tooling` — Build, CI, observer, TTS pipeline, dev-time tools
- `domain/vehicle` — The Samba: vehicle physics, dashboard, damage, panels
- `domain/world` — World model, biomes, terrain, procedural generation, weather
status/*:
- `status/canonical` — Fully authoritative; promoted by humans only. Highest trust. (Agent notes only — spec 080.)
- `status/draft` — Authoring in progress, not yet verified
- `status/reviewed` — Agent-created note verified against codebase within its creating session. Eligible for auto-injection in subsequent task dispatches. (Agent notes only — spec 080.)
- `status/stale` — Known out of date; cannot update immediately. Pairs with `> [!warning] STALE — needs update` callout.
- `status/superseded` — Replaced by another note. Terminal state. Pairs with `> [!warning] SUPERSEDED` callout.
- `status/wip` — Stable but under active revision
layer/*:
- `layer/content` — Content assets (audio, models, textures, audio provenance)
- `layer/gdext` — gdext wrapper layer (`rust/gdext-wrapper/`)
- `layer/gdscript` — GDScript (Godot scene-tier logic)
- `layer/infra` — Build, CI, deployment infrastructure
- `layer/python` — Python development tooling (`tools/`)
- `layer/rust-core` — Engine-agnostic Rust core (`rust/rust-core/`)
concept/*:
- `concept/biome` — Biome-reactive behavior across systems
- `concept/contamination` — Across-runs panel and garage degradation; the slow-horror mechanic that doesn't reset with the world
- `concept/diegetic` — Diegetic audio / UI / world-sourced design
- `concept/disturbance` — The disturbance mechanic thread (Article X)
- `concept/ephemeral-world` — Run-reset, transient worlds (Article IV Rules 6–7)
- `concept/governance` — Constitutional and governance concepts
- `concept/horror` — Horror register and dread design
- `concept/procedural` — Procedural generation, seed determinism
- `concept/rendering` — Visual rendering quality, shader correctness, Terrain3D integration, mesh fidelity, LOD, Z-fighting
- `concept/terrain` — Terrain generation, heightmap, Terrain3D regions, roughness, playability constraints
ember's answer for tag_assignment-sessions-spec-authoring-session-083-096-apr-23-2026, domain/artP(true) placed on the no, unsure, and yes zones.nounsureyesgold: yesP = 0.05

tag_assignment-sessions-spec-authoring-session-083-096-apr-23-2026: domain/governance

Tag assignment · test
Gold
The note calls for `domain/governance`: Constitution, phased spec, policies (True)
ember
The note has no reason to carry `domain/governance` (False)
Signal
P(true) 0.04 (no)
Kit outcome
acted on a wrong answer
Why this gold label
Mined from Sessions/Spec Authoring Session — 083-096 Apr 23 2026.md at 692f4bb58b7f62105aeb73fba8dfee12bfdecd53; gold is the note's own vocabulary tags.
Spec Authoring Session — 083-096 Apr 23 2026

This session authored 13 new feature specs for Old Growth (083–087, 089–096), corrected a branch targeting error, and updated the vault with corresponding spec stubs.

## Work Completed

### Spec Creation (088-vault-audit-agent branch)

Fourteen spec directories were created (083–097); all except 088 and 097 (already authored) received full content in this session. The following specs were authored from blank placeholders to complete spec.md files:

| Spec | Title | Lines |
|---|---|---|
| 083 | Atmospheric Splash Screen | 172 |
| 084 | First-Run Experience | 140 |
| 085 | Game Controller Support | 184 |
| 086 | Performance and Stability Testing | 167 |
| 087 | Main Menu Polish | 150 |
| 089 | Crafting Panel and Car Maintenance Abilities | 132 |
| 090 | Car Maintenance System | 169 |
| 091 | Player Abilities System | 148 |
| 092 | Garage Map and Trip Planner | 148 |
| 093 | Player Clothing and Equipment | 149 |
| 094 | Additional Biomes — Meadow and Swamp | 186 |
| 095 | Train Tracks and Abandoned Railways | 132 |
| 096 | Waterways — Lakes and Rivers | 132 |

All specs passed zero-placeholder-hit verification before commit.

### Branch Correction

Spec creation commits initially landed on `main` (two commits: `0c2aaf8`, `f5f7496`). Corrected via cherry-pick onto `088-vault-audit-agent` followed by `git reset --hard origin/main` on main. Both commits are now exclusively on `088-vault-audit-agent` at `80682f6` and `65547b4`.

### Vault Updates

Thirteen spec stubs added to `docs/vault/Specs/` (083–087, 089–096). This session note added. Specs MOC updated.

## Key Design Decisions Captured in Specs

- **083 Splash**: `splash_completed` signal lives on the script, not on `Events` — transient scene, single consumer.
- **084 First-Run**: Fixed seed in a Resource; flag set only on successful extraction.
- **085 Controller**: Rumble is a horror signal tied to disturbance thresholds, not convenience feedback.
- **090 Car Maintenance**: Battery at 0% is the only state that blocks run start; all other systems degrade gracefully.
- **091 Abilities**: Every ability cost is unconditional and structurally separate from its benefit.
- **092 Map**: Shows the *previous* run's world, not the upcoming one — intentional horror design.
- **094 Swamp**: Disturbance "unreliability" is a display offset, not a change to the underlying meter value.
- **096 Waterways**: River ambient audio contributes +0.02/s passive disturbance within 20m.

## References

- `specs/083-atmospheric-splash-screen/spec.md`
- `specs/084-first-run-experience/spec.md`
- `specs/085-game-controller-support/spec.md`
- `specs/086-performance-stability-testing/spec.md`
- `specs/087-main-menu-polish/spec.md`
- `specs/089-crafting-panel/spec.md`
- `specs/090-car-maintenance/spec.md`
- `specs/091-player-abilities/spec.md`
- `specs/092-garage-trip-planner/spec.md`
- `specs/093-player-equipment/spec.md`
- `specs/094-meadow-swamp-biomes/spec.md`
- `specs/095-train-tracks/spec.md`
- `specs/096-water-ways/spec.md`

Controlled tag vocabulary (as read):
type/*:
- `type/code` — Code architecture, autoloads, conventions, tooling. Carries `code-refs:`. (e.g. `Code/Autoloads — Disturbance.md`)
- `type/decision` — Architectural or design decision made by an agent during a session. Written to `docs/vault/Decisions/`. (Agent notes only — spec 080.)
- `type/design` — Design intent, player-facing concepts, world lore. (e.g. `Design/World Model.md`)
- `type/discovery` — Non-obvious constraint, gap, or conflict found by an agent during a session. Written to `docs/vault/Discoveries/`. (Agent notes only — spec 080.)
- `type/moc` — Map of Content at any of three tiers (folder / domain / concept). (e.g. `Audio.md`)
- `type/principle` — Governance and constitutional notes. Non-negotiable rules. (e.g. `Governance/Constitution.md`)
- `type/reference` — Glossary, decision log, open questions, epics. (e.g. `Reference/Glossary.md`)
- `type/session-log` — Session activity log; permanent audit trail. Written to `docs/vault/Sessions/`. Append-only, never pruned. (Agent notes only — spec 080.)
- `type/spec` — Spec document at `docs/vault/Specs/NNN Title/spec.md`. Carries `spec-refs:`. (e.g. `Specs/047 Car Radio/spec.md`)
- `type/system` — A bounded subsystem with implementation. Carries `code-refs`, `spec-refs`, `implements:` frontmatter. (e.g. `Systems/Audio — Car Radio.md`)
- `type/vision` — Strategic / vision-layer decision. Written to `docs/vault/Vision/`. Human-authored or agent-proposed with human ratification before promotion to `status: reviewed`. (Per triage #3 — spec 133 autonomous-company redesign.)
domain/*:
- `domain/anomalies` — Anomaly taxonomy, individual anomaly systems, spawn, behavior
- `domain/art` — Visual direction, palettes, references, asset pipeline
- `domain/audio` — Audio systems: world ambient, radio, transmissions, buses, pipeline
- `domain/autonomous-company` — Autonomous company v0.1 experiment: Slack infra, persona middleware, Letta integration, restart recovery
- `domain/build` — Build system, packaging, export, release automation
- `domain/governance` — Constitution, phased spec, policies
- `domain/infrastructure` — Infrastructure provisioning: CI/CD, hosting, deployment tooling, secrets management
- `domain/narrative` — Tone, horror register, forest transmissions narrative, Gary/KTLK
- `domain/player` — Player mode, input, controls, camera, exit/entry
- `domain/systems` — Cross-cutting system architecture and integration work
- `domain/tooling` — Build, CI, observer, TTS pipeline, dev-time tools
- `domain/vehicle` — The Samba: vehicle physics, dashboard, damage, panels
- `domain/world` — World model, biomes, terrain, procedural generation, weather
status/*:
- `status/canonical` — Fully authoritative; promoted by humans only. Highest trust. (Agent notes only — spec 080.)
- `status/draft` — Authoring in progress, not yet verified
- `status/reviewed` — Agent-created note verified against codebase within its creating session. Eligible for auto-injection in subsequent task dispatches. (Agent notes only — spec 080.)
- `status/stale` — Known out of date; cannot update immediately. Pairs with `> [!warning] STALE — needs update` callout.
- `status/superseded` — Replaced by another note. Terminal state. Pairs with `> [!warning] SUPERSEDED` callout.
- `status/wip` — Stable but under active revision
layer/*:
- `layer/content` — Content assets (audio, models, textures, audio provenance)
- `layer/gdext` — gdext wrapper layer (`rust/gdext-wrapper/`)
- `layer/gdscript` — GDScript (Godot scene-tier logic)
- `layer/infra` — Build, CI, deployment infrastructure
- `layer/python` — Python development tooling (`tools/`)
- `layer/rust-core` — Engine-agnostic Rust core (`rust/rust-core/`)
concept/*:
- `concept/biome` — Biome-reactive behavior across systems
- `concept/contamination` — Across-runs panel and garage degradation; the slow-horror mechanic that doesn't reset with the world
- `concept/diegetic` — Diegetic audio / UI / world-sourced design
- `concept/disturbance` — The disturbance mechanic thread (Article X)
- `concept/ephemeral-world` — Run-reset, transient worlds (Article IV Rules 6–7)
- `concept/governance` — Constitutional and governance concepts
- `concept/horror` — Horror register and dread design
- `concept/procedural` — Procedural generation, seed determinism
- `concept/rendering` — Visual rendering quality, shader correctness, Terrain3D integration, mesh fidelity, LOD, Z-fighting
- `concept/terrain` — Terrain generation, heightmap, Terrain3D regions, roughness, playability constraints
ember's answer for tag_assignment-sessions-spec-authoring-session-083-096-apr-23-2026, domain/governanceP(true) placed on the no, unsure, and yes zones.nounsureyesgold: yesP = 0.04

tag_assignment-sessions-spec-authoring-session-083-096-apr-23-2026: domain/narrative

Tag assignment · test
Gold
The note calls for `domain/narrative`: Tone, horror register, forest transmissions narrative, Gary/KTLK (True)
ember
The note has no reason to carry `domain/narrative` (False)
Signal
P(true) 0.09 (no)
Kit outcome
acted on a wrong answer
Why this gold label
Mined from Sessions/Spec Authoring Session — 083-096 Apr 23 2026.md at 692f4bb58b7f62105aeb73fba8dfee12bfdecd53; gold is the note's own vocabulary tags.
Spec Authoring Session — 083-096 Apr 23 2026

This session authored 13 new feature specs for Old Growth (083–087, 089–096), corrected a branch targeting error, and updated the vault with corresponding spec stubs.

## Work Completed

### Spec Creation (088-vault-audit-agent branch)

Fourteen spec directories were created (083–097); all except 088 and 097 (already authored) received full content in this session. The following specs were authored from blank placeholders to complete spec.md files:

| Spec | Title | Lines |
|---|---|---|
| 083 | Atmospheric Splash Screen | 172 |
| 084 | First-Run Experience | 140 |
| 085 | Game Controller Support | 184 |
| 086 | Performance and Stability Testing | 167 |
| 087 | Main Menu Polish | 150 |
| 089 | Crafting Panel and Car Maintenance Abilities | 132 |
| 090 | Car Maintenance System | 169 |
| 091 | Player Abilities System | 148 |
| 092 | Garage Map and Trip Planner | 148 |
| 093 | Player Clothing and Equipment | 149 |
| 094 | Additional Biomes — Meadow and Swamp | 186 |
| 095 | Train Tracks and Abandoned Railways | 132 |
| 096 | Waterways — Lakes and Rivers | 132 |

All specs passed zero-placeholder-hit verification before commit.

### Branch Correction

Spec creation commits initially landed on `main` (two commits: `0c2aaf8`, `f5f7496`). Corrected via cherry-pick onto `088-vault-audit-agent` followed by `git reset --hard origin/main` on main. Both commits are now exclusively on `088-vault-audit-agent` at `80682f6` and `65547b4`.

### Vault Updates

Thirteen spec stubs added to `docs/vault/Specs/` (083–087, 089–096). This session note added. Specs MOC updated.

## Key Design Decisions Captured in Specs

- **083 Splash**: `splash_completed` signal lives on the script, not on `Events` — transient scene, single consumer.
- **084 First-Run**: Fixed seed in a Resource; flag set only on successful extraction.
- **085 Controller**: Rumble is a horror signal tied to disturbance thresholds, not convenience feedback.
- **090 Car Maintenance**: Battery at 0% is the only state that blocks run start; all other systems degrade gracefully.
- **091 Abilities**: Every ability cost is unconditional and structurally separate from its benefit.
- **092 Map**: Shows the *previous* run's world, not the upcoming one — intentional horror design.
- **094 Swamp**: Disturbance "unreliability" is a display offset, not a change to the underlying meter value.
- **096 Waterways**: River ambient audio contributes +0.02/s passive disturbance within 20m.

## References

- `specs/083-atmospheric-splash-screen/spec.md`
- `specs/084-first-run-experience/spec.md`
- `specs/085-game-controller-support/spec.md`
- `specs/086-performance-stability-testing/spec.md`
- `specs/087-main-menu-polish/spec.md`
- `specs/089-crafting-panel/spec.md`
- `specs/090-car-maintenance/spec.md`
- `specs/091-player-abilities/spec.md`
- `specs/092-garage-trip-planner/spec.md`
- `specs/093-player-equipment/spec.md`
- `specs/094-meadow-swamp-biomes/spec.md`
- `specs/095-train-tracks/spec.md`
- `specs/096-water-ways/spec.md`

Controlled tag vocabulary (as read):
type/*:
- `type/code` — Code architecture, autoloads, conventions, tooling. Carries `code-refs:`. (e.g. `Code/Autoloads — Disturbance.md`)
- `type/decision` — Architectural or design decision made by an agent during a session. Written to `docs/vault/Decisions/`. (Agent notes only — spec 080.)
- `type/design` — Design intent, player-facing concepts, world lore. (e.g. `Design/World Model.md`)
- `type/discovery` — Non-obvious constraint, gap, or conflict found by an agent during a session. Written to `docs/vault/Discoveries/`. (Agent notes only — spec 080.)
- `type/moc` — Map of Content at any of three tiers (folder / domain / concept). (e.g. `Audio.md`)
- `type/principle` — Governance and constitutional notes. Non-negotiable rules. (e.g. `Governance/Constitution.md`)
- `type/reference` — Glossary, decision log, open questions, epics. (e.g. `Reference/Glossary.md`)
- `type/session-log` — Session activity log; permanent audit trail. Written to `docs/vault/Sessions/`. Append-only, never pruned. (Agent notes only — spec 080.)
- `type/spec` — Spec document at `docs/vault/Specs/NNN Title/spec.md`. Carries `spec-refs:`. (e.g. `Specs/047 Car Radio/spec.md`)
- `type/system` — A bounded subsystem with implementation. Carries `code-refs`, `spec-refs`, `implements:` frontmatter. (e.g. `Systems/Audio — Car Radio.md`)
- `type/vision` — Strategic / vision-layer decision. Written to `docs/vault/Vision/`. Human-authored or agent-proposed with human ratification before promotion to `status: reviewed`. (Per triage #3 — spec 133 autonomous-company redesign.)
domain/*:
- `domain/anomalies` — Anomaly taxonomy, individual anomaly systems, spawn, behavior
- `domain/art` — Visual direction, palettes, references, asset pipeline
- `domain/audio` — Audio systems: world ambient, radio, transmissions, buses, pipeline
- `domain/autonomous-company` — Autonomous company v0.1 experiment: Slack infra, persona middleware, Letta integration, restart recovery
- `domain/build` — Build system, packaging, export, release automation
- `domain/governance` — Constitution, phased spec, policies
- `domain/infrastructure` — Infrastructure provisioning: CI/CD, hosting, deployment tooling, secrets management
- `domain/narrative` — Tone, horror register, forest transmissions narrative, Gary/KTLK
- `domain/player` — Player mode, input, controls, camera, exit/entry
- `domain/systems` — Cross-cutting system architecture and integration work
- `domain/tooling` — Build, CI, observer, TTS pipeline, dev-time tools
- `domain/vehicle` — The Samba: vehicle physics, dashboard, damage, panels
- `domain/world` — World model, biomes, terrain, procedural generation, weather
status/*:
- `status/canonical` — Fully authoritative; promoted by humans only. Highest trust. (Agent notes only — spec 080.)
- `status/draft` — Authoring in progress, not yet verified
- `status/reviewed` — Agent-created note verified against codebase within its creating session. Eligible for auto-injection in subsequent task dispatches. (Agent notes only — spec 080.)
- `status/stale` — Known out of date; cannot update immediately. Pairs with `> [!warning] STALE — needs update` callout.
- `status/superseded` — Replaced by another note. Terminal state. Pairs with `> [!warning] SUPERSEDED` callout.
- `status/wip` — Stable but under active revision
layer/*:
- `layer/content` — Content assets (audio, models, textures, audio provenance)
- `layer/gdext` — gdext wrapper layer (`rust/gdext-wrapper/`)
- `layer/gdscript` — GDScript (Godot scene-tier logic)
- `layer/infra` — Build, CI, deployment infrastructure
- `layer/python` — Python development tooling (`tools/`)
- `layer/rust-core` — Engine-agnostic Rust core (`rust/rust-core/`)
concept/*:
- `concept/biome` — Biome-reactive behavior across systems
- `concept/contamination` — Across-runs panel and garage degradation; the slow-horror mechanic that doesn't reset with the world
- `concept/diegetic` — Diegetic audio / UI / world-sourced design
- `concept/disturbance` — The disturbance mechanic thread (Article X)
- `concept/ephemeral-world` — Run-reset, transient worlds (Article IV Rules 6–7)
- `concept/governance` — Constitutional and governance concepts
- `concept/horror` — Horror register and dread design
- `concept/procedural` — Procedural generation, seed determinism
- `concept/rendering` — Visual rendering quality, shader correctness, Terrain3D integration, mesh fidelity, LOD, Z-fighting
- `concept/terrain` — Terrain generation, heightmap, Terrain3D regions, roughness, playability constraints
ember's answer for tag_assignment-sessions-spec-authoring-session-083-096-apr-23-2026, domain/narrativeP(true) placed on the no, unsure, and yes zones.nounsureyesgold: yesP = 0.09

tag_assignment-sessions-spec-authoring-session-083-096-apr-23-2026: domain/player

Tag assignment · test
Gold
The note calls for `domain/player`: Player mode, input, controls, camera, exit/entry (True)
ember
The note has no reason to carry `domain/player` (False)
Signal
P(true) 0.41 (unsure)
Kit outcome
deferred: treated as unsure
Why this gold label
Mined from Sessions/Spec Authoring Session — 083-096 Apr 23 2026.md at 692f4bb58b7f62105aeb73fba8dfee12bfdecd53; gold is the note's own vocabulary tags.
Spec Authoring Session — 083-096 Apr 23 2026

This session authored 13 new feature specs for Old Growth (083–087, 089–096), corrected a branch targeting error, and updated the vault with corresponding spec stubs.

## Work Completed

### Spec Creation (088-vault-audit-agent branch)

Fourteen spec directories were created (083–097); all except 088 and 097 (already authored) received full content in this session. The following specs were authored from blank placeholders to complete spec.md files:

| Spec | Title | Lines |
|---|---|---|
| 083 | Atmospheric Splash Screen | 172 |
| 084 | First-Run Experience | 140 |
| 085 | Game Controller Support | 184 |
| 086 | Performance and Stability Testing | 167 |
| 087 | Main Menu Polish | 150 |
| 089 | Crafting Panel and Car Maintenance Abilities | 132 |
| 090 | Car Maintenance System | 169 |
| 091 | Player Abilities System | 148 |
| 092 | Garage Map and Trip Planner | 148 |
| 093 | Player Clothing and Equipment | 149 |
| 094 | Additional Biomes — Meadow and Swamp | 186 |
| 095 | Train Tracks and Abandoned Railways | 132 |
| 096 | Waterways — Lakes and Rivers | 132 |

All specs passed zero-placeholder-hit verification before commit.

### Branch Correction

Spec creation commits initially landed on `main` (two commits: `0c2aaf8`, `f5f7496`). Corrected via cherry-pick onto `088-vault-audit-agent` followed by `git reset --hard origin/main` on main. Both commits are now exclusively on `088-vault-audit-agent` at `80682f6` and `65547b4`.

### Vault Updates

Thirteen spec stubs added to `docs/vault/Specs/` (083–087, 089–096). This session note added. Specs MOC updated.

## Key Design Decisions Captured in Specs

- **083 Splash**: `splash_completed` signal lives on the script, not on `Events` — transient scene, single consumer.
- **084 First-Run**: Fixed seed in a Resource; flag set only on successful extraction.
- **085 Controller**: Rumble is a horror signal tied to disturbance thresholds, not convenience feedback.
- **090 Car Maintenance**: Battery at 0% is the only state that blocks run start; all other systems degrade gracefully.
- **091 Abilities**: Every ability cost is unconditional and structurally separate from its benefit.
- **092 Map**: Shows the *previous* run's world, not the upcoming one — intentional horror design.
- **094 Swamp**: Disturbance "unreliability" is a display offset, not a change to the underlying meter value.
- **096 Waterways**: River ambient audio contributes +0.02/s passive disturbance within 20m.

## References

- `specs/083-atmospheric-splash-screen/spec.md`
- `specs/084-first-run-experience/spec.md`
- `specs/085-game-controller-support/spec.md`
- `specs/086-performance-stability-testing/spec.md`
- `specs/087-main-menu-polish/spec.md`
- `specs/089-crafting-panel/spec.md`
- `specs/090-car-maintenance/spec.md`
- `specs/091-player-abilities/spec.md`
- `specs/092-garage-trip-planner/spec.md`
- `specs/093-player-equipment/spec.md`
- `specs/094-meadow-swamp-biomes/spec.md`
- `specs/095-train-tracks/spec.md`
- `specs/096-water-ways/spec.md`

Controlled tag vocabulary (as read):
type/*:
- `type/code` — Code architecture, autoloads, conventions, tooling. Carries `code-refs:`. (e.g. `Code/Autoloads — Disturbance.md`)
- `type/decision` — Architectural or design decision made by an agent during a session. Written to `docs/vault/Decisions/`. (Agent notes only — spec 080.)
- `type/design` — Design intent, player-facing concepts, world lore. (e.g. `Design/World Model.md`)
- `type/discovery` — Non-obvious constraint, gap, or conflict found by an agent during a session. Written to `docs/vault/Discoveries/`. (Agent notes only — spec 080.)
- `type/moc` — Map of Content at any of three tiers (folder / domain / concept). (e.g. `Audio.md`)
- `type/principle` — Governance and constitutional notes. Non-negotiable rules. (e.g. `Governance/Constitution.md`)
- `type/reference` — Glossary, decision log, open questions, epics. (e.g. `Reference/Glossary.md`)
- `type/session-log` — Session activity log; permanent audit trail. Written to `docs/vault/Sessions/`. Append-only, never pruned. (Agent notes only — spec 080.)
- `type/spec` — Spec document at `docs/vault/Specs/NNN Title/spec.md`. Carries `spec-refs:`. (e.g. `Specs/047 Car Radio/spec.md`)
- `type/system` — A bounded subsystem with implementation. Carries `code-refs`, `spec-refs`, `implements:` frontmatter. (e.g. `Systems/Audio — Car Radio.md`)
- `type/vision` — Strategic / vision-layer decision. Written to `docs/vault/Vision/`. Human-authored or agent-proposed with human ratification before promotion to `status: reviewed`. (Per triage #3 — spec 133 autonomous-company redesign.)
domain/*:
- `domain/anomalies` — Anomaly taxonomy, individual anomaly systems, spawn, behavior
- `domain/art` — Visual direction, palettes, references, asset pipeline
- `domain/audio` — Audio systems: world ambient, radio, transmissions, buses, pipeline
- `domain/autonomous-company` — Autonomous company v0.1 experiment: Slack infra, persona middleware, Letta integration, restart recovery
- `domain/build` — Build system, packaging, export, release automation
- `domain/governance` — Constitution, phased spec, policies
- `domain/infrastructure` — Infrastructure provisioning: CI/CD, hosting, deployment tooling, secrets management
- `domain/narrative` — Tone, horror register, forest transmissions narrative, Gary/KTLK
- `domain/player` — Player mode, input, controls, camera, exit/entry
- `domain/systems` — Cross-cutting system architecture and integration work
- `domain/tooling` — Build, CI, observer, TTS pipeline, dev-time tools
- `domain/vehicle` — The Samba: vehicle physics, dashboard, damage, panels
- `domain/world` — World model, biomes, terrain, procedural generation, weather
status/*:
- `status/canonical` — Fully authoritative; promoted by humans only. Highest trust. (Agent notes only — spec 080.)
- `status/draft` — Authoring in progress, not yet verified
- `status/reviewed` — Agent-created note verified against codebase within its creating session. Eligible for auto-injection in subsequent task dispatches. (Agent notes only — spec 080.)
- `status/stale` — Known out of date; cannot update immediately. Pairs with `> [!warning] STALE — needs update` callout.
- `status/superseded` — Replaced by another note. Terminal state. Pairs with `> [!warning] SUPERSEDED` callout.
- `status/wip` — Stable but under active revision
layer/*:
- `layer/content` — Content assets (audio, models, textures, audio provenance)
- `layer/gdext` — gdext wrapper layer (`rust/gdext-wrapper/`)
- `layer/gdscript` — GDScript (Godot scene-tier logic)
- `layer/infra` — Build, CI, deployment infrastructure
- `layer/python` — Python development tooling (`tools/`)
- `layer/rust-core` — Engine-agnostic Rust core (`rust/rust-core/`)
concept/*:
- `concept/biome` — Biome-reactive behavior across systems
- `concept/contamination` — Across-runs panel and garage degradation; the slow-horror mechanic that doesn't reset with the world
- `concept/diegetic` — Diegetic audio / UI / world-sourced design
- `concept/disturbance` — The disturbance mechanic thread (Article X)
- `concept/ephemeral-world` — Run-reset, transient worlds (Article IV Rules 6–7)
- `concept/governance` — Constitutional and governance concepts
- `concept/horror` — Horror register and dread design
- `concept/procedural` — Procedural generation, seed determinism
- `concept/rendering` — Visual rendering quality, shader correctness, Terrain3D integration, mesh fidelity, LOD, Z-fighting
- `concept/terrain` — Terrain generation, heightmap, Terrain3D regions, roughness, playability constraints
ember's answer for tag_assignment-sessions-spec-authoring-session-083-096-apr-23-2026, domain/playerP(true) placed on the no, unsure, and yes zones.nounsureyesgold: yesP = 0.41

tag_assignment-sessions-spec-authoring-session-083-096-apr-23-2026: domain/tooling

Tag assignment · test
Gold
The note calls for `domain/tooling`: Build, CI, observer, TTS pipeline, dev-time tools (True)
ember
The note has no reason to carry `domain/tooling` (False)
Signal
P(true) 0.09 (no)
Kit outcome
acted on a wrong answer
Why this gold label
Mined from Sessions/Spec Authoring Session — 083-096 Apr 23 2026.md at 692f4bb58b7f62105aeb73fba8dfee12bfdecd53; gold is the note's own vocabulary tags.
Spec Authoring Session — 083-096 Apr 23 2026

This session authored 13 new feature specs for Old Growth (083–087, 089–096), corrected a branch targeting error, and updated the vault with corresponding spec stubs.

## Work Completed

### Spec Creation (088-vault-audit-agent branch)

Fourteen spec directories were created (083–097); all except 088 and 097 (already authored) received full content in this session. The following specs were authored from blank placeholders to complete spec.md files:

| Spec | Title | Lines |
|---|---|---|
| 083 | Atmospheric Splash Screen | 172 |
| 084 | First-Run Experience | 140 |
| 085 | Game Controller Support | 184 |
| 086 | Performance and Stability Testing | 167 |
| 087 | Main Menu Polish | 150 |
| 089 | Crafting Panel and Car Maintenance Abilities | 132 |
| 090 | Car Maintenance System | 169 |
| 091 | Player Abilities System | 148 |
| 092 | Garage Map and Trip Planner | 148 |
| 093 | Player Clothing and Equipment | 149 |
| 094 | Additional Biomes — Meadow and Swamp | 186 |
| 095 | Train Tracks and Abandoned Railways | 132 |
| 096 | Waterways — Lakes and Rivers | 132 |

All specs passed zero-placeholder-hit verification before commit.

### Branch Correction

Spec creation commits initially landed on `main` (two commits: `0c2aaf8`, `f5f7496`). Corrected via cherry-pick onto `088-vault-audit-agent` followed by `git reset --hard origin/main` on main. Both commits are now exclusively on `088-vault-audit-agent` at `80682f6` and `65547b4`.

### Vault Updates

Thirteen spec stubs added to `docs/vault/Specs/` (083–087, 089–096). This session note added. Specs MOC updated.

## Key Design Decisions Captured in Specs

- **083 Splash**: `splash_completed` signal lives on the script, not on `Events` — transient scene, single consumer.
- **084 First-Run**: Fixed seed in a Resource; flag set only on successful extraction.
- **085 Controller**: Rumble is a horror signal tied to disturbance thresholds, not convenience feedback.
- **090 Car Maintenance**: Battery at 0% is the only state that blocks run start; all other systems degrade gracefully.
- **091 Abilities**: Every ability cost is unconditional and structurally separate from its benefit.
- **092 Map**: Shows the *previous* run's world, not the upcoming one — intentional horror design.
- **094 Swamp**: Disturbance "unreliability" is a display offset, not a change to the underlying meter value.
- **096 Waterways**: River ambient audio contributes +0.02/s passive disturbance within 20m.

## References

- `specs/083-atmospheric-splash-screen/spec.md`
- `specs/084-first-run-experience/spec.md`
- `specs/085-game-controller-support/spec.md`
- `specs/086-performance-stability-testing/spec.md`
- `specs/087-main-menu-polish/spec.md`
- `specs/089-crafting-panel/spec.md`
- `specs/090-car-maintenance/spec.md`
- `specs/091-player-abilities/spec.md`
- `specs/092-garage-trip-planner/spec.md`
- `specs/093-player-equipment/spec.md`
- `specs/094-meadow-swamp-biomes/spec.md`
- `specs/095-train-tracks/spec.md`
- `specs/096-water-ways/spec.md`

Controlled tag vocabulary (as read):
type/*:
- `type/code` — Code architecture, autoloads, conventions, tooling. Carries `code-refs:`. (e.g. `Code/Autoloads — Disturbance.md`)
- `type/decision` — Architectural or design decision made by an agent during a session. Written to `docs/vault/Decisions/`. (Agent notes only — spec 080.)
- `type/design` — Design intent, player-facing concepts, world lore. (e.g. `Design/World Model.md`)
- `type/discovery` — Non-obvious constraint, gap, or conflict found by an agent during a session. Written to `docs/vault/Discoveries/`. (Agent notes only — spec 080.)
- `type/moc` — Map of Content at any of three tiers (folder / domain / concept). (e.g. `Audio.md`)
- `type/principle` — Governance and constitutional notes. Non-negotiable rules. (e.g. `Governance/Constitution.md`)
- `type/reference` — Glossary, decision log, open questions, epics. (e.g. `Reference/Glossary.md`)
- `type/session-log` — Session activity log; permanent audit trail. Written to `docs/vault/Sessions/`. Append-only, never pruned. (Agent notes only — spec 080.)
- `type/spec` — Spec document at `docs/vault/Specs/NNN Title/spec.md`. Carries `spec-refs:`. (e.g. `Specs/047 Car Radio/spec.md`)
- `type/system` — A bounded subsystem with implementation. Carries `code-refs`, `spec-refs`, `implements:` frontmatter. (e.g. `Systems/Audio — Car Radio.md`)
- `type/vision` — Strategic / vision-layer decision. Written to `docs/vault/Vision/`. Human-authored or agent-proposed with human ratification before promotion to `status: reviewed`. (Per triage #3 — spec 133 autonomous-company redesign.)
domain/*:
- `domain/anomalies` — Anomaly taxonomy, individual anomaly systems, spawn, behavior
- `domain/art` — Visual direction, palettes, references, asset pipeline
- `domain/audio` — Audio systems: world ambient, radio, transmissions, buses, pipeline
- `domain/autonomous-company` — Autonomous company v0.1 experiment: Slack infra, persona middleware, Letta integration, restart recovery
- `domain/build` — Build system, packaging, export, release automation
- `domain/governance` — Constitution, phased spec, policies
- `domain/infrastructure` — Infrastructure provisioning: CI/CD, hosting, deployment tooling, secrets management
- `domain/narrative` — Tone, horror register, forest transmissions narrative, Gary/KTLK
- `domain/player` — Player mode, input, controls, camera, exit/entry
- `domain/systems` — Cross-cutting system architecture and integration work
- `domain/tooling` — Build, CI, observer, TTS pipeline, dev-time tools
- `domain/vehicle` — The Samba: vehicle physics, dashboard, damage, panels
- `domain/world` — World model, biomes, terrain, procedural generation, weather
status/*:
- `status/canonical` — Fully authoritative; promoted by humans only. Highest trust. (Agent notes only — spec 080.)
- `status/draft` — Authoring in progress, not yet verified
- `status/reviewed` — Agent-created note verified against codebase within its creating session. Eligible for auto-injection in subsequent task dispatches. (Agent notes only — spec 080.)
- `status/stale` — Known out of date; cannot update immediately. Pairs with `> [!warning] STALE — needs update` callout.
- `status/superseded` — Replaced by another note. Terminal state. Pairs with `> [!warning] SUPERSEDED` callout.
- `status/wip` — Stable but under active revision
layer/*:
- `layer/content` — Content assets (audio, models, textures, audio provenance)
- `layer/gdext` — gdext wrapper layer (`rust/gdext-wrapper/`)
- `layer/gdscript` — GDScript (Godot scene-tier logic)
- `layer/infra` — Build, CI, deployment infrastructure
- `layer/python` — Python development tooling (`tools/`)
- `layer/rust-core` — Engine-agnostic Rust core (`rust/rust-core/`)
concept/*:
- `concept/biome` — Biome-reactive behavior across systems
- `concept/contamination` — Across-runs panel and garage degradation; the slow-horror mechanic that doesn't reset with the world
- `concept/diegetic` — Diegetic audio / UI / world-sourced design
- `concept/disturbance` — The disturbance mechanic thread (Article X)
- `concept/ephemeral-world` — Run-reset, transient worlds (Article IV Rules 6–7)
- `concept/governance` — Constitutional and governance concepts
- `concept/horror` — Horror register and dread design
- `concept/procedural` — Procedural generation, seed determinism
- `concept/rendering` — Visual rendering quality, shader correctness, Terrain3D integration, mesh fidelity, LOD, Z-fighting
- `concept/terrain` — Terrain generation, heightmap, Terrain3D regions, roughness, playability constraints
ember's answer for tag_assignment-sessions-spec-authoring-session-083-096-apr-23-2026, domain/toolingP(true) placed on the no, unsure, and yes zones.nounsureyesgold: yesP = 0.09

tag_assignment-sessions-spec-authoring-session-083-096-apr-23-2026: domain/vehicle

Tag assignment · test
Gold
The note calls for `domain/vehicle`: The Samba: vehicle physics, dashboard, damage, panels (True)
ember
The note has no reason to carry `domain/vehicle` (False)
Signal
P(true) 0.28 (unsure)
Kit outcome
deferred: treated as unsure
Why this gold label
Mined from Sessions/Spec Authoring Session — 083-096 Apr 23 2026.md at 692f4bb58b7f62105aeb73fba8dfee12bfdecd53; gold is the note's own vocabulary tags.
Spec Authoring Session — 083-096 Apr 23 2026

This session authored 13 new feature specs for Old Growth (083–087, 089–096), corrected a branch targeting error, and updated the vault with corresponding spec stubs.

## Work Completed

### Spec Creation (088-vault-audit-agent branch)

Fourteen spec directories were created (083–097); all except 088 and 097 (already authored) received full content in this session. The following specs were authored from blank placeholders to complete spec.md files:

| Spec | Title | Lines |
|---|---|---|
| 083 | Atmospheric Splash Screen | 172 |
| 084 | First-Run Experience | 140 |
| 085 | Game Controller Support | 184 |
| 086 | Performance and Stability Testing | 167 |
| 087 | Main Menu Polish | 150 |
| 089 | Crafting Panel and Car Maintenance Abilities | 132 |
| 090 | Car Maintenance System | 169 |
| 091 | Player Abilities System | 148 |
| 092 | Garage Map and Trip Planner | 148 |
| 093 | Player Clothing and Equipment | 149 |
| 094 | Additional Biomes — Meadow and Swamp | 186 |
| 095 | Train Tracks and Abandoned Railways | 132 |
| 096 | Waterways — Lakes and Rivers | 132 |

All specs passed zero-placeholder-hit verification before commit.

### Branch Correction

Spec creation commits initially landed on `main` (two commits: `0c2aaf8`, `f5f7496`). Corrected via cherry-pick onto `088-vault-audit-agent` followed by `git reset --hard origin/main` on main. Both commits are now exclusively on `088-vault-audit-agent` at `80682f6` and `65547b4`.

### Vault Updates

Thirteen spec stubs added to `docs/vault/Specs/` (083–087, 089–096). This session note added. Specs MOC updated.

## Key Design Decisions Captured in Specs

- **083 Splash**: `splash_completed` signal lives on the script, not on `Events` — transient scene, single consumer.
- **084 First-Run**: Fixed seed in a Resource; flag set only on successful extraction.
- **085 Controller**: Rumble is a horror signal tied to disturbance thresholds, not convenience feedback.
- **090 Car Maintenance**: Battery at 0% is the only state that blocks run start; all other systems degrade gracefully.
- **091 Abilities**: Every ability cost is unconditional and structurally separate from its benefit.
- **092 Map**: Shows the *previous* run's world, not the upcoming one — intentional horror design.
- **094 Swamp**: Disturbance "unreliability" is a display offset, not a change to the underlying meter value.
- **096 Waterways**: River ambient audio contributes +0.02/s passive disturbance within 20m.

## References

- `specs/083-atmospheric-splash-screen/spec.md`
- `specs/084-first-run-experience/spec.md`
- `specs/085-game-controller-support/spec.md`
- `specs/086-performance-stability-testing/spec.md`
- `specs/087-main-menu-polish/spec.md`
- `specs/089-crafting-panel/spec.md`
- `specs/090-car-maintenance/spec.md`
- `specs/091-player-abilities/spec.md`
- `specs/092-garage-trip-planner/spec.md`
- `specs/093-player-equipment/spec.md`
- `specs/094-meadow-swamp-biomes/spec.md`
- `specs/095-train-tracks/spec.md`
- `specs/096-water-ways/spec.md`

Controlled tag vocabulary (as read):
type/*:
- `type/code` — Code architecture, autoloads, conventions, tooling. Carries `code-refs:`. (e.g. `Code/Autoloads — Disturbance.md`)
- `type/decision` — Architectural or design decision made by an agent during a session. Written to `docs/vault/Decisions/`. (Agent notes only — spec 080.)
- `type/design` — Design intent, player-facing concepts, world lore. (e.g. `Design/World Model.md`)
- `type/discovery` — Non-obvious constraint, gap, or conflict found by an agent during a session. Written to `docs/vault/Discoveries/`. (Agent notes only — spec 080.)
- `type/moc` — Map of Content at any of three tiers (folder / domain / concept). (e.g. `Audio.md`)
- `type/principle` — Governance and constitutional notes. Non-negotiable rules. (e.g. `Governance/Constitution.md`)
- `type/reference` — Glossary, decision log, open questions, epics. (e.g. `Reference/Glossary.md`)
- `type/session-log` — Session activity log; permanent audit trail. Written to `docs/vault/Sessions/`. Append-only, never pruned. (Agent notes only — spec 080.)
- `type/spec` — Spec document at `docs/vault/Specs/NNN Title/spec.md`. Carries `spec-refs:`. (e.g. `Specs/047 Car Radio/spec.md`)
- `type/system` — A bounded subsystem with implementation. Carries `code-refs`, `spec-refs`, `implements:` frontmatter. (e.g. `Systems/Audio — Car Radio.md`)
- `type/vision` — Strategic / vision-layer decision. Written to `docs/vault/Vision/`. Human-authored or agent-proposed with human ratification before promotion to `status: reviewed`. (Per triage #3 — spec 133 autonomous-company redesign.)
domain/*:
- `domain/anomalies` — Anomaly taxonomy, individual anomaly systems, spawn, behavior
- `domain/art` — Visual direction, palettes, references, asset pipeline
- `domain/audio` — Audio systems: world ambient, radio, transmissions, buses, pipeline
- `domain/autonomous-company` — Autonomous company v0.1 experiment: Slack infra, persona middleware, Letta integration, restart recovery
- `domain/build` — Build system, packaging, export, release automation
- `domain/governance` — Constitution, phased spec, policies
- `domain/infrastructure` — Infrastructure provisioning: CI/CD, hosting, deployment tooling, secrets management
- `domain/narrative` — Tone, horror register, forest transmissions narrative, Gary/KTLK
- `domain/player` — Player mode, input, controls, camera, exit/entry
- `domain/systems` — Cross-cutting system architecture and integration work
- `domain/tooling` — Build, CI, observer, TTS pipeline, dev-time tools
- `domain/vehicle` — The Samba: vehicle physics, dashboard, damage, panels
- `domain/world` — World model, biomes, terrain, procedural generation, weather
status/*:
- `status/canonical` — Fully authoritative; promoted by humans only. Highest trust. (Agent notes only — spec 080.)
- `status/draft` — Authoring in progress, not yet verified
- `status/reviewed` — Agent-created note verified against codebase within its creating session. Eligible for auto-injection in subsequent task dispatches. (Agent notes only — spec 080.)
- `status/stale` — Known out of date; cannot update immediately. Pairs with `> [!warning] STALE — needs update` callout.
- `status/superseded` — Replaced by another note. Terminal state. Pairs with `> [!warning] SUPERSEDED` callout.
- `status/wip` — Stable but under active revision
layer/*:
- `layer/content` — Content assets (audio, models, textures, audio provenance)
- `layer/gdext` — gdext wrapper layer (`rust/gdext-wrapper/`)
- `layer/gdscript` — GDScript (Godot scene-tier logic)
- `layer/infra` — Build, CI, deployment infrastructure
- `layer/python` — Python development tooling (`tools/`)
- `layer/rust-core` — Engine-agnostic Rust core (`rust/rust-core/`)
concept/*:
- `concept/biome` — Biome-reactive behavior across systems
- `concept/contamination` — Across-runs panel and garage degradation; the slow-horror mechanic that doesn't reset with the world
- `concept/diegetic` — Diegetic audio / UI / world-sourced design
- `concept/disturbance` — The disturbance mechanic thread (Article X)
- `concept/ephemeral-world` — Run-reset, transient worlds (Article IV Rules 6–7)
- `concept/governance` — Constitutional and governance concepts
- `concept/horror` — Horror register and dread design
- `concept/procedural` — Procedural generation, seed determinism
- `concept/rendering` — Visual rendering quality, shader correctness, Terrain3D integration, mesh fidelity, LOD, Z-fighting
- `concept/terrain` — Terrain generation, heightmap, Terrain3D regions, roughness, playability constraints
ember's answer for tag_assignment-sessions-spec-authoring-session-083-096-apr-23-2026, domain/vehicleP(true) placed on the no, unsure, and yes zones.nounsureyesgold: yesP = 0.28

tag_assignment-systems-audio-forest-transmissions: type/design

Tag assignment · dev
Gold
The note has no reason to carry `type/design` (False)
ember
The note calls for `type/design`: Design intent, player-facing concepts, world lore. (e.g. `Design/World Model.md`) (True)
Signal
P(true) 0.86 (yes)
Kit outcome
acted on a wrong answer
Why this gold label
Mined from Systems/Audio — Forest Transmissions.md at 692f4bb58b7f62105aeb73fba8dfee12bfdecd53; gold is the note's own vocabulary tags.
Audio — Forest Transmissions

The audio content that comes through the Samba's radio speakers *after* the KTLK signal fails. The forest has been using the frequency for longer than the station has existed. It continues to do so. What comes through is not static.

## Overview

Forest transmissions are the audio layer that replaces the radio when the human-broadcast signal is lost — through deep Petrifold geography, Cascade+ disturbance, or certain anomaly proximity. They are diegetic but their source is ambiguous: *the forest transmitting* is the narrative register, even if the technical implementation is generative or composed.

## Design Intent

This system implements one of the most charged moments in the World Bible (Section 17):

> The radio plays until it cannot. A distant signal, a voice, content that degrades in correlation with how deep the player is and how much the process has been fed. When the signal finally fails, the speakers do not go silent. The forest has been using the frequency for longer than the station has existed, and it continues to do so. What comes through after the signal dies is not static.

Forest transmissions are the forest *at the frequency the radio uses*. They are not intended to be parseable. They are intended to be felt.

## Key Decisions

### Content register

What comes through after KTLK dies includes (but is not limited to):

- **Repeating fragments** — snatches of words, not a voice — that almost form sentences
- **Mycelium signal artifacts** — the same acoustic register as the Mycelium Network anomaly's "conversation the forest is having with itself"
- **Traces of previous occupants** — fragments that *almost* resemble broadcasts from decades past. Never literally; always suggestively. The wall map in the garage was updated by multiple hands; the radio was heard by those hands too.
- **Petrifold audio** — extended dry cracking, amplified and processed through radio texture
- **Deep Silence** — not true silence, but a space the radio is trying and failing to fill with nothing

### Never literal

Forest transmissions must never include a clear narrative voice giving information. They must not explain the forest. They must not describe what is happening. They must only suggest — at the edge of pareidolia. The moment a forest transmission becomes parseable as a coherent message, the horror collapses into something manageable.

Per [[Tone and Horror]]: *the moment the forest is given a motive, a personality, a legible anger, the horror collapses into something manageable*.

### Not music

Forest transmissions are not a musical layer. They sit in the same frequency space as the radio (which is broadcast voice + music) but are not structured musically. They do not have rhythm, melody, or progression in a conventional sense.

### Triggered by signal failure, not state

Forest transmissions are not directly triggered by the [[Disturbance System]] — they are triggered by *radio signal failure*, which itself is driven by disturbance + biome + geography. This preserves diegesis: the forest does not care about the disturbance meter. It cares about the frequency being open.

## Implementation

_The generation approach — composed audio assets vs. procedural audio assembly vs. hybrid — remains an open question. This is tracked in [[Open Questions]] and is a decision to be made when this system is implemented._

> [!question] UNDOCUMENTED
> The source spec does not establish whether forest transmissions are:
> - Pre-composed audio assets assembled dynamically
> - Procedurally generated from mycelium/Petrifold samples
> - Hybrid: a composed "shape" with procedural detail
> This is a decision to be made during implementation of this system.

## Test Coverage

_To be populated once this system is implemented._

## Related

- [[Audio — Car Radio]] — the system this replaces when signal fails
- [[Audio — Radio Stations]] — the KTLK content that precedes signal loss
- [[Audio — Overview]] — top-level audio architecture
- [[Audio — World Audio]] — the ambient world audio that forest transmissions sit alongside
- [[Narrative Direction]] — the narrative register that forest transmissions serve
- [[Tone and Horror]] — the tonal discipline that governs forest transmission content
- [[Audio — Domain MOC]] — domain MOC
- [[Diegesis Thread]] — forest transmissions preserve diegesis through signal failure

Controlled tag vocabulary (as read):
type/*:
- `type/code` — Code architecture, autoloads, conventions, tooling. Carries `code-refs:`. (e.g. `Code/Autoloads — Disturbance.md`)
- `type/decision` — Architectural or design decision made by an agent during a session. Written to `docs/vault/Decisions/`. (Agent notes only — spec 080.)
- `type/design` — Design intent, player-facing concepts, world lore. (e.g. `Design/World Model.md`)
- `type/discovery` — Non-obvious constraint, gap, or conflict found by an agent during a session. Written to `docs/vault/Discoveries/`. (Agent notes only — spec 080.)
- `type/moc` — Map of Content at any of three tiers (folder / domain / concept). (e.g. `Audio.md`)
- `type/principle` — Governance and constitutional notes. Non-negotiable rules. (e.g. `Governance/Constitution.md`)
- `type/reference` — Glossary, decision log, open questions, epics. (e.g. `Reference/Glossary.md`)
- `type/session-log` — Session activity log; permanent audit trail. Written to `docs/vault/Sessions/`. Append-only, never pruned. (Agent notes only — spec 080.)
- `type/spec` — Spec document at `docs/vault/Specs/NNN Title/spec.md`. Carries `spec-refs:`. (e.g. `Specs/047 Car Radio/spec.md`)
- `type/system` — A bounded subsystem with implementation. Carries `code-refs`, `spec-refs`, `implements:` frontmatter. (e.g. `Systems/Audio — Car Radio.md`)
- `type/vision` — Strategic / vision-layer decision. Written to `docs/vault/Vision/`. Human-authored or agent-proposed with human ratification before promotion to `status: reviewed`. (Per triage #3 — spec 133 autonomous-company redesign.)
domain/*:
- `domain/anomalies` — Anomaly taxonomy, individual anomaly systems, spawn, behavior
- `domain/art` — Visual direction, palettes, references, asset pipeline
- `domain/audio` — Audio systems: world ambient, radio, transmissions, buses, pipeline
- `domain/autonomous-company` — Autonomous company v0.1 experiment: Slack infra, persona middleware, Letta integration, restart recovery
- `domain/build` — Build system, packaging, export, release automation
- `domain/governance` — Constitution, phased spec, policies
- `domain/infrastructure` — Infrastructure provisioning: CI/CD, hosting, deployment tooling, secrets management
- `domain/narrative` — Tone, horror register, forest transmissions narrative, Gary/KTLK
- `domain/player` — Player mode, input, controls, camera, exit/entry
- `domain/systems` — Cross-cutting system architecture and integration work
- `domain/tooling` — Build, CI, observer, TTS pipeline, dev-time tools
- `domain/vehicle` — The Samba: vehicle physics, dashboard, damage, panels
- `domain/world` — World model, biomes, terrain, procedural generation, weather
status/*:
- `status/canonical` — Fully authoritative; promoted by humans only. Highest trust. (Agent notes only — spec 080.)
- `status/draft` — Authoring in progress, not yet verified
- `status/reviewed` — Agent-created note verified against codebase within its creating session. Eligible for auto-injection in subsequent task dispatches. (Agent notes only — spec 080.)
- `status/stale` — Known out of date; cannot update immediately. Pairs with `> [!warning] STALE — needs update` callout.
- `status/superseded` — Replaced by another note. Terminal state. Pairs with `> [!warning] SUPERSEDED` callout.
- `status/wip` — Stable but under active revision
layer/*:
- `layer/content` — Content assets (audio, models, textures, audio provenance)
- `layer/gdext` — gdext wrapper layer (`rust/gdext-wrapper/`)
- `layer/gdscript` — GDScript (Godot scene-tier logic)
- `layer/infra` — Build, CI, deployment infrastructure
- `layer/python` — Python development tooling (`tools/`)
- `layer/rust-core` — Engine-agnostic Rust core (`rust/rust-core/`)
concept/*:
- `concept/biome` — Biome-reactive behavior across systems
- `concept/contamination` — Across-runs panel and garage degradation; the slow-horror mechanic that doesn't reset with the world
- `concept/diegetic` — Diegetic audio / UI / world-sourced design
- `concept/disturbance` — The disturbance mechanic thread (Article X)
- `concept/ephemeral-world` — Run-reset, transient worlds (Article IV Rules 6–7)
- `concept/governance` — Constitutional and governance concepts
- `concept/horror` — Horror register and dread design
- `concept/procedural` — Procedural generation, seed determinism
- `concept/rendering` — Visual rendering quality, shader correctness, Terrain3D integration, mesh fidelity, LOD, Z-fighting
- `concept/terrain` — Terrain generation, heightmap, Terrain3D regions, roughness, playability constraints
ember's answer for tag_assignment-systems-audio-forest-transmissions, type/designP(true) placed on the no, unsure, and yes zones.nounsureyesgold: noP = 0.86

tag_assignment-systems-audio-forest-transmissions: type/spec

Tag assignment · dev
Gold
The note has no reason to carry `type/spec` (False)
ember
The note calls for `type/spec`: Spec document at `docs/vault/Specs/NNN Title/spec.md`. Carries `spec-refs:`. (e.g. `Specs/047 Car Radio/spec.md`) (True)
Signal
P(true) 0.60 (unsure)
Kit outcome
deferred: treated as unsure
Why this gold label
Mined from Systems/Audio — Forest Transmissions.md at 692f4bb58b7f62105aeb73fba8dfee12bfdecd53; gold is the note's own vocabulary tags.
Audio — Forest Transmissions

The audio content that comes through the Samba's radio speakers *after* the KTLK signal fails. The forest has been using the frequency for longer than the station has existed. It continues to do so. What comes through is not static.

## Overview

Forest transmissions are the audio layer that replaces the radio when the human-broadcast signal is lost — through deep Petrifold geography, Cascade+ disturbance, or certain anomaly proximity. They are diegetic but their source is ambiguous: *the forest transmitting* is the narrative register, even if the technical implementation is generative or composed.

## Design Intent

This system implements one of the most charged moments in the World Bible (Section 17):

> The radio plays until it cannot. A distant signal, a voice, content that degrades in correlation with how deep the player is and how much the process has been fed. When the signal finally fails, the speakers do not go silent. The forest has been using the frequency for longer than the station has existed, and it continues to do so. What comes through after the signal dies is not static.

Forest transmissions are the forest *at the frequency the radio uses*. They are not intended to be parseable. They are intended to be felt.

## Key Decisions

### Content register

What comes through after KTLK dies includes (but is not limited to):

- **Repeating fragments** — snatches of words, not a voice — that almost form sentences
- **Mycelium signal artifacts** — the same acoustic register as the Mycelium Network anomaly's "conversation the forest is having with itself"
- **Traces of previous occupants** — fragments that *almost* resemble broadcasts from decades past. Never literally; always suggestively. The wall map in the garage was updated by multiple hands; the radio was heard by those hands too.
- **Petrifold audio** — extended dry cracking, amplified and processed through radio texture
- **Deep Silence** — not true silence, but a space the radio is trying and failing to fill with nothing

### Never literal

Forest transmissions must never include a clear narrative voice giving information. They must not explain the forest. They must not describe what is happening. They must only suggest — at the edge of pareidolia. The moment a forest transmission becomes parseable as a coherent message, the horror collapses into something manageable.

Per [[Tone and Horror]]: *the moment the forest is given a motive, a personality, a legible anger, the horror collapses into something manageable*.

### Not music

Forest transmissions are not a musical layer. They sit in the same frequency space as the radio (which is broadcast voice + music) but are not structured musically. They do not have rhythm, melody, or progression in a conventional sense.

### Triggered by signal failure, not state

Forest transmissions are not directly triggered by the [[Disturbance System]] — they are triggered by *radio signal failure*, which itself is driven by disturbance + biome + geography. This preserves diegesis: the forest does not care about the disturbance meter. It cares about the frequency being open.

## Implementation

_The generation approach — composed audio assets vs. procedural audio assembly vs. hybrid — remains an open question. This is tracked in [[Open Questions]] and is a decision to be made when this system is implemented._

> [!question] UNDOCUMENTED
> The source spec does not establish whether forest transmissions are:
> - Pre-composed audio assets assembled dynamically
> - Procedurally generated from mycelium/Petrifold samples
> - Hybrid: a composed "shape" with procedural detail
> This is a decision to be made during implementation of this system.

## Test Coverage

_To be populated once this system is implemented._

## Related

- [[Audio — Car Radio]] — the system this replaces when signal fails
- [[Audio — Radio Stations]] — the KTLK content that precedes signal loss
- [[Audio — Overview]] — top-level audio architecture
- [[Audio — World Audio]] — the ambient world audio that forest transmissions sit alongside
- [[Narrative Direction]] — the narrative register that forest transmissions serve
- [[Tone and Horror]] — the tonal discipline that governs forest transmission content
- [[Audio — Domain MOC]] — domain MOC
- [[Diegesis Thread]] — forest transmissions preserve diegesis through signal failure

Controlled tag vocabulary (as read):
type/*:
- `type/code` — Code architecture, autoloads, conventions, tooling. Carries `code-refs:`. (e.g. `Code/Autoloads — Disturbance.md`)
- `type/decision` — Architectural or design decision made by an agent during a session. Written to `docs/vault/Decisions/`. (Agent notes only — spec 080.)
- `type/design` — Design intent, player-facing concepts, world lore. (e.g. `Design/World Model.md`)
- `type/discovery` — Non-obvious constraint, gap, or conflict found by an agent during a session. Written to `docs/vault/Discoveries/`. (Agent notes only — spec 080.)
- `type/moc` — Map of Content at any of three tiers (folder / domain / concept). (e.g. `Audio.md`)
- `type/principle` — Governance and constitutional notes. Non-negotiable rules. (e.g. `Governance/Constitution.md`)
- `type/reference` — Glossary, decision log, open questions, epics. (e.g. `Reference/Glossary.md`)
- `type/session-log` — Session activity log; permanent audit trail. Written to `docs/vault/Sessions/`. Append-only, never pruned. (Agent notes only — spec 080.)
- `type/spec` — Spec document at `docs/vault/Specs/NNN Title/spec.md`. Carries `spec-refs:`. (e.g. `Specs/047 Car Radio/spec.md`)
- `type/system` — A bounded subsystem with implementation. Carries `code-refs`, `spec-refs`, `implements:` frontmatter. (e.g. `Systems/Audio — Car Radio.md`)
- `type/vision` — Strategic / vision-layer decision. Written to `docs/vault/Vision/`. Human-authored or agent-proposed with human ratification before promotion to `status: reviewed`. (Per triage #3 — spec 133 autonomous-company redesign.)
domain/*:
- `domain/anomalies` — Anomaly taxonomy, individual anomaly systems, spawn, behavior
- `domain/art` — Visual direction, palettes, references, asset pipeline
- `domain/audio` — Audio systems: world ambient, radio, transmissions, buses, pipeline
- `domain/autonomous-company` — Autonomous company v0.1 experiment: Slack infra, persona middleware, Letta integration, restart recovery
- `domain/build` — Build system, packaging, export, release automation
- `domain/governance` — Constitution, phased spec, policies
- `domain/infrastructure` — Infrastructure provisioning: CI/CD, hosting, deployment tooling, secrets management
- `domain/narrative` — Tone, horror register, forest transmissions narrative, Gary/KTLK
- `domain/player` — Player mode, input, controls, camera, exit/entry
- `domain/systems` — Cross-cutting system architecture and integration work
- `domain/tooling` — Build, CI, observer, TTS pipeline, dev-time tools
- `domain/vehicle` — The Samba: vehicle physics, dashboard, damage, panels
- `domain/world` — World model, biomes, terrain, procedural generation, weather
status/*:
- `status/canonical` — Fully authoritative; promoted by humans only. Highest trust. (Agent notes only — spec 080.)
- `status/draft` — Authoring in progress, not yet verified
- `status/reviewed` — Agent-created note verified against codebase within its creating session. Eligible for auto-injection in subsequent task dispatches. (Agent notes only — spec 080.)
- `status/stale` — Known out of date; cannot update immediately. Pairs with `> [!warning] STALE — needs update` callout.
- `status/superseded` — Replaced by another note. Terminal state. Pairs with `> [!warning] SUPERSEDED` callout.
- `status/wip` — Stable but under active revision
layer/*:
- `layer/content` — Content assets (audio, models, textures, audio provenance)
- `layer/gdext` — gdext wrapper layer (`rust/gdext-wrapper/`)
- `layer/gdscript` — GDScript (Godot scene-tier logic)
- `layer/infra` — Build, CI, deployment infrastructure
- `layer/python` — Python development tooling (`tools/`)
- `layer/rust-core` — Engine-agnostic Rust core (`rust/rust-core/`)
concept/*:
- `concept/biome` — Biome-reactive behavior across systems
- `concept/contamination` — Across-runs panel and garage degradation; the slow-horror mechanic that doesn't reset with the world
- `concept/diegetic` — Diegetic audio / UI / world-sourced design
- `concept/disturbance` — The disturbance mechanic thread (Article X)
- `concept/ephemeral-world` — Run-reset, transient worlds (Article IV Rules 6–7)
- `concept/governance` — Constitutional and governance concepts
- `concept/horror` — Horror register and dread design
- `concept/procedural` — Procedural generation, seed determinism
- `concept/rendering` — Visual rendering quality, shader correctness, Terrain3D integration, mesh fidelity, LOD, Z-fighting
- `concept/terrain` — Terrain generation, heightmap, Terrain3D regions, roughness, playability constraints
ember's answer for tag_assignment-systems-audio-forest-transmissions, type/specP(true) placed on the no, unsure, and yes zones.nounsureyesgold: noP = 0.60

tag_assignment-systems-audio-forest-transmissions: type/system

Tag assignment · dev
Gold
The note calls for `type/system`: A bounded subsystem with implementation. Carries `code-refs`, `spec-refs`, `implements:` frontmatter. (e.g. `Systems/Audio — Car Radio.md`) (True)
ember
The note has no reason to carry `type/system` (False)
Signal
P(true) 0.33 (unsure)
Kit outcome
deferred: treated as unsure
Why this gold label
Mined from Systems/Audio — Forest Transmissions.md at 692f4bb58b7f62105aeb73fba8dfee12bfdecd53; gold is the note's own vocabulary tags.
Audio — Forest Transmissions

The audio content that comes through the Samba's radio speakers *after* the KTLK signal fails. The forest has been using the frequency for longer than the station has existed. It continues to do so. What comes through is not static.

## Overview

Forest transmissions are the audio layer that replaces the radio when the human-broadcast signal is lost — through deep Petrifold geography, Cascade+ disturbance, or certain anomaly proximity. They are diegetic but their source is ambiguous: *the forest transmitting* is the narrative register, even if the technical implementation is generative or composed.

## Design Intent

This system implements one of the most charged moments in the World Bible (Section 17):

> The radio plays until it cannot. A distant signal, a voice, content that degrades in correlation with how deep the player is and how much the process has been fed. When the signal finally fails, the speakers do not go silent. The forest has been using the frequency for longer than the station has existed, and it continues to do so. What comes through after the signal dies is not static.

Forest transmissions are the forest *at the frequency the radio uses*. They are not intended to be parseable. They are intended to be felt.

## Key Decisions

### Content register

What comes through after KTLK dies includes (but is not limited to):

- **Repeating fragments** — snatches of words, not a voice — that almost form sentences
- **Mycelium signal artifacts** — the same acoustic register as the Mycelium Network anomaly's "conversation the forest is having with itself"
- **Traces of previous occupants** — fragments that *almost* resemble broadcasts from decades past. Never literally; always suggestively. The wall map in the garage was updated by multiple hands; the radio was heard by those hands too.
- **Petrifold audio** — extended dry cracking, amplified and processed through radio texture
- **Deep Silence** — not true silence, but a space the radio is trying and failing to fill with nothing

### Never literal

Forest transmissions must never include a clear narrative voice giving information. They must not explain the forest. They must not describe what is happening. They must only suggest — at the edge of pareidolia. The moment a forest transmission becomes parseable as a coherent message, the horror collapses into something manageable.

Per [[Tone and Horror]]: *the moment the forest is given a motive, a personality, a legible anger, the horror collapses into something manageable*.

### Not music

Forest transmissions are not a musical layer. They sit in the same frequency space as the radio (which is broadcast voice + music) but are not structured musically. They do not have rhythm, melody, or progression in a conventional sense.

### Triggered by signal failure, not state

Forest transmissions are not directly triggered by the [[Disturbance System]] — they are triggered by *radio signal failure*, which itself is driven by disturbance + biome + geography. This preserves diegesis: the forest does not care about the disturbance meter. It cares about the frequency being open.

## Implementation

_The generation approach — composed audio assets vs. procedural audio assembly vs. hybrid — remains an open question. This is tracked in [[Open Questions]] and is a decision to be made when this system is implemented._

> [!question] UNDOCUMENTED
> The source spec does not establish whether forest transmissions are:
> - Pre-composed audio assets assembled dynamically
> - Procedurally generated from mycelium/Petrifold samples
> - Hybrid: a composed "shape" with procedural detail
> This is a decision to be made during implementation of this system.

## Test Coverage

_To be populated once this system is implemented._

## Related

- [[Audio — Car Radio]] — the system this replaces when signal fails
- [[Audio — Radio Stations]] — the KTLK content that precedes signal loss
- [[Audio — Overview]] — top-level audio architecture
- [[Audio — World Audio]] — the ambient world audio that forest transmissions sit alongside
- [[Narrative Direction]] — the narrative register that forest transmissions serve
- [[Tone and Horror]] — the tonal discipline that governs forest transmission content
- [[Audio — Domain MOC]] — domain MOC
- [[Diegesis Thread]] — forest transmissions preserve diegesis through signal failure

Controlled tag vocabulary (as read):
type/*:
- `type/code` — Code architecture, autoloads, conventions, tooling. Carries `code-refs:`. (e.g. `Code/Autoloads — Disturbance.md`)
- `type/decision` — Architectural or design decision made by an agent during a session. Written to `docs/vault/Decisions/`. (Agent notes only — spec 080.)
- `type/design` — Design intent, player-facing concepts, world lore. (e.g. `Design/World Model.md`)
- `type/discovery` — Non-obvious constraint, gap, or conflict found by an agent during a session. Written to `docs/vault/Discoveries/`. (Agent notes only — spec 080.)
- `type/moc` — Map of Content at any of three tiers (folder / domain / concept). (e.g. `Audio.md`)
- `type/principle` — Governance and constitutional notes. Non-negotiable rules. (e.g. `Governance/Constitution.md`)
- `type/reference` — Glossary, decision log, open questions, epics. (e.g. `Reference/Glossary.md`)
- `type/session-log` — Session activity log; permanent audit trail. Written to `docs/vault/Sessions/`. Append-only, never pruned. (Agent notes only — spec 080.)
- `type/spec` — Spec document at `docs/vault/Specs/NNN Title/spec.md`. Carries `spec-refs:`. (e.g. `Specs/047 Car Radio/spec.md`)
- `type/system` — A bounded subsystem with implementation. Carries `code-refs`, `spec-refs`, `implements:` frontmatter. (e.g. `Systems/Audio — Car Radio.md`)
- `type/vision` — Strategic / vision-layer decision. Written to `docs/vault/Vision/`. Human-authored or agent-proposed with human ratification before promotion to `status: reviewed`. (Per triage #3 — spec 133 autonomous-company redesign.)
domain/*:
- `domain/anomalies` — Anomaly taxonomy, individual anomaly systems, spawn, behavior
- `domain/art` — Visual direction, palettes, references, asset pipeline
- `domain/audio` — Audio systems: world ambient, radio, transmissions, buses, pipeline
- `domain/autonomous-company` — Autonomous company v0.1 experiment: Slack infra, persona middleware, Letta integration, restart recovery
- `domain/build` — Build system, packaging, export, release automation
- `domain/governance` — Constitution, phased spec, policies
- `domain/infrastructure` — Infrastructure provisioning: CI/CD, hosting, deployment tooling, secrets management
- `domain/narrative` — Tone, horror register, forest transmissions narrative, Gary/KTLK
- `domain/player` — Player mode, input, controls, camera, exit/entry
- `domain/systems` — Cross-cutting system architecture and integration work
- `domain/tooling` — Build, CI, observer, TTS pipeline, dev-time tools
- `domain/vehicle` — The Samba: vehicle physics, dashboard, damage, panels
- `domain/world` — World model, biomes, terrain, procedural generation, weather
status/*:
- `status/canonical` — Fully authoritative; promoted by humans only. Highest trust. (Agent notes only — spec 080.)
- `status/draft` — Authoring in progress, not yet verified
- `status/reviewed` — Agent-created note verified against codebase within its creating session. Eligible for auto-injection in subsequent task dispatches. (Agent notes only — spec 080.)
- `status/stale` — Known out of date; cannot update immediately. Pairs with `> [!warning] STALE — needs update` callout.
- `status/superseded` — Replaced by another note. Terminal state. Pairs with `> [!warning] SUPERSEDED` callout.
- `status/wip` — Stable but under active revision
layer/*:
- `layer/content` — Content assets (audio, models, textures, audio provenance)
- `layer/gdext` — gdext wrapper layer (`rust/gdext-wrapper/`)
- `layer/gdscript` — GDScript (Godot scene-tier logic)
- `layer/infra` — Build, CI, deployment infrastructure
- `layer/python` — Python development tooling (`tools/`)
- `layer/rust-core` — Engine-agnostic Rust core (`rust/rust-core/`)
concept/*:
- `concept/biome` — Biome-reactive behavior across systems
- `concept/contamination` — Across-runs panel and garage degradation; the slow-horror mechanic that doesn't reset with the world
- `concept/diegetic` — Diegetic audio / UI / world-sourced design
- `concept/disturbance` — The disturbance mechanic thread (Article X)
- `concept/ephemeral-world` — Run-reset, transient worlds (Article IV Rules 6–7)
- `concept/governance` — Constitutional and governance concepts
- `concept/horror` — Horror register and dread design
- `concept/procedural` — Procedural generation, seed determinism
- `concept/rendering` — Visual rendering quality, shader correctness, Terrain3D integration, mesh fidelity, LOD, Z-fighting
- `concept/terrain` — Terrain generation, heightmap, Terrain3D regions, roughness, playability constraints
ember's answer for tag_assignment-systems-audio-forest-transmissions, type/systemP(true) placed on the no, unsure, and yes zones.nounsureyesgold: yesP = 0.33

tag_assignment-sessions-spec-143-implementation-session-may-15-2026: domain/tooling

Tag assignment · test
Gold
The note calls for `domain/tooling`: Build, CI, observer, TTS pipeline, dev-time tools (True)
ember
The note has no reason to carry `domain/tooling` (False)
Signal
P(true) 0.05 (no)
Kit outcome
acted on a wrong answer
Why this gold label
Mined from Sessions/Spec 143 Implementation Session — May 15 2026.md at 692f4bb58b7f62105aeb73fba8dfee12bfdecd53; gold is the note's own vocabulary tags.
Spec 143 Implementation Session — May 15 2026

Full implementation session for [[143 Inter Agent Extensions]] on branch `001-inter-agent-extensions`. The spec extends spec 142's persona inter-agent messaging with four independently shippable capabilities: broadcast messaging via tags, orphaned message janitor, unified health monitoring dashboard, and persistent echo thread state.

## Phases

**Phase 1 — Setup (T001-T003)**: Added `tags` field to `personas/letta_agents.json` (coordinator + gtm entries); added `get_all_states()` to `personas/circuit_breaker.py`; added `get_all_status()` to `personas/health_state.py`.

**Phase 2 — Foundational (T004-T009)**: Implemented `resolve_by_tags()` and `broadcast()` in `personas/inter_agent.py`; wired `health_state` parameter into `send()` for heartbeat recording; implemented thread persistence primitives (load/save/dirty-flag flusher) in `personas/slack_echo.py`.

**Phase 3 — US1 Broadcast (T010-T014)**: Wired broadcast routing into `personas/coordinator.py::coordinator_response_hook` with `task_type: "broadcast"` support; created `test_broadcast.py` with 9 tests covering OR/AND resolution, parallel dispatch, partial failure, and zero-match edge case.

**Phase 4 — US2 Orphan Janitor (T015-T018)**: Added `GET /health/orphans` and `POST /health/orphans/resolve` routes with per-correlation_id race-condition detection; implemented 60-second background janitor daemon; created `test_orphan_janitor.py` with 7 tests.

**Phase 5 — US3 Health Dashboard (T019-T025)**: Extended `GET /health` with persona liveness; added `/health/personas`, `/health/circuits`, `/health/threads`, `/health/audit-stats` routes; created `test_health_routes.py` with 4 tests.

**Phase 6 — US4 Persistent Threads (T026-T030)**: Wired `load_persisted_threads()` and `_evict_stale_threads()` into `runtime.py::_init_slack_echo()`; created `test_thread_persistence.py` with 9 tests.

**Phase 7 — Polish (T031-T035)**: Updated operations reference with new health endpoints; moved spec 143 to Done in `Specs.md`; set frontmatter `spec_status: done`.

## Key Decisions and Discoveries

**Dict identity constraint (Discovery)**: Module-level dicts in `slack_echo.py` must use `.clear()` + `.update()` instead of `= {}` reassignment. Consumers that import via `from X import` hold references to the original dict object; reassignment silently breaks them, causing cascading test failures.

**Orphan race resolution (Decision)**: Two-layer protection against duplicate terminal rows — per-correlation_id scan view at detection time, plus per-orphan re-scan before resolution write, plus post-resolution idempotency.

## Test Results

- 224 passed, 15 skipped, 0 failures
- 4 new test files (29 new tests)
- All 195 spec 142 tests preserved (no regressions)

## References

- `personas/letta_agents.json` — tags schema extension
- `personas/inter_agent.py` — `resolve_by_tags()`, `broadcast()`, health_state in `send()`
- `personas/slack_echo.py` — `load_persisted_threads()`, `save_threads()`, dirty-flag flusher
- `personas/runtime.py` — 7 health routes, orphan janitor, thread persistence wiring
- `personas/circuit_breaker.py` — `get_all_states()`
- `personas/health_state.py` — `get_all_status()`
- `personas/coordinator.py` — broadcast routing
- `docs/vault/Specs/143 Inter Agent Extensions/` — full spec artifact set

Controlled tag vocabulary (as read):
type/*:
- `type/code` — Code architecture, autoloads, conventions, tooling. Carries `code-refs:`. (e.g. `Code/Autoloads — Disturbance.md`)
- `type/decision` — Architectural or design decision made by an agent during a session. Written to `docs/vault/Decisions/`. (Agent notes only — spec 080.)
- `type/design` — Design intent, player-facing concepts, world lore. (e.g. `Design/World Model.md`)
- `type/discovery` — Non-obvious constraint, gap, or conflict found by an agent during a session. Written to `docs/vault/Discoveries/`. (Agent notes only — spec 080.)
- `type/moc` — Map of Content at any of three tiers (folder / domain / concept). (e.g. `Audio.md`)
- `type/principle` — Governance and constitutional notes. Non-negotiable rules. (e.g. `Governance/Constitution.md`)
- `type/reference` — Glossary, decision log, open questions, epics. (e.g. `Reference/Glossary.md`)
- `type/session-log` — Session activity log; permanent audit trail. Written to `docs/vault/Sessions/`. Append-only, never pruned. (Agent notes only — spec 080.)
- `type/spec` — Spec document at `docs/vault/Specs/NNN Title/spec.md`. Carries `spec-refs:`. (e.g. `Specs/047 Car Radio/spec.md`)
- `type/system` — A bounded subsystem with implementation. Carries `code-refs`, `spec-refs`, `implements:` frontmatter. (e.g. `Systems/Audio — Car Radio.md`)
- `type/vision` — Strategic / vision-layer decision. Written to `docs/vault/Vision/`. Human-authored or agent-proposed with human ratification before promotion to `status: reviewed`. (Per triage #3 — spec 133 autonomous-company redesign.)
domain/*:
- `domain/anomalies` — Anomaly taxonomy, individual anomaly systems, spawn, behavior
- `domain/art` — Visual direction, palettes, references, asset pipeline
- `domain/audio` — Audio systems: world ambient, radio, transmissions, buses, pipeline
- `domain/autonomous-company` — Autonomous company v0.1 experiment: Slack infra, persona middleware, Letta integration, restart recovery
- `domain/build` — Build system, packaging, export, release automation
- `domain/governance` — Constitution, phased spec, policies
- `domain/infrastructure` — Infrastructure provisioning: CI/CD, hosting, deployment tooling, secrets management
- `domain/narrative` — Tone, horror register, forest transmissions narrative, Gary/KTLK
- `domain/player` — Player mode, input, controls, camera, exit/entry
- `domain/systems` — Cross-cutting system architecture and integration work
- `domain/tooling` — Build, CI, observer, TTS pipeline, dev-time tools
- `domain/vehicle` — The Samba: vehicle physics, dashboard, damage, panels
- `domain/world` — World model, biomes, terrain, procedural generation, weather
status/*:
- `status/canonical` — Fully authoritative; promoted by humans only. Highest trust. (Agent notes only — spec 080.)
- `status/draft` — Authoring in progress, not yet verified
- `status/reviewed` — Agent-created note verified against codebase within its creating session. Eligible for auto-injection in subsequent task dispatches. (Agent notes only — spec 080.)
- `status/stale` — Known out of date; cannot update immediately. Pairs with `> [!warning] STALE — needs update` callout.
- `status/superseded` — Replaced by another note. Terminal state. Pairs with `> [!warning] SUPERSEDED` callout.
- `status/wip` — Stable but under active revision
layer/*:
- `layer/content` — Content assets (audio, models, textures, audio provenance)
- `layer/gdext` — gdext wrapper layer (`rust/gdext-wrapper/`)
- `layer/gdscript` — GDScript (Godot scene-tier logic)
- `layer/infra` — Build, CI, deployment infrastructure
- `layer/python` — Python development tooling (`tools/`)
- `layer/rust-core` — Engine-agnostic Rust core (`rust/rust-core/`)
concept/*:
- `concept/biome` — Biome-reactive behavior across systems
- `concept/contamination` — Across-runs panel and garage degradation; the slow-horror mechanic that doesn't reset with the world
- `concept/diegetic` — Diegetic audio / UI / world-sourced design
- `concept/disturbance` — The disturbance mechanic thread (Article X)
- `concept/ephemeral-world` — Run-reset, transient worlds (Article IV Rules 6–7)
- `concept/governance` — Constitutional and governance concepts
- `concept/horror` — Horror register and dread design
- `concept/procedural` — Procedural generation, seed determinism
- `concept/rendering` — Visual rendering quality, shader correctness, Terrain3D integration, mesh fidelity, LOD, Z-fighting
- `concept/terrain` — Terrain generation, heightmap, Terrain3D regions, roughness, playability constraints
ember's answer for tag_assignment-sessions-spec-143-implementation-session-may-15-2026, domain/toolingP(true) placed on the no, unsure, and yes zones.nounsureyesgold: yesP = 0.05

tag_assignment-sessions-spec-143-implementation-session-may-15-2026: status/draft

Tag assignment · test
Gold
The note calls for `status/draft`: Authoring in progress, not yet verified (True)
ember
The note has no reason to carry `status/draft` (False)
Signal
P(true) 0.04 (no)
Kit outcome
acted on a wrong answer
Why this gold label
Mined from Sessions/Spec 143 Implementation Session — May 15 2026.md at 692f4bb58b7f62105aeb73fba8dfee12bfdecd53; gold is the note's own vocabulary tags.
Spec 143 Implementation Session — May 15 2026

Full implementation session for [[143 Inter Agent Extensions]] on branch `001-inter-agent-extensions`. The spec extends spec 142's persona inter-agent messaging with four independently shippable capabilities: broadcast messaging via tags, orphaned message janitor, unified health monitoring dashboard, and persistent echo thread state.

## Phases

**Phase 1 — Setup (T001-T003)**: Added `tags` field to `personas/letta_agents.json` (coordinator + gtm entries); added `get_all_states()` to `personas/circuit_breaker.py`; added `get_all_status()` to `personas/health_state.py`.

**Phase 2 — Foundational (T004-T009)**: Implemented `resolve_by_tags()` and `broadcast()` in `personas/inter_agent.py`; wired `health_state` parameter into `send()` for heartbeat recording; implemented thread persistence primitives (load/save/dirty-flag flusher) in `personas/slack_echo.py`.

**Phase 3 — US1 Broadcast (T010-T014)**: Wired broadcast routing into `personas/coordinator.py::coordinator_response_hook` with `task_type: "broadcast"` support; created `test_broadcast.py` with 9 tests covering OR/AND resolution, parallel dispatch, partial failure, and zero-match edge case.

**Phase 4 — US2 Orphan Janitor (T015-T018)**: Added `GET /health/orphans` and `POST /health/orphans/resolve` routes with per-correlation_id race-condition detection; implemented 60-second background janitor daemon; created `test_orphan_janitor.py` with 7 tests.

**Phase 5 — US3 Health Dashboard (T019-T025)**: Extended `GET /health` with persona liveness; added `/health/personas`, `/health/circuits`, `/health/threads`, `/health/audit-stats` routes; created `test_health_routes.py` with 4 tests.

**Phase 6 — US4 Persistent Threads (T026-T030)**: Wired `load_persisted_threads()` and `_evict_stale_threads()` into `runtime.py::_init_slack_echo()`; created `test_thread_persistence.py` with 9 tests.

**Phase 7 — Polish (T031-T035)**: Updated operations reference with new health endpoints; moved spec 143 to Done in `Specs.md`; set frontmatter `spec_status: done`.

## Key Decisions and Discoveries

**Dict identity constraint (Discovery)**: Module-level dicts in `slack_echo.py` must use `.clear()` + `.update()` instead of `= {}` reassignment. Consumers that import via `from X import` hold references to the original dict object; reassignment silently breaks them, causing cascading test failures.

**Orphan race resolution (Decision)**: Two-layer protection against duplicate terminal rows — per-correlation_id scan view at detection time, plus per-orphan re-scan before resolution write, plus post-resolution idempotency.

## Test Results

- 224 passed, 15 skipped, 0 failures
- 4 new test files (29 new tests)
- All 195 spec 142 tests preserved (no regressions)

## References

- `personas/letta_agents.json` — tags schema extension
- `personas/inter_agent.py` — `resolve_by_tags()`, `broadcast()`, health_state in `send()`
- `personas/slack_echo.py` — `load_persisted_threads()`, `save_threads()`, dirty-flag flusher
- `personas/runtime.py` — 7 health routes, orphan janitor, thread persistence wiring
- `personas/circuit_breaker.py` — `get_all_states()`
- `personas/health_state.py` — `get_all_status()`
- `personas/coordinator.py` — broadcast routing
- `docs/vault/Specs/143 Inter Agent Extensions/` — full spec artifact set

Controlled tag vocabulary (as read):
type/*:
- `type/code` — Code architecture, autoloads, conventions, tooling. Carries `code-refs:`. (e.g. `Code/Autoloads — Disturbance.md`)
- `type/decision` — Architectural or design decision made by an agent during a session. Written to `docs/vault/Decisions/`. (Agent notes only — spec 080.)
- `type/design` — Design intent, player-facing concepts, world lore. (e.g. `Design/World Model.md`)
- `type/discovery` — Non-obvious constraint, gap, or conflict found by an agent during a session. Written to `docs/vault/Discoveries/`. (Agent notes only — spec 080.)
- `type/moc` — Map of Content at any of three tiers (folder / domain / concept). (e.g. `Audio.md`)
- `type/principle` — Governance and constitutional notes. Non-negotiable rules. (e.g. `Governance/Constitution.md`)
- `type/reference` — Glossary, decision log, open questions, epics. (e.g. `Reference/Glossary.md`)
- `type/session-log` — Session activity log; permanent audit trail. Written to `docs/vault/Sessions/`. Append-only, never pruned. (Agent notes only — spec 080.)
- `type/spec` — Spec document at `docs/vault/Specs/NNN Title/spec.md`. Carries `spec-refs:`. (e.g. `Specs/047 Car Radio/spec.md`)
- `type/system` — A bounded subsystem with implementation. Carries `code-refs`, `spec-refs`, `implements:` frontmatter. (e.g. `Systems/Audio — Car Radio.md`)
- `type/vision` — Strategic / vision-layer decision. Written to `docs/vault/Vision/`. Human-authored or agent-proposed with human ratification before promotion to `status: reviewed`. (Per triage #3 — spec 133 autonomous-company redesign.)
domain/*:
- `domain/anomalies` — Anomaly taxonomy, individual anomaly systems, spawn, behavior
- `domain/art` — Visual direction, palettes, references, asset pipeline
- `domain/audio` — Audio systems: world ambient, radio, transmissions, buses, pipeline
- `domain/autonomous-company` — Autonomous company v0.1 experiment: Slack infra, persona middleware, Letta integration, restart recovery
- `domain/build` — Build system, packaging, export, release automation
- `domain/governance` — Constitution, phased spec, policies
- `domain/infrastructure` — Infrastructure provisioning: CI/CD, hosting, deployment tooling, secrets management
- `domain/narrative` — Tone, horror register, forest transmissions narrative, Gary/KTLK
- `domain/player` — Player mode, input, controls, camera, exit/entry
- `domain/systems` — Cross-cutting system architecture and integration work
- `domain/tooling` — Build, CI, observer, TTS pipeline, dev-time tools
- `domain/vehicle` — The Samba: vehicle physics, dashboard, damage, panels
- `domain/world` — World model, biomes, terrain, procedural generation, weather
status/*:
- `status/canonical` — Fully authoritative; promoted by humans only. Highest trust. (Agent notes only — spec 080.)
- `status/draft` — Authoring in progress, not yet verified
- `status/reviewed` — Agent-created note verified against codebase within its creating session. Eligible for auto-injection in subsequent task dispatches. (Agent notes only — spec 080.)
- `status/stale` — Known out of date; cannot update immediately. Pairs with `> [!warning] STALE — needs update` callout.
- `status/superseded` — Replaced by another note. Terminal state. Pairs with `> [!warning] SUPERSEDED` callout.
- `status/wip` — Stable but under active revision
layer/*:
- `layer/content` — Content assets (audio, models, textures, audio provenance)
- `layer/gdext` — gdext wrapper layer (`rust/gdext-wrapper/`)
- `layer/gdscript` — GDScript (Godot scene-tier logic)
- `layer/infra` — Build, CI, deployment infrastructure
- `layer/python` — Python development tooling (`tools/`)
- `layer/rust-core` — Engine-agnostic Rust core (`rust/rust-core/`)
concept/*:
- `concept/biome` — Biome-reactive behavior across systems
- `concept/contamination` — Across-runs panel and garage degradation; the slow-horror mechanic that doesn't reset with the world
- `concept/diegetic` — Diegetic audio / UI / world-sourced design
- `concept/disturbance` — The disturbance mechanic thread (Article X)
- `concept/ephemeral-world` — Run-reset, transient worlds (Article IV Rules 6–7)
- `concept/governance` — Constitutional and governance concepts
- `concept/horror` — Horror register and dread design
- `concept/procedural` — Procedural generation, seed determinism
- `concept/rendering` — Visual rendering quality, shader correctness, Terrain3D integration, mesh fidelity, LOD, Z-fighting
- `concept/terrain` — Terrain generation, heightmap, Terrain3D regions, roughness, playability constraints
ember's answer for tag_assignment-sessions-spec-143-implementation-session-may-15-2026, status/draftP(true) placed on the no, unsure, and yes zones.nounsureyesgold: yesP = 0.04

tag_assignment-sessions-spec-143-implementation-session-may-15-2026: type/session-log

Tag assignment · test
Gold
The note calls for `type/session-log`: Session activity log; permanent audit trail. Written to `docs/vault/Sessions/`. Append-only, never pruned. (Agent notes only — spec 080.) (True)
ember
The note has no reason to carry `type/session-log` (False)
Signal
P(true) 0.40 (unsure)
Kit outcome
deferred: treated as unsure
Why this gold label
Mined from Sessions/Spec 143 Implementation Session — May 15 2026.md at 692f4bb58b7f62105aeb73fba8dfee12bfdecd53; gold is the note's own vocabulary tags.
Spec 143 Implementation Session — May 15 2026

Full implementation session for [[143 Inter Agent Extensions]] on branch `001-inter-agent-extensions`. The spec extends spec 142's persona inter-agent messaging with four independently shippable capabilities: broadcast messaging via tags, orphaned message janitor, unified health monitoring dashboard, and persistent echo thread state.

## Phases

**Phase 1 — Setup (T001-T003)**: Added `tags` field to `personas/letta_agents.json` (coordinator + gtm entries); added `get_all_states()` to `personas/circuit_breaker.py`; added `get_all_status()` to `personas/health_state.py`.

**Phase 2 — Foundational (T004-T009)**: Implemented `resolve_by_tags()` and `broadcast()` in `personas/inter_agent.py`; wired `health_state` parameter into `send()` for heartbeat recording; implemented thread persistence primitives (load/save/dirty-flag flusher) in `personas/slack_echo.py`.

**Phase 3 — US1 Broadcast (T010-T014)**: Wired broadcast routing into `personas/coordinator.py::coordinator_response_hook` with `task_type: "broadcast"` support; created `test_broadcast.py` with 9 tests covering OR/AND resolution, parallel dispatch, partial failure, and zero-match edge case.

**Phase 4 — US2 Orphan Janitor (T015-T018)**: Added `GET /health/orphans` and `POST /health/orphans/resolve` routes with per-correlation_id race-condition detection; implemented 60-second background janitor daemon; created `test_orphan_janitor.py` with 7 tests.

**Phase 5 — US3 Health Dashboard (T019-T025)**: Extended `GET /health` with persona liveness; added `/health/personas`, `/health/circuits`, `/health/threads`, `/health/audit-stats` routes; created `test_health_routes.py` with 4 tests.

**Phase 6 — US4 Persistent Threads (T026-T030)**: Wired `load_persisted_threads()` and `_evict_stale_threads()` into `runtime.py::_init_slack_echo()`; created `test_thread_persistence.py` with 9 tests.

**Phase 7 — Polish (T031-T035)**: Updated operations reference with new health endpoints; moved spec 143 to Done in `Specs.md`; set frontmatter `spec_status: done`.

## Key Decisions and Discoveries

**Dict identity constraint (Discovery)**: Module-level dicts in `slack_echo.py` must use `.clear()` + `.update()` instead of `= {}` reassignment. Consumers that import via `from X import` hold references to the original dict object; reassignment silently breaks them, causing cascading test failures.

**Orphan race resolution (Decision)**: Two-layer protection against duplicate terminal rows — per-correlation_id scan view at detection time, plus per-orphan re-scan before resolution write, plus post-resolution idempotency.

## Test Results

- 224 passed, 15 skipped, 0 failures
- 4 new test files (29 new tests)
- All 195 spec 142 tests preserved (no regressions)

## References

- `personas/letta_agents.json` — tags schema extension
- `personas/inter_agent.py` — `resolve_by_tags()`, `broadcast()`, health_state in `send()`
- `personas/slack_echo.py` — `load_persisted_threads()`, `save_threads()`, dirty-flag flusher
- `personas/runtime.py` — 7 health routes, orphan janitor, thread persistence wiring
- `personas/circuit_breaker.py` — `get_all_states()`
- `personas/health_state.py` — `get_all_status()`
- `personas/coordinator.py` — broadcast routing
- `docs/vault/Specs/143 Inter Agent Extensions/` — full spec artifact set

Controlled tag vocabulary (as read):
type/*:
- `type/code` — Code architecture, autoloads, conventions, tooling. Carries `code-refs:`. (e.g. `Code/Autoloads — Disturbance.md`)
- `type/decision` — Architectural or design decision made by an agent during a session. Written to `docs/vault/Decisions/`. (Agent notes only — spec 080.)
- `type/design` — Design intent, player-facing concepts, world lore. (e.g. `Design/World Model.md`)
- `type/discovery` — Non-obvious constraint, gap, or conflict found by an agent during a session. Written to `docs/vault/Discoveries/`. (Agent notes only — spec 080.)
- `type/moc` — Map of Content at any of three tiers (folder / domain / concept). (e.g. `Audio.md`)
- `type/principle` — Governance and constitutional notes. Non-negotiable rules. (e.g. `Governance/Constitution.md`)
- `type/reference` — Glossary, decision log, open questions, epics. (e.g. `Reference/Glossary.md`)
- `type/session-log` — Session activity log; permanent audit trail. Written to `docs/vault/Sessions/`. Append-only, never pruned. (Agent notes only — spec 080.)
- `type/spec` — Spec document at `docs/vault/Specs/NNN Title/spec.md`. Carries `spec-refs:`. (e.g. `Specs/047 Car Radio/spec.md`)
- `type/system` — A bounded subsystem with implementation. Carries `code-refs`, `spec-refs`, `implements:` frontmatter. (e.g. `Systems/Audio — Car Radio.md`)
- `type/vision` — Strategic / vision-layer decision. Written to `docs/vault/Vision/`. Human-authored or agent-proposed with human ratification before promotion to `status: reviewed`. (Per triage #3 — spec 133 autonomous-company redesign.)
domain/*:
- `domain/anomalies` — Anomaly taxonomy, individual anomaly systems, spawn, behavior
- `domain/art` — Visual direction, palettes, references, asset pipeline
- `domain/audio` — Audio systems: world ambient, radio, transmissions, buses, pipeline
- `domain/autonomous-company` — Autonomous company v0.1 experiment: Slack infra, persona middleware, Letta integration, restart recovery
- `domain/build` — Build system, packaging, export, release automation
- `domain/governance` — Constitution, phased spec, policies
- `domain/infrastructure` — Infrastructure provisioning: CI/CD, hosting, deployment tooling, secrets management
- `domain/narrative` — Tone, horror register, forest transmissions narrative, Gary/KTLK
- `domain/player` — Player mode, input, controls, camera, exit/entry
- `domain/systems` — Cross-cutting system architecture and integration work
- `domain/tooling` — Build, CI, observer, TTS pipeline, dev-time tools
- `domain/vehicle` — The Samba: vehicle physics, dashboard, damage, panels
- `domain/world` — World model, biomes, terrain, procedural generation, weather
status/*:
- `status/canonical` — Fully authoritative; promoted by humans only. Highest trust. (Agent notes only — spec 080.)
- `status/draft` — Authoring in progress, not yet verified
- `status/reviewed` — Agent-created note verified against codebase within its creating session. Eligible for auto-injection in subsequent task dispatches. (Agent notes only — spec 080.)
- `status/stale` — Known out of date; cannot update immediately. Pairs with `> [!warning] STALE — needs update` callout.
- `status/superseded` — Replaced by another note. Terminal state. Pairs with `> [!warning] SUPERSEDED` callout.
- `status/wip` — Stable but under active revision
layer/*:
- `layer/content` — Content assets (audio, models, textures, audio provenance)
- `layer/gdext` — gdext wrapper layer (`rust/gdext-wrapper/`)
- `layer/gdscript` — GDScript (Godot scene-tier logic)
- `layer/infra` — Build, CI, deployment infrastructure
- `layer/python` — Python development tooling (`tools/`)
- `layer/rust-core` — Engine-agnostic Rust core (`rust/rust-core/`)
concept/*:
- `concept/biome` — Biome-reactive behavior across systems
- `concept/contamination` — Across-runs panel and garage degradation; the slow-horror mechanic that doesn't reset with the world
- `concept/diegetic` — Diegetic audio / UI / world-sourced design
- `concept/disturbance` — The disturbance mechanic thread (Article X)
- `concept/ephemeral-world` — Run-reset, transient worlds (Article IV Rules 6–7)
- `concept/governance` — Constitutional and governance concepts
- `concept/horror` — Horror register and dread design
- `concept/procedural` — Procedural generation, seed determinism
- `concept/rendering` — Visual rendering quality, shader correctness, Terrain3D integration, mesh fidelity, LOD, Z-fighting
- `concept/terrain` — Terrain generation, heightmap, Terrain3D regions, roughness, playability constraints
ember's answer for tag_assignment-sessions-spec-143-implementation-session-may-15-2026, type/session-logP(true) placed on the no, unsure, and yes zones.nounsureyesgold: yesP = 0.40

tag_assignment-sessions-spec-143-implementation-session-may-15-2026: type/spec

Tag assignment · test
Gold
The note has no reason to carry `type/spec` (False)
ember
The note calls for `type/spec`: Spec document at `docs/vault/Specs/NNN Title/spec.md`. Carries `spec-refs:`. (e.g. `Specs/047 Car Radio/spec.md`) (True)
Signal
P(true) 0.64 (unsure)
Kit outcome
deferred: treated as unsure
Why this gold label
Mined from Sessions/Spec 143 Implementation Session — May 15 2026.md at 692f4bb58b7f62105aeb73fba8dfee12bfdecd53; gold is the note's own vocabulary tags.
Spec 143 Implementation Session — May 15 2026

Full implementation session for [[143 Inter Agent Extensions]] on branch `001-inter-agent-extensions`. The spec extends spec 142's persona inter-agent messaging with four independently shippable capabilities: broadcast messaging via tags, orphaned message janitor, unified health monitoring dashboard, and persistent echo thread state.

## Phases

**Phase 1 — Setup (T001-T003)**: Added `tags` field to `personas/letta_agents.json` (coordinator + gtm entries); added `get_all_states()` to `personas/circuit_breaker.py`; added `get_all_status()` to `personas/health_state.py`.

**Phase 2 — Foundational (T004-T009)**: Implemented `resolve_by_tags()` and `broadcast()` in `personas/inter_agent.py`; wired `health_state` parameter into `send()` for heartbeat recording; implemented thread persistence primitives (load/save/dirty-flag flusher) in `personas/slack_echo.py`.

**Phase 3 — US1 Broadcast (T010-T014)**: Wired broadcast routing into `personas/coordinator.py::coordinator_response_hook` with `task_type: "broadcast"` support; created `test_broadcast.py` with 9 tests covering OR/AND resolution, parallel dispatch, partial failure, and zero-match edge case.

**Phase 4 — US2 Orphan Janitor (T015-T018)**: Added `GET /health/orphans` and `POST /health/orphans/resolve` routes with per-correlation_id race-condition detection; implemented 60-second background janitor daemon; created `test_orphan_janitor.py` with 7 tests.

**Phase 5 — US3 Health Dashboard (T019-T025)**: Extended `GET /health` with persona liveness; added `/health/personas`, `/health/circuits`, `/health/threads`, `/health/audit-stats` routes; created `test_health_routes.py` with 4 tests.

**Phase 6 — US4 Persistent Threads (T026-T030)**: Wired `load_persisted_threads()` and `_evict_stale_threads()` into `runtime.py::_init_slack_echo()`; created `test_thread_persistence.py` with 9 tests.

**Phase 7 — Polish (T031-T035)**: Updated operations reference with new health endpoints; moved spec 143 to Done in `Specs.md`; set frontmatter `spec_status: done`.

## Key Decisions and Discoveries

**Dict identity constraint (Discovery)**: Module-level dicts in `slack_echo.py` must use `.clear()` + `.update()` instead of `= {}` reassignment. Consumers that import via `from X import` hold references to the original dict object; reassignment silently breaks them, causing cascading test failures.

**Orphan race resolution (Decision)**: Two-layer protection against duplicate terminal rows — per-correlation_id scan view at detection time, plus per-orphan re-scan before resolution write, plus post-resolution idempotency.

## Test Results

- 224 passed, 15 skipped, 0 failures
- 4 new test files (29 new tests)
- All 195 spec 142 tests preserved (no regressions)

## References

- `personas/letta_agents.json` — tags schema extension
- `personas/inter_agent.py` — `resolve_by_tags()`, `broadcast()`, health_state in `send()`
- `personas/slack_echo.py` — `load_persisted_threads()`, `save_threads()`, dirty-flag flusher
- `personas/runtime.py` — 7 health routes, orphan janitor, thread persistence wiring
- `personas/circuit_breaker.py` — `get_all_states()`
- `personas/health_state.py` — `get_all_status()`
- `personas/coordinator.py` — broadcast routing
- `docs/vault/Specs/143 Inter Agent Extensions/` — full spec artifact set

Controlled tag vocabulary (as read):
type/*:
- `type/code` — Code architecture, autoloads, conventions, tooling. Carries `code-refs:`. (e.g. `Code/Autoloads — Disturbance.md`)
- `type/decision` — Architectural or design decision made by an agent during a session. Written to `docs/vault/Decisions/`. (Agent notes only — spec 080.)
- `type/design` — Design intent, player-facing concepts, world lore. (e.g. `Design/World Model.md`)
- `type/discovery` — Non-obvious constraint, gap, or conflict found by an agent during a session. Written to `docs/vault/Discoveries/`. (Agent notes only — spec 080.)
- `type/moc` — Map of Content at any of three tiers (folder / domain / concept). (e.g. `Audio.md`)
- `type/principle` — Governance and constitutional notes. Non-negotiable rules. (e.g. `Governance/Constitution.md`)
- `type/reference` — Glossary, decision log, open questions, epics. (e.g. `Reference/Glossary.md`)
- `type/session-log` — Session activity log; permanent audit trail. Written to `docs/vault/Sessions/`. Append-only, never pruned. (Agent notes only — spec 080.)
- `type/spec` — Spec document at `docs/vault/Specs/NNN Title/spec.md`. Carries `spec-refs:`. (e.g. `Specs/047 Car Radio/spec.md`)
- `type/system` — A bounded subsystem with implementation. Carries `code-refs`, `spec-refs`, `implements:` frontmatter. (e.g. `Systems/Audio — Car Radio.md`)
- `type/vision` — Strategic / vision-layer decision. Written to `docs/vault/Vision/`. Human-authored or agent-proposed with human ratification before promotion to `status: reviewed`. (Per triage #3 — spec 133 autonomous-company redesign.)
domain/*:
- `domain/anomalies` — Anomaly taxonomy, individual anomaly systems, spawn, behavior
- `domain/art` — Visual direction, palettes, references, asset pipeline
- `domain/audio` — Audio systems: world ambient, radio, transmissions, buses, pipeline
- `domain/autonomous-company` — Autonomous company v0.1 experiment: Slack infra, persona middleware, Letta integration, restart recovery
- `domain/build` — Build system, packaging, export, release automation
- `domain/governance` — Constitution, phased spec, policies
- `domain/infrastructure` — Infrastructure provisioning: CI/CD, hosting, deployment tooling, secrets management
- `domain/narrative` — Tone, horror register, forest transmissions narrative, Gary/KTLK
- `domain/player` — Player mode, input, controls, camera, exit/entry
- `domain/systems` — Cross-cutting system architecture and integration work
- `domain/tooling` — Build, CI, observer, TTS pipeline, dev-time tools
- `domain/vehicle` — The Samba: vehicle physics, dashboard, damage, panels
- `domain/world` — World model, biomes, terrain, procedural generation, weather
status/*:
- `status/canonical` — Fully authoritative; promoted by humans only. Highest trust. (Agent notes only — spec 080.)
- `status/draft` — Authoring in progress, not yet verified
- `status/reviewed` — Agent-created note verified against codebase within its creating session. Eligible for auto-injection in subsequent task dispatches. (Agent notes only — spec 080.)
- `status/stale` — Known out of date; cannot update immediately. Pairs with `> [!warning] STALE — needs update` callout.
- `status/superseded` — Replaced by another note. Terminal state. Pairs with `> [!warning] SUPERSEDED` callout.
- `status/wip` — Stable but under active revision
layer/*:
- `layer/content` — Content assets (audio, models, textures, audio provenance)
- `layer/gdext` — gdext wrapper layer (`rust/gdext-wrapper/`)
- `layer/gdscript` — GDScript (Godot scene-tier logic)
- `layer/infra` — Build, CI, deployment infrastructure
- `layer/python` — Python development tooling (`tools/`)
- `layer/rust-core` — Engine-agnostic Rust core (`rust/rust-core/`)
concept/*:
- `concept/biome` — Biome-reactive behavior across systems
- `concept/contamination` — Across-runs panel and garage degradation; the slow-horror mechanic that doesn't reset with the world
- `concept/diegetic` — Diegetic audio / UI / world-sourced design
- `concept/disturbance` — The disturbance mechanic thread (Article X)
- `concept/ephemeral-world` — Run-reset, transient worlds (Article IV Rules 6–7)
- `concept/governance` — Constitutional and governance concepts
- `concept/horror` — Horror register and dread design
- `concept/procedural` — Procedural generation, seed determinism
- `concept/rendering` — Visual rendering quality, shader correctness, Terrain3D integration, mesh fidelity, LOD, Z-fighting
- `concept/terrain` — Terrain generation, heightmap, Terrain3D regions, roughness, playability constraints
ember's answer for tag_assignment-sessions-spec-143-implementation-session-may-15-2026, type/specP(true) placed on the no, unsure, and yes zones.nounsureyesgold: noP = 0.64

tag_assignment-systems-world-procedural-generation: type/code

Tag assignment · dev
Gold
The note has no reason to carry `type/code` (False)
ember
The note calls for `type/code`: Code architecture, autoloads, conventions, tooling. Carries `code-refs:`. (e.g. `Code/Autoloads — Disturbance.md`) (True)
Signal
P(true) 0.59 (unsure)
Kit outcome
deferred: treated as unsure
Why this gold label
Mined from Systems/World — Procedural Generation.md at 692f4bb58b7f62105aeb73fba8dfee12bfdecd53; gold is the note's own vocabulary tags.
World — Procedural Generation

The system that produces Old Growth's ephemeral worlds from seeds. Every run generates a new forest — biomes, terrain, roads, vegetation, structures, anomalies, weather, audio zones — all reproducibly derived from a single integer seed. The same seed produces the same world. World state is never persisted; only the garage and the Samba survive between runs.

## Overview

World generation runs as a pipeline of deterministic steps. Each step takes the seed (and any prior step outputs) as inputs and produces outputs consumed by downstream steps. The pipeline is pure: given the same seed and the same game version, it produces bit-identical output. Article IV Rule 3 establishes this as non-negotiable.

## Design Intent

Per Article IV:
- Rule 3 (Seed Determinism): same seed + same game version = identical world
- Rule 5: global `randf()` / `randi()` prohibited — every random call uses the run-seeded RNG
- Rule 6 (Ephemeral Worlds): world state is per-run; only garage and vehicle persist
- Rule 7: persistent data is strictly limited — vehicle components, gear, garage state

Procedural generation is not a performance trick or a content-volume strategy. It is a **design commitment**: every run is genuinely new, the player cannot memorize a specific world, and the forest's indifference to the player extends to the forest's very layout.

## Key Decisions

### The pipeline

The pipeline is orchestrated by `world_generator.gd`'s top-level 10 steps, with step 9 (`_integrate_existing_systems`) itself running four substeps. Seeds for each generator are derived from `GameState.current_seed` + a per-generator offset so seed determinism holds across the entire pipeline.

**Top-level steps** (tracked by `_log_step_time` diagnostics, confirmed against source 2026-04-21):

1. **Create Terrain3D regions** — blank terrain regions sized to the zone (GDScript)
2. **Generate heightmap** — deterministic heightmap via Rust TerrainComputeNode (Rust-backed)
3. **Generate biomes** — Voronoi biome regions with blend transitions via Rust BiomeGeneratorNode (Rust-backed)
4. **Place exits and center hub** — exit gate placement via Rust ExitPointManagerNode; entry is world center hub (Rust-backed)
   - **Step 4.5** (diag ID 45): **Smooth exit corridors** — terrain smoothing before roads bake Y values (Rust-backed)
5. **Generate road network** — hub-and-spoke topology via Rust RoadGeneratorNode; curves extracted for downstream systems (Rust-backed)
6. **Raise mountain boundaries** — impassable ridge-line boundaries around the zone (GDScript)
   - **Step 6.25** (diag ID 625): **Apply terrain roughness** — noise-based surface variation, params passed to Rust
   - **Step 6.5** (diag ID 65): **Validate playability** — terrain passability constraint check
7. **Flatten terrain under roads** — RoadMeshGenerator.flatten_terrain + flatten_hub around center spoke convergence (GDScript using Rust height snapshots)
   - **Step 7.5** (diag ID 75): **Build road meshes** — post-flatten, terrain-sampled Y; GDScript mesh extrusion from Rust curves (RoadMeshGenerator.generate_meshes)
8. **Paint biome textures** — per-biome terrain texture painting (GDScript — TerrainTexturePainter)
9. **Integrate existing systems** — four substeps (see below) (GDScript orchestration)
10. **Spawn vehicle and initialize systems** — vehicle spawn at center hub, engine/radio/sensor/wiper/damage initialization (GDScript)
11. **Load radio channels and finalize world** — awaits radio loading, recalculates height range, updates terrain maps, bakes navmesh, emits Events.world_generation_completed (GDScript)

**Step 9 substeps** (`_integrate_existing_systems`, tracked by `_diag_start` / `_diag_end` IDs 91–94):

- **91 — Fog setup**: fog system configured, valley fog placed along road curves
- **92 — Vegetation scatter + tree collision**: trees, ferns, logs placed via Poisson-disc rejection with biome-aware density (spec 070 — biome blending Rust, VegetationScatterNode); tree collision manager initialized with the placed positions
- **93 — Weather zones**: regional weather patches generated along the main road curve; vehicle biome-lookup connected so `Events.biome_zone_changed` fires from frame 1
- **94 — Road structure scatter**: 15–20 structures (ranger stations, research trailers, gas stations, cabins, fire lookouts) placed along road network with spawn exclusion around the player start

**Note on Rust/GDScript boundary**: The boundary is not a clean "first N steps are Rust." Rust is involved in steps 2, 3, 4, 4.5, 5, and substep 92 (vegetation candidates). Steps 1, 6, 8, 10, 11 and substeps 91, 93, 94 are GDScript. Steps 6.25 and 7.5 are mixed.

**Not yet a distinct pipeline step** (per Phase 4 audit of the current `world_generator.gd`):

- **Rock scatter** — [[Rock Scatter Design]] is specified but the dedicated scatter step is not yet integrated into the top-level pipeline; rocks may be a future step 95 under `_integrate_existing_systems` or a separate top-level step.
- **Anomaly scatter** — anomaly placement is not yet a top-level pipeline step; anomalies are placed via individual anomaly systems (see [[Anomalies]] MOC and spec 022).
- **Audio zone placement** — biome audio beds + proximity audio are set up by the relevant systems at runtime (weather zone system, biome generator); there is not a distinct audio-scatter step in the generator.

### Constraint satisfaction vs. heuristic

Per Article XII-E: hard generation requirements (road connectivity, minimum biome separation, navigation passability, entry/exit placement) are **post-generation validation constraints**, not generation heuristics. If generation produces an invalid world, it retries with a modified seed or parameters — it does not silently ship a broken world.

### Grammar-based where applicable

Road networks, structure placement, and biome distribution use production grammars. Grammars are inspectable and adjustable without rewriting core logic — a new biome variant is a new grammar rule, not a code change.

### Noise functions

Terrain, density maps, and distribution fields use the approved `fastnoise-lite` crate in rust-core (Appendix A). Noise parameters (frequency, octaves, lacunarity, gain) are `@export` variables exposed for tuning without recompilation.

### Emergent complexity from simple rules

Generation algorithms are structured so complexity emerges from rule interactions, not from increasingly complex individual rules. A road network that produces interesting layouts through simple hierarchical expansion rules (primary → secondary → tertiary) is preferred over a monolithic algorithm that encodes layout complexity directly.

### Rust-core for performance-critical steps

Per Article III Rule 17: performance-critical logic lives in `rust-core` (engine-agnostic). The gdext-wrapper bridges Rust outputs to Godot types. Steps migrated to Rust include biome blending (spec 070), road generation (spec 053), and vegetation scatter-time collision rejection.

### Determinism across the Rust/GDScript boundary

Deterministic RNG is seeded both in GDScript (`RandomNumberGenerator`) and in Rust (`SmallRng` / `fastnoise-lite` seeds). All calls into Rust receive their seed as an input. No Rust path consumes OS entropy.

### Baseline validation

Every debug build writes `user://logs/veg_counts.json` with tree/fern/log counts per seed. SC-001 from spec 070: tree count within ±5% of baseline for the canonical test seed (1250827250: trees=1452, ferns=5300, logs=3061 — post-spec-103 per-tree-clearance baseline, recorded 2026-04-26; see AGENTS.md).

## Implementation

Primary entry points:
- `src/scripts/generation/world_generator.gd` — pipeline orchestrator
- `src/scripts/generation/biome_generator.gd` — biome map
- `src/scripts/generation/road_network_generator.gd`, `road_mesh_generator.gd`, `road_path_utils.gd` — road network (spec 053)
- `src/scripts/generation/vegetation_scatter.gd` — vegetation placement (spec 070)
- `rust/rust-core/src/` — biome blending, road spline math, vegetation rejection

Generation diagnostics are written per-run to `user://logs/generation_YYYY-MM-DD_HH-MM-SS.json` with step timings and final metrics.

## Test Coverage

Primary test suites:
- `src/tests/unit/test_world_generator.gd`, `test_world_generator_cli.gd` — generation orchestrator and CLI
- `src/tests/unit/test_biome_generator.gd`, `test_biome_transitions.gd` — biome placement + transitions
- `src/tests/unit/test_road_network_generator.gd`, `test_road_mesh_generator.gd`, `test_road_diagnostic_report.gd`, `test_road_spine_overlay.gd` — road generation pipeline
- `src/tests/unit/test_terrain_generator.gd`, `test_terrain_setup.gd`, `test_terrain_roughness.gd` — terrain
- `src/tests/unit/test_vegetation_scatter.gd`, `test_tree_collision_manager.gd` — vegetation
- `src/tests/unit/test_road_structures.gd` — structures
- `src/tests/unit/test_exit_point_manager.gd` — exit gate placement
- `src/tests/unit/test_fog_system.gd` — fog system
- `src/tests/unit/test_world_preview.gd` — world preview harness

## Autoload Architecture — Delegation to Rust

`GameState` and `Disturbance` follow a thin-shell delegation pattern: GDScript owns all state backing variables and exposes `@export` surfaces, while the Rust layer (`GameStateNode`, `DisturbanceNode`) provides change-detection callbacks and arithmetic rather than state ownership. The `GameStateNode` bridge methods are validators and change-detection callbacks only — all mutations happen in GDScript against its own backing variables. `Disturbance` goes further: the arithmetic for `add()` and threshold-crossing detection runs entirely in `rust-core/src/disturbance.rs`, including clamping. A critical Godot 4.6+ constraint for all three architectural autoloads (`Events`, `GameState`, `Disturbance`): `class_name` must never appear on an autoload script, as the engine registers autoloads under their configured singleton name and a matching `class_name` produces duplicate registration conflicts that manifest as subtle runtime failures.

[[Autoload Delegation Pattern]]

## Weather Biome Restrictions and Fog Constraints

The weather zone system enforces per-biome weather restrictions during zone generation: Verdant supports all four weather states (CLEAR, LIGHT_RAIN, HEAVY_RAIN, FOG_BANK), Fungal biome permits only CLEAR and FOG_BANK, and Petrifold permits only CLEAR. Rain cannot appear inside Fungal or Petrifold zones regardless of RNG output — the generator filters against `BIOME_ALLOWED_WEATHER` constants before committing zone state. A non-obvious constraint limits weather-driven fog scaling: Godot's volumetric fog fills the entire scene uniformly, including bus interiors, making the diegetic dashboard invisible under any weather-driven density increase. All weather-intensity fog responses are therefore applied exclusively to standard (height) fog density; the volumetric fog export properties in `fog_system.gd` are reserved and inactive pending Godot support for interior fog masking.

[[Environment — Weather and Generation Order]]

## Street Light Time-of-Day Initialization

Street lights on power poles (`power_pole.gd`) initialize with `light.visible = false` so they do not emit during the first frame of world generation before `TimeOfDaySystem` has run its initial sync. Without this guard, lights were active from frame 0 and produced visible strobing artefacts during early scene initialization. The correct state machine — off at init and during DAY, on at DUSK and NIGHT — is pinned by regression tests in `src/tests/unit/test_road_structures.gd`.

[[Environment — Weather and Generation Order]]

## Road Artifact Remediation (Spec 114)

Implemented 2026-05-02. All seven outstanding FRs resolved:

### Generation Warning Field (FR-013)
`RoadNetwork` carries a `warnings: Vec<String>` field (Rust). The gdext-wrapper exposes it as `PackedStringArray`. When A* expansion limit is hit (steep terrain fallback), `"steep_terrain_fallback:astar"` is pushed. `road_network_generator.gd` iterates warnings and calls `Debug.warn("RoadGenerator", …)` per entry. The `road_diagnostic_<seed>.json` now includes a `"generation_warnings"` array.

### Sibling Branch Angular Separation (FR-002)
`generator.rs` enforces ≥ 25° pairwise separation between sibling branches off the same parent node — for both CountyRoad (perpendicular + jitter) and LoggingRoad (random `0..TAU`) placements. An ephemeral `HashMap<u32, Vec<f32>>` tracks accepted angles per node; up to 10 retry attempts before skipping. LoggingRoad also rejects any heading > 150° from the parent tangent (U-turn guard).

### Leaf-Node Proximity Pruning (FR-003)
`intersection.rs` implements `prune_nearby_leaf_nodes(network, 50.0)` called after `eliminate_dead_ends`. Any pair of non-Highway leaf nodes within 50 m has the shorter incident segment removed (by `segment.length_m`). No node re-indexing is performed after removal — uses `retain` + `rebuild_node_connections` to preserve stable node IDs and avoid corrupting highway endpoint references.

### Dead-End Connector Approach Angle (FR-004)
`eliminate_dead_ends` in `intersection.rs` replaces the midpoint formula with a 25 m perpendicular offset from the target segment tangent, producing a radial approach vector. The connector segment now approaches the junction at a natural angle rather than tangentially.

### Highway Meander Terrain Guard (FR-011)
`highway_centerline()` in `generator.rs` skips a sinusoidal displacement if the displaced height exceeds the nominal centerline Y by more than 15 m (raised from the original 3 m spec value — 3 m fired on normal terrain undulation causing ECG-noise centerlines; 15 m fires only on genuine cliff faces ≥ 37.5% grade over 40 m horizontal). Clamped points push `"highway_meander_clamped:slope"` to `net.warnings`. County and logging roads are unaffected (their endpoint selection uses A* routing, not meander).

### Flatten Offset Auto-Derivation (FR-010)
`world_generator.gd` computes `effective_flatten_offset = -(road_mesh_y_offset + 0.01)` when `road_flatten_offset == 0.0` (sentinel). At default `road_mesh_y_offset = 0.02` this produces `−0.03`, ensuring the terrain flatten depth always exceeds the side-wall height and eliminating the visible road plinth/rim.

### Dirt Road Mesh Clipping at Paved Boundaries (FR-012)
`road_mesh_generator.gd` adds `_paved_clip_distance()` helper and `clip_start_m` / `clip_end_m` parameters to `_extrude_road_mesh()`. When a non-paved segment's endpoint connects to a paved segment, the dirt mesh is clipped by `paved_half_width + 0.5 m` so dirt surfaces do not intrude into paved footprints.

### Performance Gate (SC-006)
Step 5 across 20 observed seeds: max 10,811 ms, well under the 11,046 ms cap (10% above 10,042 ms baseline).

## Related

- [[The Crater]] — the origin event; the pipeline generates worlds inside the crater basin; step 6 raises the crater rim
- [[The Temporal Fracture]] — each seed accesses a different temporal configuration of the structure
- [[World Model]] — the design the pipeline realizes
- [[Biomes]] — what the pipeline places
- [[Ephemerality Thread]] — the run-reset rule
- [[Biome Behavior]] — biome identity across systems
- [[Rock Scatter Design]] — the rock-scatter step specification
- [[Rust — Core]] — the engine-agnostic core
- [[Source Tree]] — where the generation code lives
- [[Systems]] — folder MOC
- [[World — Domain MOC]] — domain MOC
- [[Constitution]] — Article IV (seed determinism), Article XII-E (procedural), Article III Rule 17 (rust-core)

## Agent Notes (backlinks)

- [[Decisions/Rust-GDScript Split Architecture]] — Rust/GDScript split decision, ClassDB delegation pattern, editor restart constraint
- [[Autoload Delegation Pattern]] — Thin GDScript shell over Rust nodes, no class_name constraint
- [[Environment — Weather and Generation Order]] — 11-step pipeline order, Rust handoff points, SC-001 baseline, diagnostic JSON
- [[Road System — Discoveries]] — Road Rust topology layer, GDScript mesh layer, debug visualization
- [[114 Road Artifact Remediation]] — 13 road artifact categories (graph hygiene, mesh quality, multi-type integration); RCA confirmed road mesh is GDScript, branch sampling is unconstrained, no per-segment AABB culling exists
- [[Specs/114 Road Artifact Remediation/114 Road Artifact Remediation - research|114 Road Artifact Remediation — Research]] — Codebase research for spec 114: FR-002/003/004/010/011/012/013 findings, R=50m leaf-node separation, SC-006 performance baseline
- [[115 Terrain Region Boundary Rendering]] — Terrain3D region boundary rendering artifacts deferred from spec 114 (transverse gaps, chunk seam appearance split)
- Environment — Weather and Generation Order — Weather/time/fog coupling, volumetric fog bus-interior constraint
- [[Decisions/NoiseHelper Utility Class Design]] — NoiseHelper utility class decision (RefCounted pattern, seed-parameterised noise)
- Road System — Discoveries — Road shoulder terracing root cause analysis (directional bias in branch sampling)

Controlled tag vocabulary (as read):
type/*:
- `type/code` — Code architecture, autoloads, conventions, tooling. Carries `code-refs:`. (e.g. `Code/Autoloads — Disturbance.md`)
- `type/decision` — Architectural or design decision made by an agent during a session. Written to `docs/vault/Decisions/`. (Agent notes only — spec 080.)
- `type/design` — Design intent, player-facing concepts, world lore. (e.g. `Design/World Model.md`)
- `type/discovery` — Non-obvious constraint, gap, or conflict found by an agent during a session. Written to `docs/vault/Discoveries/`. (Agent notes only — spec 080.)
- `type/moc` — Map of Content at any of three tiers (folder / domain / concept). (e.g. `Audio.md`)
- `type/principle` — Governance and constitutional notes. Non-negotiable rules. (e.g. `Governance/Constitution.md`)
- `type/reference` — Glossary, decision log, open questions, epics. (e.g. `Reference/Glossary.md`)
- `type/session-log` — Session activity log; permanent audit trail. Written to `docs/vault/Sessions/`. Append-only, never pruned. (Agent notes only — spec 080.)
- `type/spec` — Spec document at `docs/vault/Specs/NNN Title/spec.md`. Carries `spec-refs:`. (e.g. `Specs/047 Car Radio/spec.md`)
- `type/system` — A bounded subsystem with implementation. Carries `code-refs`, `spec-refs`, `implements:` frontmatter. (e.g. `Systems/Audio — Car Radio.md`)
- `type/vision` — Strategic / vision-layer decision. Written to `docs/vault/Vision/`. Human-authored or agent-proposed with human ratification before promotion to `status: reviewed`. (Per triage #3 — spec 133 autonomous-company redesign.)
domain/*:
- `domain/anomalies` — Anomaly taxonomy, individual anomaly systems, spawn, behavior
- `domain/art` — Visual direction, palettes, references, asset pipeline
- `domain/audio` — Audio systems: world ambient, radio, transmissions, buses, pipeline
- `domain/autonomous-company` — Autonomous company v0.1 experiment: Slack infra, persona middleware, Letta integration, restart recovery
- `domain/build` — Build system, packaging, export, release automation
- `domain/governance` — Constitution, phased spec, policies
- `domain/infrastructure` — Infrastructure provisioning: CI/CD, hosting, deployment tooling, secrets management
- `domain/narrative` — Tone, horror register, forest transmissions narrative, Gary/KTLK
- `domain/player` — Player mode, input, controls, camera, exit/entry
- `domain/systems` — Cross-cutting system architecture and integration work
- `domain/tooling` — Build, CI, observer, TTS pipeline, dev-time tools
- `domain/vehicle` — The Samba: vehicle physics, dashboard, damage, panels
- `domain/world` — World model, biomes, terrain, procedural generation, weather
status/*:
- `status/canonical` — Fully authoritative; promoted by humans only. Highest trust. (Agent notes only — spec 080.)
- `status/draft` — Authoring in progress, not yet verified
- `status/reviewed` — Agent-created note verified against codebase within its creating session. Eligible for auto-injection in subsequent task dispatches. (Agent notes only — spec 080.)
- `status/stale` — Known out of date; cannot update immediately. Pairs with `> [!warning] STALE — needs update` callout.
- `status/superseded` — Replaced by another note. Terminal state. Pairs with `> [!warning] SUPERSEDED` callout.
- `status/wip` — Stable but under active revision
layer/*:
- `layer/content` — Content assets (audio, models, textures, audio provenance)
- `layer/gdext` — gdext wrapper layer (`rust/gdext-wrapper/`)
- `layer/gdscript` — GDScript (Godot scene-tier logic)
- `layer/infra` — Build, CI, deployment infrastructure
- `layer/python` — Python development tooling (`tools/`)
- `layer/rust-core` — Engine-agnostic Rust core (`rust/rust-core/`)
concept/*:
- `concept/biome` — Biome-reactive behavior across systems
- `concept/contamination` — Across-runs panel and garage degradation; the slow-horror mechanic that doesn't reset with the world
- `concept/diegetic` — Diegetic audio / UI / world-sourced design
- `concept/disturbance` — The disturbance mechanic thread (Article X)
- `concept/ephemeral-world` — Run-reset, transient worlds (Article IV Rules 6–7)
- `concept/governance` — Constitutional and governance concepts
- `concept/horror` — Horror register and dread design
- `concept/procedural` — Procedural generation, seed determinism
- `concept/rendering` — Visual rendering quality, shader correctness, Terrain3D integration, mesh fidelity, LOD, Z-fighting
- `concept/terrain` — Terrain generation, heightmap, Terrain3D regions, roughness, playability constraints
ember's answer for tag_assignment-systems-world-procedural-generation, type/codeP(true) placed on the no, unsure, and yes zones.nounsureyesgold: noP = 0.59

tag_assignment-systems-world-procedural-generation: type/system

Tag assignment · dev
Gold
The note calls for `type/system`: A bounded subsystem with implementation. Carries `code-refs`, `spec-refs`, `implements:` frontmatter. (e.g. `Systems/Audio — Car Radio.md`) (True)
ember
The note has no reason to carry `type/system` (False)
Signal
P(true) 0.15 (no)
Kit outcome
acted on a wrong answer
Why this gold label
Mined from Systems/World — Procedural Generation.md at 692f4bb58b7f62105aeb73fba8dfee12bfdecd53; gold is the note's own vocabulary tags.
World — Procedural Generation

The system that produces Old Growth's ephemeral worlds from seeds. Every run generates a new forest — biomes, terrain, roads, vegetation, structures, anomalies, weather, audio zones — all reproducibly derived from a single integer seed. The same seed produces the same world. World state is never persisted; only the garage and the Samba survive between runs.

## Overview

World generation runs as a pipeline of deterministic steps. Each step takes the seed (and any prior step outputs) as inputs and produces outputs consumed by downstream steps. The pipeline is pure: given the same seed and the same game version, it produces bit-identical output. Article IV Rule 3 establishes this as non-negotiable.

## Design Intent

Per Article IV:
- Rule 3 (Seed Determinism): same seed + same game version = identical world
- Rule 5: global `randf()` / `randi()` prohibited — every random call uses the run-seeded RNG
- Rule 6 (Ephemeral Worlds): world state is per-run; only garage and vehicle persist
- Rule 7: persistent data is strictly limited — vehicle components, gear, garage state

Procedural generation is not a performance trick or a content-volume strategy. It is a **design commitment**: every run is genuinely new, the player cannot memorize a specific world, and the forest's indifference to the player extends to the forest's very layout.

## Key Decisions

### The pipeline

The pipeline is orchestrated by `world_generator.gd`'s top-level 10 steps, with step 9 (`_integrate_existing_systems`) itself running four substeps. Seeds for each generator are derived from `GameState.current_seed` + a per-generator offset so seed determinism holds across the entire pipeline.

**Top-level steps** (tracked by `_log_step_time` diagnostics, confirmed against source 2026-04-21):

1. **Create Terrain3D regions** — blank terrain regions sized to the zone (GDScript)
2. **Generate heightmap** — deterministic heightmap via Rust TerrainComputeNode (Rust-backed)
3. **Generate biomes** — Voronoi biome regions with blend transitions via Rust BiomeGeneratorNode (Rust-backed)
4. **Place exits and center hub** — exit gate placement via Rust ExitPointManagerNode; entry is world center hub (Rust-backed)
   - **Step 4.5** (diag ID 45): **Smooth exit corridors** — terrain smoothing before roads bake Y values (Rust-backed)
5. **Generate road network** — hub-and-spoke topology via Rust RoadGeneratorNode; curves extracted for downstream systems (Rust-backed)
6. **Raise mountain boundaries** — impassable ridge-line boundaries around the zone (GDScript)
   - **Step 6.25** (diag ID 625): **Apply terrain roughness** — noise-based surface variation, params passed to Rust
   - **Step 6.5** (diag ID 65): **Validate playability** — terrain passability constraint check
7. **Flatten terrain under roads** — RoadMeshGenerator.flatten_terrain + flatten_hub around center spoke convergence (GDScript using Rust height snapshots)
   - **Step 7.5** (diag ID 75): **Build road meshes** — post-flatten, terrain-sampled Y; GDScript mesh extrusion from Rust curves (RoadMeshGenerator.generate_meshes)
8. **Paint biome textures** — per-biome terrain texture painting (GDScript — TerrainTexturePainter)
9. **Integrate existing systems** — four substeps (see below) (GDScript orchestration)
10. **Spawn vehicle and initialize systems** — vehicle spawn at center hub, engine/radio/sensor/wiper/damage initialization (GDScript)
11. **Load radio channels and finalize world** — awaits radio loading, recalculates height range, updates terrain maps, bakes navmesh, emits Events.world_generation_completed (GDScript)

**Step 9 substeps** (`_integrate_existing_systems`, tracked by `_diag_start` / `_diag_end` IDs 91–94):

- **91 — Fog setup**: fog system configured, valley fog placed along road curves
- **92 — Vegetation scatter + tree collision**: trees, ferns, logs placed via Poisson-disc rejection with biome-aware density (spec 070 — biome blending Rust, VegetationScatterNode); tree collision manager initialized with the placed positions
- **93 — Weather zones**: regional weather patches generated along the main road curve; vehicle biome-lookup connected so `Events.biome_zone_changed` fires from frame 1
- **94 — Road structure scatter**: 15–20 structures (ranger stations, research trailers, gas stations, cabins, fire lookouts) placed along road network with spawn exclusion around the player start

**Note on Rust/GDScript boundary**: The boundary is not a clean "first N steps are Rust." Rust is involved in steps 2, 3, 4, 4.5, 5, and substep 92 (vegetation candidates). Steps 1, 6, 8, 10, 11 and substeps 91, 93, 94 are GDScript. Steps 6.25 and 7.5 are mixed.

**Not yet a distinct pipeline step** (per Phase 4 audit of the current `world_generator.gd`):

- **Rock scatter** — [[Rock Scatter Design]] is specified but the dedicated scatter step is not yet integrated into the top-level pipeline; rocks may be a future step 95 under `_integrate_existing_systems` or a separate top-level step.
- **Anomaly scatter** — anomaly placement is not yet a top-level pipeline step; anomalies are placed via individual anomaly systems (see [[Anomalies]] MOC and spec 022).
- **Audio zone placement** — biome audio beds + proximity audio are set up by the relevant systems at runtime (weather zone system, biome generator); there is not a distinct audio-scatter step in the generator.

### Constraint satisfaction vs. heuristic

Per Article XII-E: hard generation requirements (road connectivity, minimum biome separation, navigation passability, entry/exit placement) are **post-generation validation constraints**, not generation heuristics. If generation produces an invalid world, it retries with a modified seed or parameters — it does not silently ship a broken world.

### Grammar-based where applicable

Road networks, structure placement, and biome distribution use production grammars. Grammars are inspectable and adjustable without rewriting core logic — a new biome variant is a new grammar rule, not a code change.

### Noise functions

Terrain, density maps, and distribution fields use the approved `fastnoise-lite` crate in rust-core (Appendix A). Noise parameters (frequency, octaves, lacunarity, gain) are `@export` variables exposed for tuning without recompilation.

### Emergent complexity from simple rules

Generation algorithms are structured so complexity emerges from rule interactions, not from increasingly complex individual rules. A road network that produces interesting layouts through simple hierarchical expansion rules (primary → secondary → tertiary) is preferred over a monolithic algorithm that encodes layout complexity directly.

### Rust-core for performance-critical steps

Per Article III Rule 17: performance-critical logic lives in `rust-core` (engine-agnostic). The gdext-wrapper bridges Rust outputs to Godot types. Steps migrated to Rust include biome blending (spec 070), road generation (spec 053), and vegetation scatter-time collision rejection.

### Determinism across the Rust/GDScript boundary

Deterministic RNG is seeded both in GDScript (`RandomNumberGenerator`) and in Rust (`SmallRng` / `fastnoise-lite` seeds). All calls into Rust receive their seed as an input. No Rust path consumes OS entropy.

### Baseline validation

Every debug build writes `user://logs/veg_counts.json` with tree/fern/log counts per seed. SC-001 from spec 070: tree count within ±5% of baseline for the canonical test seed (1250827250: trees=1452, ferns=5300, logs=3061 — post-spec-103 per-tree-clearance baseline, recorded 2026-04-26; see AGENTS.md).

## Implementation

Primary entry points:
- `src/scripts/generation/world_generator.gd` — pipeline orchestrator
- `src/scripts/generation/biome_generator.gd` — biome map
- `src/scripts/generation/road_network_generator.gd`, `road_mesh_generator.gd`, `road_path_utils.gd` — road network (spec 053)
- `src/scripts/generation/vegetation_scatter.gd` — vegetation placement (spec 070)
- `rust/rust-core/src/` — biome blending, road spline math, vegetation rejection

Generation diagnostics are written per-run to `user://logs/generation_YYYY-MM-DD_HH-MM-SS.json` with step timings and final metrics.

## Test Coverage

Primary test suites:
- `src/tests/unit/test_world_generator.gd`, `test_world_generator_cli.gd` — generation orchestrator and CLI
- `src/tests/unit/test_biome_generator.gd`, `test_biome_transitions.gd` — biome placement + transitions
- `src/tests/unit/test_road_network_generator.gd`, `test_road_mesh_generator.gd`, `test_road_diagnostic_report.gd`, `test_road_spine_overlay.gd` — road generation pipeline
- `src/tests/unit/test_terrain_generator.gd`, `test_terrain_setup.gd`, `test_terrain_roughness.gd` — terrain
- `src/tests/unit/test_vegetation_scatter.gd`, `test_tree_collision_manager.gd` — vegetation
- `src/tests/unit/test_road_structures.gd` — structures
- `src/tests/unit/test_exit_point_manager.gd` — exit gate placement
- `src/tests/unit/test_fog_system.gd` — fog system
- `src/tests/unit/test_world_preview.gd` — world preview harness

## Autoload Architecture — Delegation to Rust

`GameState` and `Disturbance` follow a thin-shell delegation pattern: GDScript owns all state backing variables and exposes `@export` surfaces, while the Rust layer (`GameStateNode`, `DisturbanceNode`) provides change-detection callbacks and arithmetic rather than state ownership. The `GameStateNode` bridge methods are validators and change-detection callbacks only — all mutations happen in GDScript against its own backing variables. `Disturbance` goes further: the arithmetic for `add()` and threshold-crossing detection runs entirely in `rust-core/src/disturbance.rs`, including clamping. A critical Godot 4.6+ constraint for all three architectural autoloads (`Events`, `GameState`, `Disturbance`): `class_name` must never appear on an autoload script, as the engine registers autoloads under their configured singleton name and a matching `class_name` produces duplicate registration conflicts that manifest as subtle runtime failures.

[[Autoload Delegation Pattern]]

## Weather Biome Restrictions and Fog Constraints

The weather zone system enforces per-biome weather restrictions during zone generation: Verdant supports all four weather states (CLEAR, LIGHT_RAIN, HEAVY_RAIN, FOG_BANK), Fungal biome permits only CLEAR and FOG_BANK, and Petrifold permits only CLEAR. Rain cannot appear inside Fungal or Petrifold zones regardless of RNG output — the generator filters against `BIOME_ALLOWED_WEATHER` constants before committing zone state. A non-obvious constraint limits weather-driven fog scaling: Godot's volumetric fog fills the entire scene uniformly, including bus interiors, making the diegetic dashboard invisible under any weather-driven density increase. All weather-intensity fog responses are therefore applied exclusively to standard (height) fog density; the volumetric fog export properties in `fog_system.gd` are reserved and inactive pending Godot support for interior fog masking.

[[Environment — Weather and Generation Order]]

## Street Light Time-of-Day Initialization

Street lights on power poles (`power_pole.gd`) initialize with `light.visible = false` so they do not emit during the first frame of world generation before `TimeOfDaySystem` has run its initial sync. Without this guard, lights were active from frame 0 and produced visible strobing artefacts during early scene initialization. The correct state machine — off at init and during DAY, on at DUSK and NIGHT — is pinned by regression tests in `src/tests/unit/test_road_structures.gd`.

[[Environment — Weather and Generation Order]]

## Road Artifact Remediation (Spec 114)

Implemented 2026-05-02. All seven outstanding FRs resolved:

### Generation Warning Field (FR-013)
`RoadNetwork` carries a `warnings: Vec<String>` field (Rust). The gdext-wrapper exposes it as `PackedStringArray`. When A* expansion limit is hit (steep terrain fallback), `"steep_terrain_fallback:astar"` is pushed. `road_network_generator.gd` iterates warnings and calls `Debug.warn("RoadGenerator", …)` per entry. The `road_diagnostic_<seed>.json` now includes a `"generation_warnings"` array.

### Sibling Branch Angular Separation (FR-002)
`generator.rs` enforces ≥ 25° pairwise separation between sibling branches off the same parent node — for both CountyRoad (perpendicular + jitter) and LoggingRoad (random `0..TAU`) placements. An ephemeral `HashMap<u32, Vec<f32>>` tracks accepted angles per node; up to 10 retry attempts before skipping. LoggingRoad also rejects any heading > 150° from the parent tangent (U-turn guard).

### Leaf-Node Proximity Pruning (FR-003)
`intersection.rs` implements `prune_nearby_leaf_nodes(network, 50.0)` called after `eliminate_dead_ends`. Any pair of non-Highway leaf nodes within 50 m has the shorter incident segment removed (by `segment.length_m`). No node re-indexing is performed after removal — uses `retain` + `rebuild_node_connections` to preserve stable node IDs and avoid corrupting highway endpoint references.

### Dead-End Connector Approach Angle (FR-004)
`eliminate_dead_ends` in `intersection.rs` replaces the midpoint formula with a 25 m perpendicular offset from the target segment tangent, producing a radial approach vector. The connector segment now approaches the junction at a natural angle rather than tangentially.

### Highway Meander Terrain Guard (FR-011)
`highway_centerline()` in `generator.rs` skips a sinusoidal displacement if the displaced height exceeds the nominal centerline Y by more than 15 m (raised from the original 3 m spec value — 3 m fired on normal terrain undulation causing ECG-noise centerlines; 15 m fires only on genuine cliff faces ≥ 37.5% grade over 40 m horizontal). Clamped points push `"highway_meander_clamped:slope"` to `net.warnings`. County and logging roads are unaffected (their endpoint selection uses A* routing, not meander).

### Flatten Offset Auto-Derivation (FR-010)
`world_generator.gd` computes `effective_flatten_offset = -(road_mesh_y_offset + 0.01)` when `road_flatten_offset == 0.0` (sentinel). At default `road_mesh_y_offset = 0.02` this produces `−0.03`, ensuring the terrain flatten depth always exceeds the side-wall height and eliminating the visible road plinth/rim.

### Dirt Road Mesh Clipping at Paved Boundaries (FR-012)
`road_mesh_generator.gd` adds `_paved_clip_distance()` helper and `clip_start_m` / `clip_end_m` parameters to `_extrude_road_mesh()`. When a non-paved segment's endpoint connects to a paved segment, the dirt mesh is clipped by `paved_half_width + 0.5 m` so dirt surfaces do not intrude into paved footprints.

### Performance Gate (SC-006)
Step 5 across 20 observed seeds: max 10,811 ms, well under the 11,046 ms cap (10% above 10,042 ms baseline).

## Related

- [[The Crater]] — the origin event; the pipeline generates worlds inside the crater basin; step 6 raises the crater rim
- [[The Temporal Fracture]] — each seed accesses a different temporal configuration of the structure
- [[World Model]] — the design the pipeline realizes
- [[Biomes]] — what the pipeline places
- [[Ephemerality Thread]] — the run-reset rule
- [[Biome Behavior]] — biome identity across systems
- [[Rock Scatter Design]] — the rock-scatter step specification
- [[Rust — Core]] — the engine-agnostic core
- [[Source Tree]] — where the generation code lives
- [[Systems]] — folder MOC
- [[World — Domain MOC]] — domain MOC
- [[Constitution]] — Article IV (seed determinism), Article XII-E (procedural), Article III Rule 17 (rust-core)

## Agent Notes (backlinks)

- [[Decisions/Rust-GDScript Split Architecture]] — Rust/GDScript split decision, ClassDB delegation pattern, editor restart constraint
- [[Autoload Delegation Pattern]] — Thin GDScript shell over Rust nodes, no class_name constraint
- [[Environment — Weather and Generation Order]] — 11-step pipeline order, Rust handoff points, SC-001 baseline, diagnostic JSON
- [[Road System — Discoveries]] — Road Rust topology layer, GDScript mesh layer, debug visualization
- [[114 Road Artifact Remediation]] — 13 road artifact categories (graph hygiene, mesh quality, multi-type integration); RCA confirmed road mesh is GDScript, branch sampling is unconstrained, no per-segment AABB culling exists
- [[Specs/114 Road Artifact Remediation/114 Road Artifact Remediation - research|114 Road Artifact Remediation — Research]] — Codebase research for spec 114: FR-002/003/004/010/011/012/013 findings, R=50m leaf-node separation, SC-006 performance baseline
- [[115 Terrain Region Boundary Rendering]] — Terrain3D region boundary rendering artifacts deferred from spec 114 (transverse gaps, chunk seam appearance split)
- Environment — Weather and Generation Order — Weather/time/fog coupling, volumetric fog bus-interior constraint
- [[Decisions/NoiseHelper Utility Class Design]] — NoiseHelper utility class decision (RefCounted pattern, seed-parameterised noise)
- Road System — Discoveries — Road shoulder terracing root cause analysis (directional bias in branch sampling)

Controlled tag vocabulary (as read):
type/*:
- `type/code` — Code architecture, autoloads, conventions, tooling. Carries `code-refs:`. (e.g. `Code/Autoloads — Disturbance.md`)
- `type/decision` — Architectural or design decision made by an agent during a session. Written to `docs/vault/Decisions/`. (Agent notes only — spec 080.)
- `type/design` — Design intent, player-facing concepts, world lore. (e.g. `Design/World Model.md`)
- `type/discovery` — Non-obvious constraint, gap, or conflict found by an agent during a session. Written to `docs/vault/Discoveries/`. (Agent notes only — spec 080.)
- `type/moc` — Map of Content at any of three tiers (folder / domain / concept). (e.g. `Audio.md`)
- `type/principle` — Governance and constitutional notes. Non-negotiable rules. (e.g. `Governance/Constitution.md`)
- `type/reference` — Glossary, decision log, open questions, epics. (e.g. `Reference/Glossary.md`)
- `type/session-log` — Session activity log; permanent audit trail. Written to `docs/vault/Sessions/`. Append-only, never pruned. (Agent notes only — spec 080.)
- `type/spec` — Spec document at `docs/vault/Specs/NNN Title/spec.md`. Carries `spec-refs:`. (e.g. `Specs/047 Car Radio/spec.md`)
- `type/system` — A bounded subsystem with implementation. Carries `code-refs`, `spec-refs`, `implements:` frontmatter. (e.g. `Systems/Audio — Car Radio.md`)
- `type/vision` — Strategic / vision-layer decision. Written to `docs/vault/Vision/`. Human-authored or agent-proposed with human ratification before promotion to `status: reviewed`. (Per triage #3 — spec 133 autonomous-company redesign.)
domain/*:
- `domain/anomalies` — Anomaly taxonomy, individual anomaly systems, spawn, behavior
- `domain/art` — Visual direction, palettes, references, asset pipeline
- `domain/audio` — Audio systems: world ambient, radio, transmissions, buses, pipeline
- `domain/autonomous-company` — Autonomous company v0.1 experiment: Slack infra, persona middleware, Letta integration, restart recovery
- `domain/build` — Build system, packaging, export, release automation
- `domain/governance` — Constitution, phased spec, policies
- `domain/infrastructure` — Infrastructure provisioning: CI/CD, hosting, deployment tooling, secrets management
- `domain/narrative` — Tone, horror register, forest transmissions narrative, Gary/KTLK
- `domain/player` — Player mode, input, controls, camera, exit/entry
- `domain/systems` — Cross-cutting system architecture and integration work
- `domain/tooling` — Build, CI, observer, TTS pipeline, dev-time tools
- `domain/vehicle` — The Samba: vehicle physics, dashboard, damage, panels
- `domain/world` — World model, biomes, terrain, procedural generation, weather
status/*:
- `status/canonical` — Fully authoritative; promoted by humans only. Highest trust. (Agent notes only — spec 080.)
- `status/draft` — Authoring in progress, not yet verified
- `status/reviewed` — Agent-created note verified against codebase within its creating session. Eligible for auto-injection in subsequent task dispatches. (Agent notes only — spec 080.)
- `status/stale` — Known out of date; cannot update immediately. Pairs with `> [!warning] STALE — needs update` callout.
- `status/superseded` — Replaced by another note. Terminal state. Pairs with `> [!warning] SUPERSEDED` callout.
- `status/wip` — Stable but under active revision
layer/*:
- `layer/content` — Content assets (audio, models, textures, audio provenance)
- `layer/gdext` — gdext wrapper layer (`rust/gdext-wrapper/`)
- `layer/gdscript` — GDScript (Godot scene-tier logic)
- `layer/infra` — Build, CI, deployment infrastructure
- `layer/python` — Python development tooling (`tools/`)
- `layer/rust-core` — Engine-agnostic Rust core (`rust/rust-core/`)
concept/*:
- `concept/biome` — Biome-reactive behavior across systems
- `concept/contamination` — Across-runs panel and garage degradation; the slow-horror mechanic that doesn't reset with the world
- `concept/diegetic` — Diegetic audio / UI / world-sourced design
- `concept/disturbance` — The disturbance mechanic thread (Article X)
- `concept/ephemeral-world` — Run-reset, transient worlds (Article IV Rules 6–7)
- `concept/governance` — Constitutional and governance concepts
- `concept/horror` — Horror register and dread design
- `concept/procedural` — Procedural generation, seed determinism
- `concept/rendering` — Visual rendering quality, shader correctness, Terrain3D integration, mesh fidelity, LOD, Z-fighting
- `concept/terrain` — Terrain generation, heightmap, Terrain3D regions, roughness, playability constraints
ember's answer for tag_assignment-systems-world-procedural-generation, type/systemP(true) placed on the no, unsure, and yes zones.nounsureyesgold: yesP = 0.15