neon-sprawl/docs/plans/E3M2-prototype-backlog.md

15 KiB
Raw Blame History

E3.M2 — Prototype story backlog (RefinementAndRecipeExecution)

Working backlog for Epic 3 — Slice 3 (recipes and crafting pipeline). Decomposition and contracts: E3.M2 — RefinementAndRecipeExecution.

Labels (Linear): every issue E3.M2; add server / Story as listed per issue.

Precursor (do not re-scope): NEO-42 ships RefineActivitySkillXpGrant.GrantOnSuccessfulCraftOrRefine10 refine XP with sourceKind: activity on successful craft/refine completion. Slice 3 calls that helper from the real CraftResult success path; NEO-42 does not own recipe validation, inventory mutation, or craft HTTP.

Upstream (must be landed): E3.M3 Slice 1 — frozen item catalog, IPlayerInventoryStore, PlayerInventoryOperations, inventory HTTP (NEO-50NEO-56). E3.M1 Slice 2 — gather → scrap_metal_bulk (NEO-57NEO-64). E2.M2 grant path (NEO-38).

Prototype craft spine (frozen in E3M2-01): eight RecipeDef rows proving gather → process → make on the frozen six-item catalog — two process (refine) recipes, six make recipes covering every prototypeRole output except material / intermediate (those are inputs). All recipes use requiredSkillId: refine (no separate Make skill row in the prototype skill trio). Station tags, skill level gates, and batch-quantity POST are out of scope for Slice 3.

Linear issues (created): attach docs/plans/NEO-*-implementation-plan.md on the same branch as implementation work.

Slug Linear
E3M2-01 NEO-65
E3M2-02 NEO-66
E3M2-03 NEO-67
E3M2-04 NEO-68
E3M2-05 NEO-69
E3M2-06 NEO-70
E3M2-07 NEO-71

Dependency graph in Linear: E3M2-02 (NEO-66) blocked by E3M2-01 (NEO-65). E3M2-03 (NEO-67) blocked by E3M2-02 (NEO-66). E3M2-04 (NEO-68) blocked by E3M2-03 (NEO-67). E3M2-05 (NEO-69) blocked by E3M2-03 (NEO-67) and E3.M3 inventory store (NEO-54). E3M2-06 (NEO-70) blocked by E3M2-05 (NEO-69). E3M2-07 (NEO-71) blocked by E3M2-05 (NEO-69; may parallel E3M2-06).

Board order: each issue carries estimate 17 matching slug order (E3M2-01 = 1 … E3M2-07 = 7). On the Epic 3 project board, use Display options → Ordering → Estimate (ascending) so Todo reads top-to-bottom in delivery order.


Story order (recommended)

Order Slug Depends on
1 E3M2-01 E3.M3 item catalog (NEO-50)
2 E3M2-02 E3M2-01
3 E3M2-03 E3M2-02
4 E3M2-04 E3M2-03
5 E3M2-05 E3M2-03, E3.M3 inventory store (NEO-54+)
6 E3M2-06 E3M2-05
7 E3M2-07 E3M2-05

Downstream (separate modules): E7.M1 quest steps requiring crafted items; E3.M4 durability sinks; E4.M1 bench/station placement later.


Kickoff decisions (decomposition defaults)

Topic Decision Rationale
Recipe count 8 frozen defs (epic minimum 812) Two refine paths + six make outputs without expanding the item catalog
Skill id refine on every recipe Prototype skill trio has no separate Make skill; matches NEO-42
Skill level gates None in prototype requiredSkillLevel omitted or 0; gates are a content follow-up
Station / bench tags None in prototype Craft always allowed via HTTP; zone/bench gating defers to E4.M1
Craft wire surface POST /game/players/{id}/craft Mirror NEO-55 inventory POST pattern; no station interact in Slice 3
Request shape recipeId + optional quantity default 1 One craft execution per POST; multi-output comes from recipe outputs
Atomic commit Consume all inputs, then grant all outputs, then XP Roll back input removal if output grant fails (mirror gather engine rollback)
XP RefineActivitySkillXpGrant once per successful craft NEO-42 already landed; E3M2-05 owns the call site
RNG / quality / failure None — deterministic success when inputs + bag space allow Soft craft failure and quality tiers are pre-production (crafting.md)
Primary demo loop Gather scrap_metal_bulkrefine_scrap_standardmake_field_stim_mk0 Proves combat-relevant consumable from world nodes

