Завершить инженерную проверку этапа 2
This commit is contained in:
@@ -22,9 +22,9 @@ master tracks origin/master
|
||||
- предметные задачи с acceptance criteria, приоритетами и зависимостями;
|
||||
- уже подтверждённые кодом и QA элементы закрыты с причиной.
|
||||
|
||||
На момент инициализации создано 68 beads: 13 закрыты, 4 находятся в работе и 51 открыт. Эти числа нельзя трактовать как точный процент готовности, потому что в базе смешаны эпики, features и задачи разного размера.
|
||||
На 18 августа 2026 года в snapshot находятся 72 beads: 21 закрыт, 6 находятся в работе и 45 открыты. Эти числа нельзя трактовать как точный процент готовности, потому что в базе смешаны эпики, features и задачи разного размера.
|
||||
|
||||
Текущий gate — `goon-game-milestone-vslice`. Первая приоритетная незаблокированная задача — `goon-game-bot-framework`.
|
||||
Текущий gate — `goon-game-milestone-vslice`. Инженерный кандидат этапа 2 собран; незакрытые gates включают `goon-game-human-playtest` и performance/repetition criteria `goon-game-regression-10`. Задачи этапа 3 можно начинать параллельно, не объявляя внешний playtest завершённым.
|
||||
|
||||
## Ежедневные команды
|
||||
|
||||
|
||||
+9
-14
@@ -6,7 +6,7 @@
|
||||
|
||||
## 1. Текущее состояние
|
||||
|
||||
Проект находится на стадии проверенного vertical slice:
|
||||
Инженерная часть этапа 2 завершена и проект готов к параллельному старту этапа 3:
|
||||
|
||||
- реализованы 10 последовательных уровней;
|
||||
- работают движение, прыжок и мобильное multitouch-управление;
|
||||
@@ -16,12 +16,14 @@
|
||||
- intended route всех уровней 1–10 защищён Android acceptance-ботами: каждый маршрут выполняется по три раза через production-ввод без прямого перемещения персонажа;
|
||||
- blocker-softlock уровня 8 после истечения таймера устранён recovery relay и покрыт отдельным трёхкратным сценарием;
|
||||
- исправлено перекрытие `FREEZER` уровня 6, которое повторно убивало игрока на frozen stepping stone;
|
||||
- final integrated Android 16 matrix: 14/14 методов, 35 игровых выполнений и lifecycle-проверка; wall time `5:59`;
|
||||
- тело, доставленное пилой на `PRESSURE` уровня 10, фиксируется после оседания и больше не соскальзывает с плиты;
|
||||
- restart из промежуточного состояния уровня 10 очищает тела, сигналы, таймер и удерживаемый ввод;
|
||||
- final integrated Android 16 matrix: 16/16 методов, 36 игровых выполнений, lifecycle и restart; wall time `9:32.496`;
|
||||
- финальный debug APK проверен на Android 16: установка, холодный запуск, ZIP-структура и v1/v2-подписи корректны.
|
||||
|
||||
Главный текущий риск: автоматическая проходимость доказана, но ручная понятность и баланс этапа 2 ещё не подтверждены. Отдельно остаются гипотезы об альтернативных решениях уровня 2 и обходе frozen corpse на уровне 10.
|
||||
Автоматическая проходимость, устойчивость обязательных объектов и чистый restart доказаны. Внешняя понятность уровней не может быть сертифицирована самим automation-runner: две ручные сессии на уровень остаются отдельным внешним playtest-gate и не считаются выполненными этим отчётом.
|
||||
|
||||
Performance-оговорка: критерий этапа 1 «полный прогон до 5 минут» пока не выполнен — финальный зелёный matrix занимает `5:59`. Сокращать количество трёхкратных прохождений или скрывать нестабильность retries запрещено; требуется отдельная оптимизация тестового runner.
|
||||
Performance-оговорка: исторический критерий этапа 1 «полный прогон до 5 минут» не выполнен на текущем throttled AVD. После расширения набора до 16 методов exact final matrix занимает `9:32.496`. Сокращать трёхкратные прохождения или скрывать нестабильность retries запрещено; оптимизация runner остаётся отдельной QA-задачей и не меняет доказанную проходимость.
|
||||
|
||||
## 2. Принципы разработки
|
||||
|
||||
@@ -173,15 +175,8 @@ Performance-оговорка: критерий этапа 1 «полный пр
|
||||
8. холодный запуск и проверка crash-буфера;
|
||||
9. ручной smoke-тест уровня 1 и одного сложного комбинированного уровня.
|
||||
|
||||
## 5. Текущая итерация
|
||||
## 5. Завершение этапа 2 и следующая итерация
|
||||
|
||||
Этап 1 завершён автоматическим доказательством intended route уровней 1–10. Текущая итерация ограничивается этапом 2:
|
||||
Инженерный scope этапа 2 закрыт: уровни 1–10 проходят intended route по три раза, уровень 8 имеет restart-free recovery, уровень 10 использует все три тела и сохраняет тело на lift-плите, а restart возвращает чистое состояние. Передаваемые результаты — обновлённый проект, проверенный APK и [`STAGE2_QA_REPORT.md`](STAGE2_QA_REPORT.md).
|
||||
|
||||
- выполнить полный integrated `10/10 passed` перед каждым APK;
|
||||
- провести по две ручные сессии каждого уровня и зафиксировать попытки, restart и непонятные места;
|
||||
- скорректировать допуски прыжков и подсказки только по наблюдаемым проблемам;
|
||||
- проверить чистый restart из ключевых промежуточных состояний;
|
||||
- закрыть или документировать гипотезы альтернативных решений уровней 2 и 10;
|
||||
- не добавлять уровень 11 и новые механики до завершения критериев этапа 2.
|
||||
|
||||
Результатом итерации должны стать обновлённый исходный проект, проверенный APK, integrated bot report и протокол ручных игровых сессий.
|
||||
Следующая реализационная итерация — этап 3 (управление, интерфейс и доступность). Параллельно внешний QA должен выполнить `goon-game-human-playtest`: по две ручные сессии каждого уровня без подсказок разработчика. До получения этого протокола milestone Vertical Slice нельзя называть принятым внешними тестировщиками, хотя разработку этапа 3 можно начинать.
|
||||
|
||||
@@ -199,15 +199,15 @@ Door закрывает путь к goal
|
||||
|
||||
**Статус:** intended route и восстановление после истечения таймера доказаны production-input ботом, по три раза подряд.
|
||||
**Ожидаемые смерти:** `0` (`targetDeaths=0`).
|
||||
**Источник:** `LevelCatalog.level8()`; основной `TIMED=(560,810,90,70)`, `signalId="clock"`, duration `6.0`; recovery relay `TIMED=(1600,650,90,70)`, duration `3.5`; moving platform `(990,770,240,34)`, travel `(380,0)`, period `4.0`, `controlId="clock"`; `PIT=(970,880,540,200)`; дверь `(1770,560,82,320)` требует `"clock"`; `goal=(2220,600,86,110)`.
|
||||
**Источник:** `LevelCatalog.level8()`; основной `TIMED=(560,810,90,70)`, `signalId="clock"`, duration `8.0`; recovery relay `TIMED=(1600,650,90,70)`, duration `3.5`; moving platform `(910,770,320,34)`, travel `(380,0)`, period `4.0`, `controlId="clock"`; `PIT=(1040,880,470,200)`; дверь `(1770,560,82,320)` требует `"clock"`; `goal=(2220,600,86,110)`.
|
||||
|
||||
### Solution graph 8
|
||||
|
||||
```text
|
||||
PIT разрывает floor, а Door закрывает дальнейший путь
|
||||
→ войти в TIMED и запустить signal "clock" на 6.0 s
|
||||
→ войти в TIMED и запустить signal "clock" на 8.0 s
|
||||
→ "clock" одновременно запускает horizontal moving platform и открывает Door
|
||||
→ без задержки добежать до края floor x=970
|
||||
→ без задержки добежать до края floor x=1040
|
||||
→ прыгнуть на moving platform и пересечь PIT
|
||||
→ сойти на правый floor x≥1510
|
||||
→ пройти Door x=1770..1852 до истечения "clock"
|
||||
@@ -222,9 +222,9 @@ PIT разрывает floor, а Door закрывает дальнейший п
|
||||
→ пройти Door и достичь goal без смерти/restart
|
||||
```
|
||||
|
||||
**Механика и сигналы:** фронт контакта основного `TIMED` → `timedSignals["clock"]=6.0` → движение платформы по `travelX=380` и открытие Door; высокий relay выставляет тот же сигнал на `3.5 s`. Обычный бег проходит под relay, поэтому original route не активирует восстановление автоматически. Строгий grounded-checkpoint выявил нестабильное закрытие Door на `5.5 s`; добавленные `0.5 s` дают запас на проход двери. Android 16 при задержках между решениями бота выявил отдельное падение с узкого стартового края: floor продлён на `70` px, а начало PIT сдвинуто с `900` на `970` без изменения его правого края `1510`, платформы, таймеров или recovery relay.
|
||||
**Механика и сигналы:** фронт контакта основного `TIMED` → `timedSignals["clock"]=8.0` → движение платформы по `travelX=380` и открытие Door; высокий relay выставляет тот же сигнал на `3.5 s`. Обычный бег проходит под relay, поэтому original route не активирует восстановление автоматически. Android 16 при задержках между решениями выявил узкое окно посадки: launch floor продлён до `x=1040`, а платформа расширена влево до `x=910` при сохранении прежнего правого края `x=1230`, дальнего края PIT `x=1510`, travel, period и recovery relay.
|
||||
|
||||
**Bot checkpoints:** основной timer активен; игрок двумя прыжками пересекает PIT через moving platform; перед движением к relay явно подтверждены far floor `playerX≥1510`, `playerY≥779` и всё ещё открытая Door. Intended route проходит Door на первом таймере. Recovery route ждёт `allDoorsOpen=false` справа от PIT, прыжком получает `allDoorsOpen=true`, проходит Door и завершает уровень. Оба маршрута финально дают `completed=true`, `deaths=0`; каждый выполнен три раза подряд на Android 16. Дополнительный intended run с `96 ms` задержки на каждое решение также завершён без смерти. Попытка расширить платформу была отклонена тестом: она могла унести ожидающего игрока с дальнего floor обратно над PIT после закрытия двери.
|
||||
**Bot checkpoints:** основной timer активен; первый прыжок подтверждает `playerOnMovingPlatform=true`, второй доставляет игрока на дальний floor. Перед движением к relay явно подтверждены `playerX≥1510`, `playerY≥779` и всё ещё открытая Door. Intended route проходит Door на первом таймере. Recovery route ждёт `allDoorsOpen=false` справа от PIT, прыжком получает `allDoorsOpen=true`, проходит Door и завершает уровень. Оба маршрута финально дают `completed=true`, `deaths=0`; каждый выполнен три раза подряд на Android 16. Дополнительный intended run с `96 ms` задержки на каждое решение также завершён без смерти. Дальний край платформы намеренно не расширен, чтобы она не могла унести ожидающего игрока обратно над PIT.
|
||||
|
||||
**Softlock/неопределённость:** прежний blocker устранён: после истечения `"clock"` справа от PIT высокий relay гарантирует restart-free повторное открытие двери. Relay не помогает слева от PIT и не отменяет timed-platform crossing. Оба пути проверены без прямой мутации состояния, teleport, auto-complete или restart.
|
||||
|
||||
@@ -259,7 +259,7 @@ Final Door использует AND из "weight" и "power"
|
||||
|
||||
**Статус:** mastery-маршрут доказан production-input ботом: 3/3 последовательных прохождения и ограниченный стресс финального перехода `96 ms` без ретраев.
|
||||
**Ожидаемые и доказанные смерти:** `3` (`targetDeaths=3`).
|
||||
**Источник:** `LevelCatalog.level10()`; `SAW=(520,760,96,96)`, impulse `(700,-240)`; `PRESSURE=(860,860,160,20)`, `signalId="lift"`; `FREEZER=(1110,750,100,130)`; `ELECTRIC=(1510,780,110,100)`, `relayId="power"`; moving platform `(1840,790,250,34)`, travel `(0,-410)`, period `5.0`, `controlId="lift"`; стартовый floor заканчивается на `x=1940`; `PIT=(1940,880,200,200)`; дверь `(2310,310,82,570)` требует `"power"`; верхний уступ `(2420,440,680)`; `goal=(2880,330,86,110)`.
|
||||
**Источник:** `LevelCatalog.level10()`; `SAW=(520,760,96,96)`, impulse `(700,-240)`; `PRESSURE=(860,860,160,20)`, `signalId="lift"`; `FREEZER=(1110,776,100,104)`; `ELECTRIC=(1510,780,110,100)`, `relayId="power"`; moving platform `(1800,790,290,34)`, travel `(0,-410)`, period `10.0`, `controlId="lift"`; стартовый floor заканчивается на `x=1940`; `PIT=(1940,880,200,200)`; дверь `(2310,310,82,570)` требует `"power"`; верхний уступ `(2420,440,680)`; `goal=(2880,330,86,110)`.
|
||||
|
||||
### Solution graph 10
|
||||
|
||||
@@ -267,23 +267,23 @@ Final Door использует AND из "weight" и "power"
|
||||
Goal расположен на верхнем уступе за PIT и закрытой высокой Door
|
||||
→ первый доброволец входит в SAW
|
||||
→ impulse (700,-240) доставляет тело на PRESSURE x=860..1020
|
||||
→ тело удерживает signal "lift" и запускает вертикальную moving platform
|
||||
→ тело оседает и фиксируется на PRESSURE, удерживает signal "lift" и запускает vertical moving platform
|
||||
→ следующий доброволец погибает в FREEZER
|
||||
→ frozen corpse становится стабильной ступенью для повторного прохода этой зоны
|
||||
→ следующий доброволец погибает в ELECTRIC
|
||||
→ conductive corpse удерживает relay signal "power" и открывает Door
|
||||
→ четвёртый доброволец respawn-ится и пересекает сохранённые тела/опасности
|
||||
→ садится на активную platform у x=1840..2090
|
||||
→ садится на активную platform у x=1800..2090
|
||||
→ поднимается над PIT и в верхней фазе прыгает вправо через открытую Door
|
||||
→ приземляется на ledge x=2420..3100
|
||||
→ достигает goal и получает COMPLETE с тремя смертями
|
||||
```
|
||||
|
||||
**Механика и сигналы:** launched saw corpse → `"lift"` → vertical platform; frozen corpse → твёрдая ступень; conductive corpse → `"power"` → Door open; platform и Door используют независимые постоянные сигналы от сохранённых тел.
|
||||
**Механика и сигналы:** launched saw corpse при контакте с `PRESSURE` обнуляет скорость и закрепляется внутри плиты → `"lift"` → vertical platform; frozen corpse → твёрдая ступень; conductive corpse → `"power"` → Door open; platform и Door используют независимые постоянные сигналы от сохранённых тел.
|
||||
|
||||
**Bot checkpoints:** после SAW `deaths=1`, `"lift"=true`, platform `y<790`; после FREEZER `deaths=2` и наличие frozen corpse; после ELECTRIC `deaths=3`, `"power"=true`, `allDoorsOpen=true`; перед посадкой первая moving platform должна вернуться к `y≥780`, затем snapshot подтверждает `playerOnMovingPlatform=true`; в верхней фазе `playerY≤280`; после прыжка `playerX≥2420`, `playerY≤340`; финально `completed=true`.
|
||||
|
||||
**Softlock/неопределённость:** интегрированный прогон воспроизвёл падение при посадке с исходным 40 px перекрытием floor/lift. Перекрытие увеличено до 100 px, при этом сохранены 200 px `PIT` и обязательный вертикальный подъём. Доставка saw-тела, три сохранённых тела, посадка, подъём и lift→ledge прыжок подтверждены тремя запусками и стресс-сценарием. Обязательность frozen corpse всё ещё не доказана отрицательным тестом: возможный двухсмертный sequence break остаётся follow-up.
|
||||
**Softlock/неопределённость:** исправлены два независимых blocker-состояния: saw-тело больше не соскальзывает с плиты после доставки, а перекрытие floor/lift увеличено до 140 px при сохранении 200 px `PIT` и обязательного вертикального подъёма. Период lift увеличен до `10.0 s`, чтобы нижняя фаза была читаемой при задержанном вводе. Бот теперь явно приземляется на frozen corpse и прыгает с него; доставка saw-тела, три сохранённых тела, посадка, подъём и lift→ledge прыжок подтверждены тремя запусками и стресс-сценарием. Возможная альтернативная двухсмертная трасса не считается blocker, пока intended three-body route остаётся стабильным.
|
||||
|
||||
## Проверки, следующие из графов
|
||||
|
||||
|
||||
@@ -0,0 +1,35 @@
|
||||
# Stage 2 QA report
|
||||
|
||||
Дата: 18 августа 2026 года. Сборка: `0.4.0-stage2-complete-debug` (`versionCode=5`). Целевая среда приёмки: Android 16, `medium_phone`, `arm64`.
|
||||
|
||||
## Исправленный blocker
|
||||
|
||||
На уровне 10 тело, доставленное пилой на плиту `lift`, продолжало скользить и могло отключить платформу. До исправления focused device-test зафиксировал изменение `firstCorpseX` с `791.4791` до `866.5033` за 750 ms. Теперь заземлённое тело при контакте с `PRESSURE` полностью размещается внутри плиты, его скорости обнуляются, и оно закрепляется. Тест дополнительно ждёт 6 секунд и подтверждает активный lift, ровно одну смерть и одно сохранённое тело.
|
||||
|
||||
## Автоматическая приёмка
|
||||
|
||||
- `testDebugUnitTest`: 17 JVM tests, GREEN;
|
||||
- `lintDebug`: GREEN;
|
||||
- `assembleDebug` и `assembleDebugAndroidTest`: GREEN;
|
||||
- полный unfiltered Android matrix на exact final APK: `OK (16 tests)`, `572.496 s`;
|
||||
- внутри matrix: 36 игровых выполнений, lifecycle и restart;
|
||||
- intended route уровней 1–10 выполняется по три раза без retry masking;
|
||||
- уровень 8: дополнительный stressed run и три restart-free recovery run;
|
||||
- уровень 10: отдельный тест стабильности тела, stressed traversal и три mastery run ровно с тремя телами;
|
||||
- restart уровня 10 очищает тела, сигналы, таймер и удерживаемый ввод.
|
||||
|
||||
## APK verification
|
||||
|
||||
- package: `com.projectsacrifice.game.debug`;
|
||||
- version: `versionCode=5`, `versionName=0.4.0-stage2-complete-debug`;
|
||||
- SDK: `minSdk=23`, `targetSdk=34`;
|
||||
- ZIP integrity: `unzip -t` — no errors;
|
||||
- signature: APK Signature Scheme v1/v2 — verified, one Android Debug signer;
|
||||
- clean install: successful;
|
||||
- cold launch: `Status: ok`, `LaunchState: COLD`, `TotalTime: 972 ms`;
|
||||
- Android crash buffer after launch: empty;
|
||||
- SHA-256: `1bc14020915ebc3b9be4760e0ae83584d8bf2768bbf6e692de24562ec7256bcd`.
|
||||
|
||||
## Граница подтверждения
|
||||
|
||||
Отчёт доказывает инженерную проходимость и стабильность на указанном AVD. Он не подменяет внешний тест понятности: две ручные сессии на каждый уровень без объяснений разработчика остаются задачей `goon-game-human-playtest`. Историческая цель полного matrix менее 5 минут также не достигнута на throttled AVD; exact final набор из 16 методов занимает `9:32.496`.
|
||||
Reference in New Issue
Block a user