NEO-112: document quest catalog CI and reconcile implementation plan

pull/151/head
VinPropane 2026-05-31 21:16:12 -04:00
parent 81ef9b94cb
commit 765075f3cf
5 changed files with 21 additions and 9 deletions

View File

@ -13,6 +13,7 @@ Data-driven definitions (skills, items, recipes, quests) validated in CI with **
| [`npc-behaviors/`](npc-behaviors/) | NPC behavior archetype catalogs; each row matches [`schemas/npc-behavior-def.schema.json`](schemas/npc-behavior-def.schema.json) — **stable `id`**, **`archetypeKind`**, aggro/leash radii, telegraph + attack timings for [E5.M2](../docs/decomposition/modules/E5_M2_NpcAiAndBehaviorProfiles.md) |
| [`encounters/`](encounters/) | Encounter templates; each row matches [`schemas/encounter-def.schema.json`](schemas/encounter-def.schema.json) — **stable `id`**, completion criteria, **`rewardTableId`** for [E5.M3](../docs/decomposition/modules/E5_M3_EncounterAndRewardTables.md) |
| [`reward-tables/`](reward-tables/) | Reward table catalogs; each row matches [`schemas/reward-table.schema.json`](schemas/reward-table.schema.json) — **stable `id`**, **`fixedGrants`** referencing frozen item ids for [E5.M3](../docs/decomposition/modules/E5_M3_EncounterAndRewardTables.md) |
| [`quests/`](quests/) | Quest catalogs; each row matches [`schemas/quest-def.schema.json`](schemas/quest-def.schema.json) (steps via [`quest-step-def.schema.json`](schemas/quest-step-def.schema.json), objectives via [`quest-objective-def.schema.json`](schemas/quest-objective-def.schema.json)) — **stable `id`**, **`prerequisiteQuestIds`**, step/objective graph for [E7.M1](../docs/decomposition/modules/E7_M1_QuestStateMachine.md) |
| [`resource-nodes/`](resource-nodes/) | Resource node + yield catalogs; node rows match [`schemas/resource-node-def.schema.json`](schemas/resource-node-def.schema.json), yield rows match [`schemas/resource-yield-row.schema.json`](schemas/resource-yield-row.schema.json) — **stable `nodeDefId`**, **`gatherLens`**, **`maxGathers`** for [E3.M1](../docs/decomposition/modules/E3_M1_ResourceNodeAndGatherLoop.md) |
**Prototype Slice 1 (NEO-33):** CI expects **exactly three** skill rows with ids **`salvage`**, **`refine`**, **`intrusion`** (gather + process + tech). Each row must declare **`allowedXpSourceKinds`** (non-empty); see [E2.M1 — Designer note: `allowedXpSourceKinds`](../docs/decomposition/modules/E2_M1_SkillDefinitionRegistry.md#designer-note-allowedxpsourcekinds-and-grant-call-sites) for what each kind means for grant wiring.
@ -29,6 +30,8 @@ Data-driven definitions (skills, items, recipes, quests) validated in CI with **
**Prototype E5 Slice 3 — encounters + rewards (NEO-100):** CI expects **exactly one** encounter id **`prototype_combat_pocket`** and one reward table id **`prototype_combat_pocket_clear`** aligned to [E5.M3 encounter freeze](../docs/decomposition/modules/E5_M3_EncounterAndRewardTables.md#prototype-slice-3-freeze-e5m3-01). **`requiredNpcInstanceIds`** must match the three E5.M2 NPC instance ids; **`fixedGrants`** reference frozen item ids only. **Do not rename** ids after ship—change **`displayName`** only. See [E5M3-prototype-backlog.md](../docs/plans/E5M3-prototype-backlog.md).
**Prototype E7 Slice 1 — quests (NEO-112):** CI expects **exactly four** quest ids aligned to [E7.M1 quest freeze](../docs/decomposition/modules/E7_M1_QuestStateMachine.md#prototype-slice-1-freeze-e7m1-01) — **`prototype_quest_gather_intro`**, **`prototype_quest_refine_intro`**, **`prototype_quest_combat_intro`**, **`prototype_quest_operator_chain`**. Objective **`itemId`** / **`recipeId`** / **`encounterId`** cross-refs must resolve to frozen item, recipe, and encounter catalogs; **`prerequisiteQuestIds`** must be acyclic and reference known quest ids; operator chain terminal step is **`inventory_has_item`** **`contract_handoff_token`** ×1. **Do not rename** quest `id` after ship—change **`displayName`** only. See [E7M1-prototype-backlog.md](../docs/plans/E7M1-prototype-backlog.md) and [NEO-112 plan](../docs/plans/NEO-112-implementation-plan.md).
**Prototype Slice 4 (NEO-45):** CI expects **exactly one** `MasteryTrack` for **`salvage`** only (`refine` / `intrusion` have no mastery rows yet). Tier 1 @ skill level **2** is a **mutually exclusive** branch pick (`scrap_efficiency` vs `bulk_haul`) with **no** perks; tier 2 @ level **4** unlocks one perk per branch path. **Do not rename** `branchId` / `perkId` after ship—change `displayName` only. See [E2.M3 — Designer note](../docs/decomposition/modules/E2_M3_MasteryAndPerkUnlocks.md#designer-note-tiers-branches-and-level-gates) and [freeze table](../docs/decomposition/modules/E2_M3_MasteryAndPerkUnlocks.md#prototype-slice-4-freeze--salvage-flagship-neo-45).
Server load path and hot-reload policy are TBD; keep files versioned here as the source of truth.

View File

@ -59,6 +59,8 @@ Content tooling **Slice 1** — schemas + CI; **Slice 4** — server parity hard
**Encounter catalogs ([NEO-100](https://linear.app/neon-sprawl/issue/NEO-100)):** the same script validates each row in `content/encounters/*_encounters.json` against [`content/schemas/encounter-def.schema.json`](../../../content/schemas/encounter-def.schema.json), rejects **duplicate `id`** across files, cross-checks **`rewardTableId`** against reward table catalogs, and (E5 Slice 3) enforces the **frozen one-encounter** id set (`prototype_combat_pocket`) with **`requiredNpcInstanceIds`** matching the three E5.M2 NPC instance ids.
**Quest catalogs ([NEO-112](https://linear.app/neon-sprawl/issue/NEO-112)):** the same script validates each row in `content/quests/*_quests.json` against [`content/schemas/quest-def.schema.json`](../../../content/schemas/quest-def.schema.json) (steps via [`quest-step-def.schema.json`](../../../content/schemas/quest-step-def.schema.json), objectives via [`quest-objective-def.schema.json`](../../../content/schemas/quest-objective-def.schema.json)), rejects **duplicate `id`** across files and duplicate step/objective ids within a quest, cross-checks objective **`itemId`** / **`recipeId`** / **`encounterId`** against frozen item, recipe, and encounter catalogs, enforces **acyclic `prerequisiteQuestIds`**, and (E7 Slice 1) enforces the **frozen four-quest** id set with operator chain terminal **`inventory_has_item`** **`contract_handoff_token`** ×1.
**Decomposition vocabulary:** the same workflow runs [`scripts/check_decomposition_language.py`](../../../scripts/check_decomposition_language.py) (stdlib only) over `docs/decomposition/**/*.md` to catch wording that treats **combat** as a leveled **`SkillDef`** line instead of **gig** progression (see script docstring for patterns). Adjust the script if a future doc needs a documented exception.
## Source anchors

File diff suppressed because one or more lines are too long

View File

@ -93,10 +93,10 @@ Working backlog for **Epic 7 — Slice 1** ([quest core and persistence](../deco
**Acceptance criteria**
- [ ] PR gate validates quest JSON against schema.
- [ ] Exactly four prototype quest ids; duplicate `id` fails CI.
- [ ] Every objective reference resolves to a frozen catalog id.
- [ ] Stable id list documented in module doc freeze box.
- [x] PR gate validates quest JSON against schema.
- [x] Exactly four prototype quest ids; duplicate `id` fails CI.
- [x] Every objective reference resolves to a frozen catalog id.
- [x] Stable id list documented in module doc freeze box.
**Client counterpart:** none (infrastructure-only).

View File

@ -41,10 +41,17 @@
## Acceptance criteria checklist
- [ ] PR gate validates quest JSON against schema.
- [ ] Exactly four prototype quest ids; duplicate `id` fails CI.
- [ ] Every objective reference resolves to a frozen catalog id.
- [ ] Stable id list documented in module doc freeze box (already present; verify after ship).
- [x] PR gate validates quest JSON against schema.
- [x] Exactly four prototype quest ids; duplicate `id` fails CI.
- [x] Every objective reference resolves to a frozen catalog id.
- [x] Stable id list documented in module doc freeze box (already present; verify after ship).
## Implementation reconciliation (shipped)
- **Schemas:** [`quest-objective-def.schema.json`](../../content/schemas/quest-objective-def.schema.json), [`quest-step-def.schema.json`](../../content/schemas/quest-step-def.schema.json), [`quest-def.schema.json`](../../content/schemas/quest-def.schema.json).
- **Catalog:** [`prototype_quests.json`](../../content/quests/prototype_quests.json) — four frozen quest rows per E7.M1 freeze table.
- **CI:** `PROTOTYPE_E7M1_QUEST_IDS`, prerequisite acyclic gate, objective cross-ref gates, chain terminal token gate in [`validate_content.py`](../../scripts/validate_content.py); duplicate quest/step/objective id rejection.
- **Docs:** CT.M1 quest paragraph, `content/README.md` quests row + E7M1 paragraph, alignment register E7.M1 row, E7M1-01 backlog checkboxes.
## Technical approach