Handbooks
Руководства

Поддержание актуальности

Resync сравнивает старый граф вызовов с новым и перегенерирует только то, что действительно изменилось. Тронули три файла — платите за три файла.

handbook resync --case <case-dir> --work <workdir>

Документация гниёт, потому что её обновление стоит столько же, сколько написание. Resync делает обновление пропорциональным изменению.

Контракт кейса

Кейс — это каталог, который вы собираете сами. Он отвечает на два вопроса: как код выглядит сейчас и каким должно было быть изменение.

cases/upload-retry/
  edited/       the changed source tree             REQUIRED
  plan.md       what the change was                 optional — SHARPENS the scope
  change.diff   unified diff vs the previous tree   optional — WIDENS the scope
mkdir -p cases/upload-retry
cp -R $REPO cases/upload-retry/edited
cp plan.md cases/upload-retry/
git -C $REPO diff HEAD~1 > cases/upload-retry/change.diff

handbook resync --case cases/upload-retry --work work/api

Декларации и диффы могут только расширять набор

Дифф графа — это нижняя граница: если байты файла изменились, он будет обновлён независимо от того, упоминал ли его план. План, занизивший собственный радиус поражения, не может привести к устаревшей странице.

Пустой change.diff означает «делать нечего», и запуск чисто пропускается, а не трактуется как «изменилось всё».

Что он делает на самом деле

  1. Повторно анализирует изменённое дерево — свежий граф phase 1.
  2. Сравнивает старое с новым → изменённые / добавленные / удалённые файлы.
  3. Перегенерирует карточки для изменённых и добавленных файлов.
  4. Назначает добавленные файлы, убирает удалённые, согласует корзины.
  5. Перестраивает организацию затронутых этапов — детерминированно, без LLM.
  6. Заново повествует затронутые этапы и обзор системы. Благодаря кэшу по хешу содержимого незатронутый этап вообще не повествуется заново.
  7. Обновляет регистры.
  8. Обновляет уже отрендеренные результаты в <work>/handbook (--no-render, чтобы пропустить).
stdout
{
  "skipped": false,
  "changedFiles": ["src/upload.py"],
  "addedFiles": [],
  "deletedFiles": [],
  "affectedStages": ["stage-3"],
  "cardsRegenerated": 1,
  "narrated": true,
  "rendered": ["work/api/handbook/overview.md", "work/api/handbook/stage-3.md"]
}

Как дифф ловит изменения

СигналОбнаруживает
Хеш содержимогоПравку тела на месте, не трогающую номера строк и сигнатуры, — случай, который структурный дифф пропускает целиком
Набор функцийДобавленные, удалённые или переименованные функции
Сигнатуры и диапазоны строкПерекроенные функции
Рёбра вызововНовые или исчезнувшие связи, в том числе входящие в незатронутые файлы и исходящие из них
Набор файловДобавленные и удалённые файлы

Пофайловые хеши были проставлены на этапе phase 1 ровно для этой цели. Граф, созданный до их появления, откатывается к структуре — деградация, но никогда не ошибка.

Работа без эндпоинта

handbook resync --case cases/x --work work/api --no-llm

Структурные факты обновляются — граф вызовов, перечень функций, назначение, порядок, — а к назначению каждой затронутой карточки добавляется (stale: code changed since narration).

Это честная деградация. Альтернатива — оставить прозу нетронутой и непомеченной — это handbook, который тихо лжёт.

Возврат исправлений

handbook resync --case cases/x --work work/api \
  --corrections skills/api/corrections.jsonl

Файлы, названные в corrections.jsonl, попадают в набор обновления, даже если их байты не менялись, потому что утверждение, которому противоречит исходник, — достаточный повод заново описать файл. Использованный файл после этого архивируется с меткой времени, поэтому одно и то же исправление не может примениться дважды.

Некорректные строки сообщаются в report.corrections.problems и никогда не фатальны — одна плохая строка, записанная одним агентом, не должна блокировать обновление.

Детализация и язык остаются как были

--detail и --narrate-lang по умолчанию не заданы, а незаданность означает «соответствовать тому, каким этот handbook уже является». Resync никогда молча не понизит глубокий handbook до краткого и не переключит китайский handbook на английский.

Передавайте их явно только тогда, когда вы действительно хотите сменить глубину или язык, — и ожидайте смешанный handbook, пока каждая карточка не будет перегенерирована.

Когда вместо этого перегенерировать

Resync прокатывает вперёд производный слой. Перегенерируйте, когда должна измениться структура:

СитуацияЧто делать
Изменилась пара файловresync
Рефакторинг переместил код между модулямиresync — дифф графа с этим справляется
Вы добавили целую новую подсистемуresync, затем проверьте, годится ли ещё скелет
Скелет больше не описывает системуgenerate --phase 2b,2c,3 --synth-mode doctor
Вы сменили язык повествования или глубинуgenerate --phase 2a / --phase 3 --refresh
Половина репозитория переписанаgenerate с нуля — дешевле, чем огромный resync

Автоматизация

.github/workflows/handbook-resync.yml
on:
  push:
    branches: [main]

jobs:
  resync:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
        with: { fetch-depth: 2 }
      - run: |
          mkdir -p case
          cp -R . case/edited
          git diff HEAD~1 > case/change.diff
      - run: handbook resync --case case --work work/api
        env:
          OPENAI_API_KEY: ${{ secrets.OPENAI_API_KEY }}
      - run: handbook validate --skill skills/api --source .

edited/ можно и вовсе пропустить, когда вы запускаете resync программно: опция editedRoot указывает на живое дерево — именно так Studio выполняет его на месте, не копируя репозиторий.

Безопасность

  • Та же блокировка каталога, что и у generate, поэтому resync никогда не переплетётся с параллельной генерацией на тех же артефактах.
  • Промежуточная область phase 1 всегда вычищается<case>/.resync-phase1 не переживает вызов ни при успехе, ни при сбое.
  • Карточки удалённых файлов удаляются, поэтому удалённый файл не может задержаться в handbook.
  • ОтменяемоAbortSignal проверяется между шагами и протягивается в каждый LLM-проход.

На этой странице