«Жизнь канала»: задачи механики для копии 1in8b.life¶
24 октября 2026. Задание для агента, который ведёт backend «Жизни канала» (internal/chatgames/life/). Владелец, Gorkiy, решил: механику ведёт этот агент, а визуальная часть (сайт, мини-приложение, OBS) остаётся у визуального агента. Цель — максимально близкая копия 1in8b.life по устройству экранов и механикам, со всеми «плюшками», но в формате совместной игры чата на эфире. Код, тексты и картинки оригинала не копируем.
Связанные документы:
- life-game-design.md: замысел, текущая версия, карта кода, проверки.
- life-scene-contract.md: публичный контракт для визуальной разработки. Каждое новое публичное поле из этого списка дописывать туда, с типом, смыслом и поведением у старых жизней.
- Разбор оригинала и план по этапам: документ «Жизнь канала: путь к копии 1in8b.life» (Claude Doc владельца, https://claude.ai/artifact/A5WzJgPTWmMsEhZXVqZkHu).
Как работаем вдвоём¶
- Backend:
internal/chatgames/life/,src/server/handler_life_*,src/twitch/life_game.go, миграции, этот файл и контракт. Визуальный агент эти файлы не правит. - Визуальная часть:
../front-pulse-caster/tg-mini-app/src/components/Life*,src/life*,src/server/assets/life/overlay.html. Backend-агент их не правит; если нужна правка на фронте, опиши её здесь в разделе задачи («Фронт сделает»). - Каждая задача — отдельная ветка и PR в
master. Сливает Gorkiy. Общение в PR и с владельцем по-русски. - Публичный JSON только расширяется необязательными полями (версия состояния 1). Старые жизни продолжаются без пересчёта задним числом; отсутствующее поле означает «нет данных», фронт показывает текстовый fallback.
- Ничего приватного наружу:
seed,flags,seen,followups, будущие исходы, запланированные гости. Любой новый расчёт, который зависит от будущего, отдаётся только после того, как событие произошло. - Детерминизм: всё случайное — через
roll(seed, ключ, n)с новым уникальным ключом, чтобы повтор жизни и тесты давали один и тот же результат. - Когда задача готова, отметь её здесь (
[x], номер PR) и допиши поля в контракт. Визуальный агент берёт задачу по этой отметке.
Что уже сделано на фронте (не дублировать)¶
Этап 1, ветка feature/life-original-board: карта жизни (клетка = год, цвет по years[].stats.happiness, рамка на demography.life_expectancy), блок «Фокус этого года» из focus, circumstances, career, панель «Семья и жизнь» из people[], нумерованные варианты решения с отдельными chance/chance_basis/reason, «Вероятность: X%» при рождении из supported_birth_share, сцены по scene.key, подпись сцены с местом из residence и людьми из scene.cast. Для этого новые поля backend не нужны.
Этап 3: новая механика без тяжёлых данных¶
Порядок — по пользе для эфира; экономику (3.10) можно брать сразу после 3.1. Оценка: S — до дня, M — 2–4 дня.
3.1 Скорость, «До следующего решения», авторежим (S–M)¶
- Backend сделан, PR: #44 (ожидает слияния владельцем).
В оригинале сверху: пауза, скорость 1×/2×/4×/8×/16×, кнопка «До следующего решения» (прокрутить обычные годы до ближайшей развилки) и «Авторежим» (решения принимаются сами).
- Настройка ведущего
speed(1, 2, 4, 8, 16) поверхyear_seconds: реальная длина года =year_seconds / speed. Менять можно в любой момент, в том числе в идущей жизни (сейчас темп закрепляется при рождении: эту часть оставить дляyear_seconds, а множитель сделать оперативным). - Действие ведущего
skip_to_decision: быстро прожить обычные годы до следующего открытия решения, без пропуска событий летописи (все годы и события записываются как обычно). Ограничение сверху, например не больше 10 лет за раз, и запрет во время открытого решения. - Режим
auto_decide(флаг настройки): когда включён, решение закрывается сразу воспроизводимым автовыбором, как сейчас при отсутствии голосов, с отметкой в летописи «Авто». В оригинале это «Отныне доверять решения „Авто“». - Публично:
settings.speed,settings.auto_decide. Состояние «идёт перемотка» можно не отдавать. - Twitch-награда и голосование: при
auto_decideголосование не открывается и награда не включается. - Тесты: длина года с множителем, перемотка останавливается на решении и не теряет события, автовыбор помечен и детерминирован.
- Фронт сделает: верхнюю панель с кнопками для ведущего в пульте, показ скорости в публичной игре и OBS.
Backend готов к подключению панели: PUT .../settings принимает speed и auto_decide, POST .../skip_to_decision — {"session_id":"UUID"}. Подробности и совместимость описаны в контракте. Включение авторежима учитывает уже принятые голоса/усиления; на паузе закрывает выбор после продолжения. Новые автоматические решения не открывают голосование. Перемотка останавливается после первого такого решения. Для точной полосы на паузе добавлено remaining_milliseconds, у старых жизней fallback — секунды. Базовый year_seconds остаётся закреплённым при рождении.
3.2 «Отложить на время» (S)¶
- Сделано, PR: —
В оригинале у решения есть «Отложить на время»: развилка уходит и возвращается позже.
- Действие ведущего
postponeна открытом решении: закрыть без исхода, вернуть сцену в приватную очередь с ближайшим допустимым возрастом (через 1–3 года, в пределах возрастного окна сцены). Если окно закончилось, сцена просто не повторяется. - В летописи короткая запись «Решение отложено», без спойлера будущего.
- Голоса и платные усиления отложенного решения: вернуть так же, как при опоздавшей покупке.
- Публично: у события
kind: "decision"сoutcome: "postponed"или отдельныйkind— выбрать и описать в контракте. - Тесты: сцена возвращается один раз, не возвращается за окном, возврат усилений.
3.3 Родившиеся в ту же секунду (M)¶
- Сделано, PR: —
В оригинале рядом с героем живут четыре параллельные жизни, родившиеся в ту же секунду в разных странах по той же статистике рождений. Видно их страну, имя, возраст и короткую строку о том, что с ними сейчас; некоторые уходят раньше.
- При рождении создать 4 фоновые жизни по тем же весам стран (
supported_birth_share), со своим именем, полом, местом и достатком. Отдельный ключroll, чтобы не менять текущее рождение героя. - Каждый год — лёгкая симуляция без выборов: этап жизни, занятие, одно короткое событие раз в несколько лет, переезд, семья. Смерть только в рамках решения 3.x о тяжёлых темах (см. «Решения владельца»); до этого решения фоновые жизни не умирают раньше 60.
- Публично:
peers[]:{key, name, gender, country {key, name, flag}, place, age, alive, status, line}, гдеstatus— короткое занятие («учится», «работает в мастерской»),line— последнее событие одной фразой. Портрет фронт рисует сам поgender,skin,hair— добавить эти два поля. - В финале:
peers[]попадают в биографию одной строкой «Из четырёх, родившихся в ту же секунду…». - Тесты: детерминизм, распределение стран по весам на большой выборке, отсутствие приватных полей.
- Фронт сделает: панель «Родившиеся в ту же секунду» в игре и в комнате памяти.
3.4 Паузы-размышления (M)¶
- Сделано, PR: —
В оригинале в 5, 15, 30, 50 и 70 лет жизнь останавливается на короткий вопрос («Что для тебя сейчас важнее всего?»), ответ — одна строка, в финале эти строки возвращаются как «Слова этой жизни».
- Для эфира: в эти возрасты открывается особое решение
kind: "reflection"с 3–4 вариантами-ответами (не свободный текст, чтобы не модерировать чат). Голосование как обычно, но без шансов и денег. - Ответ сохраняется в
reflections[]:{age, question, answer}и немного влияет на узор жизни (3.5), не на показатели. - Публично:
decision.kind = "reflection",reflections[]в снимке и в финале. - Тесты: открывается ровно в эти возрасты, не ломает очередь обычных развилок, сохраняется в воспоминаниях.
- Фронт сделает: отдельную тихую карточку вопроса и раздел «Слова этой жизни» в комнате памяти.
3.5 Узор этой жизни (S–M)¶
- Сделано, PR: —
В оригинале в мемориале четыре шкалы-пары слов и архетип: «Рядом / Работа», «Корни / Ветер», «Тишина / Волны», «Сегодня / Завтра» и подпись вроде «Тот, кто прокладывает новый путь».
- Посчитать в backend по уже сохранённым фактам: выбранные ответы (их метки «семья/работа/риск/осторожность» — завести в каталоге теги ответов), переезды (
residence), смены работы и перерывы (circumstances), фокусы по годам, ответы пауз-размышлений. - Публично в завершённой жизни:
pattern {axes: [{key, left, right, value}], archetype, archetype_text},valueот −100 до 100. Слова и архетипы — свои, не из оригинала. - Для идущей жизни поле не отдавать (это итог, а не подсказка).
- Тесты: стабильность расчёта, каждая шкала реагирует на свои факты, старые жизни без тегов получают нейтральные значения.
- Фронт сделает: раздел «Узор этой жизни» в комнате памяти и строку на OBS-финале.
3.6 Эпилог близких, «Последние мгновения», «Сцена после титров» (M)¶
- Сделано, PR: —
В оригинале после смерти: что стало с близкими через годы, последние мгновения героя и короткая сцена после титров.
- В финале сгенерировать
epilogue[]:{person_key, name, role, text, scene}по живым на момент конца близким — 1–2 предложения о том, как сложилась их жизнь, на основе ихpath,goal,interest. Без выдуманной ранней истории, только вперёд от момента смерти. last_moments {text, scene, people}: где и с кем, поresidence, близким и последним событиям.post_credits {text, scene}: одна тёплая деталь изkeepsakesили самого частого фокуса.sceneв формате контракта (key,cast,props,mood), чтобы фронт нарисовал пиксельную сцену.- Тесты: эпилог только для живых, детерминизм, ссылки на настоящие
event_ids.
3.7 Справки «Данные» у событий и решений (M)¶
- Сделано, PR: —
В оригинале под событием летописи и в окне решения есть строка «Данные» с реальным фактом и источником (ВОЗ, ЮНИСЕФ и т. п.).
- Завести каталог фактов
data/facts.json:{key, country | "world", text, value, unit, year, source, url}. Только проверенные числа из открытых источников, с годом; никаких сгенерированных цифр. Покрытие — шесть стран игры. - Связать сцены и бытовые эпизоды с фактами по тегу (школа → доля охвата школой, работа → занятость, рождение → детская смертность до 5 лет и т. п.).
- Публично:
events[].dataиdecision.data:{text, source, url, year}. Необязательное поле. - Тесты: каждый факт имеет источник и год, у отсутствующего факта поле не отдаётся.
- Фронт сделает: строку «Данные» с раскрытием под событием и в решении.
3.8 Регистрация рождения целиком (S)¶
- Сделано, PR: —
В оригинале карточка «Регистрация рождения» с номером документа, связным абзацем, доходом семьи по квинтилям, жильём, возрастом и работой родителей, ожидаемой продолжительностью и смертностью до 5 лет.
- Публично в
character:income_quintile(1–5, из уже выбираемого достатка: скромный → 1–2, средний → 3, обеспеченный → 4–5, детерминированно) иhousing(короткая строка). Религию не выдумывать. - В
country.demographyдобавитьunder5_mortality_per_1000(WDISH.DYN.MORT) иgdp_per_capita_usd(WDINY.GDP.PCAP.CD) тем же скриптомscripts/update-life-demography.py, с годом и источником. - Тесты: полнота набора, новые индикаторы не нули.
- Фронт сделает: карточку регистрации, точечную карту мира и «Начать эту жизнь» для ведущего.
3.9 Счётчики на главной (S–M)¶
- Сделано, PR: —
В оригинале на главной: «пока вы здесь, родилось N человек», «сейчас живёт», «тема дня».
- Публичный endpoint без авторизации: число активных жизней всех каналов, число завершённых жизней, страны рождения последних 100. Без имён каналов, если они не публичные.
- «Родилось пока вы здесь» фронт считает сам по мировой рождаемости, backend не нужен.
3.10 Экономика: карьерный рост, своё дело, жильё и аренда, инфляция, акции (M–L)¶
- Backend сделан, PR: #46 (ожидает слияния владельцем).
Gorkiy отдельно назвал это «очень сильными механиками». Сейчас есть только деньги (finance), покупка «Собственное жильё» за 45 000 и career {track, level 0–3} с треком business. Нужно превратить это в настоящую экономику жизни, где решения чата видны через годы. Числа — игровая модель с понятной логикой, а где есть открытая статистика (инфляция, доходность), брать её с источником.
Карьерный рост на работе.
- Уровни внутри трека шире 0–3: должность с названием (стажёр → специалист → ведущий → руководитель и т. п., свои слова для каждого трека), зарплата растёт со ступенью и опытом.
- Развилки повышения: «взять больше ответственности» с шансом по знаниям, опыту и нагрузке (
circumstances.load), переход в другую компанию, учёба ради роста. Неудача —outcome: setback, без потери всего. - Публично:
career.title,career.salary(годовой доход от работы),career.promotions(число повышений).
Своё дело.
- Развилка «открыть своё дело» с 20 лет: стартовые вложения из
cashили в долг, ежегодный результат зависит от трека, знаний, нагрузки и случайности; бизнес может расти, держаться или закрыться с долгом. - Публично:
business {name, kind, since_age, value, yearly_profit, employees, status};status:growing,stable,struggling,closed. - События: первый сотрудник, тяжёлый год, предложение продать дело.
Жильё и аренда.
- Вместо одной покупки — список недвижимости: своё жильё и квартиры для сдачи. Покупка за наличные или в ипотеку (
debtс ежегодным платежом и процентом). - Сдача в аренду: ежегодный доход, простой без арендатора, ремонт. Цена жилья меняется с годами (рост с инфляцией плюс случайные колебания).
- Продажа — решение чата, деньги идут в
cash. - Публично:
assets.properties[] {key, kind, bought_age, price, value, rented, rent_income, mortgage_left}.
Инфляция.
- Годовая инфляция по стране проживания (WDI
FP.CPI.TOTL.ZG, тем же скриптом данных, с годом и источником), для будущих лет — сглаженное значение. Растут цены покупок, расходы и аренда; наличные без вложений теряют покупательную силу. - Публично:
finance.inflation(процент года),finance.real_cash(в ценах года рождения) — чтобы фронт показал «в ценах года рождения».
Вклады и акции.
- Развилки вложить часть денег: вклад (низкий надёжный процент), облигации, акции (высокая доходность в среднем и большой разброс), рискованная «горячая» компания, которая может сгореть до нуля. Кризисный год бьёт по всем акциям сразу.
- Детерминированно через
roll, без подсказок будущего: шанс показывается как и сейчас (chance,chance_basis), итог видно только в следующем году. - Публично:
assets.investments[] {key, kind, invested, value, since_age, status};status:active,sold,burned.assets.net_worth= наличные + имущество + вложения − долги, по годам вyears[].stats.net_worthдля графика.
Общее.
- Покупки ведущего за деньги остаются, но жильё переходит в
assets.properties. - В финале: строки для мемориала «Состояние в конце жизни», «Сдавал(а) N квартир», «Своё дело 12 лет» — в
biographyили отдельнымsummary. - Тесты: детерминизм, инфляция по стране, ипотека гасится, сгоревшая акция не возвращается, нет отрицательных
value, старые жизни безassetsпродолжаются. - Фронт сделает: панель «Деньги и имущество» с капиталом и графиком, карточки домов и вложений, сцены покупки, сдачи, кризиса и закрытия бизнеса.
Backend подготовлен отдельным изменением: шесть ступеней карьеры, бизнес с годовым результатом, имущество/ипотека/аренда, вложения и исторические годовые точки капитала. POST .../games/life/economy открывает финансовую тему обычным голосованием; поддержаны выбор конкретного объекта и лимит повторного обсуждения в году. Контракт 3.10 содержит поля, примеры и точные тела запросов для фронта. Инфляция — среднее WDI 2019–2023; акции/облигации — исторические сценарии США 2019–2023 (NYU Stern), а не обещание будущей доходности или национальные ставки. Остальные коэффициенты явно игровые. Старые жизни остаются на прежней модели до явного финансового действия; прошлое имущество, цены, зарплаты и капитал не дорисовываются. Новый SQL не нужен, состояние версии 1 расширено необязательными полями.
Этап 4: реальная статистика и сообщество¶
Решения владельца по этим пунктам приняты (см. ниже); это большие задачи, их лучше брать после этапа 3.
- Больше стран (L): расширить набор WDI и профили стран (места, имена, занятия). Предложить владельцу список следующих 10–20 стран и минимальный профиль, который не требует авторского текста на каждую.
- Таблицы смертности, болезни и кривая выживаемости (L): половозрастные таблицы ООН WPP, вероятность дожить до каждого возраста, причины по данным ВОЗ; публично
survival[]для кривой. Решено: как в оригинале, по статистике (см. ниже). Можно начинать. - Доход по ППС и Джини, суммы «по ценам России» (L): отдельная модель дохода, не умножение зарплатного коэффициента на ВВП. Сохранить игровые единицы как есть и добавить пересчёт для показа.
- Свечи и книга гостей (M + модерация). Решено владельцем, можно начинать:
- Писать и зажигать свечу можно только после входа через Twitch. Свеча — одна на зрителя на жизнь, без текста.
- Запись в книге гостей сначала уходит на модерацию ведущему и до одобрения видна только автору и ведущему.
- Доверие: когда у автора на этом канале уже есть несколько одобренных записей (порог в настройках, по умолчанию 3), новые публикуются сразу, без премодерации. Ведущий всё равно может позже скрыть такую запись, а при скрытии доверие автора сбрасывается.
- Кнопка «Пожаловаться» у каждой записи для вошедших зрителей; запись с жалобами (порог в настройках) скрывается до решения ведущего. Очередь жалоб и модерации в пульте ведущего.
- Лимиты против спама: длина записи, не чаще одной записи на жизнь в N минут, бан автора на канале.
- Публично только отображаемое имя Twitch и текст, без ID и других личных данных; в OBS записи по умолчанию не выводить.
- Хранение: новая Goose-миграция (записи, свечи, жалобы, доверие автора), публичный API выдаёт только одобренные записи.
- Фронт сделает: свечу с «Кто-то зажёг здесь свечу», книгу гостей в комнате памяти, кнопку жалобы и очередь модерации в пульте.
Решения владельца¶
Приняты 24.10.2026:
- Механику ведёт backend-агент, визуальную часть — визуальный агент, задачи передаются через этот файл.
- Тяжёлые события (болезни, ранняя смерть) — на основе статистики, как в оригинале. Подавать спокойно, без графических подробностей; фоновые жизни из 3.3 тоже умирают по статистике.
-
Экономика (3.10) — в приоритете: Gorkiy считает её очень сильной механикой.
-
Свечи и книга гостей: после входа через Twitch, премодерация, доверие после нескольких одобренных записей, поздняя модерация и кнопка жалобы (подробности в этапе 4).
Ещё нужно: порядок задач внутри этапа 3, если нужно не так, как здесь.
Проверки перед PR¶
go test ./internal/chatgames/life, focusedTestLifeвsrc/twitchиsrc/server.golangci-lint --concurrency 2по изменённым пакетам.- Новая Goose-миграция, если меняется схема;
sqlc generate. - Примеры в examples/life-scene-fixtures.json обновить, если появились новые поля, чтобы визуальный агент мог рисовать без production-данных.
- GitHub Actions сейчас может не запускаться из-за биллинга: прогнать проверки локально и написать результаты в PR.