clone

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

spec: align world identity diagnostics with D20

Dami committed dc618c7
commit
dc618c760165e48ceffab664e08c9b4b0e54497c
parent
2e6b487ada58c1e66789798dd6ef34385f61e63f
author
Dami <dami.etoile@gmail.com>
4 files changed, +58 -34
Mopenspec/changes/add-world-index-navigation/design.md35++++++++++++++++-------------
Mopenspec/changes/add-world-index-navigation/proposal.md8+++++--
Mopenspec/changes/add-world-index-navigation/specs/world-index-navigation/spec.md36+++++++++++++++++++++---------
Mopenspec/changes/add-world-index-navigation/tasks.md13+++++++----
M openspec/changes/add-world-index-navigation/design.md +19 -16
@@ -50,22 +50,25 @@ joining core.
5050 5151 ## Manifest world metadata5252 53-`manifest.world` is optional. When present it is an object with only these54-fields:55-56-- `glyph`: a non-empty string containing one display glyph, at most four Unicode57- code points;58-- `tagline`: an optional non-empty string of at most 120 characters;59-- `accent`: an optional token from `you`, `push`, `stop`, `win`, `sink`, or60- `defeat`.61-62-Unknown fields, invalid types, empty strings, an overlong tagline, an empty or63- multi-glyph value, and an unsupported accent reject the complete pack before64- catalog mutation. Missing fields normalize to `null`; missing `manifest.world`65- normalizes to the default world presentation (first palette glyph, no66- tagline, and the default foreground path). The normalized metadata is67- available through catalog pack records and pack-service views without68- changing share identity or level IDs.53+`manifest.world` is optional. When present it is an object with these fields:54+55+- `glyph`: exactly one grapheme cluster, counted with `Intl.Segmenter` using56+ `granularity: 'grapheme'`, and no more than 16 UTF-16 code units. This permits57+ visible emoji such as `⚙️`, ZWJ sequences, and flags while restricting the58+ card to one glyph;59+- `tagline`: at most 80 characters, one source line with no newline, sentence60+ case, and no `·` (U+00B7). The diagnostic for the middle dot is explicit:61+ `Tagline can't use ·; use a comma or a dash.`;62+- `accent`: an optional token from `you`, `push`, `stop`, `win`, `sink`,63+ `defeat`, or `tick`.64+65+World identity is presentation metadata, so an invalid optional field produces66+a nonblocking W11 note and does not reject the pack. The world falls back to67+the first palette glyph, no tagline, and the default `--fg` path. Missing68+`manifest.world` uses the same defaults. Invalid gameplay fields continue to69+reject the complete pack atomically through the existing pack validator.70+Normalized metadata and notes are available through catalog pack records and71+pack-service views without changing share identity or level IDs.6972 7073 ## Progress and chapter unlocking7174
M openspec/changes/add-world-index-navigation/proposal.md +6 -2
M openspec/changes/add-world-index-navigation/specs/world-index-navigation/spec.md +25 -11
@@ -23,23 +23,37 @@ world identity from origin or a hard-coded pack ID list.
2323 - **THEN** replacement keeps the existing world position and the fork appends2424 as a new imported world without reordering other worlds2525 26-### Requirement: World identity metadata SHALL validate atomically27-An optional `manifest.world` SHALL accept only a non-empty glyph of at most28-four Unicode code points, an optional non-empty tagline of at most 12029-characters, and an optional accent from `you`, `push`, `stop`, `win`, `sink`,30-or `defeat`. Invalid types, empty values, overlong values, unsupported accents,31-or unknown fields SHALL reject the complete pack before catalog mutation.32-Missing metadata SHALL normalize to the documented default presentation.26+### Requirement: World identity metadata SHALL use nonblocking W11 validation27+An optional `manifest.world` SHALL accept a glyph that is exactly one grapheme28+cluster counted with `Intl.Segmenter` at `granularity: 'grapheme'` and no more29+than 16 UTF-16 code units. Its tagline SHALL be at most 80 characters, contain30+no newline, use sentence case, and contain no `·` (U+00B7). Its accent SHALL31+be one of `you`, `push`, `stop`, `win`, `sink`, `defeat`, or `tick`. An invalid32+optional identity field SHALL add a nonblocking W11 note and fall back to the33+first palette glyph, no tagline, and the default `--fg` path. Invalid gameplay34+fields SHALL continue to reject the complete pack atomically.3335 3436 #### Scenario: Valid world metadata is exposed3537 - **WHEN** a pack declares `{ glyph: '🌊', tagline: 'A wet proof.', accent: 'sink' }`3638 - **THEN** the normalized catalog world exposes those values with the pack's3739 stable ID, author, origin, and registration order3840 39-#### Scenario: Invalid world metadata preserves the catalog40-- **WHEN** a pack declares `accent: 'glow'` or an overlong tagline41-- **THEN** registration fails with a field-specific validation error and the42- catalog contains the same worlds and active level as before the attempt41+#### Scenario: Invalid world metadata keeps the pack playable42+- **WHEN** a pack declares `accent: 'glow'`, a multi-grapheme glyph, or an43+ overlong tagline44+- **THEN** registration succeeds with a W11 note, uses the fallback world45+ identity, and keeps the pack's gameplay and active-level data available46+47+#### Scenario: World tagline reports the middle-dot correction clearly48+- **WHEN** a tagline contains `·`49+- **THEN** the pack receives a W11 note saying `Tagline can't use ·; use a50+ comma or a dash.` and the normalized world has no tagline51+52+#### Scenario: Gameplay validation remains atomic53+- **WHEN** a pack has valid or invalid `manifest.world` metadata but an invalid54+ gameplay field55+- **THEN** the pack is rejected by the existing gameplay validator and is not56+ added to the catalog4357 4458 #### Scenario: A legacy pack receives defaults4559 - **WHEN** an otherwise valid pack omits `manifest.world`
M openspec/changes/add-world-index-navigation/tasks.md +8 -5