ADDED Requirements
Requirement: Packs and levels SHALL have stable identities
Every pack SHALL have a stable lowercase pack id, display name, version, and ordered levels. Every level SHALL have a stable level id unique within its pack. Registry keys SHALL use the pair { packId, levelId }, and display titles SHALL not be used as identity.
Scenario: A renamed level keeps its identity
- WHEN a pack changes a level title but retains its pack id and level id
- THEN the registry treats it as the same level identity and updates only display metadata
Scenario: Duplicate level ids are rejected within a pack
- WHEN a pack contains two levels with the same level id
- THEN pack validation fails before either level is registered
Requirement: The app SHALL ship curated bundled packs
The app SHALL include a curated set of valid bundled packs, including the original three MIAU teaching puzzles as one ordered teaching pack. Bundled packs SHALL be available without a local file or URL import and SHALL pass the same identity and level validation as imported packs.
Scenario: The teaching pack is available on a clean start
- WHEN the app starts without imported content
- THEN the registry contains the MIAU teaching pack and its three original levels in stable order
Scenario: A bundled pack has invalid data
- WHEN a bundled pack fails validation during startup
- THEN the app reports the pack id and validation error and keeps other valid bundled packs available
Requirement: The registry SHALL retain multiple loaded packs
The registry SHALL retain every valid bundled, URL, and explicitly trusted local pack loaded during the session. Each pack SHALL retain its origin metadata, and selecting one pack or level SHALL not discard other valid registered content.
Scenario: Two local packs remain selectable
- WHEN the player loads two valid packs with different pack ids
- THEN both packs appear in the pack registry and levels from either pack can be selected
Scenario: A failed pack does not remove earlier content
- WHEN a later import fails validation or execution
- THEN previously registered packs remain selectable and the failed pack is absent
Requirement: The registry SHALL apply an explicit collision policy
The registry SHALL present an explicit choice when a pack id collides: Replace, which keeps the authored id and its progress, or Keep both as a copy, which creates a new fork id using the next available -2, -3, and so on suffix, records forkOf as the original id, and starts progress under the new id. A level id collision SHALL be scoped to its pack id; identical level ids in different packs SHALL coexist. Both replacement and forking SHALL validate atomically and preserve the existing pack if validation fails.
Scenario: A pack id collision offers explicit choices
- WHEN a newly loaded pack uses an existing pack id
- THEN the app offers
ReplaceandKeep both as a copy, and does not change the registry until one choice is made
Scenario: Keep both creates a fresh fork
- WHEN the player chooses
Keep both as a copyfor packgarden-basics - THEN the registry installs the imported pack under the next available id such as
garden-basics-2, recordsforkOf: garden-basics, and starts progress under the fork id
Scenario: Replace preserves authored identity
- WHEN the player chooses
Replacefor an existing pack id - THEN the new pack keeps that authored id and its existing progress key, subject to complete validation
Scenario: Same level id in different packs is allowed
- WHEN two registered packs each contain a level id
intro - THEN both levels remain addressable by their
{ packId, levelId }pair
Requirement: Pack selection SHALL identify the active content
The app SHALL expose the active pack id and level id to the engine and UI, and SHALL load a selected valid level through the existing engine validation path. A pack selection failure SHALL leave the previously active level playable.
Scenario: Selecting a level changes active identity
- WHEN the player selects level
introfrom packgarden-basics - THEN the active selection reports both ids and the engine loads that level's validated data
Scenario: Selecting an unknown level is harmless
- WHEN a stale link or UI action requests an unknown pack/level pair
- THEN the app reports the missing identity and retains the current playable level