meta { name: GET skill progression type: http seq: 1 } docs { NEO-37: per-player read model; join with GET /game/world/skill-definitions for display names. NEO-38: XP persists (in-memory/Postgres). These checks do not assume a fresh server—level must match placeholder curve level = 1 + floor(max(0,xp)/100). Restart server (or truncate DB in Postgres mode) to see all-zero defaults again. } get { url: {{baseUrl}}/game/players/dev-local-1/skill-progression body: none auth: none } tests { test("returns 200 JSON with schema v1 and skills array", function () { expect(res.getStatus()).to.equal(200); expect(res.getHeader("content-type")).to.contain("application/json"); const body = res.getBody(); expect(body.schemaVersion).to.equal(1); expect(body.playerId).to.equal("dev-local-1"); expect(body.skills).to.be.an("array"); expect(body.skills.length).to.equal(3); }); test("frozen prototype trio with levels consistent with server placeholder curve", function () { const body = res.getBody(); const ids = new Set(body.skills.map((x) => x.id)); expect(ids.has("salvage")).to.equal(true); expect(ids.has("refine")).to.equal(true); expect(ids.has("intrusion")).to.equal(true); /** Matches SkillLevelCurvePlaceholder (NEO-38): level = 1 + floor(max(0,xp)/100). */ const expectedLevel = (xp) => 1 + Math.floor(Math.max(0, xp) / 100); for (const id of ["salvage", "refine", "intrusion"]) { const row = body.skills.find((x) => x.id === id); expect(row).to.be.an("object"); expect(row.xp).to.be.a("number"); expect(row.level).to.be.a("number"); expect(row.xp).to.be.at.least(0); expect(row.level).to.be.at.least(1); expect(row.level).to.equal(expectedLevel(row.xp)); } }); }