Хэндофф: spec-059 «Заклинания и свитки» — автономная сборка
Для: новой сессии Claude, собирающей фичу целиком, пока Andrey спит. Модель работы: trust (без пред-одобрений на код), spec-driven, агент- оркестрация (2–3 исполнителя + твоя интеграция). Внешние действия (push/PR/deploy) — только по явному «да» Andrey. Язык — русский.
TL;DR
Andrey хочет: (1) базу ВСЕХ официальных заклинаний dnd.su (2 редакции), нода
spell с переключателем 2014/2024; (2) четыре новых глагола экономики:
написать свиток, переподготовить заклинание (наша house-механика),
переписать свиток → книгу и книгу → книгу (RAW-правила волшебника).
Сейчас: спека готова, разведка dnd.su готова, код не начат. В /tg этих
экранов нет, нод заклинаний в каталоге нет — это и есть работа.
Старт (порядок чтения)
spec.md(в этой папке) — полные правила, таблица цен, 4 этапа, критерии.dndsu-recon.md(в этой папке) — как устроен dnd.su/spells (закрывает Open #2: 2014=dnd.su, 2024=next.dnd.su, пары по slug, homebrew мимо).- Прогони spec-driven: спека → plan → tasks → код → ревью (папка
.specify/specs/— прецеденты 056/058; учти:.specifyна этой машине в рабочее дерево не материализуется — держи рабочие артефакты в git- трекаемом месте, эта папкаdocs/features/scrolls-and-spells/надёжна). - Бут-контекст репо —
MEMORY.mdClaude +AGENTS.md(правила проекта).
Ветка и фундамент
- Ты на
claude/spec-059-build, отпочкована от свежего origin/main — весь фундамент на месте: крафт (056:app/actions/craft.ts,lib/craft-settings.ts,lib/queries/craft-tg.ts,party_levelпетли), /tg-хаб глаголов (058:app/tg/_components/action-sheets.tsx+action-hub.tsx), общак/склад. - Старая
claude/spec-059-scrolls(только коммит спеки, отставала на 8) — не нужна, её спека восстановлена здесь вspec.md. Можно удалить.
Порядок сборки
Этап 1 — база заклинаний (фундамент, делать первым):
- Форк скрапера:
scripts/scrape_dndsu.py(кэш/fetch/html→md) +scripts/items-dndsu-codegen.ts(codegen сид-миграций) — прецедент предметов spec-018. Discover по/spells/на dnd.su И next.dnd.su. - Миграция
node_type = 'spell'+ поля (level/school/…/slug + markdown 2014 и 2024-nullable). Вики-рендер ноды (десктоп + /tg) с переключателем редакции.
Этапы 2/3/4 — глаголы (независимы, параллельно поверх базы):
- 2 «Свиток»:
scribe_settings(паттернcraft-settings.ts),runScribe(канонrunCraft), /tg-sheet в табе 🏰 Партия рядом с Крафтом. - 3 «Переподготовка»: house-механика,
50×уровень, мгновенно, глагол хаба. - 4 «Копирование»: свиток→книга (расход свитка) и книга→книга (нарратив),
50×уровень + 2ч×уровень, RAW. - Все три — новые глаголы spec-058-хаба (
action-hub.tsx/ спелл-контекст).
Критические грабли (набито этой сессией — не наступи)
- PostgREST embed-ambiguity = молчаливый пустой каталог. Второй FK на
nodesиз дочерней таблицы (у насitem_attributes.schema_for_node_id) сделал ВСЕ эмбедыnodes → child!inner(...)неоднозначными → пустые каталог/покупка/крафт, БЕЗ ошибки (код делалconst { data }, глотая error). Если связываешьspell/scrollс нодами через FK — не плоди второй FK на nodes из одной таблицы; предпочитай soft-link (uuid-колонка без FK) + отдельный резолв-запрос. После DDL-смены схемы обязательноnotify pgrst, 'reload schema'(иначе PostgREST держит старую топологию). См.MEMORY.md → postgrest-embed-fk-ambiguity. - Числа механики = ДМ-настройки, НЕ хардкод (AGENTS.md). Таблица цен
свитков,
50×уровень,2ч×уровень, hoursPerDay/Week, maxSpellLevel- формула(правило, не настройка) →scribe_settings/spell_settingsвcampaigns.settings, parse-хелпер с дефолтами (паттернparseCraftSettings). Числа из спеки = дефолты парсера. - Read-хелперы должны падать ГРОМКО.
const { data } = await …глотает ошибку → пустой список маскирует сбой под «нет данных» (потеряли час на пустых схемах). Бери{ data, error }иif (error) throw error— экран ловит и показывает ошибку. - Sidebar cache (AGENTS.md): вставка/правка
node_types/nodes(новые типыspell/scroll, сид спеллов) трогаетnodes→ инвалидируй (invalidateSidebar/invalidateSidebarRemoteдля CLI-сида). - Накат миграций (
MEMORY.md → db-migration-apply): сам катишь на прод —ssh andrey@37.27.254.49 "docker exec -i supabase-db psql -U supabase_admin -d postgres -v ON_ERROR_STOP=1" < …/NNN.sql. Verify-блок обязателен (стиль 124–129). После schema-DDL — reload PostgREST (см. грабли №1). - /tg нельзя превьюить в браузере (нужна Telegram initData). Верификация:
npm run typecheck+npm run build+vitest+ агент ux-auditor (обязателен после любой /tg UI-правки и перед PR). Плюс ручной смоук Andrey. - party_level уже = 9 (задано этой сессией). maxSpellLevel(9)=5-й круг.
Открытые решения (взяты дефолты — помечай при несогласии)
Из spec.md → Open: деньги переподготовки/копирования — с кошелька PC
(дефолт) vs общак; событие ленты — mode 'scribe'/'reprep'/'copy' в типе
'craft' vs отдельные типы (реши в Plan по чистоте union); связь свиток→спелл
— soft-link uuid vs fields (см. грабли №1 — избегай второго FK на nodes).
Заговор при переподготовке = 0 зм (бесплатно). Эти форки не блокируют сборку —
бери дефолт, помечай в коде, Andrey отревьюит.
Связанное (не дубли)
- 3 tg-фикса ждут PR на ветке
claude/fix-tg-portrait(портрет при смене PC;listSchemasгромкая ошибка; взятие из общака по получателю + остаток в TakeSheet). Не переделывай — они готовы, ждут «да» Andrey на push/PR. - Вопрос Andrey (в бэклог): кнопка «Mother of Learning» в супергруппе как
в личке. Ответ Claude: постоянной menu-button (у поля ввода) в группах
Telegram нет — это только приват. Реалистично: закреплённое сообщение с
inline web_app-кнопкой ИЛИ Direct-Link Mini App
t.me/<bot>/<app>в закрепе/описании группы. Attachment-menu-бот — только для крупных ботов через аппрув Telegram. Оформить как мелкую задачу, если Andrey подтвердит.