# NEO-39 — Manual QA checklist

| Field | Value |
|-------|-------|
| Key | NEO-39 |
| Title | Data-driven skill level curve + CI validation |
| Linear | https://linear.app/neon-sprawl/issue/NEO-39/data-driven-skill-level-curve-ci-validation |
| Plan | `docs/plans/NEO-39-implementation-plan.md` |
| Branch | `NEO-39-data-driven-skill-level-curve-ci-validation` |

## 1) Setup sanity

- [ ] From repo root, run `python3 scripts/validate_content.py` and confirm output reports both skill catalogs and level curve catalogs as valid.
- [ ] Confirm `content/skills/prototype_level_curve.json` exists and includes ascending thresholds (`level` and `requiredXp` increase row-to-row).
- [ ] Start server from `server/NeonSprawl.Server` with `dotnet run` and verify startup succeeds (no level-curve load errors).

## 2) Happy path (acceptance criteria coverage)

- [ ] `GET /game/players/dev-local-1/skill-progression` returns `200` and JSON with `schemaVersion: 1`, `playerId: "dev-local-1"`, and skill rows.
- [ ] Post a grant that does not cross the next threshold and confirm `level` remains unchanged.

```bash
curl -sS -X POST "http://localhost:5253/game/players/dev-local-1/skill-progression" \
  -H "Content-Type: application/json" \
  -d '{"schemaVersion":1,"skillId":"salvage","amount":99,"sourceKind":"activity"}'
```

- [ ] Post an additional grant that crosses a threshold and confirm the response contains `levelUps` with expected `previousLevel` and `newLevel`.

```bash
curl -sS -X POST "http://localhost:5253/game/players/dev-local-1/skill-progression" \
  -H "Content-Type: application/json" \
  -d '{"schemaVersion":1,"skillId":"salvage","amount":1,"sourceKind":"activity"}'
```

- [ ] Read back progression and verify the skill `xp`/`level` matches the level-curve file thresholds (data-driven behavior, no code edits needed for tuning).

```bash
curl -sS "http://localhost:5253/game/players/dev-local-1/skill-progression"
```

## 3) Failure modes

- [ ] Temporarily break `content/skills/prototype_level_curve.json` (for example: set first row to `{ "level": 1, "requiredXp": 5 }`) and re-run `python3 scripts/validate_content.py`; confirm non-zero exit with a curve validation error.
- [ ] With the same invalid curve file, start server and confirm boot fails fast with a level-curve validation/load error.
- [ ] Restore valid curve file content and confirm validator + server startup both return to green.

## 4) No regressions around skill catalogs

- [ ] Confirm skill catalog validation still works with `*_skills.json` naming (existing prototype skill catalog validates successfully).
- [ ] Confirm progression GET/POST endpoints still behave as before for deny paths (`unknown_skill`, `source_kind_not_allowed`, `invalid_amount`) while level computation follows curve content.
