канон: «почему» больше не отправляется в architecture.md
Три документа — CLAUDE.md, паспорт и openspec/config.yaml — велели писать причину отвергнутого решения в architecture.md. По канону дом «почему» это design.md изменения и промоут в docs/adr/, а architecture.md переезд как раз опустошает: обоснования шли ровно туда, откуда их вычищают. Раздел «Процесс» в CLAUDE.md пересказывал шаги пайплайна дословно — тот же второй дом, что уже вычищен из config.yaml. Осталось три вещи, которые действительно проектные: автономность, prior art, «поток не останавливается». config.yaml пересказывал паспорт и инвариант безопасности — стали ссылками. docs/review.md ссылался на healthlog-review-rubric и healthlog-task-pipeline, удалённые вместе с проектными копиями. Первое — указание на будущее, поэтому исправлено на проходы rubric и ops; второе оставлено историей с пометкой. README.md называл architecture.md домом «принятых решений» и не упоминал database.md и adr/ вовсе. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -145,28 +145,26 @@ Module path — `git.vakhrushev.me/av/healthlog`.
|
||||
- **Что такое «сделана»:** пайплайн `av-dev-pipeline:task-pipeline` пройден
|
||||
целиком **и** критерии приёмки задачи проверены поимённо.
|
||||
|
||||
## Процесс
|
||||
## Как здесь принято работать
|
||||
|
||||
Задачи — в [docs/tasks/BACKLOG.md](docs/tasks/BACKLOG.md) (один файл на запись,
|
||||
индексы производны), цели — в [docs/tasks/PLAN.md](docs/tasks/PLAN.md). Ведёт их
|
||||
скилл `av-dev-pm:tasks`, спринт и ритуал между спринтами — `av-dev-pm:session`.
|
||||
Задачи и спринт ведёт `av-dev-pm`, работу над задачей — `av-dev-pipeline`.
|
||||
Порядок шагов, состав проходов ревью и правила ведения задач здесь **не
|
||||
пересказываются**: их дом — сами скиллы, а проектная настройка конвейера —
|
||||
[docs/review.md](docs/review.md). Пересказ разъедется на первой же правке
|
||||
скилла, и разойдётся молча.
|
||||
|
||||
Работа над задачей идёт скиллом `av-dev-pipeline:task-pipeline`: задача →
|
||||
`opsx:explore` → `opsx:propose` → ревью спек (профиль `design`) → `opsx:apply` →
|
||||
ревью кода → `opsx:archive` → закрытие задачи → коммит. Ревью — скилл
|
||||
`av-dev-pipeline:review-pipeline`, проходы — агенты `av-dev-pipeline:review-*`,
|
||||
проектная настройка конвейера — [docs/review.md](docs/review.md).
|
||||
Проектного здесь три вещи:
|
||||
|
||||
**Действуем автономно.** Умолчание — делать, а не спрашивать. Вопрос, который
|
||||
решать не мне, **выносится в раздел «Вопросы»** файла задачи и помечается тегом
|
||||
`question`; задача с открытым вопросом в спринт не берётся, а сама работа
|
||||
переформулируется на остаток и доводится до коммита. Спрашиваем немедленно
|
||||
только про **необратимое** — список выше.
|
||||
**Действуем автономно.** Умолчание — делать, а не спрашивать. Немедленно
|
||||
спрашиваем только про **необратимое** — список выше. Остальное, что решать не
|
||||
мне, уходит вопросом в файл задачи, а работа переформулируется на остаток и
|
||||
доводится до коммита.
|
||||
|
||||
**Развилка или вопрос — сперва prior art.** Проект не уникален: прежде чем
|
||||
проектировать своё, смотрим, как это решено в референсах
|
||||
[паспорта](docs/passport.md) и в интернете. Готовое решение либо берётся, либо
|
||||
отвергается с названной причиной — и причина идёт в `architecture.md`.
|
||||
**Развилка или вопрос — сперва prior art.** Проект не уникален; правило и
|
||||
референсы — [docs/passport.md](docs/passport.md), раздел «Мы не делаем
|
||||
уникального». Отвергли готовое решение — причина идёт в `design.md` изменения,
|
||||
а оттуда промоутом в [docs/adr/](docs/adr/README.md). В `architecture.md`
|
||||
обоснования больше не пишем: он переопределён как обзор.
|
||||
|
||||
**Поток не останавливается.** Телефон шлёт непрерывно и молча. Сломанный приём,
|
||||
оставленный работать, теряет данные необратимо: доставка, не попавшая в
|
||||
@@ -174,27 +172,17 @@ Module path — `git.vakhrushev.me/av/healthlog`.
|
||||
|
||||
## Конвенции
|
||||
|
||||
Механизируемое проверяет `task lint` (`.golangci.yml`): форма логов
|
||||
(`sloglint`), `fmt.Print*` / `os.Getenv` / `time.Now` мимо единых точек
|
||||
(`forbidigo`), сравнение ошибок (`errorlint`), сторонние пакеты ошибок
|
||||
(`depguard`). Пересказывать эти правила не нужно — линтер скажет точнее.
|
||||
Механизируемое проверяет `task lint` по `.golangci.yml`, прозой остаётся то,
|
||||
что правилом не выражается — [docs/conventions/](docs/conventions/README.md).
|
||||
Перечень правил и перечень записей есть в обоих файлах; здесь они не
|
||||
дублируются.
|
||||
|
||||
Прозой остаётся то, что правилом не выражается:
|
||||
[docs/conventions/README.md](docs/conventions/README.md) — уровень лога по адресату,
|
||||
единственный логирующий чекпоинт на доменной границе, трансляция ошибки на
|
||||
внешней границе, самодокументируемый `config.example.toml`, время в БД в UTC
|
||||
RFC 3339, ULID через `ident`.
|
||||
|
||||
Отдельно: **тесты на разбор формата HAE держим на реальных пакетах** в
|
||||
`testdata`. Документация формата тонкая и местами расходится с тем, что
|
||||
приложение реально шлёт, — источником истины служат живые данные.
|
||||
|
||||
Что показал реальный поток — [docs/research/apple-health.md](docs/research/apple-health.md).
|
||||
Читать **до** работы над разбором: там же лежат находки, которых нет в
|
||||
документации HAE (поле `source` существует; порядок ключей в JSON нестабилен,
|
||||
поэтому хеш содержимого считается по канонической форме с рекурсивной
|
||||
сортировкой; мелкая группировка даёт интерполяцию, а не измерения). Файл
|
||||
пополняется по мере накопления доставок.
|
||||
Отдельно, потому что это решает, каким тестам верить: **тесты на разбор формата
|
||||
HAE держим на реальных пакетах** в `testdata`. Документация формата тонкая и
|
||||
местами расходится с тем, что приложение реально шлёт, — источником истины
|
||||
служат живые данные, [docs/research/apple-health.md](docs/research/apple-health.md).
|
||||
Читать **до** работы над разбором: скорее всего вопрос о формате уже закрыт
|
||||
измерением.
|
||||
|
||||
## Язык
|
||||
|
||||
|
||||
@@ -160,7 +160,11 @@ curl -i -H 'If-None-Match: W/"…"' localhost:8080/api/v1/metrics # 304
|
||||
- [docs/passport.md](docs/passport.md) — цель проекта, типовые сценарии
|
||||
работы, референсы: чужие проекты, у которых смотрим решения, прежде чем
|
||||
придумывать своё
|
||||
- [docs/architecture.md](docs/architecture.md) — устройство, схема данных, API, принятые решения
|
||||
- [docs/architecture.md](docs/architecture.md) — устройство: принципы,
|
||||
компоненты, внешние границы, эксплуатация, деплой
|
||||
- [docs/database.md](docs/database.md) — схема хранилища и настройки с
|
||||
числовым значением
|
||||
- [docs/adr/](docs/adr/README.md) — почему решено именно так
|
||||
- [docs/conventions/](docs/conventions/README.md) — как пишем код
|
||||
- [docs/security.md](docs/security.md) — периметр и модель угроз
|
||||
- [docs/review.md](docs/review.md) — настройка конвейера ревью и журнал дефектов
|
||||
|
||||
+2
-1
@@ -120,7 +120,8 @@ HAE), а сырой архив получает право быть подчищ
|
||||
> **Развилка или вопрос — сперва prior art.** Прежде чем проектировать своё,
|
||||
> посмотреть, как это сделано в проектах ниже и в интернете. Готовое решение
|
||||
> либо берётся, либо отвергается **с названной причиной** — и тогда причина
|
||||
> идёт в [architecture.md](architecture.md), а не теряется.
|
||||
> идёт в `design.md` изменения, а оттуда промоутом в [adr/](adr/README.md),
|
||||
> а не теряется.
|
||||
|
||||
Формулировка «у всех так, а у нас иначе, потому что…» — это готовое
|
||||
обоснование решения. Формулировка «я придумал вот так» — ещё нет.
|
||||
|
||||
+4
-2
@@ -191,7 +191,7 @@
|
||||
«`import + replay` даёт то же состояние» ни один из них не проверял на
|
||||
конкретном правиле: он записан в архитектуре как свойство системы, а не как
|
||||
критерий для каждого узла, читающего состояние.
|
||||
- **Что меняем:** в рубрику `healthlog-review-rubric` и в проход `ops` — вопрос
|
||||
- **Что меняем:** в проходы `rubric` и `ops` — вопрос
|
||||
«читает ли узел состояние, которое сам же меняет, и остаётся ли он функцией
|
||||
от префикса журнала». Дешевле правила: любой запрос к `delivery` из свёртки
|
||||
обязан иметь границу по `received_at` разбираемой доставки. Тест сходимости
|
||||
@@ -227,7 +227,9 @@
|
||||
## 2026-08-02 — чекпоинт кода прошёл без трёх проходов, и ровно они нашли всё [проскочил]
|
||||
|
||||
- **Где:** конвейер, а не код: коммит `f8200f7` («тренировки и записи с
|
||||
собственным `id`»), шаг 7 скилла `healthlog-task-pipeline`, профиль `deep`.
|
||||
собственным `id`»), шаг 7 пайплайна задачи (тогда — проектная копия
|
||||
`healthlog-task-pipeline`, ныне `av-dev-pipeline:task-pipeline`), профиль
|
||||
`deep`.
|
||||
- **Симптом:** изменение было закоммичено и заархивировано как прошедшее ревью.
|
||||
Дозапуск трёх пропущенных проходов на **уже закоммиченном** коде дал девять
|
||||
причин, семь из которых пошли в работу с прогнанными оракулами: скелет из
|
||||
|
||||
+17
-20
@@ -27,27 +27,24 @@ context: |
|
||||
скилл av-dev-pipeline:review-pipeline, проектная настройка — docs/review.md.
|
||||
|
||||
Конвенции кода (соблюдать при apply):
|
||||
- Механизируемое проверяет `task gate` (линтер, сборка, тесты, race,
|
||||
покрытие изменённых строк, миграции, образцы конфига, секреты и данные о
|
||||
здоровье в индексе). Состав шагов и правил здесь не пересказываем — он
|
||||
растёт, а гейт скажет точнее и всегда актуальнее.
|
||||
- Прозой остаётся то, что правилом не выражается: docs/conventions/README.md.
|
||||
Читаем в источнике, а не отсюда — конвенции дописываются по ходу задач.
|
||||
- Безопасность: данные о здоровье чувствительнее токенов. Ни тела запросов,
|
||||
ни значения точек не попадают в логи выше DEBUG; ничего из ./data не
|
||||
попадает под контроль версий — это проверяет гейт.
|
||||
- Механизируемое проверяет `task gate`, прозой остаётся
|
||||
docs/conventions/README.md. Ни состав шагов гейта, ни перечень конвенций
|
||||
здесь не пересказываем: и то и другое растёт по ходу задач, а источник
|
||||
скажет точнее и всегда актуальнее.
|
||||
|
||||
Что это за проект:
|
||||
- ЧИТАЙ ПЕРЕД ПРЕДЛОЖЕНИЕМ: docs/passport.md — цель и её граница (чем проект
|
||||
НЕ является), типовые сценарии работы, референсы.
|
||||
- Вкратце: healthlog — хранилище данных Apple Health, а не аналитика:
|
||||
принять, дедуплицировать, сохранить, отдать. Состояние пересобирается из
|
||||
журнала доставок, поэтому свёртка обязана быть детерминированной.
|
||||
- Развилка или блокер — сперва prior art. Проект не уникален: готовые решения
|
||||
смотрим в референсах паспорта, отвергаем — с названной причиной, и причина
|
||||
идёт в architecture.md.
|
||||
- Инварианты целиком — в CLAUDE.md, архитектура — в docs/architecture.md,
|
||||
периметр и модель угроз — в docs/security.md, схема — в docs/database.md.
|
||||
Что это за проект — читай перед предложением, а не отсюда:
|
||||
- docs/passport.md — цель, её граница (чем проект НЕ является), потребители,
|
||||
типовые сценарии, референсы;
|
||||
- CLAUDE.md — инварианты с severity и семантика гейта;
|
||||
- docs/architecture.md — устройство; docs/database.md — схема;
|
||||
docs/security.md — периметр и модель угроз; docs/adr/ — почему решено так.
|
||||
Пересказа этих документов здесь нет намеренно: второй дом факта расходится с
|
||||
первым молча, и заметно это становится в предложении, которое уже написано.
|
||||
|
||||
Развилка или блокер — сперва prior art. Проект не уникален: готовые решения
|
||||
смотрим в референсах паспорта, отвергаем — с названной причиной, и причина
|
||||
идёт в design.md этого же изменения (оттуда её промоутит в docs/adr/ скилл
|
||||
av-dev-pm:docs).
|
||||
|
||||
Разведка уже проведена, догадки о формате не нужны:
|
||||
- docs/research/apple-health.md — находки на живом потоке, во многом расходящиеся с
|
||||
|
||||
Reference in New Issue
Block a user