NEO-40: add progression telemetry hook comment sites
parent
178ff2b625
commit
effd234ee3
|
|
@ -6,6 +6,7 @@ meta {
|
|||
|
||||
docs {
|
||||
NEO-38: single skill XP grant + allowlist + level-up metadata; see server README.
|
||||
NEO-40: same contract; server adds comment-only telemetry hook markers (no request/response change).
|
||||
}
|
||||
|
||||
post {
|
||||
|
|
|
|||
|
|
@ -19,7 +19,9 @@
|
|||
|
||||
**NEO-39 landed:** data-driven **`LevelCurve`** at `content/skills/prototype_level_curve.json` with schema `content/schemas/level-curve.schema.json`; CI validation extended in `scripts/validate_content.py`; server boot now fail-fast loads curve content and uses it for XP→level resolution in skill progression GET/POST paths (no code edit required for threshold tuning).
|
||||
|
||||
**Still backlog within this module:** telemetry hook sites (**NEO-40**); callers in Slice 3 (**NEO-41**–**NEO-43**). Keep this paragraph and [documentation tracking](documentation_and_implementation_alignment.md) in sync as Slice 2 stories merge.
|
||||
**NEO-40 landed:** comment-only **telemetry hook sites** in `SkillProgressionSnapshotApi` (`POST …/skill-progression`) for future catalog events **`xp_grant`** and **`level_up`** ([implementation plan](../../plans/NEO-40-implementation-plan.md)); manual QA **[`NEO-40.md`](../../manual-qa/NEO-40.md)**.
|
||||
|
||||
**Still backlog within this module:** callers in Slice 3 (**NEO-41**–**NEO-43**). Keep this paragraph and [documentation tracking](documentation_and_implementation_alignment.md) in sync as Slice 2 stories merge.
|
||||
|
||||
## Purpose
|
||||
|
||||
|
|
|
|||
|
|
@ -0,0 +1,32 @@
|
|||
# Manual QA — NEO-40 (progression telemetry hook sites)
|
||||
|
||||
Reference: [implementation plan](../plans/NEO-40-implementation-plan.md), [NEO-38 manual QA](./NEO-38.md) (same server surface).
|
||||
|
||||
## Preconditions
|
||||
|
||||
- Same as NEO-38: run `NeonSprawl.Server` (`dotnet run` from `server/NeonSprawl.Server`; default `http://localhost:5253`).
|
||||
- This story adds **comments only**; behavior matches NEO-38.
|
||||
|
||||
```bash
|
||||
BASE=http://localhost:5253
|
||||
ID=dev-local-1
|
||||
```
|
||||
|
||||
## Verify API unchanged
|
||||
|
||||
1. **Grant** (same as NEO-38 happy path):
|
||||
|
||||
```bash
|
||||
curl -sS -i -X POST "${BASE}/game/players/${ID}/skill-progression" \
|
||||
-H "Content-Type: application/json" \
|
||||
-d '{"schemaVersion":1,"skillId":"salvage","amount":10,"sourceKind":"activity"}'
|
||||
```
|
||||
|
||||
Expect **HTTP 200**, `granted` **true**, `progression` and `levelUps` present as before.
|
||||
|
||||
2. **Level-up path** (optional, same as NEO-38 bonus): large grant on `intrusion` if XP crosses the curve threshold; expect `levelUps` non-empty when a boundary is crossed.
|
||||
|
||||
## Code review check
|
||||
|
||||
- Open `server/NeonSprawl.Server/Game/Skills/SkillProgressionSnapshotApi.cs` and confirm **comment blocks** mark **`xp_grant`** (after successful `TryApplyXpDelta`) and **`level_up`** (inside `nextLevel > prevLevel`), referencing **E9.M1** / no production ingest.
|
||||
- Confirm there are **no** new `ILogger` or metrics calls for these events.
|
||||
|
|
@ -34,8 +34,8 @@
|
|||
|
||||
## Acceptance criteria checklist
|
||||
|
||||
- [ ] Hook locations in **grant** + **level-up** path; documented here **and** in code comments referencing future **`xp_grant`** / **`level_up`** (and **time-to-first-level-up** intent where appropriate).
|
||||
- [ ] **No** mistaken high-volume logging to production pipelines (no new log statements for these hooks).
|
||||
- [x] Hook locations in **grant** + **level-up** path; documented here **and** in code comments referencing future **`xp_grant`** / **`level_up`** (and **time-to-first-level-up** intent where appropriate).
|
||||
- [x] **No** mistaken high-volume logging to production pipelines (no new log statements for these hooks).
|
||||
|
||||
## Technical approach
|
||||
|
||||
|
|
@ -53,14 +53,14 @@
|
|||
|
||||
| Path | Purpose |
|
||||
|------|---------|
|
||||
| **none** | Hook sites are **comment markers** on the existing NEO-38 route; no new types or files required. |
|
||||
| `docs/manual-qa/NEO-40.md` | Manual QA checklist (API parity + comment review). |
|
||||
|
||||
## Files to modify
|
||||
|
||||
| Path | Rationale |
|
||||
|------|-----------|
|
||||
| `server/NeonSprawl.Server/Game/Skills/SkillProgressionSnapshotApi.cs` | Insert **telemetry hook site** comments on the **successful grant** path (`xp_grant`) and **level-up** branch (`level_up`); optional one-line **time-to-first-level-up** intent. |
|
||||
| `docs/decomposition/modules/E2_M2_XpAwardAndLevelEngine.md` | **Only if** a single sentence improves traceability from module doc → hook file; otherwise **none** (YAGNI). |
|
||||
| `docs/decomposition/modules/E2_M2_XpAwardAndLevelEngine.md` | **NEO-40 landed** line + backlog sentence updated (replaces “telemetry still backlog”). |
|
||||
|
||||
## Tests
|
||||
|
||||
|
|
|
|||
|
|
@ -6,6 +6,7 @@ using Xunit;
|
|||
|
||||
namespace NeonSprawl.Server.Tests.Game.Skills;
|
||||
|
||||
/// <summary>Regression tests for <c>POST …/skill-progression</c> (NEO-38). NEO-40 adds comment-only hook sites; JSON contract unchanged.</summary>
|
||||
public sealed class SkillProgressionGrantApiTests
|
||||
{
|
||||
private static SkillProgressionGrantRequest Grant(
|
||||
|
|
|
|||
|
|
@ -81,11 +81,20 @@ public static class SkillProgressionSnapshotApi
|
|||
return Results.NotFound();
|
||||
}
|
||||
|
||||
// --- Telemetry hook site (NEO-40): future E9.M1 catalog event `xp_grant` ---
|
||||
// No ingest here until the telemetry catalog exists. Planned payload fields: playerId,
|
||||
// skillId, amount, sourceKind; optional correlation/request ids when Slice 3 wires callers.
|
||||
|
||||
var prevLevel = levelCurve.LevelFromTotalXp(prevXp);
|
||||
var nextLevel = levelCurve.LevelFromTotalXp(newXp);
|
||||
var levelUps = new List<SkillLevelUpJson>();
|
||||
if (nextLevel > prevLevel)
|
||||
{
|
||||
// --- Telemetry hook site (NEO-40): future E9.M1 catalog event `level_up` ---
|
||||
// Planned fields: playerId, skillId, previousLevel, newLevel. No logging (comments-only).
|
||||
// Time-to-first-level-up: needs first-seen / milestone persistence not present here; wire
|
||||
// when catalog + storage exist (likely derived from `level_up` or a dedicated milestone).
|
||||
|
||||
levelUps.Add(
|
||||
new SkillLevelUpJson
|
||||
{
|
||||
|
|
|
|||
Loading…
Reference in New Issue