neon-sprawl/docs/reviews/2026-05-16-NEO-45.md

66 lines
6.9 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

# Documentation review — NEO-45 (E2.M3 salvage mastery catalog + schemas + CI)
**Date:** 2026-05-16
**Scope:** E2.M3 Slice 4 documentation and content contract for [NEO-45](https://linear.app/neon-sprawl/issue/NEO-45): `docs/plans/NEO-45-implementation-plan.md`, `docs/plans/E2M3-pre-production-backlog.md`, `docs/decomposition/modules/E2_M3_MasteryAndPerkUnlocks.md`, related Epic 2 / CT.M1 / alignment / register / `content/README.md`, and hybrid-progression ground truth (`docs/game-design/skills.md`, `progression.md`, `gigs.md`).
**Base:** Workspace as of 2026-05-16; `python3 scripts/validate_content.py` and `python3 scripts/check_decomposition_language.py` both exit 0.
## Verdict
**Approve with suggestions**
## Summary
NEO-45 documentation is largely coherent with shipped content: the implementation plan, E2.M3 module freeze table, CT.M1 CI paragraph, `content/README.md`, and alignment row accurately describe the **salvage-only** prototype track, tier gates (2 / 4), branch ids, perk ids, and CI gates. Hybrid vocabulary is preserved (skill mastery vs gig progression; no separate mastery XP bar; skill level from E2.M2). The main gaps are **tracking drift**: E2.M3 module and dependency register still say **Planned** while NEO-45 content is landed; the pre-production backlog leaves E2M3-01 acceptance boxes unchecked though the implementation plan marks them complete. The E2.M3 **Data contract** section should name the top-level **`perks` map** explicitly (decided at kickoff, present in schema and plan, omitted from the module doc body).
## Documentation checked
| Document | Result |
|----------|--------|
| `docs/plans/NEO-45-implementation-plan.md` | **Matches** — kickoff decisions, frozen ids, technical approach, acceptance checklist, and verification steps align with `content/mastery/prototype_salvage_mastery.json`, `content/schemas/mastery-catalog.schema.json`, and `scripts/validate_content.py` behavior. |
| `docs/decomposition/modules/E2_M3_MasteryAndPerkUnlocks.md` | **Partially matches** — freeze table, designer note, gig/skill separation, and artifact paths are correct; **Status** still **Planned**; **Data contract** omits top-level `perks` map shape. |
| `docs/plans/E2M3-pre-production-backlog.md` | **Partially matches** — E2M3-01 scope matches NEO-45; **acceptance criteria checkboxes for E2M3-01 remain unchecked** despite landed catalog/CI. |
| `docs/decomposition/modules/CT_M1_ContentValidationPipeline.md` | **Matches** — mastery paragraph matches script gates (schema, `skillId`, duplicate `perkId`, branch integrity, salvage-only Slice 4). |
| `docs/decomposition/modules/documentation_and_implementation_alignment.md` | **Matches** — E2.M3 row correctly states NEO-45 landed and follow-on NEO-4649 planned. |
| `docs/decomposition/modules/module_dependency_register.md` | **Partially matches** — E2.M3 note and Linear ordering are current; register **Status** column still **Planned** vs alignment **In Progress**. |
| `docs/decomposition/epics/epic_02_skills_and_progression.md` | **Matches** — E2.M3 / Slice 4 pointers, skill-vs-gig XP split, and salvage flagship scope. |
| `docs/decomposition/modules/E2_M2_XpAwardAndLevelEngine.md` | **Matches** — E2.M3 cross-link for level-up re-evaluation; no mastery XP bar implied. |
| `content/README.md` | **Matches**`mastery/` row, Slice 4 freeze, validate command; anchors target E2.M3 designer + freeze headings. |
| `content/schemas/mastery-catalog.schema.json` | **Matches** — documents E2.M3 module; `schemaVersion`, `perks`, `tracks`, `tierIndex`, stable id patterns. |
| `content/mastery/prototype_salvage_mastery.json` | **Matches** — one `salvage` track; tier 1 empty `perkIds`; tier 2 perks; frozen ids per module freeze table. |
| `docs/game-design/skills.md` | **Matches** — Mastery and perks section points to E2.M3; respec open; gig tree separate. |
| `docs/game-design/progression.md` | **Matches** — skill vs gig vocabulary; no mastery XP conflation. |
| `docs/game-design/gigs.md` | **Partially matches** — per-gig mastery called **open**; line referencing “E2.M3-style expression” for **gig** mastery is easy to misread as the E2.M3 **module** (skill-only). |
| `docs/decomposition/modules/E2_M1_SkillDefinitionRegistry.md` | **N/A** — no mastery-specific change required; `salvage` id exists for cross-check. |
| `scripts/validate_content.py` | **Matches** — docs describe gates implemented in `_validate_mastery_catalogs` / `_prototype_slice4_gate`. |
## Blocking issues
(none)
## Suggestions
1. **E2.M3 module + register status** — Set **Status** to **In Progress** in `E2_M3_MasteryAndPerkUnlocks.md` (summary table) and `module_dependency_register.md` (E2.M3 row), mirroring E2.M1 after NEO-33 and the alignment doc **In Progress** row. Reserve **Done** for when NEO-49 closes the Slice 4 engine/HTTP/telemetry slice.
2. **E2M3-pre-production-backlog E2M3-01 checkboxes** — Mark the three E2M3-01 acceptance criteria `[x]` when NEO-45 is merged/Done in Linear, or add a one-line note under E2M3-01: “Catalog + CI: **NEO-45** (see implementation plan).”
3. **E2.M3 Data contract — catalog shape** — Add a short subsection (or extend **Data contract**) documenting the shipped JSON layout: top-level **`perks`** map (keys = `perkId`), **`tracks`** array, **`MasteryTrack.tiers[]`** with `tierIndex` / `requiredLevel` / `branches[]` / `perkIds[]`. Link `content/schemas/mastery-catalog.schema.json` and note map-key === `PerkDef.id` (enforced in CI).
4. **NEO-46 plan handoff** — When kicking off NEO-46, reference NEO-45 plan **gate constants** (salvage-only track count, branch-set equality tier-to-tier) so server loader parity stays explicit (already listed as a risk in the NEO-45 plan).
5. **`gigs.md` gig-mastery line** — Clarify “E2.M3-style expression” means **analogous branch/perk depth for gigs**, not the E2.M3 **skill** module; optional cross-link to a future gig-mastery epic/module when named.
## Nits
- Tier 2 branches in `prototype_salvage_mastery.json` omit `displayName` while tier 1 includes it — valid per schema; optional designer note that `displayName` is optional per branch row.
- Module **Acceptance criteria (E2.M3 / Slice 4)** bullets describe **runtime** unlock behavior (NEO-47+); consider a footnote that NEO-45 satisfies **data + CI** only.
## Verification
- `pip install -r scripts/requirements-content.txt && python3 scripts/validate_content.py` — expect `content OK` with 1 mastery catalog and 1 mastery track.
- `python3 scripts/check_decomposition_language.py` — exit 0.
- After doc edits: grep `E2.M3` status in `module_dependency_register.md` vs `documentation_and_implementation_alignment.md` for consistency.
- Open `content/README.md` links to E2.M3 `#designer-note-tiers-branches-and-level-gates` and `#prototype-slice-4-freeze--salvage-flagship-neo-45` in the GitHub UI (anchor fragility check).
- Manual negative cases from NEO-45 plan (unknown `skillId`, duplicate `perkId`, extra track) — confirm stderr messages remain actionable.