Design Review: Base Building — 2026-08-27
Document reviewed:
design/gdd/base-building.md(874 lines, status "Designed, pending independent /design-review")
Review mode: full (7 specialist agents + creative-director senior synthesis)
Re-review: No — first independent review
Specialists consulted: game-designer, systems-designer, economy-designer, network-programmer, ux-designer, qa-lead, unity-specialist
Senior reviewer: creative-director
Verdict: NEEDS REVISION
Not MAJOR. The design's identity is sound — the orbit test (Rule 3), commit atomicity (Rule 6), the no-ledger discipline (Rule 7), total refund (Rule 9), and the stationPresent contract (F3) all cohere with Crafting, Inventory, Harvesting, and Tide. The defects are almost entirely one type: **the specification is more confident than its foundations** — constants cited that don't exist, ranges declared safe that aren't jointly safe, purity claimed for tests that need a live scene, an invariant asserted ("no softlock is possible by construction") with a counterexample in an unchecked dimension, and fantasy prose promising readings the mechanics can't produce.
Completeness: 8/8 sections present
Dependency Graph
- ✓ crafting-system.md — exists (GDD Reviewed)
- ✓ tide-scheduler.md — exists (GDD Reviewed)
- ✓ inventory-hauling-2026-08-26.md — exists (quick-spec)
- ✓ save-persistence-2026-08-26.md — exists (quick-spec; adopts EC 13–15 posture)
- ✓ art-bible.md — exists (Approved)
Bidirectional consistency confirmed in Crafting and Inventory; LDU correctly uncoupled.
Required Before Implementation (blocking)
- [systems-designer] CI gates bind to constants that don't exist. AC-46's
mixedHaulTimberPerSessionand the "35–50% of mixed haul" figures appear nowhere in harvesting-system.md; AC-45'slowEndPartyHaul(165) is prose there, not a named constant. The "live-recomputed, never hardcoded" gates have nothing to bind to. Fix: Harvesting exports both as first-class named constants; BB's AC-45/46 cite them by name. - [systems-designer] Safe ranges are not jointly safe.
wallCost6 × 60 ÷ 70 timber/session = 6 sessions — fails the 2–4 CI band from inside the declared safe ranges. All four cost knobs at +50% → bootstrapRatio 0.436 vs the 0.35 ceiling. Fix: state that per-knob safe ranges are marginal-only and the CI gates are the joint authority (or narrow the ranges). - **[unity-specialist + game-designer + network-programmer] The player-trap surface, two facets, neither named.** (a) F1 never checks player occupancy — a wall can be committed on top of a standing player, including a remote player whose owner-authoritative movement cannot be rewound. (b) Edge Case 20's "no softlock is possible by construction" is false spatially: a full-bag player enclosed by walls cannot demolish an exit (F2
CanAddgate). Fix: seventh conjunctnoPlayerOccupancyor explicit accepted-with-mitigation ruling; rename EC20 to "no material softlock"; add a spatial-enclosure edge case with a ruling. - [qa-lead + network-programmer + unity-specialist] AC misclassification cluster. AC-20b's "exact same host tick" is not observable under NGO's ordered host queue (arrival order already is the tiebreak) — split into pure-tiebreak
[UNIT]+ tick-window[INTEGRATION], and pin single-ordered-channel host-arrival as a netcode-ADR input. AC-27 and F1'svalidTerraincannot be EditMode-pure — mandate injected plain-data snapshots (ITerrainQuery+ registry POCO). Schema-negative ACs ("searched for") must become reflection-based allow-list assertions; AC-7b/AC-39/AC-38's architecture-absence claims route to architecture-review. AC-45/46's mutation test must assert arithmetic-consistent change, not "any delta." AC-9 splits into bit-identical-edge[UNIT]+ honest[MANUAL]sign-off. - [qa-lead] AC-53/54 are unfixably flaky as specified — disconnect-at-exact- commit-tick as a live race violates the project's determinism rule. Fix: mocked disconnect-state tests (mark player disconnected, invoke the commit path directly).
Plus Rule 11 split (ruled at Axis 2, below): 11a atomicity (locked, stays) / 11b input cadence (/ux-design-owned; hold-to-repeat and drag-row permitted as sequential atomic commits with no queue or pending state).
Recommended Revisions
- [game-designer] The arrival beat has no implementing mechanism — the fantasy's stated anchor (homecoming) has no spec, AC, or OQ, while placement got all three. Add an OQ owned by BB +
/ux-design+ art-bible; do not invent the mechanism in BB. - **[network-programmer + game-designer + unity-specialist] Placement-latency feel never validated** — joiners get 70–140ms dead air before the host-confirmed thunk (host gets 0ms). Add one
[MANUAL]playtest AC; escalate host-vs-client asymmetry to technical-director as a cross-cutting instant-commit concern. - [systems-designer]
stationRangeownership contradiction — "locked" in BB, tunable 2–6u in Crafting. Crafting owns the knob; BB cites consumed-not-owned and documents the F1/F3 double duty. - **[systems-designer + ux-designer] Reason-string precedence + display/debounce contract undefined** (repeated cross-system gap — Crafting has it too). Suggested precedence: reach → bounds → socket → terrain → overlap → materials.
- [ux-designer] Gamepad stick-to-cursor transfer function unspecified — AC-8 guarantees outcome parity, not effort parity. Name as
/ux-designdeliverable. - [ux-designer] Demolish targeting mechanism unspecified — specify or explicitly delegate with a named owner.
- [game-designer + systems-designer] Inert relics (EC13) — permanent tombstone contradicts the whole-shape test and EC18's registry-bound assumption. Fix: relic demolish allowed for zero refund ("nothing left to salvage").
- [qa-lead] Shore-usability has no validating AC — only
socketNoBuildRadius > 0is checked, not clearance of the tide-deposit geometry Rule 3 declares systemic. - [ux-designer] Picker affordability text contradicts F1 — picker reads player-centric; the commit gate is placement-spot-centric. Fix the picker text.
- **[economy-designer, scope-corrected by creative-director] Economy sink question (new — distinct from OQ4/OQ8).** After ~session 3 timber/fiber/sinew all lose their last sinks while the faucet recurs unbounded; 8-fiber chests make banking effectively free and infinite, killing harvesting's bank-or-push tension. Not BB's invariant to own: add an accepted-with-rationale note in Formulas + a new OQ owned by economy + producer targeted at the MVP playtest. The lifetime-sink-vs-faucet invariant routes to a cross-system economy pass.
Specialist Disagreements (adjudicated, both sides preserved)
- Axis 1 — staleness/dead-end as blocking [game-designer, economy-designer] vs. the prior CD-GDD-ALIGN gate: ruled already adjudicated for building's dead zone (crafting OQ9 negative ruling stands; a prediction about the playtest outcome is not new evidence — OQ8's falsification instrument stands). But the haul-loop economy evidence is new and gets its own OQ (Recommended #10).
- Axis 2 — Rule 11 vs. 60-confirm repetition fatigue [ux-designer]: **partially upheld** — Rule 11 conflates atomicity (load-bearing, locked) with input cadence (locked by accident of phrasing). Split into 11a/11b as above.
- Axis 3 — snap uniformity vs. collective authorship [game-designer]: **rejected as a defect** — silhouette coherence over authorship texture is the pillar hierarchy resolving correctly; but the prose overclaims ("read 'all of us built this, at different times' from the shapes alone" as an MVP register) and must be trimmed. Same editorial treatment for the "workbench someone shifted" line vs. the five-step demolish-and-re-place round trip.
Explicitly rejected/downgraded (recorded, not silently dropped): full-refund- invalidates-perimeter-metric (metric measures time-to-first-completion); stationRange knob split (YAGNI); picker scalability (Tier 1); staleness-as-blocking (re-litigates the gate); bootstrap-order softness (accurate, no action).
Routed out, not blocking this GDD:
- → netcode ADR: CARRY rail ambiguity at disconnect-commit (owner-rail CARRY vs host-rail debit); join-snapshot vs in-flight-commit ordering;
instanceIdreissue on save rollback; single-ordered-channel host-arrival requirement; NetworkObject vs NetworkList-driven structure instantiation (BB story scoping is sequenced behind this decision). - → technical-director: host-vs-client feel asymmetry on all instant-commit systems; "all host-rail commits are single non-yielding synchronous blocks" as a binding cross-cutting constraint; Render-Graph shader cost of the dashed ghost + reach-following grid vs the <100 draw-call budget.
- → art-bible fix-pass (queue grows by two): ghost dash-gap ratio + strip-to-black test on the ghost grammar; inert-relic visual treatment (already queued).
- → cross-system economy pass: lifetime-sink-capacity vs recurring-faucet invariant.
- → home-island content authoring: buildable-area spatial budget (does the island minus exclusions actually fit a 60-segment perimeter + stations + walk space?).
Nice-to-Have
AC-43 boundary direction restated in-AC; build-mode EXIT transition test (converse of AC-11); SharedStorage "component" terminology parenthetical; grid-overlay draw-call guidance at /asset-spec time; structures.json runtime-boot failure behavior (loud reject defined for the parser, undefined for async Addressables boot path); AC-8 sequenced behind OQ6 (gridCellSize unpinned).
Senior Verdict [creative-director] — abridged
NEEDS REVISION, six change-sets to clear (the five blocking items + one editorial/flag pass). What the GDD does unusually well, recorded so the finding volume doesn't misrepresent it: enforcement at the provider (orbit test), the no-ledger test applied one layer before the field would exist, the declined-RecipeDef-reuse reasoning, absences named as intent (Enemy AI / LDU / Base-Defense rows), and the MVP honesty clause — "a section whose entire purpose is to prevent the doc from claiming more than it delivers." Every defect is the same failure mode: a well-reasoned claim never adversarially checked against its own dependencies.
Scope Signal
Rough scope signal: L (5 upstream dependencies, 4 formulas + 2 CI gates, hard coupling to Crafting/Inventory/Save, story scoping sequenced behind the netcode ADR) — producer should verify before sprint planning.