# Stage 6: challenges, collectibles и production progression ## Принятый результат Срез добавляет стабильную идентичность уровня и три независимых production challenge-критерия: целевое число жертв, целевое время и collectible. Лучший результат накапливается между разными прохождениями и отображается как 0–3 звезды. Каталог расширен до 18 уровней. `Threefold Proof` обучает всем трём критериям на одном безопасном маршруте; intended route выполняется production-input ботом три раза подряд без teleport, прямой мутации completion или retry masking. ## Контракты - `LevelDefinition.levelId` и `worldId` являются стабильными lowercase ID. Legacy-контент без полей получает `legacy.level-NN` / `legacy`. - Optional `collectible` — world-space box. После пересечения он исчезает в текущей попытке, сохраняется при Activity recreation и сбрасывается restart. - `ChallengeResult` независимо вычисляет casualty, time и collectible criteria. На legacy-уровне без collectible третья звезда означает core completion. - `ProgressStore` save v3 хранит completion, лучшие deaths/time и collectible по `levelId`. V1/V2 numeric keys мигрируют в ID keys без потери данных. - Active session v5 сохраняет `collectibleFound`; V4 и более старые snapshots восстанавливаются с безопасным `false`. - Result UI и level cards показывают лучший star row. Complete screen сохраняет Stage 3 строки Current/Best/Targets, добавляет три challenge rows и следующую цель. RU/EN и non-color labels являются частью контракта. - SVG/TSV exporter публикует collectible и LevelID; validator проверяет ID и границы collectible до упаковки APK. ## TDD и найденные регрессии RED сначала зафиксировали отсутствующие `ChallengeResult`, stable IDs, JSON schema, ID-based persistence, session collectible, completion/UI copy, catalog level 18 и exporter output. Review добавил отдельный RED на duplicate stable LevelID: catalog loader теперь отклоняет конфликт до того, как два уровня разделят progress key. Каждый контракт проводился в GREEN отдельно. Первый полный Android run (`52` tests) нашёл ещё два интеграционных RED: 1. Stage 3 result snapshot потерял локализованный prefix `Цели` после добавления challenge rows. Prefix и видимая строка targets восстановлены. 2. Real-time late-level driver мог пропустить узкое окно пилы уровня 10 между двумя AVD polls. Late-level acceptance переведён на существующие fixed production physics ticks: обычное решение принимает решения каждые 16 ms симуляции, stress сохраняет 96 ms. Физика, input, collision, точные смерти и geometry не менялись. После исправления вся late-level matrix прошла `6/6`; level 10 normal выполняется три раза, отдельный stress route — один раз. Один предварительный повтор после нескольких непрерывных full runs получил environmental `frameP95=41.02 ms`; тот же неизменённый APK сразу прошёл изолированный 34-ms gate. Финальный exact run выполнен после cold AVD restart на host GPU и прошёл performance test внутри полного порядка. Бюджет не ослаблялся. ## Финальные gates На Android 16 ARM64 candidate: - `:level-format:test`: `2/2`; - `testDebugUnitTest`: `116/116`; - `lintDebug`, `assembleDebug`, `assembleDebugAndroidTest`: GREEN после `clean`; - validator: `18` levels, `formatVersion=1`, `physicsVersion=1`; - focused challenge/restore/result matrix: `9/9`; - exact unfiltered instrumentation: `OK (52 tests)`, `551.773 s`; - APK ZIP integrity: no errors; внутри APK `18` level JSON; - debug APK SHA-256: `0b70a0a1a508425c311d7de473318e3bb83407f5f27e9dd4a8e1876b2eb25344`. APK: `app/build/outputs/apk/debug/app-debug.apk`.