E3M2-01 — Prototype RecipeDef catalog + schemas + CI

Goal: Lock content shape and CI validation for eight frozen recipes before server load.

In scope

  • content/schemas/recipe-def.schema.json and content/schemas/recipe-io-row.schema.json (input/output row shape).
  • content/recipes/prototype_recipes.json with stable id values (see module doc freeze table).
  • scripts/validate_content.py: schema validation, duplicate ids, exact eight-recipe allowlist, recipeKind coverage (process + make), cross-check that every itemId in inputs/outputs exists in content/items/, every requiredSkillId exists in content/skills/.
  • Designer note in E3_M2 + content/README.md.

Out of scope

  • Server loader, craft engine, HTTP.

Acceptance criteria

  • PR gate validates recipe JSON against schema.
  • Exactly eight prototype recipe ids; duplicate id fails CI.
  • Every input/output references a valid frozen item id; every recipe references refine.
  • Stable id list documented in module doc freeze box.

Landed (NEO-65): content/recipes/prototype_recipes.json, recipe-def.schema.json, recipe-io-row.schema.json, CI gates in validate_content.py; plan NEO-65-implementation-plan.md.


E3M2-02 — Server recipe catalog load (fail-fast)

Goal: Disk → host: startup load of content/recipes/*.json with CI-parity validation.

Kickoff note (NEO-66): Duplicate PROTOTYPE_SLICE3_RECIPE_IDS (and Slice 3 gate rules) in C# with an explicit “keep in sync with scripts/validate_content.py comment — mirror NEO-51 PrototypeSlice1ItemCatalogRules / PROTOTYPE_SLICE1_ITEM_IDS.

In scope

  • Loader + catalog types under server/NeonSprawl.Server/Game/Crafting/ (path TBD in plan).
  • Fail-fast on malformed files, duplicate ids, unknown item ids (cross-check IItemDefinitionRegistry), unknown skill ids (cross-check ISkillDefinitionRegistry).
  • Unit tests (AAA) for loader happy path and failure modes.

Out of scope

  • Per-player craft state, HTTP, inventory mutation.

Acceptance criteria

  • Server refuses boot when recipe catalog invalid (mirror E3.M1 / E3.M3 catalog behavior).
  • Catalog resolves RecipeDef and I/O rows by recipe id.

Landed (NEO-66): server/NeonSprawl.Server/Game/Crafting/RecipeDefinitionCatalogLoader, RecipeDefinitionCatalog, PrototypeSlice3RecipeCatalogRules; plan NEO-66-implementation-plan.md.


E3M2-03 — Recipe definition registry + DI

Goal: Injectable IRecipeDefinitionRegistry consumed by craft engine and HTTP.

In scope

  • RecipeDefinitionRegistry implementation + DI registration.
  • Unit tests (AAA): lookup, unknown id, input/output metadata, recipeKind.

Out of scope

  • HTTP, persistence.

Acceptance criteria

  • Host resolves registry from DI; unknown recipeId distinguishable from valid ids in tests.

Landed (NEO-67): IRecipeDefinitionRegistry + RecipeDefinitionRegistry in server/NeonSprawl.Server/Game/Crafting/; plan NEO-67-implementation-plan.md.


E3M2-04 — GET world recipe-definitions

Goal: Versioned read-only catalog for Bruno, client preview, and tooling — mirror NEO-53 item-definitions pattern.

In scope

  • GET /game/world/recipe-definitions + DTOs + API tests (AAA).
  • Bruno folder bruno/neon-sprawl-server/recipe-definitions/.
  • server/README.md section.

Out of scope

  • Per-player craft history or cooldown state.

Acceptance criteria

  • GET returns all eight prototype recipes with schema version field and input/output summary fields needed for QA.
  • Bruno happy path documented.

Landed (NEO-68): GET /game/world/recipe-definitionsRecipeDefinitionsWorldApi + DTOs in server/NeonSprawl.Server/Game/Crafting/; plan NEO-68-implementation-plan.md; manual QA NEO-68; Bruno bruno/neon-sprawl-server/recipe-definitions/.


E3M2-05 — CraftResult engine (consume inputs, grant outputs, refine XP)

Goal: Single server operation that resolves CraftResult: validate recipe + inventory, atomically remove inputs and add outputs via PlayerInventoryOperations, award refine XP via RefineActivitySkillXpGrant on success.

In scope

  • CraftOperations / CraftResult types in server/NeonSprawl.Server/Game/Crafting/.
  • Stable deny reason codes: unknown_recipe, insufficient_materials, inventory_full, invalid_quantity (if quantity validated).
  • Rollback input removal when output grant fails.
  • Unit tests (AAA) with stub inventory + progression stores; NEO-42 grant invoked on success path.
  • Document CraftResult shape in module doc (server-internal until promoted to wire).

Out of scope

  • Craft HTTP (E3M2-06).
  • Client HUD.
  • Skill level gates, station checks, craft failure RNG.

Acceptance criteria

  • Successful craft removes configured inputs and adds outputs deterministically.
  • Insufficient materials returns stable reasonCode with no inventory change.
  • Full bag on output returns stable reasonCode; inputs are not consumed (or are rolled back).
  • refine skill XP increases by 10 on success (NEO-42).
  • make_prototype_armor respects equipment slot rules from E3.M3 when bag is full but equip slot empty.

Landed (NEO-69): CraftOperations.TryCraft + CraftResult in server/NeonSprawl.Server/Game/Crafting/; plan NEO-69-implementation-plan.md; server README — Craft engine (NEO-69).


E3M2-06 — Craft HTTP + Bruno gather→refine→make spine

Goal: Versioned POST /game/players/{id}/craft wired to craft engine; Bruno documents full prototype loop from gather through combat-relevant output.

In scope

  • POST /game/players/{id}/craft + DTOs + API tests (AAA).
  • Known-player gate via IPositionStateStore (NEO-37 / NEO-55 pattern).
  • Bruno bruno/neon-sprawl-server/craft/ with spine: seed or gather scrap_metal_bulkrefine_scrap_standardmake_field_stim_mk0 → GET inventory + GET skill-progression shows refine XP delta.
  • Bruno deny paths: unknown recipe, insufficient materials, inventory full on output.
  • server/README.md; integration tests (AAA) where practical.

Out of scope

Acceptance criteria

  • POST success returns structured CraftResult (or HTTP envelope) matching engine outcome.
  • Bruno spine completes without manual inventory POST shortcuts (gather interact allowed for scrap).
  • At least one deny path documented per major reasonCode.
  • Epic 3 Slice 3 acceptance: player completes gather → refine → usable item (field_stim_mk0 consumable).

E3M2-07 — item_crafted / craft_failed telemetry hook sites

Goal: Comment-only hooks on craft success and structured deny for future E9.M1 catalog events.

In scope

  • Hook placement in CraftOperations (success + deny before commit — engine-only, mirror NEO-64 gather pattern).
  • TODO(E9.M1) comments; no production logging.
  • README + module doc pointer; note time-to-first-craft is a future metric derived from these events + session context (no separate hook in prototype).

Out of scope

  • Telemetry ingest, dashboards.
  • HTTP-layer duplicate hooks if engine owns the contract.

Acceptance criteria

  • Hook sites documented in code and server/README.md.
  • Matches Epic 3 Slice 3 telemetry vocabulary in epic_03.

After this backlog

  • Epic 3 prototype server gather/craft spine complete when E3M2-07 lands; playable client loop completes with Epic 3 Slice 5 (NEO-72NEO-75).
  • Slice 4 (E3.M4 + E3.M5) sinks/policy remains pre-production.
  • Track delivery in Linear; keep blockedBy links synchronized if scope changes.
  • For each issue kickoff, add docs/plans/{NEO-XX}-implementation-plan.md per story-kickoff.
  • Add docs/manual-qa/{NEO-XX}.md when craft HTTP lands (E3M2-06+).