1## ADDED Requirements23### Requirement: Packs and levels SHALL have stable identities4Every 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.56#### Scenario: A renamed level keeps its identity7- **WHEN** a pack changes a level title but retains its pack id and level id8- **THEN** the registry treats it as the same level identity and updates only display metadata910#### Scenario: Duplicate level ids are rejected within a pack11- **WHEN** a pack contains two levels with the same level id12- **THEN** pack validation fails before either level is registered1314### Requirement: The app SHALL ship curated bundled packs15The 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.1617#### Scenario: The teaching pack is available on a clean start18- **WHEN** the app starts without imported content19- **THEN** the registry contains the MIAU teaching pack and its three original levels in stable order2021#### Scenario: A bundled pack has invalid data22- **WHEN** a bundled pack fails validation during startup23- **THEN** the app reports the pack id and validation error and keeps other valid bundled packs available2425### Requirement: The registry SHALL retain multiple loaded packs26The 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.2728#### Scenario: Two local packs remain selectable29- **WHEN** the player loads two valid packs with different pack ids30- **THEN** both packs appear in the pack registry and levels from either pack can be selected3132#### Scenario: A failed pack does not remove earlier content33- **WHEN** a later import fails validation or execution34- **THEN** previously registered packs remain selectable and the failed pack is absent3536### Requirement: The registry SHALL apply an explicit collision policy37The 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.3839#### Scenario: A pack id collision offers explicit choices40- **WHEN** a newly loaded pack uses an existing pack id41- **THEN** the app offers `Replace` and `Keep both as a copy`, and does not change the registry until one choice is made4243#### Scenario: Keep both creates a fresh fork44- **WHEN** the player chooses `Keep both as a copy` for pack `garden-basics`45- **THEN** the registry installs the imported pack under the next available id such as `garden-basics-2`, records `forkOf: garden-basics`, and starts progress under the fork id4647#### Scenario: Replace preserves authored identity48- **WHEN** the player chooses `Replace` for an existing pack id49- **THEN** the new pack keeps that authored id and its existing progress key, subject to complete validation5051#### Scenario: Same level id in different packs is allowed52- **WHEN** two registered packs each contain a level id `intro`53- **THEN** both levels remain addressable by their `{ packId, levelId }` pair5455### Requirement: Pack selection SHALL identify the active content56The 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.5758#### Scenario: Selecting a level changes active identity59- **WHEN** the player selects level `intro` from pack `garden-basics`60- **THEN** the active selection reports both ids and the engine loads that level's validated data6162#### Scenario: Selecting an unknown level is harmless63- **WHEN** a stale link or UI action requests an unknown pack/level pair64- **THEN** the app reports the missing identity and retains the current playable level