clone

a browser grid puzzle game where you push words around to rewrite the rules of each level

main
miau-is-true / openspec / specs / world-index-navigation / spec.md
spec.md 7.2K source

world-index-navigation Specification

Purpose

TBD - created by archiving change add-world-index-navigation. Update Purpose after archive.

Requirements

Requirement: Each registered pack SHALL own a world and INDEX sheet range

The catalog and INDEX layout SHALL create one world record and one or more pack-owned sheets for every registered pack, including core. Sheets SHALL hold at most fifteen nodes, and a world with more than fifteen proofs SHALL continue onto another sheet in the same world. World order SHALL be core first, then bundled registration order, then imported install order. Layout SHALL NOT infer world identity from origin or a hard-coded pack ID list.

Scenario: Bundled packs remain separate worlds

  • WHEN core, crossword, crate-works, and tidewater are registered in that order as the approved default bundle
  • THEN the layout exposes four worlds in that order, with each pack's nodes in its own sheet range and no bundled node assigned worldId: core

Scenario: Example packs remain available through import

  • WHEN garden-basics or word-lab is imported
  • THEN it becomes its own world after the default bundle without changing core, crossword, crate-works, or tidewater progress and order

Scenario: A long pack continues within its own world

  • WHEN an imported pack has sixteen ordered proofs
  • THEN it receives two sheets with the same world ID, fifteen nodes on the first sheet, and one node on the second sheet

Scenario: Registration order survives replacement and forking

  • WHEN a bundled pack is replaced or an imported pack is forked
  • THEN replacement keeps the existing world position and the fork appends as a new imported world without reordering other worlds

Requirement: World identity metadata SHALL use nonblocking W11 validation

An optional manifest.world SHALL accept a glyph that is exactly one grapheme cluster counted with Intl.Segmenter at granularity: 'grapheme' and no more than 16 UTF-16 code units. Its tagline SHALL be at most 80 characters, contain no newline, use sentence case, and contain no · (U+00B7). Its accent SHALL be one of you, push, stop, win, sink, defeat, or tick. An invalid optional identity field SHALL add a nonblocking W11 note and fall back to the first palette glyph, no tagline, and the default --fg path. Invalid gameplay fields SHALL continue to reject the complete pack atomically.

Scenario: Valid world metadata is exposed

  • WHEN a pack declares { glyph: '🌊', tagline: 'A wet proof.', accent: 'sink' }
  • THEN the normalized catalog world exposes those values with the pack's stable ID, author, origin, and registration order

Scenario: Invalid world metadata keeps the pack playable

  • WHEN a pack declares accent: 'glow', a multi-grapheme glyph, or an overlong tagline
  • THEN registration succeeds with a W11 note, uses the fallback world identity, and keeps the pack's gameplay and active-level data available

Scenario: World tagline reports the middle-dot correction clearly

  • WHEN a tagline contains ·
  • THEN the pack receives a W11 note saying Tagline can't use ·; use a comma or a dash. and the normalized world has no tagline

Scenario: Gameplay validation remains atomic

  • WHEN a pack has valid or invalid manifest.world metadata but an invalid gameplay field
  • THEN the pack is rejected by the existing gameplay validator and is not added to the catalog

Scenario: A legacy pack receives defaults

  • WHEN an otherwise valid pack omits manifest.world
  • THEN registration succeeds and its world metadata uses the default glyph, no tagline, and the default foreground path accent

Requirement: INDEX progress SHALL be scoped per world

The INDEX view model SHALL expose the active world ID/number, world name, world completion count, total proof count, and current world-strip position. Solved state SHALL remain keyed by { packId, levelId }. The opener of every world SHALL be available, later proofs SHALL unlock in order within that world, and a proof solved in one world SHALL not unlock or count toward another world.

Scenario: Completion counts do not leak between worlds

  • WHEN one proof is solved in world alpha and none is solved in world beta
  • THEN alpha reports 1 / alphaTotal, beta reports 0 / betaTotal, and beta's second proof remains locked behind beta's opener

Scenario: Entering a world selects its local cursor

  • WHEN the player leaves world alpha after selecting its third proof and later returns
  • THEN the INDEX restores alpha's saved cursor when it still exists, or selects alpha's first available node, without changing the active proof in another world

Requirement: INDEX SHALL navigate between worlds without wraparound

The navigator SHALL map Q/E, gamepad LB/RB, and one two-finger horizontal swipe per gesture to one-world-left/right actions. Walking forward from a world's terminal path node SHALL enter the next world's first node; walking backward from the first node SHALL enter the previous world's terminal node. The first and last world boundaries SHALL be no-ops with existing blocked-navigation feedback. Intra-world sheet boundaries SHALL remain distinct from world boundaries.

Scenario: Q and E switch one adjacent world

  • WHEN the active world is the second of three and the player presses Q once, then E once
  • THEN the navigator enters world one, then world two, with one transition per input and no proof move recorded

Scenario: Outer boundaries do not wrap

  • WHEN the player presses Q in world one or E in world three
  • THEN the world and active proof remain unchanged and the navigator returns a blocked-navigation indication

Scenario: Path edges cross worlds in travel direction

  • WHEN the player walks right off the final path node of world one
  • THEN the cursor enters world two's first node; walking left from world two's first node returns to world one's final node, without wrapping past the first or last world

Requirement: INDEX SHALL provide a stable world presentation seam

The INDEX scene SHALL consume a pure world view model containing world number, world count, name, glyph, tagline, accent, per-world completion, and strip position. The first entry into a world and Workshop PLAY SHALL emit a world-card request with origin index or workshop, at most once per world per session. The seam SHALL not change integer board coordinates or simulation state.

Scenario: First entry requests a world card

  • WHEN the player enters an unvisited world from INDEX
  • THEN the scene emits one world-card request containing that world's normalized identity and origin: index before settling on its sheet

Scenario: Workshop PLAY requests the same card seam

  • WHEN the player chooses PLAY for an unvisited pack in Workshop
  • THEN the scene emits one world-card request with origin: workshop, preserving the pack's first node and current simulation state

Scenario: Re-entry does not replay the card

  • WHEN the player returns to a world whose card request was already settled during the current session
  • THEN the world header view model updates without another card request