save/e2e: #51 — wire generateRing attach into resolveJumpTask + spread-limit e2e

- resolveJumpTask: build existingEdgeKeys from all jump routes (both
  endpoints in the save's system set), pass all systems except the
  target as attachCandidates, insert closing routes for each attach.
- save.test.ts: jump test now expects 1–4 fresh systems (was pinned
  to exactly 4); A/B snapshot test stays green (both paths share the
  same resolveJumpTask code).
- e2e/helpers.ts: update stale comment ('4 fresh neighbours' →
  '1–4 new systems').
- e2e/smoke.spec.ts: new test verifying 1–4 mints, all undiscovered,
  each routed to the target, and BFS connectivity of the full graph.
This commit is contained in:
2026-10-06 12:18:33 +00:00
parent 90de8818f8
commit ab22a7e68b
4 changed files with 71 additions and 11 deletions
+7 -6
View File
@@ -49,12 +49,13 @@ export async function resolveAction(page: Page, path: string, data: Record<strin
}
// Jump to an adjacent system, preferring one that is still undiscovered. Every jump into an
// undiscovered system generates 4 fresh neighbours (lib/game/world.ts), so fresh territory is
// always available — picking the FIRST edge instead ping-pongs between exhausted systems, because
// edges come back in insertion order and the oldest route out of a system is usually the one that
// led here. Falls back to any non-current adjacent system if none is undiscovered. The jump is
// queued with a default one-person crew and ticked to completion (resolveAction) before this
// returns, so the caller is already standing in the target system, not merely en route to it.
// undiscovered system mints a seeded-random 1–4 new systems (at least one always minted —
// lib/game/world.ts #51), so fresh territory is always available — picking the FIRST edge
// instead ping-pongs between exhausted systems, because edges come back in insertion order and
// the oldest route out of a system is usually the one that led here. Falls back to any
// non-current adjacent system if none is undiscovered. The jump is queued with a default
// one-person crew and ticked to completion (resolveAction) before this returns, so the caller
// is already standing in the target system, not merely en route to it.
export async function jumpToFreshSystem(page: Page): Promise<WorldState> {
const world = (await (await page.request.get('/api/world')).json()) as WorldState;
const currentId = world.systems.find((s) => s.current)!.id;