Architecture Traceability Index
Last Updated: 2026-09-07 (/architecture-review; report: architecture-review-2026-09-07.md) — coverage unchanged since 2026-09-01 Engine: Unity 6.3 LTS (6000.3)
Coverage Summary
- Total requirements: 111 (94 baseline from
architecture.md+ 17 surfaced 2026-08-28) - Covered: 73 (66 %)
- Partial: 26
- Gaps: 12
- Foundation layer: 0 gaps
Changed 2026-09-01: ADR-0013 and ADR-0014 were Accepted (after review findings E14/E15/E16/E17 and F1/F2 were applied), moving coverage from 64 / 28 / 19 → 73 / 26 / 12. tr-registry.yaml is unmodified — no new requirements were surfaced, so all 111 IDs keep their numbers.
| 2026-08-28 | 2026-09-01 | |
|---|---|---|
| ✅ Covered | 64 | 73 |
| ⚠️ Partial | 28 | 26 |
| ❌ Gap | 19 | 12 |
- Gaps closed (7): TR-tint-001/002/003, TR-bb-009 (ADR-0013) · TR-ui-001/003 (ADR-0014) · TR-ui-002 moved gap → partial.
- Partials resolved (3): TR-cam-001 (ADR-0013) · TR-ui-004, TR-combat-013 (ADR-0014).
- TR-tide-008 was already ✅; its "driver → ADR-0013" remainder is now closed.
- TR-ui-002 remains ⚠️ on one of three limbs: edge indicators and who-took-what are covered; the world-space ping needs a
Pingbinding that does not exist in ADR-0007, and the who-took-what tags need ADR-0010's transfer-broadcast payload. Both are declared in ADR-0014's "Blocked On" table.
2026-09-07 (architecture-review-2026-09-07.md): no coverage change — no GDD technical requirement changed and no ADR was added, so the matrix below stands at 73 / 26 / 12 and tr-registry.yaml is untouched. First Requirements Traceability Matrix published at requirements-traceability.md: 61/112 (54 %) requirements have the full GDD → ADR → Story → Test chain (Foundation 79 %, Presentation 75 %, Core 55 %, Feature 11 %). Note TR-inv-002/TR-inv-004: the ❌ below is correct for the ADR column, but their single-machine halves are implemented and tested (core-inventory-carry) — only the ADR-0010 authority-rail halves remain. Same session: the review's HIGH + MEDIUM amendment sets were applied to ADR-0001/0003/0004/0005/0006/0013/0015 (no coverage effect — none adds or removes a requirement).
- All 12 remaining gaps sit in Core/Feature, assigned to ADR-0008/0009/0010/0011/0012 (netcode wire is playtest-gated) or deliberately deferred to implementation (TR-cam-002). Foundation and Presentation are gap-free.
Legend: ✅ covered · ⚠️ partial (the model half is decided; the named remainder is another ADR's) · ❌ gap (no ADR). TR-IDs are stable — see tr-registry.yaml.
Full Matrix
| Requirement ID | System | Requirement | ADR Coverage | Status |
|---|---|---|---|---|
| TR-tide-001 | Tide | DockedLands(seed, t, config) pure function in an engine-free assembly | ADR-0001, ADR-0003 | ✅ |
| TR-tide-002 | Tide | long UTC seconds, StableHash64, FloorDiv/FloorMod; System.Random/GetHashCode/Mathf/float banned | ADR-0001 | ✅ |
| TR-tide-003 | Tide | host-authoritative t replicated; client evaluation presentation-only | ADR-0001 (roles) | ⚠️ wire → ADR-0008 |
| TR-tide-004 | Tide | monotonic lastKnownGoodT, persisted | ADR-0001, ADR-0004 | ✅ |
| TR-tide-005 | Tide | NextBoundary schedule-one-wake-up, no polling, ±5 s | ADR-0001 | ✅ (conflict C1 — caller to be single) |
| TR-tide-006 | Tide | dock/undock edge events + PreloadLeadTime notice | ADR-0001, ADR-0005 | ✅ |
| TR-tide-007 | Tide | derived-only API; raw t/φ/W never exposed | ADR-0001 | ✅ |
| TR-tide-008 | Tide | amber/violet intensities (double); violet held through EvictionGrace | ADR-0001, ADR-0013 §5 (driver; neutral on LandTornDown; V5) | ✅ |
| TR-tide-009 | Tide | TideConfig data-driven, validated, versioned; epoch on N change | ADR-0001, ADR-0006 | ✅ |
| TR-tide-010 | Tide | ≤ 50 µs / 0 alloc hard gates (TD ruling); ≤ 0.1 ms advisory | ADR-0001 | ✅ (GDD header still says advisory — sync) |
| TR-tide-011 | Tide | signed long cycle/docking/round indices — negatives legitimate | ADR-0001 | ✅ |
| TR-tide-012 | Tide | culture/thread-independent bit-identical schedule math | ADR-0001 | ✅ |
| TR-tide-013 | Tide | client extrapolated t ≤ host t + one replication interval | — | ⚠️ → ADR-0008 |
| TR-net-001 | Netcode | NGO 2.x host-and-play; no dedicated server / migration / rollback | technical-preferences; every ADR | ⚠️ → ADR-0008 |
| TR-net-002 | Netcode | two authority rails | ADR-0002 (host rail) | ⚠️ owner rail → ADR-0009 |
| TR-net-003 | Netcode | late-join full snapshot | — | ❌ → ADR-0008 |
| TR-net-004 | Netcode | disconnect retains HP/Downed/timer; rejoin = late join | ADR-0015 (PlayerKey rows), ADR-0004 §6 | ⚠️ → ADR-0008 |
| TR-net-005 | Netcode | Steam transport (package TBD) | — | ❌ → ADR-0008 |
| TR-net-006 | Netcode | one ordered arrival channel; tiebreak lowest OwnerClientId | ADR-0002 | ✅ |
| TR-net-007 | Netcode | every host-rail commit a non-yielding critical section | ADR-0002, ADR-0003 | ✅ |
| TR-net-008 | Netcode | drain phase pinned vs owner movement writes | ADR-0002 | ✅ (stage measured → ADR-0008) |
| TR-net-009 | Netcode | fired commits never un-happen on disconnect; un-fired intents are no-ops | ADR-0002 §9 | ✅ |
| TR-cam-001 | Camera | orthographic 64 px/u at 1080p, integer multiples; PPU 32, point | ADR-0003 (unit/PPU pin), ADR-0013 (fragment-stage tint changes no sampling/geometry) | ✅ |
| TR-cam-002 | Camera | smoothed follow + aim bias; never detaches; hard cuts; no shake | — | ❌ deferred to implementation (architecture ruling) |
| TR-save-001 | Save | one host-owned file; write-temp-then-swap; rolling backups | ADR-0004 | ✅ |
| TR-save-002 | Save | persisted tables incl. both instanceId counters, TideState, equipped instances | ADR-0004 | ✅ |
| TR-save-003 | Save | per-drain durability within flushDeadlineMs; loss unit = drains since lastDurableDrain | ADR-0004 | ✅ |
| TR-save-004 | Save | saveFormatVersion/configVersion gate; never migrate silently | ADR-0004 | ✅ |
| TR-save-005 | Save | fixed reconcile pipeline; owners' predicates; only HarvestDiff droppable | ADR-0004, ADR-0003 | ✅ |
| TR-save-006 | Save | load: full HP, no Downed, position per tide EC1; no merge/import path | ADR-0004, ADR-0003 | ✅ |
| TR-save-007 | Save | no file I/O on the host main thread during play | ADR-0004 | ✅ |
| TR-save-008 | Save | late flush = loud log, never a gameplay effect | ADR-0004 | ✅ |
| TR-save-009 | Save | loading raises no gameplay events | ADR-0004 | ✅ |
| TR-move-001 | Movement | Input System; one action map; decoupled persistent aim | ADR-0007 | ✅ |
| TR-move-002 | Movement | owner-authoritative predicted locomotion 6 u/s, instant accel | — | ❌ → ADR-0009 |
| TR-move-003 | Movement | collision blocks never damages; no player/enemy body collision | — | ❌ → ADR-0011 |
| TR-move-004 | Movement | remotes interpolated never extrapolated | — | ❌ → ADR-0009 |
| TR-move-005 | Movement | closed teleport-snap list; EC21 correction as interpolated write | ADR-0015 (Snap), ADR-0005 (deposit events) | ⚠️ write mode → ADR-0009 |
| TR-move-006 | Movement | schema-negative: no MoveSpeedModifier/stamina/encumbrance | ADR-0003 | ✅ |
| TR-inv-001 | Inventory | ItemStack + CanAdd/Add/Remove/Count; tagged stacks never merge | ADR-0003 (shape) | ⚠️ ops → ADR-0010 |
| TR-inv-002 | Inventory | CarryInventory owner-auth; SharedStorage host-auth instances | — | ❌ → ADR-0010 |
| TR-inv-003 | Inventory | transfers atomic host transactions in arrival order | ADR-0002 (model) | ⚠️ IInventoryTx → ADR-0010 |
| TR-inv-004 | Inventory | no world-item entities; 2 equipment slots | — | ❌ → ADR-0010 |
| TR-inv-005 | Inventory | stack-list serialization (CARRY per player, STORAGE per container) | ADR-0004 | ⚠️ owner impl → ADR-0010 |
| TR-inv-006 | Inventory | transferBatchWindow host-transaction batching knob | — | ⚠️ → ADR-0010 |
| TR-inv-007 | Inventory | CARRY replication representation (undefined in the quick-spec) | — | ❌ → ADR-0010 |
| TR-combat-001 | Combat | player state machine + Hurt overlay | ADR-0015 | ✅ |
| TR-combat-002 | Combat | unified strike intent at windup start | ADR-0015 | ✅ (encoding → ADR-0008) |
| TR-combat-003 | Combat | host resolves at host-stamped instant vs current positions | ADR-0015 | ✅ |
| TR-combat-004 | Combat | predicted vs host-confirmed feedback split | ADR-0015 §6 | ⚠️ presenters deferred |
| TR-combat-005 | Combat | F1–F5 pure, AwayFromZero, EditMode | ADR-0003, ADR-0015 | ✅ |
| TR-combat-006 | Combat | IEnemyCombat.EnterTelegraph; telegraph ≥ 400 ms; stagger; knockback; interrupt | ADR-0015 | ✅ |
| TR-combat-007 | Combat | telegraph phase replicated state | ADR-0015 (named) | ⚠️ representation → ADR-0008 |
| TR-combat-008 | Combat | dash i-frames owner-auth; host wins if not received | ADR-0015 | ✅ |
| TR-combat-009 | Combat | Downed/revive/bleed-out/Dead → home; keep-everything | ADR-0015 | ✅ |
| TR-combat-010 | Combat | soft-close first on the host tick | ADR-0002 | ✅ |
| TR-combat-011 | Combat | SwingLanded/DamageAbsorbed host-confirmed only | ADR-0003, ADR-0015 | ✅ |
| TR-combat-012 | Combat | load validation (telegraph, phase sum, DR, bands, unarmed) | ADR-0006 | ✅ |
| TR-combat-013 | Combat | HUD data: own/party HP, Downed indicator, damage numbers | ADR-0015 (IPlayerCombatView), ADR-0014 (HUD panel + world-space flyouts) | ✅ |
| TR-combat-014 | Combat | same-tick mutual kill: enemy damage first, both apply | ADR-0002 (1b), ADR-0015 | ✅ |
| TR-combat-015 | Combat | combat state never persisted | ADR-0004 §6 | ✅ |
| TR-ldu-001 | LDU | preload / activate at φ / teardown at grace expiry | ADR-0005 | ✅ |
| TR-ldu-002 | LDU | layout() pure, byte-identical | ADR-0003, ADR-0005 | ✅ |
| TR-ldu-003 | LDU | KnownLandTemplates append-only, seeded, permanent | ADR-0004, ADR-0005 | ✅ |
| TR-ldu-004 | LDU | sole-source warning; depositPoint + socketNoBuildRadius per socket | ADR-0005, ADR-0006 | ✅ |
| TR-ldu-005 | LDU | enemy spawn contract | ADR-0005 (call) | ⚠️ → ADR-0012 |
| TR-ldu-006 | LDU | traversalProfile; stripTimeEstimate CI readout | ADR-0006 | ✅ |
| TR-ldu-007 | LDU | memory: ≤ 2 GB; one atlas per template; 64 MB budget owned by LandLifecycle | ADR-0005 | ✅ |
| TR-ldu-008 | LDU | Append at first φ only, never at preload | ADR-0005 | ✅ |
| TR-harv-001 | Harvesting | node swingsRemaining host-auth, replicated | ADR-0005 (LandNet list home) | ⚠️ → ADR-0010 |
| TR-harv-002 | Harvesting | three-gate resolution in one critical section | ADR-0002 | ✅ |
| TR-harv-003 | Harvesting | HarvestDiff sparse, synchronous write | ADR-0004 (order/predicate) | ⚠️ key schema → ADR-0010 |
| TR-harv-004 | Harvesting | referent chosen at windup start; own phase constants | ADR-0003, ADR-0015 | ✅ |
| TR-harv-005 | Harvesting | integer deterministic yield; teardown after last-tick resolution | ADR-0002, ADR-0003 | ✅ |
| TR-harv-006 | Harvesting | load validation | ADR-0006 | ✅ |
| TR-harv-007 | Harvesting | host proximity sanity check; confirmed crack/flyout | ADR-0002, ADR-0015 | ⚠️ bound → ADR-0008 |
| TR-harv-008 | Harvesting | harvestWindup + harvestActive ≥ 0.18 load rule | ADR-0006 stage 3 | ✅ |
| TR-craft-001 | Crafting | RecipeDef + 11-row validation | ADR-0006 | ✅ |
| TR-craft-002 | Crafting | KnownRecipes union reconcile | ADR-0004 | ✅ |
| TR-craft-003 | Crafting | craft legality + commit critical section | ADR-0002 (model) | ⚠️ command unowned — crafting runtime ADR |
| TR-craft-004 | Crafting | InstanceMetadata table; orphan/mystery reconcile | ADR-0004, ADR-0003 (IGearHooks) | ⚠️ owner impl unowned |
| TR-craft-005 | Crafting | hook values per tier + override; ceilings validated | ADR-0006 | ✅ |
| TR-craft-006 | Crafting | durability drain from events; instant repair | ADR-0003, ADR-0015 (events) | ⚠️ drain/repair impl — no Required-ADR row |
| TR-craft-007 | Crafting | era gate reads KnownLandTemplates; ItemDef.SourceTemplates | ADR-0006, ADR-0005 | ✅ |
| TR-craft-008 | Crafting | craft beat predicted; host commit; no occupancy lock | — | ❌ → ADR-0008 / crafting runtime ADR |
| TR-craft-009 | Crafting | schema-negatives; instant swap equip | ADR-0003 | ✅ |
| TR-craft-010 | Crafting | stationRange one knob, two semantics (Craft reach / BB cost draw) | ADR-0006 stage 6 | ✅ |
| TR-bb-001 | Base Building | StructureDef + 12-row validation | ADR-0006 | ✅ |
| TR-bb-002 | Base Building | StructureInstance registry; replication | ADR-0003 (shape) | ⚠️ → ADR-0011 |
| TR-bb-003 | Base Building | client-local build mode; pure snap; no-alloc F1 | ADR-0003 | ✅ |
| TR-bb-004 | Base Building | placementLegality 8 conjuncts, pure; one critical section | ADR-0002, ADR-0003 | ✅ |
| TR-bb-005 | Base Building | demolishLegality; refund to CARRY; relic reconcile | ADR-0004 | ⚠️ command → ADR-0011 |
| TR-bb-006 | Base Building | two station predicates; storage placement spawns SharedStorage | ADR-0003 | ⚠️ SharedStorage → ADR-0010 |
| TR-bb-007 | Base Building | wall colliders; EC21 owner-rail correction | ADR-0003 (FindCorrectionCell) | ⚠️ → ADR-0011 / ADR-0009 |
| TR-bb-008 | Base Building | CI gates live-recomputed | ADR-0006 stage 10 | ✅ |
| TR-bb-009 | Base Building | ghost outline + grid overlay < 100 draw calls | ADR-0013 §8 (ghost 0 + grid 1 = +1; V4 marginal delta) | ✅ |
| TR-bb-010 | Base Building | EC21 four-neighbour ring-check algorithm pinned | ADR-0003 | ✅ |
| TR-bb-011 | Base Building | host-position read semantics (exact host / one-RTT remote) | ADR-0003 (IHostPositions) | ✅ |
| TR-ai-001 | Enemy AI | host-simulated flat state machines; no client AI | ADR-0015 (step 3) | ⚠️ → ADR-0012 |
| TR-ai-002 | Enemy AI | separation steering; aggro/leash/de-aggro heal | — | ❌ → ADR-0012 |
| TR-ai-003 | Enemy AI | maxUninterruptibleTelegraphsPerTarget = 1 | ADR-0006, ADR-0015 | ✅ |
| TR-ai-004 | Enemy AI | composition pure of (template, variationSeed); ephemeral | ADR-0003 (home) | ⚠️ → ADR-0012 |
| TR-ai-005 | Enemy AI | density monotonic load-check; only EnterTelegraph | ADR-0006, ADR-0015 | ✅ |
| TR-ui-001 | UI/HUD | closed screen-space HUD list; UI Toolkit (architecture ruling) | ADR-0014 §1 (UI Toolkit screens + sprite world-space) | ✅ |
| TR-ui-002 | UI/HUD | co-op affordances | ADR-0014 (edge indicators, who-took-what) | ⚠️ ping → ADR-0007 Ping binding; tags → ADR-0010 payload |
| TR-ui-003 | UI/HUD | reason-string precedence / stability / hysteresis | ADR-0014 §6 (ReasonSelector.Step pure, in Rules) | ✅ |
| TR-ui-004 | UI/HUD | aggregation ban; gamepad nav + focus; contrast; no animation-gated input | ADR-0007 (rebind, capture), ADR-0014 (schema-negative aggregation test, focus, USS gate) | ✅ |
| TR-tint-001 | Tide-Tint | one Shader Graph sprite shader; _TideTint/_TideAmount globals; never MPBs | ADR-0013 §1 (Scope = Global; V1 + absence editor test) | ✅ |
| TR-tint-002 | Tide-Tint | DriftLayer taxonomy exclusions | ADR-0013 §2 (exclusion by material, not runtime branch; V3) | ✅ |
| TR-tint-003 | Tide-Tint | consumes tide floats per frame; future post-process Render-Graph-native | ADR-0013 §5–§6 (TideTintDriver; no custom pass at MVP) | ✅ |
| TR-tint-004 | Art/Netcode | flipbook animation via synced frameIndex | — | ❌ → ADR-0008 / ADR-0012 |
Known Gaps
| ID | Suggested ADR |
|---|---|
| TR-net-003, TR-net-005, TR-tint-004 | ADR-0008 Netcode wire (playtest-gated) |
| TR-move-002, TR-move-004 | ADR-0009 Player transform authority |
| TR-inv-002, TR-inv-004, TR-inv-007 | ADR-0010 Inventory replication |
| TR-craft-008 | ADR-0008 + crafting runtime ADR (proposed Required-ADR row 16) |
| TR-move-003 | ADR-0011 Structure registry + colliders |
| TR-ai-002 | ADR-0012 Enemy simulation |
| TR-bb-009, TR-tint-001, TR-tint-002, TR-tint-003 | ADR-0013 Tide-tint render pipeline |
| TR-ui-001, TR-ui-002, TR-ui-003 | ADR-0014 UI stack |
| TR-cam-002 | deferred to implementation (architecture ruling) |
Superseded Requirements
| ID | What changed |
|---|---|
| TR-save-003 | Quick-spec Rule 3 restated by ADR-0004 (per-drain durability); registry text updated 2026-08-28, ID retained |
| TR-ui-001 | "UI Toolkit" attributed to architecture.md, not the quick-spec; text updated |
| TR-net-006/007/008 | Source attributed to TD reviews / ADR-0002 rather than the netcode quick-spec |