NEO-147: update decomposition tracking and strike review findings

pull/188/head
VinPropane 2026-06-27 19:23:17 -04:00
parent 3549b647a5
commit fbb248770f
4 changed files with 14 additions and 11 deletions

File diff suppressed because one or more lines are too long

View File

@ -118,7 +118,7 @@ Gameplay **content and curves** default to **boot load** with optional **dev-onl
**E7.M3 note:** Epic 7 **Slice 3** backlog in Linear ([Epic 7 — Questing, Narrative, and Faction Reputation](https://linear.app/neon-sprawl/project/epic-7-questing-narrative-and-faction-reputation-a9416783ceee)): [NEO-133](https://linear.app/neon-sprawl/issue/NEO-133) → [NEO-143](https://linear.app/neon-sprawl/issue/NEO-143) **landed**; label **`E7.M3`**. See [E7M3-pre-production-backlog.md](../../plans/E7M3-pre-production-backlog.md), [E7_M3_FactionReputationLedger.md](E7_M3_FactionReputationLedger.md). Upstream: E7.M1 **Ready**, E7.M2 **Ready**. Prototype spine: two frozen factions; operator chain grants **+15 Grid Operators**; **`prototype_quest_grid_contract`** gated at **minStanding 15**; rep grants via **`completionRewardBundle.reputationGrants`**; accept deny **`faction_gate_blocked`**. **E7M3-11 / NEO-143** client capstone landed — [`NEO-143` manual QA](../../manual-qa/NEO-143.md), [client README — End-to-end faction reputation loop (NEO-143)](../../../client/README.md#end-to-end-faction-reputation-loop-neo-143), plan [NEO-143](../../plans/NEO-143-implementation-plan.md). Epic 7 Slice 3 client capstone complete.
| E7.M4 | ContractMissionGenerator | E4.M1, E5.M3, E7.M3 | ContractTemplate, ContractSeed, ContractOutcome | Pre-production | In Progress |
**E7.M4 note:** Epic 7 **Slice 4** backlog in Linear ([Epic 7 — Questing, Narrative, and Faction Reputation](https://linear.app/neon-sprawl/project/epic-7-questing-narrative-and-faction-reputation-a9416783ceee)): [NEO-144](https://linear.app/neon-sprawl/issue/NEO-144) → [NEO-154](https://linear.app/neon-sprawl/issue/NEO-154); label **`E7.M4`**. See [E7M4-pre-production-backlog.md](../../plans/E7M4-pre-production-backlog.md), [E7_M4_ContractMissionGenerator.md](E7_M4_ContractMissionGenerator.md). **E7M4-01 / NEO-144** catalog + CI landed; **E7M4-02 / NEO-145** fail-fast server catalog load + **`IContractTemplateRegistry`** landed ([NEO-145 plan](../../plans/NEO-145-implementation-plan.md)); **E7M4-03 / NEO-146** contract instance + outcome stores landed ([NEO-146 plan](../../plans/NEO-146-implementation-plan.md)). Upstream: E5.M3 **Ready**, E7.M3 **Ready**; E4.M1 live zone read deferred (content-only **`zoneDifficultyBand`** in Slice 4 v1). Prototype spine: one template **`prototype_contract_clear_combat_pocket`** → **`prototype_combat_pocket`** encounter clear → repeat **`scrap_metal_bulk` ×5** + salvage XP; economy band caps at issue. Client capstone **E7M4-11** [NEO-154](https://linear.app/neon-sprawl/issue/NEO-154).
**E7.M4 note:** Epic 7 **Slice 4** backlog in Linear ([Epic 7 — Questing, Narrative, and Faction Reputation](https://linear.app/neon-sprawl/project/epic-7-questing-narrative-and-faction-reputation-a9416783ceee)): [NEO-144](https://linear.app/neon-sprawl/issue/NEO-144) → [NEO-154](https://linear.app/neon-sprawl/issue/NEO-154); label **`E7.M4`**. See [E7M4-pre-production-backlog.md](../../plans/E7M4-pre-production-backlog.md), [E7_M4_ContractMissionGenerator.md](E7_M4_ContractMissionGenerator.md). **E7M4-01 / NEO-144** catalog + CI landed; **E7M4-02 / NEO-145** fail-fast server catalog load + **`IContractTemplateRegistry`** landed ([NEO-145 plan](../../plans/NEO-145-implementation-plan.md)); **E7M4-03 / NEO-146** contract instance + outcome stores landed ([NEO-146 plan](../../plans/NEO-146-implementation-plan.md)); **E7M4-04 / NEO-147** contract generator **`TryIssue`** landed ([NEO-147 plan](../../plans/NEO-147-implementation-plan.md)). Upstream: E5.M3 **Ready**, E7.M3 **Ready**; E4.M1 live zone read deferred (content-only **`zoneDifficultyBand`** in Slice 4 v1). Prototype spine: one template **`prototype_contract_clear_combat_pocket`** → **`prototype_combat_pocket`** encounter clear → repeat **`scrap_metal_bulk` ×5** + salvage XP; economy band caps at issue. Client capstone **E7M4-11** [NEO-154](https://linear.app/neon-sprawl/issue/NEO-154).
### Epic 8 — Social / Guild

View File

@ -70,7 +70,7 @@ Issue a validated **`active`** contract instance from **`ContractSeed`** inputs
- **Types:** `ContractGeneratorReasonCodes`, `ContractIssueOperationResult`, `ContractInstanceIds.MakeDeterministicInstanceId`.
- **Orchestrator:** `ContractGeneratorOperations.TryIssue` — band + faction template selection, deterministic id, store persist.
- **Tests:** `ContractGeneratorOperationsTests` (11 unit), `ContractGeneratorOperationsIntegrationTests` (DI), `ContractGeneratorPersistenceIntegrationTests` (`RequirePostgresFact`); **888** tests green.
- **Tests:** `ContractGeneratorOperationsTests` (13 unit), `ContractGeneratorOperationsIntegrationTests` (DI), `ContractGeneratorPersistenceIntegrationTests` (`RequirePostgresFact`); **890** tests green.
- **Docs:** `server/README.md` contract generator section; `E7_M4_ContractMissionGenerator.md` NEO-147 note.
## Technical approach
@ -169,6 +169,7 @@ No outcome-store writes in E7M4-04.
| `server/NeonSprawl.Server/Game/Contracts/ContractGeneratorOperations.cs` | `TryIssue` orchestrator |
| `server/NeonSprawl.Server.Tests/Game/Contracts/ContractGeneratorOperationsTests.cs` | AAA unit tests for issue/deny paths |
| `server/NeonSprawl.Server.Tests/Game/Contracts/ContractGeneratorOperationsIntegrationTests.cs` | DI integration test via test host |
| `server/NeonSprawl.Server.Tests/Game/Contracts/ContractGeneratorPersistenceIntegrationTests.cs` | Postgres cross-factory issue read (`RequirePostgresFact`) |
## Files to modify

View File

@ -19,12 +19,12 @@ NEO-147 adds `ContractGeneratorOperations.TryIssue`, a server-authoritative orch
| `docs/plans/NEO-147-implementation-plan.md` | **Matches** — AC checklist complete; reconciliation reflects shipped types, orchestrator, tests (11 unit + DI + Postgres), README, module note. Minor drift: plan “Files to add” omits `ContractGeneratorPersistenceIntegrationTests.cs` (listed under Tests section only). |
| `docs/plans/E7M4-pre-production-backlog.md` (E7M4-04) | **Matches** — template selection, active cap, deterministic ids, structured denies; economy lint, HTTP, completion wiring correctly out of scope. |
| `docs/decomposition/modules/E7_M4_ContractMissionGenerator.md` | **Matches** — NEO-147 generator operations paragraph + README link added. |
| `docs/decomposition/modules/documentation_and_implementation_alignment.md` | **Partially matches** — E7.M4 row stops at E7M4-03/NEO-146; should add E7M4-04/NEO-147 generator ops after merge (same follow-up pattern as NEO-146). |
| `docs/decomposition/modules/module_dependency_register.md` | **Partially matches** — E7.M4 note ends at NEO-146; optional one-line NEO-147 after merge. |
| `docs/decomposition/modules/documentation_and_implementation_alignment.md` | ~~**Partially matches** — E7.M4 row stops at E7M4-03/NEO-146; should add E7M4-04/NEO-147 generator ops after merge (same follow-up pattern as NEO-146).~~ **Done.** — E7M4-04 / NEO-147 generator ops added to E7.M4 row. |
| `docs/decomposition/modules/module_dependency_register.md` | ~~**Partially matches** — E7.M4 note ends at NEO-146; optional one-line NEO-147 after merge.~~ **Done.** — E7M4-04 / NEO-147 note added. |
| `docs/decomposition/modules/client_server_authority.md` | **N/A** — server orchestrator; authority unchanged. |
| Full-stack epic decomposition | **N/A** — server-only; client counterpart NEO-153 correctly deferred until NEO-151 HTTP. |
Register/tracking tables should be updated for E7M4-04 after merge — **should fix** (non-blocking), mirroring NEO-146 alignment follow-up.
~~Register/tracking tables should be updated for E7M4-04 after merge — **should fix** (non-blocking), mirroring NEO-146 alignment follow-up.~~ **Done.**
## Blocking issues
@ -32,16 +32,18 @@ None.
## Suggestions
1. **Update decomposition tracking for E7M4-04** — After merge, extend `documentation_and_implementation_alignment.md` E7.M4 row (and optionally `module_dependency_register.md`) with E7M4-04: `ContractGeneratorOperations.TryIssue`, reason codes, deterministic ids, README section — same pattern as NEO-145/NEO-146.
1. ~~**Update decomposition tracking for E7M4-04** — After merge, extend `documentation_and_implementation_alignment.md` E7.M4 row (and optionally `module_dependency_register.md`) with E7M4-04: `ContractGeneratorOperations.TryIssue`, reason codes, deterministic ids, README section — same pattern as NEO-145/NEO-146.~~ **Done.**
2. **Faction standing deny path** — Plan and README document faction floor via `FactionGateOperations`; unit tests cover band mismatch but not standing failure → `no_eligible_template`. Prototype template min standing is **0** (always passes with default standing), so add a unit test with a synthetic template row (`minStanding: 1`) and zero player standing to lock the orchestrator wiring (distinct from `FactionGateOperationsTests`).
2. ~~**Faction standing deny path** — Plan and README document faction floor via `FactionGateOperations`; unit tests cover band mismatch but not standing failure → `no_eligible_template`. Prototype template min standing is **0** (always passes with default standing), so add a unit test with a synthetic template row (`minStanding: 1`) and zero player standing to lock the orchestrator wiring (distinct from `FactionGateOperationsTests`).~~ **Done.**`TryIssue_ShouldDenyNoEligibleTemplate_WhenFactionStandingBelowMin`.
3. **Duplicate instance id after complete** — Plan adopted: re-issue with the same `seedBucket` after completion hits store duplicate-id deny; orchestrator maps to `invalid_ids` via `DenyCreateFailure`. Add a unit test (complete first issue, re-issue same seed) to document caller contract (“rotate `seedBucket` for a new contract”).
3. ~~**Duplicate instance id after complete** — Plan adopted: re-issue with the same `seedBucket` after completion hits store duplicate-id deny; orchestrator maps to `invalid_ids` via `DenyCreateFailure`. Add a unit test (complete first issue, re-issue same seed) to document caller contract (“rotate `seedBucket` for a new contract”).~~ **Done.**`TryIssue_ShouldDenyInvalidIds_WhenReissuingSameSeedAfterComplete`.
## Nits
- Nit: `MakeDeterministicInstanceId_ShouldMatchForSameInputs_AndDifferForDifferentSeedBucket` has an empty `// Act` block — move equality assertions into Act or fold into Arrange per AAA convention.
- Nit: `ContractGeneratorPersistenceIntegrationTests` mixes second-factory read into Act; acceptable but slightly blurs Act vs Assert compared to other integration tests.
- ~~Nit: `MakeDeterministicInstanceId_ShouldMatchForSameInputs_AndDifferForDifferentSeedBucket` has an empty `// Act` block — move equality assertions into Act or fold into Arrange per AAA convention.~~ **Done.**
- ~~Nit: `ContractGeneratorPersistenceIntegrationTests` mixes second-factory read into Act; acceptable but slightly blurs Act vs Assert compared to other integration tests.~~ **Done.** — cross-factory read moved to Assert.
- Nit: `DenyCreateFailure` fallback `invalid_ids` for duplicate completed instance id is correct per plan but coarse for future HTTP mappers — consider a dedicated reason code if NEO-151 needs clearer client messaging (defer unless HTTP design requires it).
## Verification