neon-sprawl/docs/plans/NEO-133-implementation-plan.md

7.6 KiB
Raw Permalink Blame History

NEO-133 — E7M3-01: FactionDef catalog + quest gate/rep schemas + CI

Linear: NEO-133
Branch: NEO-133-e7m3-factiondef-catalog-quest-gate-rep-schemas-ci
Backlog: E7M3-pre-production-backlog.mdE7M3-01
Module: E7_M3_FactionReputationLedger.md
Pattern: NEO-124-implementation-plan.md (schemas + catalog + validate_content.py gates)

Goal

Land faction and quest content contracts for Epic 7 Slice 3 so CI validates faction JSON, extended quest fields (factionGateRules, completionRewardBundle.reputationGrants), and the frozen five-quest prototype roster before NEO-134 server faction catalog load.

Kickoff clarifications

Decisions are already frozen in E7M3-pre-production-backlog.md — Kickoff decisions and E7_M3 — Prototype Slice 3 freeze. No blocking AskQuestion items.

Topic Decision Evidence
JSON naming camelCase: reputationGrants, factionGateRules, factionId, minStanding E7M2 bundle pattern; backlog kickoff table
Rep delivery Via completionRewardBundle.reputationGrants (E7.M2 bundle idempotency path) E7_M3 module doc; NEO-138 applies rep
Gate site Quest accept only (Slice 3) Backlog E7M3-06; zone gates deferred to E4.M1
Faction roster Exactly two ids: prototype_faction_grid_operators, prototype_faction_rust_collective E7_M3 freeze table
Quest roster Five quests: four E7.M1 onboarding + prototype_quest_grid_contract E7_M3 freeze; expands PROTOTYPE_E7M1_QUEST_IDSPROTOTYPE_E7M3_QUEST_IDS
Operator chain Add Grid Operators +15 reputationGrants; keep existing item + skill XP E7_M3 freeze
Grid contract Prereq operator chain; Grid Operators minStanding 15; objective inventory_has_item survey_drone_kit ×1; completion Rust Collective +10 E7_M3 freeze
Server loader / stores / HTTP / Godot Out of scope (NEO-134+) Backlog E7M3-01 scope
dotnet test green Minimal roster parity on existing E7.M1/E7.M2 catalog rules only (see below) Content JSON change breaks four-quest server freeze without constant sync

Minimal server parity (CI / test green only)

Adding the fifth quest and updated prototype_quests.json will fail server startup tests until PrototypeE7M1QuestCatalogRules.ExpectedQuestIds includes five ids. This is not NEO-134 loader work — only constant + freeze-table sync mirroring NEO-124 → NEO-125:

  • Extend ExpectedQuestIds + add GridContractQuestId / objective constants.
  • Add prototype_quest_grid_contract to PrototypeE7M2QuestCatalogRules.ExpectedCompletionBundles with empty itemGrants / skillXpGrants (rep-only bundle; server ParseCompletionRewardBundle ignores reputationGrants until NEO-138).
  • Operator chain JSON may include reputationGrants; server E7M2 freeze still compares item + skill XP only (unchanged normalized bundle).

No new faction loader, no IFactionDefinitionRegistry, no gate evaluation.

Files to add

Path Purpose
content/schemas/faction-def.schema.json FactionDef: id, displayName, minStanding, maxStanding, neutralStanding
content/schemas/faction-gate-rule.schema.json factionId, minStanding
content/schemas/reputation-grant-row.schema.json factionId, amount (signed int)
content/factions/prototype_factions.json Two frozen factions per E7_M3 freeze

Files to modify

Path Change
content/schemas/quest-def.schema.json Optional factionGateRules array ($ref faction-gate-rule)
content/schemas/quest-reward-bundle.schema.json Optional reputationGrants array ($ref reputation-grant-row)
content/quests/prototype_quests.json Operator chain reputationGrants; new prototype_quest_grid_contract
scripts/validate_content.py Faction load/validate; PROTOTYPE_E7M3_QUEST_IDS (5); faction cross-ref gates; PROTOTYPE_E7M3_COMPLETION_BUNDLES freeze (item + skill + rep); rename/supersede E7M1 four-quest id gate
content/README.md Document content/factions/, new schemas, five-quest roster
docs/decomposition/modules/E7_M3_FactionReputationLedger.md Mark catalog landed when done
server/.../PrototypeE7M1QuestCatalogRules.cs Five-quest roster + grid-contract constants
server/.../PrototypeE7M2QuestCatalogRules.cs Grid-contract empty item/skill bundle in freeze

CI gates (validate_content.py)

  1. Faction catalog — schema validate content/factions/*_factions.json; freeze exactly two faction ids + display names + standing band (-100…100, neutral 0).
  2. Quest rosterPROTOTYPE_E7M3_QUEST_IDS frozen set of five ids (includes all four E7M1 ids + prototype_quest_grid_contract).
  3. E7M1 gates retained — acyclic prerequisites, objective cross-refs, chain terminal token (updated for fifth quest).
  4. Faction cross-refs — every factionGateRules[].factionId and reputationGrants[].factionId must exist in faction catalog.
  5. E7M3 completion bundle freeze — per-quest expected itemGrants, skillXpGrants, reputationGrants for all five quests (supersedes E7M2 freeze for operator chain + grid contract rep rows; first three gather/craft quests unchanged).
  6. Grid contract shape — prereq operator chain; factionGateRules Grid Operators minStanding 15; objective inventory_has_item / survey_drone_kit.

Tests

Layer What
CI python3 scripts/validate_content.py (existing PR gate)
Server Existing quest catalog loader/registry tests — should pass after roster parity constants; no new [Fact] unless a regression needs explicit grid-contract coverage

Manual QA: none (content-only; Godot capstone is NEO-143).

Implementation order

  1. Schemas (faction-def, faction-gate-rule, reputation-grant-row; extend quest-def + quest-reward-bundle).
  2. prototype_factions.json + quest JSON edits.
  3. validate_content.py gates + bundle freeze tables.
  4. Minimal server roster/freeze constant sync.
  5. content/README.md + E7_M3 module doc status line.
  6. Run python3 scripts/validate_content.py and dotnet test on server project.

Out of scope (follow-on tickets)

Ticket Work
NEO-134 Server faction catalog fail-fast load
NEO-135137 Faction standing store, delta audit, gate evaluation on accept
NEO-138 RewardRouterOperations reputation apply + idempotent delivery
NEO-139143 HTTP read, telemetry, Godot HUD, capstone

Client counterpart

None for E7M3-01. Client faction HUD and capstone: NEO-142 / NEO-143.

Blocks

NEO-134 (server faction catalog load) is blocked until this catalog + CI lands.

Implementation reconciliation (shipped)

  • Schemas: faction-def, faction-gate-rule, reputation-grant-row; extended quest-def + quest-reward-bundle.
  • Catalog: prototype_factions.json (two factions); prototype_quests.json operator-chain rep + prototype_quest_grid_contract.
  • CI: PROTOTYPE_E7M3_* gates in validate_content.py (roster, faction freeze, bundle freeze, cross-refs, grid-contract shape).
  • Server parity: five-quest ExpectedQuestIds, grid-contract E7M2 bundle freeze, schema registry for new $refs.
  • Docs: content/README.md E7 Slice 3 paragraph; E7_M3 module CI line.