Crafting & Gear Identity
Status: Designed + Reviewed — independent /design-review 2026-08-26: NEEDS REVISION, all findings applied same day (
design/reviews/crafting-system-review-2026-08-26.md)
Author: Jeroen + agent panel
Last Updated: 2026-08-26
Creative Director Review (CD-GDD-ALIGN): CONCERNS (resolved) 2026-08-26 — all 3 conditions + 4 advisories applied same day (C1 OQ8 falsification criterion + pre-agreed exit; C2 aggregation ban + AC-13b; C3 provenance trigger made mechanical; A1 world-fact copy; A2 MVP-unfalsifiable note; A3 mark MVP floor; A4 Base-Building outlet note). Durability ruling approved on merits: "a wear-state presentation layer with a homecoming beat," not the mechanic the specialists rejected.
Implements Pillar: Pillar 3 — Made by Our Hands (primary: the only path from materials to power); Pillar 5 — Four Freedoms (gear-carried identity, no classes); serves Expression (#3) and Fantasy (#5) aesthetics
Overview
Crafting is how a haul becomes an era: carry materials to a station at home — workbench for cloth-tier goods, forge for the metal tiers to come — pick a known recipe, and make the thing. Every sword, shirt, and wall segment in Driftlands was made by one of the party from materials someone hauled home before the land that bore them left (Pillar 3 — there are no drops, no vendors, and ruins teach you how to make things, never hand you the thing). Because character stats are flat by design, gear is the entire power and identity system: what you wear and wield is what you are, and anything anyone crafts can be handed to anyone else — a new friend fights at parity the moment someone tosses them the group's spare sword (Pillar 5, binding). Beneath the act sits the project's item layer: Crafting owns item definitions and recipes as data — including the values consumed through other systems' hooks (Combat's DamageModifier/DamageReduction, Harvesting's HarvestModifier, capped ≤ 2.0) — while Inventory owns the stacks they live in. MVP ships the cloth tier only: a small recipe set that stands the base up fast and proves the chain; bronze opens Tier 1, with leather and iron completing the ladder — each era unlocked by the right lands docking, not by grind.
Player Fantasy
Crafting's fantasy is the maker's signature — *"that's my sword you're holding."* The payoff isn't the item; it's being known for it. The anchor moment: three sessions after the forge first lights, a new friend joins mid-session and gets handed a spare sword from the rack without ceremony. She swings it, fells a Rusher, and asks "who made this?" — and someone says "that's Alex's — he's basically our smith now." Nobody assigned Alex that. Nobody can take it from him except by out-forging him. The sword changed hands at full parity (Pillar 5); the name attached to it didn't move — and that is the actual reward. Where combat's mastery is silent and individual, and harvesting's bet is loud and shared in the moment, the maker's recognition is retrospective and asynchronous: it accrues later, off-screen, in the fact that people keep asking for your work by name.
*(MVP honesty clause, review 2026-08-26: this anchor moment is a Tier 1+ target. A 3-recipe cloth tier where everyone knows every recipe and every craft takes the same 2 seconds cannot produce specialization — there is nothing yet to be known for. MVP validates the mechanical skeleton the fantasy will stand on — marks, atomic commits, instance permanence (Rules 1, 5, 7) — the fantasy itself arrives with Tier 1's recipe volume and era gates.)*
Its biggest single scene is the era-turner: the first bronze ingot out of the forge — not a stat ticking up but a physical thing someone is holding, made from tin that drifted in on a land three weeks gone and copper someone nearly died prying from a Bulwark-guarded vein. The group's gear silhouette changes that night, someone screenshots it, and "our bronze age" becomes a phrase said unprompted (concept, Fantasy #5). The tier gate's friction is part of the meaning: you can hold the knowledge from a ruin and still wait at cloth because the right land hasn't docked — the wait is what the ingot is made of.
Its necessary shadow is the forge session: a quiet evening at the anvil while three friends push inland without you. Specialization must always remain a choice being re-made, never an obligation — the night Alex has to smith is the night the fantasy curdles into unpaid labor. And the payoff register is understated, matching the house voice: the ingot is a fact stated plainly, never a fanfare. Outcomes are deterministic — the drama lives in provenance and the decision to make, never in surprise.
**Tone and design tests this fantasy imposes (binding on future crafting features):**
- **The provenance echo (inherited from harvesting — crafting is its terminus).** No smelting, refining, or future chain step may anonymize a material into a fungible stack that has lost its land-of-origin story before it becomes gear. If a crafting flow can't answer "where did this come from," it failed the fantasy. *(Deferral annotation, ruling 2026-08-26: at MVP's cloth tier no chain step exists to anonymize anything — gear answers "who made it, when, what tier"; land-of-origin arrives with Tier 1 smelting as a craft-time summary. An honest partial deferral, not a repeal — Core Rule 6 owns the mechanism.)*
- The signature test. Anyone looking at a piece of gear — on a rack, on a friend's back — must be able to answer "who made this" from the thing itself (a mark, a name, a visual tell), never only from asking in voice chat. Anonymous gear kills the headline fantasy at the forge door.
- The choice test (Pillar 5). Nothing may make specialization sticky: no crafter-only recipes, no bonuses on "your own" gear, no cost to switching who crafts. When a feature could require "the person who's crafted most" vs. "whoever's at the station right now," always the latter. "Our best weaponsmith" stays a social fact, never a system fact.
- The era-gate honesty test. A known-but-uncraftable recipe reads as "the world hasn't offered it yet" — never "locked," never a grind prompt. Any copy nudging the player to unlock a tier faster violates Pillar 1's inheritance and the no-treadmill anti-pillar.
- The hand-tended ceiling. Making requires a player standing at a station doing it. Batch queues, walk-away automation, and labor-optimization features belong to Tier 2's CD-gated "deeper production chains" vision — below that, if we debate "stand and make" vs. "queue and leave," we choose stand and make.
Reference anchor: Valheim's material eras as chapters of group history — with one deliberate divergence: eras here arrive on the tide (the right land docking), not by walking to the next biome; anticipation replaces expedition as the gate.
Detailed Design
Core Rules
- Recipes are data. `RecipeDef = {recipeId, station, inputs[(itemId, count)], output, outputCount, craftTimeSeconds}` — all values data-driven, validated at load. Crafting owns this schema and every gear (and future consumable) recipe.
- Recipe knowledge is group knowledge. At MVP every cloth recipe is known from the first session, by everyone. When Tier 1 ruins teach recipes, the unlock is group-level (one host-authoritative
KnownRecipesset, same authority tier as SHARED-STORAGE) — never per-player (the choice test forbids crafter-only anything). - Era gating is the world's offer. A recipe is craftable iff (a) a station of the required tier is built (Base Building's fact), (b) every input's source material comes from a land template that has docked at least once (read from Land Dock/Undock's
KnownLandTemplatesregistry — a pure function over seeded content), and (c) the inputs are affordable in reach. Known-but-uncraftable recipes are always visible, greyed with a world-fact reason string — never "locked" (era-gate honesty test). The three failure causes carry distinct reason strings (review 2026-08-26 M2): no station — "you need a Workbench"; world not offered — *"no land has offered copper yet"; unaffordable — "not enough fiber in reach"*. A greyed recipe always says which of the three it is. - Two item classes.
MaterialDef(stackable, merges freely — fiber/timber/sinew) andGearDef(maxStack = 1, never merges — two swords of one recipe carry different makers). Gear instance data lives in a Crafting-owned side table keyed byinstanceId, which rides the stack as an **opaque tag Inventory stores but never interprets** (adopted by Inventory Rule 2 asItemStack.instanceTag?on 2026-08-27, cross-GDD review C2 — OQ4 resolved). - The maker's mark. `InstanceMetadata = {instanceId, itemId, crafterName, craftedAtCycle, tier, durability}
.crafterName` is a string baked at craft time — never a live client ID, so the mark survives the crafter being offline forever.craftedAtCycleis asked from the scheduler (in-fiction time: "forged three tides ago"). The mark renders from the item itself everywhere — defined as **every inspection context that shows the item** (tooltip, rack, examine; future contexts inherit the requirement automatically) — plus a visual tell (art bible). **No craft-count, no leaderboard, no queryable smith statistic exists anywhere, ever** — reputation stays a social fact (choice test; this is also the mark-farming lever: no number, no farm). - Provenance: deferred to Tier 1, annotated (ruling 2026-08-26). MVP gear answers who made it, when, at what tier — the signature test delivered in full. Land-of-origin arrives with Tier 1 smelting as a craft-time summary ("tin from the reef-shard land") derived at the consume instant — never per-stack origin bookkeeping. Cloth tier has no smelting step, so the mid-chain anonymization ban is vacuously held; the Player Fantasy's provenance-echo test carries an explicit deferral annotation rather than silence. **Trigger, not schedule (CD C3): the anonymization ban activates at the first recipe with an intermediate output consumed by another recipe — whichever tier that lands in, smelting or otherwise. Any such recipe must ship with the craft-time origin summary in the same change; introducing a chain step without it is the violation, and "Tier 1 hasn't started" is not a defence.**
- Craft flow: stand-and-make, commit at the end. Player at a station within
stationRangepicks a recipe → acraftTimeSecondsbeat (locked stance, animated) → **atomic host commit at the end of the beat: consume inputs — drawn from CARRY plus any home STORAGE container withinstationRange**, as one Inventory-Rule-6-shape transaction — produce output, create the instance and mark — **all five F1 gates and all mutations evaluated inside one host critical section** (no window betweenCanRemoveandCanAdd; gap fix, QA review). All gates re-sample at commit; any failure is an honest no-op. Moving or cancelling mid-beat is a true no-op — nothing was debited, nothing to refund. Two players racing the same last materials: first host-arrival at commit wins (house pattern). - No queues, no batches, no automation (hand-tended ceiling — explicitly scoped to station crafting; Base Building's placement flow is a separate system with its own tests). One craft at a time per player. Stations have no occupancy lock — two players at one bench run independent transactions; contention resolves at the commit gates, elbow-to-elbow.
- Durability is the edge, never the item (user ruling 2026-08-26 — Valheim-style, reconciled with flat stats). Gear drains a durability pool through use (weapon: swings landed; armor: hits absorbed; tools at Tier 1: harvest swings). At 0 the gear **never breaks, never unequips** — its modifiers dull to baseline (
DamageModifier→ 1.0,DamageReduction→ 0.0,HarvestModifier→ 1.0) until repaired. Repair is free and instant at a station of the gear's tier **or higher** (downward-inclusive, ruling 2026-08-26 — repair returns gear to spec, it isn't making something; crafting itself stays exact-tier-match) — a return-home rhythm, never a material sink, never a punishment. At MVP (cloth = baseline) durability is pure wear-state presentation with zero mechanical loss — it is **not expected to build a repair habit on its own** (free + instant + mechanically invisible builds nothing; review 2026-08-26): it exists to seed the wear-state visual grammar and give repair a home before it has teeth. It gains teeth exactly when the tier ladder does — **which means MVP playtest cannot validate this mechanic (nothing to feel); a clean MVP playtest is not evidence. See Open Question 8 (CD A2).** A new friend's dulled hand-me-down still fights at full cloth parity — the Pillar 5 floor is durability-proof by construction. Death never damages gear (combat's keep-everything). - Structures never route through Crafting. No structure items exist in inventory: Base Building owns build-mode placement and all structure costs, drawing materials directly at placement (it may reuse
RecipeDefas a data shape — its choice). Base Building is a peer, not a dependent. - No bag-upgrade item, ever (closed question). Bag capacity is a global constant; a craftable capacity item would break Harvesting's supply-vs-haul invariant and reintroduce the power divergence the flat-stats decision cut.
- Equipping is instant, free, and placeless — no station needed; swap-in-place (the unequipped item lands exactly where the new one came from — no slot churn, no drop risk).
States and Transitions
This system has deliberately fewer states than its siblings — a single-phase timed action gated once at commit; no re-sampled mid-phase gates, no lifecycle counters.
| From | Event | To | Notes |
|---|---|---|---|
| Idle/Move (at station, in range) | craft input, gates provisionally pass | Crafting | nothing debited yet |
| Crafting | craftTimeSeconds elapsed | Idle/Move | atomic commit: consume + produce + mark, all-or-nothing |
| Crafting | movement / cancel input | Idle/Move | true no-op — materials never touched |
Repair is an instant station action, not a state. Stations hold no state machine (present/absent is Base Building's fact; no occupancy lock per Rule 8).
Feedback authority split (house pattern):
| Effect | Timing |
|---|---|
| Craft stance/animation, station VFX loop, tool sounds during the beat | Instant — client-predicted (outcome-independent) |
| Materials consumed, item produced, instance + mark written, durability changes, repair completion | Host-confirmed broadcast only |
Interactions with Other Systems
| System | Crafting consumes | Crafting provides | Interface owner |
|---|---|---|---|
| Inventory | Atomic Remove(inputs from CARRY + in-range STORAGE) + Add(output) at commit (Rule 6 shape) | Final maxStack values; the instanceTag opaque pass-through (adopted in Inventory Rule 2, 2026-08-27) | Inventory owns stacks/atomicity; Crafting owns definitions |
| Combat | Swing-landed / damage-absorbed events per equipped instance (durability accounting, host-side) | DamageModifier/DamageReduction values per tier (Combat owns the hook signatures) | Combat owns hooks; Crafting owns values |
| Harvesting | Tool-swing events (Tier 1, durability) | HarvestModifier values — hard ceiling ≤ 2.0, load-enforced by Harvesting | Harvesting owns hook + ceiling; Crafting owns values beneath it |
| Base Building | — (peer) | Material item definitions; optionally the RecipeDef data shape | BB owns structures/costs/placement entirely (Rule 10) |
| Land Dock/Undock | KnownLandTemplates registry (era gate (b)) — read-only | — | LDU owns the registry — quick-spec ✅ 2026-08-27 (append at first φ activation, seeded start, no removal ever) |
| Tide Scheduler | cycleIndex (asked, timestamp only — never gating; crafting lives off the tide's clock at home) | — | Scheduler owns time |
| Save | Reconcile for KnownRecipes (union) | InstanceMetadata table — permanent, never stale-dropped (unlike harvest diffs: a maker's mark has no expiry) | Quick-spec ✅ 2026-08-26 — adopts the union + orphan rules; two-class rule confirms permanence |
| Enemy AI | — none — | — none — | No interaction: crafting happens only at home, which is hostile-free by definition (stated so it doesn't read as an omission) |
| UI/HUD | — | Recipe list + known-but-uncraftable reason strings; maker's-mark display data; durability/wear read | UI owns presentation 📌 /ux-design |
Formulas
Crafting math is deterministic and data-driven — no RNG anywhere (house rule). Where modifier math occurs downstream (combat F1/F2, harvesting F1), those systems own the computation and the pinned AwayFromZero rounding; Crafting only supplies values.
Baseline recipe table (cloth tier, MVP)
| Recipe | Station | Inputs | Output | Notes |
|---|---|---|---|---|
| Cloth Sword | Workbench | 6 fiber + 8 timber | 1 (gear) | The MVP weapon; timber-weighted (haft), zero sinew — reachable from shore+mid alone |
| Cloth Garb | Workbench | 10 fiber | 1 (gear) | Baseline armor, pure shore fiber — a first-session friend gears up from the beach (new-friend test, literal) |
| Cloth Garb, Reinforced | Workbench | 8 fiber + 3 sinew | 1 (gear) | The deep-band reward: sinew gates the best cloth armor, never the baseline — DamageReduction 0.10 per-item override (F2; ruled 2026-08-27, cross-GDD review D1 — without it this recipe was mechanically identical to Cloth Garb) |
Structures (workbench, walls, storage) are not here — Base Building owns them (Core Rule 10). No rope intermediate at cloth tier (hand-tended ceiling; multi-step chains are Tier 2's CD-gated territory). **The cloth recipe set is deliberately small (CD A4): the home-facing player's ongoing outlet at MVP is Base Building, not recipe volume — filler recipes would violate the no-treadmill anti-pillar and the hand-tended ceiling.** *(⚑ This outlet claim is unverified until Base Building's GDD exists — Open Question 9, review 2026-08-26.)*
First-session check (party-scoped, review 2026-08-26): sword + baseline garb = 16 fiber + 8 timber = 24 units, against harvesting's low-end casual session haul of ~165 — which is explicitly a **2-player combined** figure (harvesting F3); no solo low-end haul is derived anywhere, so this check validates the party's first session, not an individual's. The party's first weapon and armor land comfortably inside session one with materials to spare. The "new-friend gears up from the beach" scene is priced separately by Cloth Garb alone: 10 fiber ≈ two shore nodes (9 units each), which holds solo — on the docked land's shore band; the home island has no nodes (harvesting Rule 11, cross-GDD W3). *(The pre-sword fight is defined: combat's unarmed strike does 14 — cross-GDD review D2, 2026-08-27 — so a fresh group can clear the mid-band timber the workbench needs before anyone owns a sword.)* Too high breaks the first-session guarantee; too low (< ~10 units) makes the sword a rounding error of the trip rather than its product — the mark should cost something visible. *(Clarified 2026-08-26: "the base kit's materials" in the Overview means the session-one harvestable shore+mid materials — no starting-inventory or pre-placed-structure system exists anywhere. Base Building's bootstrap check owns the combined workbench+storage+sword+garb session-one gate.)*
F1. craftLegality
`canCraft = recipeKnown AND stationPresentExact(tier) AND worldHasOffered(inputs) AND CanRemove(inputs, CARRY ∪ STORAGE-in-range) AND CanAdd(output)`
Variables:
| Variable | Symbol | Type | Range | Description |
|---|---|---|---|---|
| Recipe known | recipeKnown | bool | — | Group-level KnownRecipes set (Rule 2); always true for cloth at MVP |
| Station present | stationPresentExact | bool | — | Base Building's fact (BB F3 — two named predicates): crafting invokes the Exact predicate; repair (Rule 9) invokes stationPresentAtLeast (naming aligned 2026-08-27, cross-GDD W6) |
| World has offered | worldHasOffered | bool | — | Every input's source template ∈ KnownLandTemplates (Rule 3, clause (b)) |
| Inputs affordable | CanRemove | bool | — | Inventory's atomic check over CARRY + in-range STORAGE |
| Output fits | CanAdd | bool | — | Inventory's check; gear is stack-of-1 |
Output Range: boolean; evaluated provisionally at craft-start, re-sampled authoritatively at commit (end of the beat). Failure at either point = honest no-op. Example: cloth sword, workbench built, fiber×6 + timber×8 reachable, bag has a free slot → canCraft = true.
F2. Tier hook ladder (provisional — Tier 1 locks; each era has an identity)
| Tier | DamageModifier |
DamageReduction |
HarvestModifier |
Era identity |
|---|---|---|---|---|
| Cloth (MVP, locked) | 1.0 | 0.0 | 1.0 | The floor — baseline is cloth |
| Bronze | 1.4 | 0.12 | 1.3 | The offense breakthrough (the era-turner must matter in a fight) |
| Leather | 1.4 | 0.22 | 1.3 | The defense breakthrough (no leather swords; armor-focused) |
| Iron | 2.2 | 0.35 | 1.8 | Both — matches combat's provisional endpoints exactly |
Constraint checks: iron 2.2/0.35 = combat's provisional values ✓; every HarvestModifier ≤ 2.0 hard ceiling ✓ with headroom (1.8 leaves Tier 2 somewhere to go). Too high at bronze: the compression threshold sits far below the old "> ~1.5" guess (corrected, review 2026-08-26) — at the provisional 1.4 itself, round(28×1.4)=39 already flattens Rusher (45–65 HP) and Spacer (55–75) to flat 2-hit kills and turns Bulwark's engineered 112-HP 4-hit boundary into 3 (combat F1's exact "variance dies" failure mode). Even 1.2 (→ 34) still flattens Rusher — the variance-preserving value may sit at or below the 1.1 floor, meaning Tier 1 may have to **trade variance against era-turner punch knowingly (Open Question 1 owns that decision). Too low** (≤ 1.1) makes the era-turner mechanically weightless — bronze reads as reskinned cloth.
Per-item overrides (added 2026-08-27, cross-GDD review D1): the tier row is the default for every GearDef of that tier; a GearDef may carry an explicit hook override that replaces the tier value for that item only. MVP's single override: **Cloth Garb, Reinforced — DamageReduction 0.10** (combat's TTD check: Bulwark's top hit 26 → 23, mistake budget 4 → 5; Rusher 16 → 14, 7 → 8). Without it the recipe was identical to Cloth Garb and the deep band — sinew, Bulwark-guarded, in no structure — had no MVP payoff at all. Overrides are validated against the same ceilings as tier values (Edge Case 16) and **must not exceed the next tier's value** or the ladder stops being monotonic — bronze's provisional 0.12 sits just above 0.10 and must not drop below it (folded into Open Question 1). The dull state (F3) returns an overridden item to the tier baseline (0.0), not to its override.
F3. durabilityDrain
durability_new = max(0, durability_old − 1) per qualifying use (weapon: landed swing; armor: hit absorbed; tool @Tier 1: harvest swing) — and `effectiveModifier = (durability > 0) ? itemValue : baselineValue, where itemValue` is the tier value or the item's F2 per-item override (cross-GDD D1)
Variables:
| Variable | Symbol | Type | Range | Description |
|---|---|---|---|---|
| Durability pool | durabilityPool | int | 300 (default; per-item data; ≥ 10 enforced at load — Edge Case 16) | Uses before dulling; sized so repair is an occasional homecoming beat, never a per-trip nag |
| Drain per use | — | int | 1 (fixed) | One qualifying use = one point; no partial or scaled drain |
| Effective modifier | effectiveModifier | float | tier value or baseline | Binary, never gradual — a decay curve would be invisible stats; sharp/dull with visible wear states is legible |
| Repair | — | — | free, instant, at tier station | Restores pool to full; no material cost, ever (user ruling) |
Output Range: [0, durabilityPool]; at MVP the dull state changes nothing (cloth = baseline) — wear states and the repair habit only. Example: bronze sword, pool 300: after 300 landed swings it swings on at cloth-equivalent 1.0 until a free workbench/forge repair restores 1.4. Theoretical drain floor (sanity note, review 2026-08-26): at combat's 0.25 s swing cycle, 300 landed swings is ≥ 75 s of pure attack-phase time — in practice several sessions of real fighting once misses, spacing, and travel are counted. Real-world cadence is unknowable pre-playtest (Open Question 2); this floor exists so a wildly wrong pool value is caught on paper first, the way tide and harvesting pin their own theoretical bounds.
F4. maxStack (finalized)
Fiber, timber, sinew: 20 locked (per-item registry placeholders resolved; the generic max_stack_cloth constant is superseded by these per-item entries — no scarcity-signaling reason to diverge; sinew's scarcity lives in node placement, not stack size).
Edge Cases
Commit races
- **If two crafts commit on the same tick with overlapping material demand**: each commit is its own atomic host transaction in arrival order (Inventory Rule 6); the second's
CanRemovere-sample sees the first's result and fails as an honest no-op — never partial, never split (Rule 7 restated for the two-crafter case QA will construct). Exact same-tick tie → lowestOwnerClientIdresolves first (the house tiebreak — combat F5, harvesting Rule 8). - **If a craft commit and another player's STORAGE withdrawal overlap the same tick**: no special ordering exists — a craft's consumption is an Inventory-Rule-6 transaction and queues like any other, host-arrival order. **No crafting-side lock exists or may ever be added.**
- If
CanAdd(output)is true at beat start but false at commit: closed — F1's authoritative re-sample at commit already resolves it (honest no-op); closure note so no reader wonders.
Disconnects
- If the crafter disconnects mid-beat: true no-op — nothing was debited at beat start, so there is nothing to resolve for the offline player (inverse of harvesting Edge Case 1's shape, same discipline).
- If the crafter disconnects exactly at the commit tick: the host resolves the commit normally — a disconnect never un-happens a fired atomic commit; output, instance, and mark land in the offline player's persisted CARRY (combat/harvesting Edge Case 1 pattern).
- If the host quits mid-craft: the session ends (host migration banned) — stated so it doesn't read as an omission (combat Edge Case 3).
The instance table
instanceIdissuance (ruling 2026-08-26): host-side monotonic counter, persisted with the save, never reused. Mechanism/replication: ADR-0010 §1 (2026-09-11) — theinstanceTagis the decimal rendering of this id; it crosses the wire asuint(TagCodec); the mark row itself rides ADR-0008's snapshot +CraftCommitted.- If reconcile finds a metadata row no stack references (orphan): dropped and logged — never resurrected as a phantom (harvesting Edge Case 20's posture). Clarification: the Interactions table's "permanent, never stale-dropped" governs marks on live gear; a row with zero referencing stacks is corruption residue, not a mark.
- If a stack carries a tag with no metadata row (inverse orphan): the tag is stripped and the item becomes unmarked "mystery gear" — never deleted (gear is indestructible, Edge Case 21), never a whole-load reject (disproportionate for a friends-only game).
- Marks survive every transfer automatically: the opaque tag rides the stack through every
Remove/Addby construction — the mechanical backbone of the signature test; closure note for the "does the mark survive a trade" probe. crafterNameconstraints: inherited from the session's already-validated display name — Crafting never re-validates. Empty at craft time → "Unknown maker" fallback (an empty mark fails the signature test). Renames are never retroactive (baked at craft). Profanity: friends-only non-concern, stated.
Durability
- **If a drain event arrives for an instance unequipped or transferred before resolution**: discarded — equipped state is re-sampled fresh at the event's resolution instant, never cached (house discipline; combat Edge Case 15's family).
- If a drain and a repair target one instance the same tick: repair resolves last — the same player-favorable-resolution principle as combat Edge Case 11 (a different mechanism: event ordering here, threshold inclusivity there). Zero stakes at MVP (cloth = baseline); the rule exists before Tier 1 gives it teeth.
- Dulled gear stays equipped and fully usable (Rule 9 restated — QA closure: yes, you can keep swinging a dulled sword; it's simply baseline).
- Hand-me-down durability: transfers with the instance exactly like the mark — a gifted sword arrives as dulled or sharp as it was handed over (closure).
15b. Disconnect during repair is structurally impossible: repair is a single instant atomic host action, not a state — either it fired (durability full) or it never happened; there is no mid-repair window to disconnect inside (closure, QA gap fix).
Config validation (load-time, fail loudly)
- One compact family, matching the sibling GDDs:
| Condition | Outcome |
|---|---|
Recipe inputs/output references an unregistered itemId | loud reject |
Empty inputs[] or missing output | loud reject (a free-item recipe is a bug or an exploit) |
craftTimeSeconds ≤ 0 | loud reject (instant craft breaks the hand-tended beat) |
craftTimeSeconds above craftTimeWarnCeiling | loud warning (a deliberately long high-tier craft isn't structurally broken — harvesting Edge Case 9's warn/reject split) |
Hook ceilings, validated at Crafting's own load (the authoring source): HarvestModifier > 2.0 / DamageModifier ≤ 0 / DamageReduction ≥ 1.0 | loud reject |
Duplicate recipeId | loud reject |
Unknown station enum value | loud reject |
output ∈ inputs (self-referencing recipe) | loud reject (no legitimate shape below Tier 2's chain design) |
durabilityPool < 10 | loud reject (floor — pool 1 would dull on the first swing) |
outputCount ≤ 0 or any inputs[].count ≤ 0 | loud reject (an item-destroying or free-fraction recipe is the same exploit family as the free-item row — review 2026-08-26) |
stationRange ≤ 0 | loud reject (a zero/negative draw radius makes every craft unaffordable — config corruption, fail loudly) |
Era gating
- First-launch bootstrap (ruling 2026-08-26): the starting land template(s) are seeded pre-known into
KnownLandTemplatesat world creation — "the first land was always docked." The gate formula stays uniform for every recipe, cloth included; no Crafting-side special case. ⚑ Constrains Land Dock/Undock's registry contract — flagged before its quick-spec locks. - **If a content patch removes a template that was the sole source of a known recipe's input**: the recipe stays craftable (registry membership is a historical fact — "docked at least once" has no un-dock clause) but becomes supply-starved:
CanRemovesimply never passes again. A supply problem, never a lock (era-gate honesty). Content-authoring constraint: patches must not remove the sole source of any known recipe's input — an authoring rule, not a runtime one.
Reconcile / persistence
- If a save's
KnownRecipespredates patch-added recipes: reconcile is union with shipped defaults — knowledge is never revoked; a patch never un-teaches what a group earned. - If
InstanceMetadatareferences a patch-removeditemId: the gear is kept as an inert curiosity — full mark preserved, definition-driven stats fall back to baseline (Rule 9's dull behavior). Never converted, never deleted: mark permanence wins.
Scope closures
- Gear is fully indestructible by construction (Rule 9 never-breaks + Inventory's no-drop/no-destroy + combat's keep-everything). Consequence: unbounded
InstanceMetadatagrowth is a stated non-concern — a friends-only group produces low hundreds of rows over the game's lifetime; no pruning mechanism exists or is needed. - If multiple stations of the required tier are in range: any one satisfies
stationPresent— no selection semantics needed (closure, house parity).
Dependencies
Upstream (Crafting depends on):
| System | Hard/Soft | Interface consumed | Status |
|---|---|---|---|
| Inventory & Hauling | Hard | Atomic Remove/Add over CARRY + in-range STORAGE at commit (Rule 6 shape); the instanceTag opaque pass-through — adopted in Inventory Rule 2, 2026-08-27 | Quick-spec ✅ |
| Combat | Hard (event source) | SwingLanded / DamageAbsorbed events per equipped instance (durability accounting) — combat's Dependencies table provides them as of 2026-08-27 (cross-GDD W2) | GDD Reviewed |
| Harvesting | Hard (Tier 1 event source) | HarvestSwingLanded events for tool durability — harvesting's Dependencies table provides them as of 2026-08-27 (Tier 1 emitter; cross-GDD W2). ⚑ Review 2026-08-26 (M3): Reinforced Garb's "deep-band reward" pricing (AC-55) is unverifiable until harvesting states the sinew-vs-rare-fiber split among its 6 deep-band nodes — flagged to harvesting's fix-pass | GDD Reviewed |
| Land Dock/Undock | Hard | KnownLandTemplates registry (era gate — Rule 3, clause (b)) — both flagged constraints honored: starting templates seeded pre-known (Edge Case 17 → LDU Rule 3), sole-source authoring rule mechanized as a load-time loud warning (Edge Case 18 → LDU Rule 4) | Quick-spec ✅ 2026-08-27 (design/quick-specs/land-dock-undock-2026-08-27.md) |
| Save & Persistence | Hard | InstanceMetadata table (permanent, never stale-dropped), KnownRecipes (union reconcile) | Quick-spec ✅ 2026-08-26 (design/quick-specs/save-persistence-2026-08-26.md) |
| Tide Scheduler | Soft | cycleIndex timestamp (asked) — never gating | GDD Reviewed |
| Art bible | Constraint source | The maker's-mark visual tell, wear states, and per-tier gear silhouettes ("the group's silhouette changes that night") | Approved. ⚑ Art-bible fix-pass item: mark + wear-state + tier-silhouette grammar |
Downstream (systems that depend on Crafting):
| Dependent | Hard/Soft | Interface provided |
|---|---|---|
| Combat | Hard | DamageModifier/DamageReduction values per tier (F2) |
| Harvesting | Hard | HarvestModifier values, ≤ 2.0 always (validated at Crafting's own load, Edge Case 16) |
| Base Building | Peer | Material item definitions; optionally the RecipeDef data shape (Rule 10) |
| UI/HUD | Soft | Recipe list + world-fact reason strings, maker's-mark display data, wear-state read |
Bidirectional-consistency obligations: Combat and Harvesting must gain the durability-event rows in their next fix-pass (flagged); Inventory's quick-spec must record the instanceTag extension decision; LDU and Save quick-specs, when authored, must honor the constraints named above and list Crafting as a dependent. Base Building is a peer both ways — neither doc gates on the other.
Forward references owned elsewhere: craft-commit RPC shape, instance-counter issuance/replication, metadata replication → **netcode ADR. Structure costs and stationRange placement semantics → Base Building. Storage formats → Save quick-spec**.
Tuning Knobs
Not tuning knobs (rules, locked by this GDD): free repair (no material cost, ever), group-level recipe knowledge, no queues/batches/automation, gear indestructibility, binary dulling (never gradual), no bag-upgrade item, commit-at-end-of-beat, mark permanence, no craft statistics. Changing any is a design change requiring GDD revision + CD gate.
| Knob | Default | Safe range | Too low | Too high | Interacts with |
|---|---|---|---|---|---|
craftTimeSeconds (cloth recipes) | 2.0 s | 1.0–4.0 | Menu-click feel — the hand-tended beat dies | Every craft becomes a chore; the 15th item drags | Per-recipe data; craftTimeWarnCeiling |
craftTimeWarnCeiling | 10 s | 5–30 | Tuning experiments nagged | Silent chore-crafts ship | Edge Case 16's warn row |
stationRange | 3 u | 2–6 | Stand-on-the-exact-tile fiddliness | Crafting (and storage draw) from across the base | The storage-draw radius is this same value — one knob, deliberately. This GDD owns the knob (ownership pinned 2026-08-27, BB design-review); Base Building consumes it in two semantics at once — its F1 placement cost-draw radius (placement-spot-centred) and F3 station reach (asker-centred). Retuning for crafting reach also retunes BB's placement material-draw — re-check BB's F1 examples and CI gates alongside |
durabilityPool (per item; cloth default) | 300 | 100–1000 (≥ 10 load floor) | Repair becomes a per-trip nag | Repair never happens; the homecoming rhythm dies | Drain fixed at 1/use — pool is the only durability lever |
| Recipe costs | Formulas table | ±50% per recipe | First-session guarantee breaks (> ~50 combined) | Sword becomes a rounding error (< ~10) | Re-run the first-session check after any change; harvesting yield rates |
| Tier hook values | F2 ladder | bronze DM 1.2–1.5; ladder monotonic per hook | Era-turner weightless | Combat TTK compression; harvest ceiling breach | Re-run combat's TTK check + the ≤ 2.0 validation after any change |
Knob-interaction warnings: recipe costs and harvesting's yield rates form one balance system — the first-session check is the shared invariant. The hook ladder is combat's and harvesting's balance wearing crafting's data — never retune it without re-running their checks. All values live in assets/data/crafting.json, validated per Edge Case 16.
Visual/Audio Requirements
Crafting's visual contract is owned by the art bible; this section states what crafting imposes and cites rather than restates.
The maker's mark is load-bearing scope, not polish (binding): the entire headline fantasy is delivered by this visual system — if it ships thin, nothing else holds the fantasy up. Requirements: the mark (crafter name + "forged N tides ago" + tier) must be readable from the item in every inspection context — tooltip, storage rack, equipped-gear examine — without asking anyone. A per-crafter visual tell at close zoom (a sigil, a stitch accent, derived stably from the crafter name) is desirable; **⚑ art-bible fix-pass item: the mark's visual grammar needs a section, alongside wear states and gear-tier silhouettes. MVP floor (CD A3): crafter name + forged-cycle + tier readable as text in all three inspection contexts (AC-13). The per-crafter visual tell at close zoom is Tier 1 scope but is the fantasy's full delivery — if it slips past Tier 1, revisit whether Fantasy #5 is actually being served.**
Tier silhouettes deliver the era-turner: the art bible's shape-hardening-by-gear-tier rule (its own key decision — structures never harden, gear does) is precisely the mechanism behind "the group's gear silhouette changes that night." Cloth reads soft and rounded; each tier hardens edges. Combat sprites are never tide-tinted, so gear reads identically under every tide state.
Wear states are binary, like the mechanic: a dulled item shows exactly one "worn" silhouette variant (frayed edge accents, shape-only, no gradients — §6.2), matching binary dulling — never a decay gradient the eye must estimate.
The craft beat: station work-loop pose and VFX during craftTimeSeconds (client-predicted); commit lands with a single understated completion beat — a thunk and the item, never a fanfare (the ingot is a fact stated plainly). Era-first crafts get their weight from animation/VFX treatment, never from added duration.
Audio: craft-loop sounds predicted; the completion thunk host-confirmed with the commit; per-material work sounds (weaving vs. hammering) desirable, not MVP-blocking.
Silhouette-first test for crafting assets (pass/fail): at solid black, 64–96 px (§5.4): station identity legible; a station never reads as a threat or a node; gear tier legible on an equipped player by shape hardening alone; the worn variant distinguishable from the fresh one at inspection zoom.
📌 *Asset Spec note: after this GDD is approved, run /asset-spec system:crafting-system.*
UI Requirements
Crafting contributes: the recipe list (every known recipe always visible; known-but-uncraftable entries greyed with **world-fact reason strings** — "no land has offered copper yet" — never "locked", never grind prompts); maker's-mark display in tooltip/rack/examine (name, forged-cycle, tier — and **no craft counts, no leaderboards, anywhere, ever**, Rule 5 restated as a UI ban); a glanceable wear indicator on equipped gear (non-modal accent); and craft-beat progress (a filling motion at the station; cancel-on-move communicated by the stance breaking, never an error dialog; the progress fill vanishes with the stance break — no drain-back animation, no confirmation, matching the true-no-op rule). Reason strings are per-cause (Rule 3's three strings — station / world / affordability — never one generic grey). Copy follows the world-facts tone rule throughout. **Aggregation ban (CD C2): the mark is readable per-item only — no UI may aggregate, sort, group, filter, or count gear by crafterName. A rack sorted by maker is a leaderboard assembled at the presentation layer; Rule 5's ban is on the fact, not merely the field.**
📌 UX Flag — Crafting: this system has UI requirements. In Pre-Production, run /ux-design for the station/recipe/rack screens before writing epics; crafting stories referencing UI must cite design/ux/, not this GDD.
Acceptance Criteria
[UNIT] = EditMode NUnit over pure logic (legality gate F1, durability math F3, config validation, reconcile rules) — the craft pipeline (Rule 7, F1–F4) must be designed pure/DI-testable, no live NGO session required. [INTEGRATION] = NGO runtime, Multiplayer Play Mode + Network Simulator — reserved for commit races under live timing, disconnect handling, and metadata replication. [MANUAL] = human feel/readability judgment, never automated — but scoped to a concrete, checkable claim. All criteria use locked baseline values (cloth tier, MVP) unless the vector specifies otherwise.
Recipes as Data (Rule 1)
- AC-1 [UNIT] GIVEN a
RecipeDefwith valid fields, WHEN loaded, THEN it parses into the schema without error and is retrievable byrecipeId.
Group-Level Recipe Knowledge (Rule 2)
- AC-2 [UNIT] GIVEN the MVP cloth recipe set, WHEN
KnownRecipesis inspected at world creation, THEN all three cloth recipes are present for every player — no per-player knowledge state exists anywhere in the schema. - AC-3 [INTEGRATION] GIVEN a Tier 1 ruin teaches a recipe, WHEN the host commits the unlock, THEN
KnownRecipesupdates once at group scope and every client observes it as known — never a per-player table.
Era Gating as World Offer (Rule 3, F1)
- AC-4 [UNIT] GIVEN all five F1 conjuncts true, WHEN F1 evaluates, THEN
canCraft=true(pinned worked example: cloth sword, workbench built, fiber×6+timber×8 reachable, free bag slot). - AC-5 [UNIT] GIVEN any one F1 conjunct false, WHEN F1 evaluates, THEN
canCraft=false— tested independently for each of the five gates. - AC-6 [UNIT] GIVEN a recipe whose input source template is not in
KnownLandTemplates, WHEN queried for UI, THEN it returns visible-but-uncraftable with a world-fact reason string — never "locked", never hidden. - AC-6b [UNIT] GIVEN each of the three F1 failure causes in isolation (no station / world-not-offered / unaffordable-in-reach), WHEN the recipe list is queried for UI, THEN each produces a distinguishable reason string naming its cause — never one shared generic "uncraftable" (Rule 3's three strings; review 2026-08-26 M2).
Two Item Classes (Rule 4)
- AC-7 [UNIT] GIVEN a
GearDefitem, WHENmaxStackis read, THEN it equals 1 and two instances of the same recipe never merge, even with identical metadata values. - AC-8 [UNIT] GIVEN a
MaterialDefitem, WHEN two stacks of the sameitemIdcombine, THEN they merge freely up tomaxStack(F4).
The Maker's Mark (Rule 5)
- AC-9 [UNIT] GIVEN a completed craft with a non-empty session display name, WHEN
InstanceMetadatais written, THENcrafterNameis baked as a static string equal to that name at craft time — not a live client ID reference. - AC-10 [UNIT] GIVEN an empty/unset display name at craft time, WHEN metadata is written, THEN
crafterName = "Unknown maker"(Edge Case 11). - AC-11 [INTEGRATION] GIVEN the crafter disconnects and the world continues, WHEN the item's mark is read by any other client, THEN
crafterNamestill resolves to the baked string — never blank, regardless of the crafter's online state. - AC-12 [UNIT] GIVEN any exposed data structure, WHEN searched for a craft-count, tally, or leaderboard field, THEN none exists anywhere in the schema (Rule 5's anti-farming clause).
- AC-13 [MANUAL] GIVEN a crafted item in three contexts — tooltip, home rack, and equipped on another player — WHEN a tester inspects each without using voice/text chat, THEN the maker's name is readable from the item itself in all three (the signature test; contexts per Rule 5's scoped "everywhere" definition).
- AC-13b [MANUAL] GIVEN the storage rack and any gear-listing UI, WHEN inspected for sort/group/filter/count affordances keyed on
crafterName, THEN none exists — the mark is per-item readable and never aggregable (Rule 5's ban extended from schema to presentation, CD C2).
Provenance Deferral (Rule 6)
- AC-14 [UNIT] GIVEN MVP cloth tier, WHEN
InstanceMetadatais inspected, THEN it containscrafterName,craftedAtCycle,tier— and no land-of-origin field (the documented deferral, not an oversight).
Craft Flow — Commit Atomicity (Rule 7)
- AC-15 [UNIT] GIVEN a craft beat begins with all gates provisionally passing, WHEN inspected mid-beat, THEN no inputs are debited and no output exists — nothing mutates at craft-start.
- AC-16 [UNIT] GIVEN a beat elapses, WHEN commit runs, THEN consume-inputs + produce-output + create-instance-and-mark execute as one atomic all-or-nothing transaction — partial application is structurally impossible.
- AC-17 [UNIT] GIVEN any F1 gate fails at the commit re-sample, WHEN commit resolves, THEN the craft is an honest no-op — no partial debit, no partial output, no error thrown.
- AC-18 [UNIT] GIVEN a craft in progress, WHEN movement or cancel fires mid-beat, THEN state returns to Idle/Move with nothing debited or refunded — a true no-op, not a refund path.
- AC-19 [INTEGRATION] GIVEN two players racing commits against the same last materials, WHEN both resolve under live host timing, THEN first host-arrival wins and the second's
CanRemovere-sample fails as an honest no-op — never split, never partial (Edge Case 1). - AC-19b [UNIT] GIVEN two craft commits with resolution on the exact same host tick, WHEN ordered, THEN the commit from the lowest
OwnerClientIdresolves first — deterministic across runs (Edge Case 1's tiebreak, house pattern). - AC-20 [UNIT] GIVEN inputs drawn from CARRY plus in-range STORAGE, WHEN
CanRemoveevaluates, THEN both sources are treated as one Inventory-Rule-6-shape transaction — never two independent checks that could desync.
No Queues, No Occupancy Lock (Rule 8)
- AC-21 [UNIT] GIVEN a player already crafting, WHEN they submit a second craft input, THEN it is rejected — one craft at a time per player, no queuing.
- AC-22 [INTEGRATION] GIVEN two players at one station submitting independent craft intents concurrently, WHEN both resolve, THEN neither is blocked by station occupancy — contention resolves only at each commit's own gates.
Durability (Rule 9, F3)
- AC-23 [UNIT] GIVEN
durabilityPool=300and a qualifying use, WHEN F3 evaluates, THENdurability_new = max(0, durability_old − 1)(pinned). - AC-24 [UNIT] GIVEN
durability=0on an equipped item, WHENeffectiveModifieris read, THEN it returns baseline (1.0/0.0/1.0) — the item is never unequipped and never destroyed. - AC-25 [UNIT] GIVEN a bronze sword dulled after exactly 300 landed swings, WHEN repaired at a station of its tier or higher, THEN durability restores to 300 free and instantly and
effectiveModifierreturns to 1.4 immediately (pinned). - AC-26 [UNIT] GIVEN gear of tier T, WHEN repair is attempted at a station of tier T or higher, THEN it succeeds — repair is downward-inclusive (Rule 9 ruling).
- AC-27 [UNIT] GIVEN gear of tier T, WHEN repair is attempted at a station below tier T, THEN it fails/is unavailable — inclusivity is one-directional.
- AC-28 [UNIT] GIVEN a drain and a repair targeting one instance the same tick, WHEN both apply, THEN repair resolves last — player-favorable tiebreak (Edge Case 13).
- AC-29 [UNIT] GIVEN a drain event for an instance unequipped/transferred before resolution, WHEN resolved, THEN the event is discarded — equipped state re-sampled fresh (Edge Case 12).
- AC-30 [UNIT] GIVEN a gear transfer between players, WHEN the new owner inspects it, THEN durability arrives exactly as it was at hand-off (Edge Case 15).
Structures, Bag Items, Equipping (Rules 10–12)
- AC-31 [UNIT] GIVEN the full crafting item registry, WHEN searched for any structure-type item, THEN none exists (Rule 10).
- AC-32 [UNIT] GIVEN the recipe and item registries, WHEN searched for any item modifying
bagSlots/maxStackcapacity, THEN none exists (Rule 11). - AC-33 [UNIT] GIVEN an equip swap, WHEN it resolves, THEN it is instant, free, station-less, and the unequipped item lands in the exact slot the new item vacated (Rule 12).
Instance Table Integrity (Edge Cases 7–11)
- AC-34 [UNIT] GIVEN repeated craft commits across a save/load cycle, WHEN
instanceIds are inspected, THEN they are host-side monotonic, persisted, and never reused. - AC-35 [UNIT] GIVEN a metadata row with zero referencing stacks at reconcile, WHEN reconcile runs, THEN the row is dropped and logged — never resurrected (Edge Case 8).
- AC-36 [UNIT] GIVEN a stack tag with no metadata row, WHEN reconcile runs, THEN the tag is stripped and the item becomes unmarked "mystery gear" — never deleted (Edge Case 9).
- AC-37 [INTEGRATION] GIVEN a marked gear instance, WHEN it passes through CARRY→STORAGE→CARRY and a full save/load cycle, THEN
instanceId,crafterName,craftedAtCycle,tier, anddurabilityare byte-identical throughout (Edge Case 10 — the signature test's mechanical backbone).
Disconnects (Edge Cases 4–6)
- AC-38 [INTEGRATION] GIVEN the crafter disconnects mid-beat, WHEN processed, THEN it is a true no-op — nothing was debited (Edge Case 4).
- AC-39 [INTEGRATION] GIVEN the crafter disconnects at the exact commit tick, WHEN the host processes it, THEN the commit resolves normally — output, instance, and mark land in the offline player's persisted CARRY (Edge Case 5).
Config Validation (load-time, fail loudly — Edge Case 16)
- AC-40 [UNIT] Recipe
inputs/outputreferencing an unregistereditemId→ load rejected. - AC-41 [UNIT] Empty
inputs[]or missingoutput→ load rejected. - AC-42 [UNIT]
craftTimeSeconds ≤ 0→ load rejected; abovecraftTimeWarnCeiling(default 10 s) → loud warning, not rejection. - AC-43 [UNIT]
HarvestModifier > 2.0→ load rejected;DamageModifier ≤ 0→ load rejected;DamageReduction ≥ 1.0→ load rejected — all at Crafting's own load (the authoring source). - AC-44 [UNIT] Duplicate
recipeId→ load rejected. - AC-45 [UNIT] Unknown
stationenum value → load rejected. - AC-46 [UNIT]
output ∈ inputs(self-referencing recipe) → load rejected. - AC-47 [UNIT]
durabilityPool < 10→ load rejected (floor). - AC-47b [UNIT]
outputCount ≤ 0or any inputcount ≤ 0→ load rejected (review 2026-08-26). - AC-47c [UNIT]
stationRange ≤ 0→ load rejected (review 2026-08-26).
Era Gating — Bootstrap & Supply (Edge Cases 17–18)
- AC-48 [UNIT] GIVEN a fresh world creation, WHEN
KnownLandTemplatesis inspected before any docking, THEN the starting template(s) are already present — seeded pre-known (Edge Case 17). - AC-49 [UNIT] GIVEN cloth recipes specifically, WHEN
worldHasOfferedevaluates, THEN they pass through the same uniform gate as every recipe — no cloth-specific bypass exists in code. - AC-50 [UNIT] GIVEN a recipe whose sole input-source template was removed by a content patch, WHEN
canCraftevaluates, THENworldHasOfferedremains true (historical membership) butCanRemovefails — supply-starved, never re-locked (Edge Case 18).
Reconcile / Persistence (Edge Cases 19–20)
- AC-51 [UNIT] GIVEN a saved
KnownRecipespredating patch-added recipes, WHEN reconcile runs, THEN the result is the union of saved + shipped defaults — nothing is ever revoked (Edge Case 19). - AC-52 [UNIT] GIVEN metadata referencing a patch-removed
itemId, WHEN reconcile runs, THEN the gear is retained as an inert curiosity — mark intact, stats at baseline, row never deleted (Edge Case 20).
Formulas — Worked Values & Design-Time Checks (F1–F4)
- AC-53 [UNIT] GIVEN the baseline recipe table, WHEN Cloth Sword + Cloth Garb costs are summed, THEN total = 16 fiber + 8 timber = 24 units (pinned).
- AC-54 [UNIT] GIVEN the live recipe table and harvesting's live constants (per-band yields,
nodesPerLandband split,bagSlots,maxStack), WHEN the first-session gate runs, THEN it recomputes the low-end party haul from those constants at test time and asserts0.06 ≤ (sword + baseline garb cost) / lowEndHaul ≤ 0.30(today: 24 / 165 ≈ 0.145) — a live cross-system invariant in harvesting AC-28's shape, never a hardcoded [10, 50] literal (respec, review 2026-08-26 C1): if harvesting's yields are retuned, this test moves with them or fails. - AC-55 [UNIT] GIVEN the Reinforced Garb recipe, WHEN validated, THEN it requires non-zero sinew while baseline Garb requires zero — sinew gates only the best cloth armor, never the baseline — and its
DamageReductionresolves to the 0.10 per-item override (> the cloth tier's 0.0, < bronze's provisional 0.12) — the deep band pays (cross-GDD review D1, 2026-08-27). - AC-56 [UNIT] GIVEN the F2 ladder (tier rows plus per-item overrides) and combat's archetype HP bands, WHEN combat's TTK check is run for every tier, THEN every tier's placed-hit count against every archetype stays inside combat's 2–4-hit band (against the Tier 1 roster's bands once authored) — the ladder is tested as a band constraint, never as pinned provisional numbers. (Reworded 2026-08-27 at the Technical Setup gate, CD concern 4: the prior form asserted iron = 2.2/0.35 exactly, a value OQ1 flags as unresolved and which, at 2.2, reduces every MVP archetype to 1–2 hits — the "stat-check win" combat's Player Fantasy forbids. Iron's parity with combat's provisional endpoints is now OQ1's to lock, not a test's to freeze.)
- AC-57 [UNIT] GIVEN every F2 tier row, WHEN
HarvestModifiervalues are compared to the 2.0 hard ceiling, THEN all four (1.0/1.3/1.3/1.8) pass, with iron's 1.8 leaving Tier 2 headroom (pinned constraint). - AC-58 [UNIT] GIVEN a bronze sword with pool 300, WHEN 300 landed swings are simulated, THEN
effectiveModifierreads 1.4 for swings 1–300 and 1.0 immediately after the 300th, until repaired (pinned). - AC-59 [UNIT] GIVEN fiber, timber, and sinew definitions, WHEN
maxStackis read, THEN all three equal 20 (F4, finalized).
Provisional-values note: F2's bronze/leather values are provisional — AC-56/AC-57 test only the locked constraints (the 2–4-hit TTK band, the ≤ 2.0 harvest ceiling), never the provisional numbers themselves. Retuning bronze/ leather must not require touching these criteria.
Minimum smoke set (run first)
- AC-16 — commit atomicity: if consume/produce/mark can partially apply, every downstream value is untrustworthy — the highest-blast-radius rule in this GDD.
- AC-37 — mark round-trip through transfer and save/load: the mechanical backbone of the entire maker's-mark fantasy; a mark lost in transit breaks the game's central hook with no error.
- AC-19 — commit races under live timing: the rule most likely to be "fixed" back toward a lock or a split by a contributor who hasn't read Rule 8.
- AC-24 — dulls-to-baseline, never breaks/unequips: a regression reads as a crash-class bug in a game with zero item loss anywhere else.
- AC-52 — inert-curiosity reconcile: the highest-consequence persistence bug this system can produce (a mark silently deleted, breaking the permanence guarantee).
Four are [UNIT]; AC-19 is [INTEGRATION] but runs headless in Multiplayer Play Mode — together under a minute as a pre-QA-handoff gate, matching the sibling smoke-set shape.
Deliberately not criteria (and why)
- "The era-turner lands as a moment" / "the forge session doesn't feel like an obligation" — feel qualities, routed to
[MANUAL]playtest evidence with lead sign-off once art/audio exists; no numeric proxy substitutes for the friend-group reaction. - Craft-commit RPC shape, instance-counter issuance/replication, metadata replication mechanism — deferred to the netcode ADR (⚑ flagged throughout); testing an unlocked wire shape tests the wrong thing.
- F2's bronze/leather values beyond the pinned constraint checks — explicitly provisional; Tier 1's to lock.
- Structure costs and placement semantics — Base Building's entirely (Rule 10); this GDD asserts only AC-31's negative.
- Maker's-mark art quality — an art-bible/asset-review concern; AC-13 covers presence-and-readability in context, not art bar.
Coverage note: Core Rules 1–12 and F1–F4 each have ≥ 1 criterion (Rule 1→AC-1; 2→AC-2–3; 3/F1→AC-4–6; 4→AC-7–8; 5→AC-9–13; 6→AC-14; 7→AC-15–20; 8→AC-21–22; 9/F3→AC-23–30; 10→AC-31; 11→AC-32; 12→AC-33; F2→AC-56–57; F4→AC-59). Every row of Edge Case 16's validation table has a dedicated criterion (AC-40–47c). Edge Case 3 is a closure covered by AC-17's re-sample claim; Edge Cases 21–22 are stated scope closures with no pass/fail surface — not criteria by design; Edge Case 15b (repair disconnect) is structurally impossible and carries no criterion.
Open Questions
| # | Question | Owner | Target |
|---|---|---|---|
| 1 | Final Tier 1 ladder lock (bronze/leather/iron values; confirm leather-between-bronze-and-iron ordering; and (c, cross-GDD D1 2026-08-27) bronze's DamageReduction must stay ≥ Reinforced Garb's 0.10 per-item override or the ladder stops being monotonic). **Must resolve (review 2026-08-26): (a) the TTK-variance-vs-era-punch trade — bronze 1.4 already flattens Rusher/Spacer to flat 2-hit and breaks Bulwark's 4-hit boundary, and the variance-preserving value may sit at/below the 1.1 weightless floor: a trade to make knowingly, not a tuning accident; (b) leather's DR checked against all three archetype top damages after rounding — at 0.22 vs bronze 0.12, Bulwark's top hit (26) rounds both tiers to the same 5-mistake budget, so "defense breakthrough" must survive rounding where it matters most** | Crafting Tier 1 pass + playtest | Tier 1 |
| 2 | durabilityPool 300 vs real session lengths — does repair land as an occasional homecoming beat or a nag? (Zero bite at MVP; rhythm only measurable at Tier 1) | Playtest | Tier 1 |
| 3 | Provenance craft-time summary mechanism + the smelting chain design it rides on (CD gate required for chains — hand-tended ceiling) | Tier 1 crafting pass | Tier 1 |
| 4 | ~~instanceTag additive extension — Inventory quick-spec sign-off~~ RESOLVED 2026-08-27 — Inventory Rule 2 now defines ItemStack = (itemId, count, instanceTag?), opaque and never merged (cross-GDD review C2) | ~~Inventory fix-pass~~ Resolved | Done |
| 5 | ~~Durability-event provider rows in Combat + Harvesting~~ RESOLVED 2026-08-27 — combat provides SwingLanded/DamageAbsorbed (host-confirmed only), harvesting provides HarvestSwingLanded (Tier 1) (cross-GDD W2) | ~~Their fix-passes~~ Resolved | Done |
| 6 | ~~KnownLandTemplates registry contract: seeded starting templates + sole-source authoring rule~~ RESOLVED 2026-08-27 — LDU quick-spec Rules 3–4 adopt both constraints (append-at-φ, seeded start, no removal; sole-source mechanized as loud load warning) | ~~Land Dock/Undock quick-spec~~ Resolved | Done |
| 7 | Maker's-mark visual grammar (per-crafter tell derivation, mark placement) | Art-bible fix-pass + /asset-spec | Pre-Production |
| 8 | Free-repair durability was chosen over both specialists' no-durability recommendation. Falsification criterion (CD C1): at Tier 1 playtest, if any player reports returning home primarily to repair (rather than repairing while home for other reasons), or reports carrying/crafting spare gear to avoid dulling, the mechanic has become hands-friction and fails Pillar 4. Pre-agreed response if falsified: raise durabilityPool first (the only lever); if a pool raise big enough to fix it makes dulling unobservable, cut durability entirely — F3 deletes cleanly (effectiveModifier collapses to tierValue; only the event-provider rows in Combat/Harvesting go unused). MVP playtest cannot answer this (zero bite by construction). | Tier 1 playtest | Tier 1 |
| 9 | ~~The "crafting runs dry by design; Base Building is the home-facing outlet" claim (CD A4) is unverified~~ RESOLVED 2026-08-26 — ruled in the negative by the Base Building GDD's MVP honesty clause (its Player Fantasy section): MVP base building is a finite stand-it-up project, not a session-to-session outlet. The home-facing dead zone after base-up is real and accepted at MVP; the ongoing-outlet role belongs to Tier 1+ building scope. CD A4's outlet claim holds only for the base-up sessions themselves. | ~~Base Building GDD author + producer~~ Resolved | ~~Base Building GDD (next)~~ Done |
| 10 | Does the gearing-up burst (~6–10 crafts × 2.0 s locked stance, back-to-back in session one) still read as hand-tended, or does "no queues" produce a queue-shaped experience anyway (stand-and-wait ×10)? Lever is craftTimeSeconds (1.0 floor) (review 2026-08-26, M1) | Playtest | First friend playtest |