Skip to content

Domain model ​

Vocabulary (use these words in code and specs) ​

  • Leaf — a node in the dependency tree not crafted further in our plan; it is bought or supplied.
  • Buyable — obtainable on the Trading Post. Priced via /v2/commerce/prices.
  • Gated input — account-bound or earned, not on the TP (Gift of Exploration, Gift of Battle, Bloodstone Shard, Obsidian Shards, Mystic Clovers). A time cost, not a gold cost. Classified programmatically from the item's flags[].
  • Forge node — a Mystic Forge combine step.
  • net_sell — the finished legendary's TP price minus the fixed 15% TP tax (5% listing + 10% exchange). The tax is hardcoded; it is not an API field.
  • Profit — net_sell − Σ cost(buyable leaves), with gated inputs treated as player-supplied.

Hard facts (do not re-litigate) ​

  • The Mystic Forge is not a crafting discipline, so no Forge recipe exists in /v2/recipes. Every legendary combine step comes from a curated, version-controlled dataset sourced from the GW2 Wiki. That dataset is this project's key maintenance point — game patches drift it. It must be typed, schema-validated by a test, and changed only deliberately.
  • Cost resolution is recursive: cost = min(buy_price, Σ children craft cost).

Legendary types & the curated dataset (graduated from spec 006) ​

Verified against the live API + GW2 Wiki on 2026-07-27/28 (specs/006-static-data/research.md).

  • One universal shape. Almost every legendary is a ~4-ingredient Mystic Forge combine: all three weapon generations, the trinkets (e.g. Aurora), the back items (e.g. Ad Infinitum), and legendary runes. Only legendary armor is different — discipline-crafted (Armorsmith/Leatherworker/Tailor) + vendor, consuming currencies as well as items. The curated recipe schema is therefore a general outputItemId + ingredients[] + method + source list (no fixed precursor/gift slots), with method reserving discipline/vendor/collection and an ingredient kind reserving currency for the armor/trinket work. (F6/F9.)
  • Sellability is a per-item /v2/commerce/prices fact, NOT a per-generation rule. Gen 1 and Gen 3 weapons are TP-sellable; Gen 2 weapons are account-bound, as are all armor, trinkets, and back items. So net_sell/the craft-for-profit persona applies to Gen 1 + Gen 3 weapons only; everything else is craft-for-self (cost + time, no resale). Never hardcode "generation ⇒ sellable" — read commerce/prices. (F7.)
  • Shared gifts are reused across types (Gift of Fortune → Gen 1 weapons and Ad Infinitum; Mystic Tribute → Gen 2 weapons and Aurora). A flat curated table keyed by outputItemId stores each shared node once; adding a legendary type is adding rows, not restructuring. (F8.)
  • Buyable-vs-gated classifier: gated ⟺ item flags[] includes AccountBound`` specifically. SoulBindOnUse / NoSell / AccountBindOnUse alone do not imply gated (e.g. The Legend is TP-buyable despite NoSell + SoulBindOnUse). /v2/commerce/prices membership is the authoritative ground truth the pricing layer reads; the flag rule is the fast static proxy. (F2/V4.)
  • Home of the curated data: packages/legendary-recipes — a JSON dataset (the api loads it at runtime) plus a Zod schema + validated loader (the guard test validates the JSON in CI). Spec 006 curates all 21 Gen 1 weapons; the schema is future-proofed for the rest.

See docs/project-brief.md for the full domain write-up (API surface, legendary structure, profit model).