- заведена `trusted-header-login` и поставлена в голову очереди
- пять задач про механику OIDC закрыты как отменённые ею
- `dev-run-task` и `api-tokens` переписаны под новый вход
- admin-owner-from-config закрыта: решение владельца 2026-08-15, ключ конфига
не заводится, требование спеки storage остаётся в силе
- dev-run-task вобрала cmd/devadmin и стоит первой строкой: инструмент и шаг
порознь не нужны, поэтому едут одной задачей
- admin-owner-from-config первой строкой: сервис заводит владельца панели
по ключу конфига; задача отменяет требование спеки storage, и это названо
в рамках
- dev-run-task следом: task dev поднимает сервис и заглушку разом, гасит
оба по Ctrl+C; зависит от ключа конфига
- main.go и journal_route_test.go переехали в cmd/transcriber без правок
содержимого; образ собирает ./cmd/transcriber поимённо
- cmd/oidcstub отвечает на /authorize, /token и /userinfo, проверок не делает
и слушает петлевой адрес: войти без Authelia стало чем
- ступень сборки приложения переехала на node:24 с alpine — musl ждёт ответа
на AAAA, которого нет, и npm ci висел вместо отказа
- заведён каталог web/ — Vue 3, роутер пятой версии, сборка Vite; собранное
вшивается через go:embed и раздаётся корневым маршрутом: разметка на
неизвестном пути вне корней сервиса, отказ контракта внутри корня
- перечень корней сервиса стал единой точкой и порождает регистрацию маршрутов,
а не описывает её; журнал раздачи пишет исход и длину пути, но не сам путь
- шаг front зовёт Node контейнером docker — Biome, юнит-тесты Vue и сборка
входят в гейт, а в Dockerfile появилась ступень приложения
- адреса приложения переехали в своё пространство `/app/`, опрос готовности
убран целиком: рубеж и причину остановки владелец узнаёт карточкой записи,
текст — отдельным адресом названного вида
- заведена единая точка отображения доменной ошибки и слой, приводящий к той же
форме отказы библиотеки: тело несёт машиночитаемый код рядом с сообщением
- у записи появились имя файла отправителя, длительность и размер своими
колонками, а у ленты владельца — свой индекс: без него страница сканировала
весь архив сервиса
- json-api-for-spa: адреса приложения уехали в своё пространство /app/,
приём стал POST /app/audiorecords, опрос /api/status/:id убран, заведены
список, карточка, текст, /app/me и /app/config; имя файла отправителя
легло своей колонкой рядом с заголовком
- три действия над записью — правка заголовка, возврат в работу и журнал
событий — собраны задачей audiorecord-actions
- голова очереди: контракт, каркас, экран загрузки, список, действия
- в прежних задачах поправлены адреса, рубежи конвейера и остатки Telegram
- шесть записей по кластерам причин: журнал под внешним значением, нулевой
код ответа в журнале, затирание вложения бедным ответом, открытый анониму
адрес подтверждения почты, рубеж расшифровки без работы, пределы длительности
- находка про код 500 у отказа приёма дописана в json-api-for-spa: там живёт
единая точка отображения доменной ошибки
- telegram-account-link и bot-api-only-through-bot-client оставлены с оговоркой,
что предмета у них нет до возвращения входа
- убраны клиент бота, транспорт обновлений, отправитель сообщений, сборка
входа при старте, секция настроек и зависимость go-telegram-bot-api; из
конвейера ушла доставка ответа отправителю — исход виден опросом готовности.
Колонки адресата и значение источника остались в схеме: применённые шаги не
переписываются
- шаг 202608140003 запрещает пустого владельца у аудиозаписи и у файла;
существующие строки он не проверяет, и это принято сознательно — искать их
надо запросом до выкладки
- ревью нашло два пред-существующих дефекта, оба закрыты: пустой второй ответ
распознавателя стирал сохранённую расшифровку, а пустая расшифровка перестала
быть заметной вместе с убранной доставкой. Попутно поднят golang.org/x/image
до v0.45.0 — красный шаг vulns, воспроизводился и на чистом master
- audiorecords вместо transcribe_jobs: приложения (texts, structures,
recognitions, record_events, topics) живут своими коллекциями, ссылки на
исходник и на приведённую копию перестали переставляться
- рубеж называет достигнутое, отказ стал признаком остановки с причиной, а
сторожей стало двое: число отказов и время в рубеже
- воркеры потеряли специализацию, их число задаётся [pipeline] workers, шаг
выбирается по рубежу, а захват отдаёт идентификатор и признак захвата
- центральная сущность — аудиозапись: файлы, тексты, структура реплик и темы
живут отдельными строками, поля очереди перестают соседствовать с содержимым,
а провайдерское уезжает в свою таблицу
- конвейер становится цепочкой рубежей с остановкой признаком: рубеж не
стирается, и запись перезапускается с места остановки
- воркеры теряют специализацию, их число задаётся конфигом
- колонка `owner` связью с `users` в обеих коллекциях новым шагом схемы
`202608140001`; чтение задачи сужено владельцем, и чужая, ничья и
несуществующая дают один ответ; правило просмотра файлов сужено им же
- приём по HTTP берёт владельца из сессии, а предъявителя без учётной записи
пользователя отвергает до чтения тела: позже пришлось бы убирать уложенный
файл, а уборки файлов сервис не умеет. Выборка воркера владельцем не сужается
- удаление учётной записи с записями отвергается стражем, и вешает его сама
сборка хранилища: сборка, забывшая его позвать, теряла защиту молча
- слово «провенанс» снято из словаря проектных текстов: у числа теперь
«происхождение», у вопроса и находки — «откуда»
- правлены форма вопроса в docs/review.md, шапка раздела об OIDC в
docs/research/pocketbase.md и две записи задач; формулировки прошли
вычитку агентами doc-wording и task-wording
- архив openspec/changes/archive/ не тронут: слово, верное на день записи,
остаётся свидетельством
- директива `go` в go.mod — единственное место, где назван патч: шаг гейта
сверяет мажор и минор, поэтому `golang:1.26-alpine` в Dockerfile и «Go 1.26»
в CLAUDE.md и README.md остались верными
- директива toolchain не заведена: она стала бы пятым местом с версией и
уронила бы сверку
- достижимых из кода уязвимостей у govulncheck больше нет; недостижимая
GO-2026-5932 в golang.org/x/crypto/openpgp остаётся объявленной
- имя приведено к конвенции, которая сама называла его расхождением;
ссылки поправлены в README, CLAUDE.md, конвенциях, docs/review.md и двух
записях задач
- в шапке docs/conventions/config.md заодно поправлен второй пункт перечня:
проверки на старте у `[auth]` и `[telegram]` уже есть
- архив openspec/changes/archive/ не тронут: это запись о прошлом
- задача оказалась шире chore: у нормированного адреса входа появляется
новый исход отказа, а обязательность проверочного кода PKCE переезжает
в настройки провайдера в хранилище
- дальше она идёт сценарием решения, следующим прогоном
- в секции [telegram] заведён обязательный ключ enabled: умолчания у него нет,
файл без него негоден; bot_token стал только ключом доступа и при
enabled = false не читается вовсе, а пустой при enabled = true роняет старт
- выключенный вход даёт подъём одним входом без единого обращения к Telegram и
записью INFO вместо прежнего WARN: это выбор владельца, а не отклонение
- отказ разбора файла настроек больше не пересказывает toml — её ParseError
несёт в тексте разбираемое значение, и оборванная строка секретного ключа
уносила его в журнал; теперь называются путь, строка, столбец и последний ключ
- CLAUDE.md, «Язык»: ссылаться можно на конкретную запись или на весь корпус
разом, но не на их количество — число протухает молча, машина его не считает.
Изъятие названо: неизменное число и историческое в записи о прошлом остаются.
- Сняты счёты capability, прогонов ревью, типизированных ошибок, воркеров,
сверок документов и правил линтера в docs/, спеке pipeline и CLAUDE.md.
- Заодно исправлено то, что этот же счёт и скрывал: типизированных ошибок три,
а не две — LostAcquisitionError был потерян из перечня.
- architecture.md: маркер над таблицей компонентов ссылался на
несуществующую capability delivery; теперь на intake, pipeline и storage,
и названо непереехавшее — приём из Telegram и деление текста по словам.
- review.md: проход, поднявший сервис, обязан его остановить, а меряющий —
убедиться, что отвечает его сборка. Цена правила уже заплачена: оставленный
процесс держал порт, и замеры ушли к прежней сборке.
- Клиент бота собирается один раз и достаётся отправителю и транспорту;
разрез прошёл по «ответил ли Telegram»: ответ «такого бота нет» роняет
старт, недоступность даёт подъём без Telegram (ADR-2026-08-13). Ожидание
при сборке ограничено сроком — иначе молчащий Telegram вешал подъём.
- Недоставленный ответ не роняет шаг: пишется с job_id и считается метрикой,
уровень по причине — WARN для неподнятого входа, ERROR для неназванного
адресата. Заведены transcriber_intake_up и transcriber_undelivered_reply_count.
- Закрыта утечка токена в журнал: отказ разбора адреса рождается раньше
обращения к клиенту, то есть мимо чистки на его границе.
- Тип сменён с chore: подъём без токена бота меняет наблюдаемое поведение и
требует нормы, которой в openspec/specs нет.
- В тело записан второй предмет работы — судьба задачи из Telegram, дошедшей до
ответа при отсутствующем боте; он же стал четвёртым критерием приёмки.
- Прежнее имя «Проверки о самих проверках» читалось против запрета в CLAUDE.md,
хотя правила в нём — линтеры над кодом проверок, то есть тот же один уровень.
- Двадцать сценариев шага были единственной проверкой над проверкой в проекте;
запрет CLAUDE.md остался без исключений.
- Ссылки на файл сняты в памятке, конвенции линтеров, журнале ревью и статусе
ADR о спеке toolchain; норма шага живёт комментариями в самом скрипте.
- Уровень проверки один: линтеры и тесты судят код сервиса, судить их самих
проект не берётся; названы попавшие под запрет виды работ.
- Пересказ решения в go-linters.md и review.md заменён ссылкой на дом.
- Из «Любой узел» в review.md убраны три свойства о годности самих проверок:
мутация теста, мутация оракула критерия, требование без сценария.
- Из go-linters.md снята «Лестница механизации», ссылки на неё переписаны
в конвенциях, их индексе и журнале дефектов.
- Инструментарий проекта спеками не нормируется: capability toolchain удалена,
норму шага сверки версий Go держат его проверки в scripts.
- Перечень capability в архитектуре и ревью сокращён до четырёх, решение
ADR-2026-08-12-spec-norms-build-toolchain помечено устаревшим.
- Отменены migrations-step-norm-and-tests, gate-steps-subject-guard и
review-config-from-go-upgrade: много механики, мало пользы.
- go-linters.md больше не числит отсутствие проверок шага migrations долгом —
это решение, а не незакрытая работа.
- migrations-step-norm-and-tests, gate-steps-subject-guard и
review-config-from-go-upgrade уехали в голову: слой проверок, которым верят
все задачи ниже;
- rollback-restores-wrong-session-duration встал рядом с соседом про откат,
bot-api-only-through-bot-client — рядом с чисткой транспорта,
pin-runtime-image-base — перед spa-skeleton, откуда начинаются пересборки;
- pipeline-spec-purpose-drift закрыта реализованной, а
docs-consistency-2026-08-13 переписана под пять оставшихся находок: шестую
свело повышение раскладки.
- ссылки на tasks/ROADMAP.md переведены на BACKLOG.md и на openspec/specs,
упоминания целей — на задачи, которые эту работу делают;
- судьи документации нашли восемь расхождений: Purpose спеки pipeline объявлял
неописанным то, что уже нормирован пятью требованиями, вид времени в
конвенции спорил со схемой, а квоты, шесть часов и отказ от Web Push жили
сразу в двух документах без ссылки друг на друга;
- два числа получили провенанс: 259 200 запросов в сутки и потолок в шесть
часов теперь ведут к записке разведки, а не читаются как замер.
- 11 записей типа goal закрыты с причиной, называющей задачи-наследники;
ROADMAP.md удалён, индекс остался один — BACKLOG.md;
- 33 записи переписаны: ссылка «Двигает пункты N «Завершения» цели» уступила
место прямому утверждению — без целей номера пунктов вели в никуда;
- шапка BACKLOG.md размечена парой <!-- стадия -->, порядок строк теперь
объявлен зависимостью, а не важностью.
Каталог скилла зовётся skills/canon, а переменная вела в skills/doc-canon:
шаг гейта скрипт не находил и краснел кодом 3, что читалось как отсутствие
плагина, — раскладку документов при этом не проверял никто.
- Перевод на канон 1 доделан: адреса служебного файла и имена скиллов
переставлены в девяти местах прозы и кода, гейт зовёт три скрипта по новым
путям, прежние docs/.docs.json и tasks/.tasks.json удалены.
- Сверка двумя агентами нашла четырнадцать расхождений, тринадцать сведены
строками: число прогонов ревью и преамбула журнала дефектов, счёт capability,
маршруты README, дубли инварианта захвата и кодов прогона, протухшие указатели
записок разведки, маркер долга на переехавшем абзаце. Срок жизни сессии
нормирует спека access, database.md на неё ссылается.
- Purpose спеки pipeline объявляет неописанным то, что в ней же и стоит; правка
идёт изменением openspec, поэтому заведена задача pipeline-spec-purpose-drift.
- четыре новые записи: проверить шаг migrations так же, как шаг сверки версий Go;
свести шесть расхождений между документами канона; запретить обращаться к Bot
API мимо клиента бота; разведка о шагах гейта, теряющих предмет
- context-cancel-in-pipeline приведена к правде: дописан перечень сделанного
попутно, критерий с оракулом «тест на трёх прерываниях подряд» разбит надвое —
проверена была только его узкая половина
- порядок заведения правила пополнен строкой: правка, снявшая последнее
употребление импорта, роняет сборку, а не проверку, и её вывод легко принять
за сработавшую мутацию. Случай был в этом же сеансе — проба приёма по HTTP
- в go-linters.md заведён раздел «Отмена и внешний собеседник», перечень
механизированного пополнен девятью правилами и двумя шагами гейта, названы
остатки: contextcheck не видит сигнатуру без контекста вовсе, шаг migrations
судит только шаги, бывшие в базе диффа, rowserrcheck и sqlclosecheck
профилактические — предмета в коде нет
- в logging.md и security.md чистка отказа Telegram описана по факту: точка одна
и лежит на границе клиента, закрыты все пять путей вместе с логгером самой
библиотеки. Прежнее «*Расхождение:* вычистки нет... она не логируется» было
неверным дважды
- в журнал дефектов записаны две находки: отказ скачивания уносил токен бота
(проскочил, жил с самого начала) и остановка сервиса хоронила конвертируемую
запись в failed (поймано ревью до коммита)
- вопрос темы operations про отмену переформулирован: спрашивать надо не
«доходит ли контекст», а «что шаг делает с задачей, деньгами и ответом
отправителю»; вопрос про таймаут оставлен с оговоркой, что проброс контекста
на него не отвечает
- в памятке: словарь кодов новых шагов, требование компилятора C у детектора
гонок и оговорка, что «CGO не нужен» относится к сборке, а не к гейту
- включены noctx, contextcheck и bodyclose (отмена доходит до внешнего вызова,
контекст приезжает сверху, тело ответа закрывается), nilerr, rowserrcheck и
sqlclosecheck (отказ не теряется молча), testifylint и nolintlint (форма
утверждения и форма подавления), плюс errcheck check-type-assertions:
непроверенное приведение типа паникует, и check-blank его не видит
- заведён шаг tests: go test -race, потому что «результат пишет только держатель
захвата» — утверждение об одновременности. Без компилятора C шаг гоняет тесты
без детектора и краснеет кодом 3 после них: гонки не повод отнимать у гейта
сами тесты
- заведён шаг migrations: у файла шага схемы допустим один статус — A. Баз диффа
две, BASE и HEAD: первая отвечает на «уже уехал» настолько, насколько свежа
origin/master, вторая ловит правку закоммиченного шага независимо от неё.
Каталог берётся из docs/.docs.json, пустой каталог роняет шаг
- единственное подавление — noctx на httptest.NewRequest в проверках: за
фикстурой запроса внешнего собеседника нет. Граница проверена мутацией —
http.Get и exec.Command из проверки правилу по-прежнему подсудны