clone

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

main
miau-is-true / openspec / changes / archive / 2026-09-24-stabilize-active-level-identity / specs / active-level-identity / spec.md
spec.md 3.3K source

ADDED Requirements

Requirement: The active level SHALL use a stable catalog identity

The application SHALL use the existing ${packId}:${localId} level ID as the canonical active-level identity. Numeric indexes MAY select a level but SHALL not be used as the durable identity across catalog mutations.

Scenario: Selection survives unrelated registration

  • WHEN the active level is selected and another pack is registered before it
  • THEN the same stable active level ID remains selected and resolves to the same level

Scenario: Replacement preserves an existing local level

  • WHEN a pack is replaced with the same pack ID and still contains the active local level ID
  • THEN the active stable ID is preserved and resolves to the replacement level

Scenario: Replacement removes the active local level

  • WHEN a pack replacement omits the active local level
  • THEN selection falls back to the replacement pack's first level or the first available catalog level, and no stale ID remains active

Requirement: Catalog reads SHALL preserve clone safety without repeated full clones

Single-level and active-level reads SHALL resolve directly from normalized catalog records. Full-list compatibility methods SHALL continue returning fresh caller-owned data, while internal derived views SHALL be invalidated on pack register, replacement, and removal.

Scenario: A caller cannot mutate a cached catalog record

  • WHEN a caller mutates a level returned by a catalog read
  • THEN a later read returns the normalized authored value

Scenario: Replacement invalidates level and pack views

  • WHEN a pack is replaced with changed metadata or levels
  • THEN subsequent reads return only replacement data and no stale cached level, pack, or level count

Scenario: Removal invalidates active and list views

  • WHEN an imported pack is removed
  • THEN subsequent reads omit its levels and the active ID resolves to a remaining level or null

Requirement: Progress and win handoffs SHALL resolve by stable identity

Progress marking, win promotion, continue navigation, and pack refresh SHALL re-resolve the captured stable level ID before acting. A catalog mutation or level transition SHALL not allow an old numeric index or reused authored ID to promote the wrong level.

Scenario: A win callback cannot promote a replaced level

  • WHEN a level is won and its pack is replaced before the delayed win handoff runs
  • THEN the callback promotes only the still-resolved stable level ID or safely abandons the stale handoff

Scenario: Progress remains attached to pack and local IDs

  • WHEN levels are reordered by registration or an unrelated pack changes
  • THEN solved progress remains attached to the original packId and localId

Requirement: Cache invalidation SHALL be observable at mutation boundaries

Catalog mutations SHALL invalidate all derived active-level, pack-summary, and level-lookup views that can contain changed records. The invalidation SHALL occur before the mutation result is returned to application callers.

Scenario: Replace refreshes summaries immediately

  • WHEN a pack replacement changes its name, world metadata, or level count
  • THEN the next pack and level reads expose replacement summaries without a refresh-only workaround