openspec: упразднена спека toolchain
- Инструментарий проекта спеками не нормируется: capability toolchain удалена, норму шага сверки версий Go держат его проверки в scripts. - Перечень capability в архитектуре и ревью сокращён до четырёх, решение ADR-2026-08-12-spec-norms-build-toolchain помечено устаревшим.
This commit is contained in:
@@ -2,6 +2,9 @@
|
||||
|
||||
- **Дата:** 2026-08-12
|
||||
- **Источник:** [openspec/changes/archive/2026-08-12-go-1-26-upgrade/design.md](../../openspec/changes/archive/2026-08-12-go-1-26-upgrade/design.md), раздел `Decisions`, Решение 2
|
||||
- **Статус:** устарело — 2026-08-13 владелец решил обратное: инструментарию в
|
||||
спеках не место. Capability `toolchain` упразднена, замены у неё нет, норму
|
||||
шага держат его проверки в `scripts/check_go_version_test.go`
|
||||
|
||||
## Решение
|
||||
|
||||
@@ -10,8 +13,9 @@
|
||||
собирают. Потребитель у неё другой: тот, кто собирает.
|
||||
|
||||
Требование о согласованности объявленной версии Go живёт нормой в
|
||||
[openspec/specs/toolchain/spec.md](../../openspec/specs/toolchain/spec.md), а не
|
||||
прозой в памятке.
|
||||
`openspec/specs/toolchain/spec.md`, а не прозой в памятке. *Уточнено 2026-08-13:
|
||||
файла по этому адресу больше нет, ссылка снята — capability упразднена, см.
|
||||
статус записи.*
|
||||
|
||||
## Почему
|
||||
|
||||
|
||||
+1
-1
@@ -39,7 +39,7 @@
|
||||
| 2026-08-12 | [Сессия живёт семь суток и не продлевает саму себя](ADR-2026-08-12-session-without-refresh.md) | |
|
||||
| 2026-08-12 | [Кого пускать в сервис, решает правило провайдера, а не сервис](ADR-2026-08-12-access-delegated-to-provider.md) | |
|
||||
| 2026-08-12 | [Код провайдера меняется на сессию вызовом собственного адреса хранилища внутри процесса](ADR-2026-08-12-oidc-exchange-via-own-route.md) | |
|
||||
| 2026-08-12 | [Спекой нормируется и инструмент сборки, а не только поведение сервиса](ADR-2026-08-12-spec-norms-build-toolchain.md) | |
|
||||
| 2026-08-12 | [Спекой нормируется и инструмент сборки, а не только поведение сервиса](ADR-2026-08-12-spec-norms-build-toolchain.md) | устарело |
|
||||
| 2026-08-12 | [Объявленную версию Go шаг гейта читает из репозитория, а не спрашивает у инструмента](ADR-2026-08-12-version-read-from-repo-not-from-tool.md) | |
|
||||
| 2026-08-12 | [Ссылка на файл открыта знанием записи, а защищает её отсутствие имени в журнале](ADR-2026-08-12-file-link-open-but-not-logged.md) | заменено на [ADR-2026-08-12-protected-file-behind-session](ADR-2026-08-12-protected-file-behind-session.md) |
|
||||
| 2026-08-12 | [Каталог данных задаётся одним ключом `[storage] data_dir`](ADR-2026-08-12-single-data-dir-config-key.md) | |
|
||||
|
||||
@@ -8,9 +8,11 @@
|
||||
[passport.md](passport.md) и в [tasks/BACKLOG.md](../tasks/BACKLOG.md); что из
|
||||
этого ещё не решено — в разделе «Открытые вопросы».
|
||||
|
||||
Заведены пять capability. Четыре первые нормируют **поведение сервиса** для его
|
||||
потребителей; пятая — исключение из первого абзаца: она нормирует не сервис, а
|
||||
инструмент, которым его собирают, и потребитель у неё другой — тот, кто собирает.
|
||||
Заведены четыре capability, и все нормируют **поведение сервиса** для его
|
||||
потребителей. Инструмент, которым сервис собирают, спеками не нормируется вовсе:
|
||||
у набора проверок и сборки другой потребитель — тот, кто собирает, — и решением
|
||||
от 2026-08-13 его нормы живут в самих шагах, их проверках и
|
||||
[conventions/go-linters.md](conventions/go-linters.md).
|
||||
|
||||
- [intake](../openspec/specs/intake/spec.md) — **только приём по HTTP**: приём и
|
||||
опрос за сессией, имя отправителя не доходит ни до хранилища, ни до журнала,
|
||||
@@ -30,11 +32,7 @@
|
||||
его дальше: вход через внешнего провайдера OIDC, чем предъявляется сессия, что
|
||||
её прекращает и какие адреса остаются открытыми. Задача `oidc-login`
|
||||
2026-08-12. Разграничения записей по владельцу здесь нет: всякий вошедший
|
||||
видит всё, что видел прежде аноним;
|
||||
- [toolchain](../openspec/specs/toolchain/spec.md) — каким инструментом и какой
|
||||
его версии собирается сервис: одно число версии Go во всех местах, где она
|
||||
названа, и шаг гейта, который это сверяет. Задача `go-1-26-upgrade`
|
||||
2026-08-12.
|
||||
видит всё, что видел прежде аноним.
|
||||
|
||||
Поведение прочих узлов, включая приём из Telegram, по-прежнему живёт только в
|
||||
коде. Задача, которая его трогает, дописывает спеку своей capability.
|
||||
|
||||
@@ -36,12 +36,12 @@ Go-проект как есть. Своё здесь — перечень пра
|
||||
- **настройка конвейера ревью, вопросы по темам и журнал дефектов** —
|
||||
[../review.md](../review.md). Перечень ниже говорит этим вопросам, чего
|
||||
спрашивать уже не нужно;
|
||||
- **поведение сервиса** — нормативные спеки `openspec/specs/`. У шага сверки
|
||||
версий Go поведение нормировано отдельно, спекой
|
||||
[toolchain](../../openspec/specs/toolchain/spec.md): это единственная проверка
|
||||
проекта, у которой есть своя capability, и потому единственная, чьи сценарии
|
||||
проверяются построчно (`scripts/check_go_version_test.go`). Второй самодельный
|
||||
шаг — `migrations` — нормы не имеет: он проверен мутацией на трёх исходах
|
||||
- **поведение сервиса** — нормативные спеки `openspec/specs/`. Шаги набора
|
||||
проверок туда не входят: инструментарий спеками не нормируется, и спека
|
||||
`toolchain`, заведённая под шаг сверки версий Go, упразднена 2026-08-13. Норму
|
||||
этого шага держат его собственные проверки — двадцать сценариев в
|
||||
`scripts/check_go_version_test.go`, и другого дома у неё нет. Второй самодельный
|
||||
шаг — `migrations` — не проверен и ими: он прогнан мутацией на трёх исходах
|
||||
(переписанный шаг, пустой каталог, чистое дерево), но регрессионных проверок у
|
||||
него нет, и дрейф его собственного шаблона имени никто не поймает. Владелец
|
||||
решил 2026-08-13 оставить это как есть: проверка над проверкой даёт много
|
||||
@@ -147,7 +147,7 @@ Go-проект как есть. Своё здесь — перечень пра
|
||||
| Правило | Где механизировано |
|
||||
| --- | --- |
|
||||
| Проверка судит ответ по готовому ответу (`Result()`), а не по живой карте заголовков обработчика | `.golangci.yml` → `forbidigo` с `analyze-types`, находки только в `*_test.go`. Судит по типу приёмника (`httptest.ResponseRecorder`), поэтому ловит любую форму: цепочкой, через переменную, по индексу карты, обходом, полем `HeaderMap`. Остаётся ревью проверка, идущая мимо recorder — через свой `http.ResponseWriter` |
|
||||
| Каждый сценарий нормы шага сверки версий проверен мутацией, а не памятью | `scripts/check_go_version_test.go` — 20 сценариев спеки `toolchain` плюс два свойства самого шага: исход не зависит от установленного `go`, и шаг не зовёт ни `go`, ни `docker`, ни сеть |
|
||||
| Каждый сценарий нормы шага сверки версий проверен мутацией, а не памятью | `scripts/check_go_version_test.go` — 20 сценариев шага плюс два его свойства: исход не зависит от установленного `go`, и шаг не зовёт ни `go`, ни `docker`, ни сеть |
|
||||
| Форма утверждения в проверках: «ожидалось» и «получено» не перепутаны местами, отказ судится `NoError`, а не `Nil`, `require` не зовут из горутины | `.golangci.yml` → `testifylint` |
|
||||
| Одновременный доступ проверен детектором, а не чтением кода | `Taskfile.yml` → шаг `tests` (`go test -race ./...`). Общее у воркеров — счётчики метрик, логгер и клиент бота; захват задачи в гонку не входит, он по построению её не даёт (одно состояние на воркер) — см. «Типовые ложноположительные» в [../review.md](../review.md). Что делает шаг без компилятора C и каким кодом краснеет — [CLAUDE.md](../../CLAUDE.md), «Гейт» |
|
||||
| Строчное подавление называет линтер и причину, а протухшее краснеет | `.golangci.yml` → `nolintlint` (`require-explanation`, `require-specific`, `allow-unused: false`) |
|
||||
|
||||
+5
-3
@@ -145,8 +145,8 @@
|
||||
`createTranscribeJob` — сегодня через него идут оба входа
|
||||
([architecture.md](architecture.md), «Единые точки проекта»).
|
||||
- `architecture`: не поехало ли поведение в `architecture.md` вместо спеки —
|
||||
заведены пять capability (`intake`, `pipeline`, `storage`, `access`,
|
||||
`toolchain`), и первые две описаны частично. Поведение прочих узлов, включая
|
||||
заведены четыре capability (`intake`, `pipeline`, `storage`, `access`), и
|
||||
первые две описаны частично. Поведение прочих узлов, включая
|
||||
приём из Telegram, живёт в обзоре под маркерами долга, а соблазн дописать туда
|
||||
ещё — самый большой.
|
||||
- `conventions`: новая колонка правится во всех четырёх местах репозитория
|
||||
@@ -472,7 +472,9 @@ API и имя не откатываются обратной правкой по
|
||||
(`scripts/check-go-version.sh`). Сверяются четыре места, а не два, — `go.mod`,
|
||||
`Dockerfile`, `CLAUDE.md`, `README.md`: в этом дефекте трое из четырёх врали
|
||||
согласованно, и парная сверка не увидела бы документ, разошедшийся с
|
||||
согласованным кодом. Норма — capability `toolchain`.
|
||||
согласованным кодом. Норму шага держат его собственные проверки
|
||||
(`scripts/check_go_version_test.go`): спека `toolchain`, бывшая его домом,
|
||||
упразднена 2026-08-13 — инструментарий спеками не нормируется.
|
||||
|
||||
## 2026-08-11 — норма требовала от сервиса недостижимого [пойман ревью]
|
||||
|
||||
|
||||
@@ -1,241 +0,0 @@
|
||||
# toolchain Specification
|
||||
|
||||
## Purpose
|
||||
|
||||
Каким инструментом и какой его версии собирается сервис, и что об этом
|
||||
проверяется до выкладки. Заведена задачей `go-1-26-upgrade` 2026-08-12 по
|
||||
дефекту, записанному в `docs/review.md` за то же число: сборочный образ разошёлся
|
||||
с требованием модуля, образ перестал собираться, а восемь шагов гейта и шесть
|
||||
проходов ревью показали зелёное.
|
||||
|
||||
Capability нормирует **не поведение сервиса** для его потребителей, а поведение
|
||||
инструмента разработки; потребитель у неё другой — тот, кто собирает сервис. Это
|
||||
осознанное исключение, и оно названо в преамбуле `docs/architecture.md`.
|
||||
|
||||
## Requirements
|
||||
### Requirement: Версия инструмента сборки объявлена одним числом
|
||||
|
||||
Проект SHALL объявлять версию Go, на которой собирается сервис, одинаково во
|
||||
всех местах, где она названа. Мест ровно четыре, и перечень закрыт: требование
|
||||
модуля в `go.mod`, сборочный образ в `Dockerfile`, строка стека в `CLAUDE.md`,
|
||||
строка стека в `README.md`.
|
||||
|
||||
Сравниваются мажор и минор. Третье число у сборочного образа MUST оставаться
|
||||
свободным, как и база образа: образ обновляется своим темпом, и требовать от
|
||||
него совпадения по патчу значило бы краснеть на каждом его обновлении. Тег
|
||||
читается по форме `golang:<мажор>.<минор>[.<патч>][-<база>]`, и берутся из него
|
||||
первые два числа.
|
||||
|
||||
Правило множественности у мест разное, потому что места устроены по-разному.
|
||||
|
||||
**Документы** — `CLAUDE.md` и `README.md` — MUST называть версию ровно один раз,
|
||||
и считается это **не по файлу, а по разделу стека**: `## Стек` в памятке,
|
||||
`## Технологии` в README. Второе вхождение числа **в этом разделе** MUST
|
||||
считаться отказом: обновят одно, второе протухнет молча. За пределами раздела
|
||||
число не читается вовсе — иначе памятка, которая по устройству ведёт историю
|
||||
закрытых долгов, роняла бы проверку на первой же правдивой строке о прошлой
|
||||
версии, а сообщение толкало бы чинить не проверку, а исторический документ.
|
||||
|
||||
**Сборочный образ** единственности не требует: каждый слой — настоящий вход
|
||||
сборки, и многослойная сборка законна. От всех вхождений `FROM golang:` MUST
|
||||
требоваться совпадение мажора и минора, а не единственность.
|
||||
|
||||
**Требование модуля** называется директивой `go` и по устройству файла
|
||||
единственно.
|
||||
|
||||
Граница раздела MUST быть определена, а не подразумеваться: раздел кончается
|
||||
следующим заголовком того же или более высокого уровня, заголовок третьего уровня
|
||||
и ниже остаётся внутри раздела, а строка, похожая на заголовок, но лежащая внутри
|
||||
блока кода, заголовком MUST не считаться. Без этого пример в чужом разделе
|
||||
открывал бы раздел стека на пустом месте, и число доставалось бы оттуда, откуда
|
||||
норма его читать не велит.
|
||||
|
||||
`go.mod` MUST не содержать директиву `toolchain`. Она называет версию **пятым**
|
||||
местом, которого перечень не знает: при `toolchain go1.27.0` четыре объявленных
|
||||
числа сойдутся, а собирать будет пятое — то есть вернётся тот самый класс
|
||||
расхождения, ради которого требование и заведено.
|
||||
|
||||
#### Scenario: Все четыре места названы одинаково
|
||||
|
||||
- **GIVEN** дерево проекта, где `go.mod`, `Dockerfile`, `CLAUDE.md` и `README.md`
|
||||
называют версию Go
|
||||
- **WHEN** их читают подряд
|
||||
- **THEN** мажор и минор совпадают во всех четырёх
|
||||
|
||||
#### Scenario: Патч сборочного образа отличается законно
|
||||
|
||||
- **GIVEN** `go.mod` требует `1.26.0`, а образ собирается на `golang:1.26.5-alpine`
|
||||
- **WHEN** версии сравнивают
|
||||
- **THEN** расхождением это не считается
|
||||
|
||||
#### Scenario: База сборочного образа сменилась
|
||||
|
||||
- **GIVEN** образ переехал с `golang:1.26-alpine` на `golang:1.26-bookworm`
|
||||
- **WHEN** версии сравнивают
|
||||
- **THEN** расхождением это не считается
|
||||
|
||||
#### Scenario: Раздел стека называет версию дважды
|
||||
|
||||
- **GIVEN** раздел стека в `CLAUDE.md` называет версию два раза
|
||||
- **WHEN** версии сравнивают
|
||||
- **THEN** это расхождение, даже если оба числа одинаковы
|
||||
|
||||
#### Scenario: Число за пределами раздела стека не читается
|
||||
|
||||
- **GIVEN** `CLAUDE.md` вне раздела стека упоминает прошлую версию Go — например
|
||||
записью о закрытом долге
|
||||
- **WHEN** версии сравнивают
|
||||
- **THEN** расхождением это не считается
|
||||
|
||||
#### Scenario: Сборочный образ собран в два слоя
|
||||
|
||||
- **GIVEN** `Dockerfile` содержит два `FROM golang:` с одним мажором и минором
|
||||
- **WHEN** версии сравнивают
|
||||
- **THEN** расхождением это не считается
|
||||
|
||||
#### Scenario: Слои сборочного образа разошлись между собой
|
||||
|
||||
- **GIVEN** `Dockerfile` содержит два `FROM golang:` с разными минорами
|
||||
- **WHEN** версии сравнивают
|
||||
- **THEN** это расхождение
|
||||
|
||||
#### Scenario: Заголовок раздела встретился внутри блока кода
|
||||
|
||||
- **GIVEN** документ в чужом разделе показывает пример, внутри которого есть
|
||||
строка, совпадающая с заголовком раздела стека, а ниже названо другое число
|
||||
- **WHEN** версии сравнивают
|
||||
- **THEN** число из примера не читается, и расхождением это не считается
|
||||
|
||||
#### Scenario: Раздел стека закрыт заголовком верхнего уровня
|
||||
|
||||
- **GIVEN** после раздела стека идёт заголовок первого уровня, а ниже названа
|
||||
прошлая версия
|
||||
- **WHEN** версии сравнивают
|
||||
- **THEN** это число не читается, и расхождением не считается
|
||||
|
||||
#### Scenario: Раздела стека нет вовсе
|
||||
|
||||
- **GIVEN** в документе нет раздела, где называется версия
|
||||
- **WHEN** запускают шаг сверки
|
||||
- **THEN** он завершается отказом и называет недостающий раздел
|
||||
|
||||
#### Scenario: Модуль объявляет версию пятым местом
|
||||
|
||||
- **GIVEN** `go.mod` содержит директиву `toolchain`
|
||||
- **WHEN** версии сравнивают
|
||||
- **THEN** это расхождение
|
||||
|
||||
### Requirement: Объявленное число — то, на котором проект собирается
|
||||
|
||||
Объявленная версия SHALL быть той, на которой сервис действительно собирается и
|
||||
проходит тесты. Согласованность четырёх строк между собой этого не доказывает:
|
||||
четыре одинаковых числа несуществующей версии требованию о согласованности
|
||||
удовлетворяют, а собрать на них нельзя.
|
||||
|
||||
Проверка эта MUST оставаться за человеком и MUST не входить в набор проверок:
|
||||
она требует сборки образа, а сборка образа набором проверок не делается
|
||||
намеренно — дорого. Подъём версии MUST не уезжать в основную ветку, пока сборка
|
||||
образа и тесты на объявленном числе не прогнаны.
|
||||
|
||||
#### Scenario: Версию подняли
|
||||
|
||||
- **GIVEN** объявленную версию Go подняли во всех четырёх местах
|
||||
- **WHEN** изменение готовят к мерджу
|
||||
- **THEN** до мерджа на этой версии прогнаны сборка образа и тесты
|
||||
|
||||
### Requirement: Расхождение версий роняет набор проверок
|
||||
|
||||
Набор проверок `task gate` SHALL включать шаг, который сравнивает объявленные
|
||||
версии между собой и MUST завершаться отказом, когда они разошлись. Сообщение
|
||||
отказа MUST называть **все четыре места и прочитанное в каждом число** — не одну
|
||||
разошедшуюся пару: в дефекте 2026-08-12 три места из четырёх говорили одно и то
|
||||
же и неверными были именно они, а по сообщению о паре человек чинит не то место.
|
||||
|
||||
Шаг MUST судить по содержимому файлов репозитория и MUST не спрашивать
|
||||
установленный инструмент — ни `go version`, ни `go env`, ни `GOTOOLCHAIN`. Исход
|
||||
его MUST быть функцией коммита, а не машины: шаг, чей ответ зависит от того, что
|
||||
стоит на хосте, воспроизводит ровно ту подмену, которая держала дефект
|
||||
2026-08-12 невидимым — там `go build ./...` шёл на хостовом Go, а объявленное
|
||||
число не проверял никто.
|
||||
|
||||
Шаг MUST работать сравнением строк — без сборки образа, без docker и без сети —
|
||||
и MUST не зависеть от рабочего каталога, из которого запущен. Шаг MUST только
|
||||
читать: файлов он не правит и разошедшихся мест не чинит.
|
||||
|
||||
Коды выхода MUST следовать общему словарю проверочных шагов проекта; словарь
|
||||
объявляет раздел «Гейт» в `CLAUDE.md`, и здесь он не повторяется. Своего словаря шаг
|
||||
MUST не заводить: четвёртый шаг с собственной семантикой сделал бы это
|
||||
утверждение неверным.
|
||||
|
||||
Место, где числа не нашлось вовсе, MUST считаться отказом с именем этого места.
|
||||
«Нечего сравнивать» исходом MUST не быть: пропавшая строка иначе выглядела бы
|
||||
как совпадение.
|
||||
|
||||
Отказ чтения места MUST не выглядеть как отсутствие числа. Место, которое
|
||||
существует, но не читается, — это отказ окружения, и сообщение MUST говорить о
|
||||
нечитаемости, а не о ненайденной версии: иначе шаг отправляет чинить документ, в
|
||||
котором строка на месте, а сломаны права.
|
||||
|
||||
#### Scenario: Разошёлся сборочный образ
|
||||
|
||||
- **GIVEN** `Dockerfile` называет версию, отличную от прочих трёх мест
|
||||
- **WHEN** запускают `task gate`
|
||||
- **THEN** шаг сверки завершается отказом
|
||||
- **AND** сообщение называет все четыре места и число каждого
|
||||
- **AND** весь набор проверок краснеет
|
||||
|
||||
#### Scenario: Разошлось требование модуля
|
||||
|
||||
- **GIVEN** `go.mod` называет версию, отличную от прочих трёх мест
|
||||
- **WHEN** запускают шаг сверки
|
||||
- **THEN** он завершается отказом и называет `go.mod` среди разошедшихся
|
||||
|
||||
#### Scenario: Разошлась памятка
|
||||
|
||||
- **GIVEN** `CLAUDE.md` называет версию, отличную от прочих трёх мест
|
||||
- **WHEN** запускают шаг сверки
|
||||
- **THEN** он завершается отказом и называет `CLAUDE.md` среди разошедшихся
|
||||
|
||||
#### Scenario: Разошёлся README
|
||||
|
||||
- **GIVEN** `README.md` называет версию, отличную от прочих трёх мест
|
||||
- **WHEN** запускают шаг сверки
|
||||
- **THEN** он завершается отказом и называет `README.md` среди разошедшихся
|
||||
|
||||
#### Scenario: Версии совпадают
|
||||
|
||||
- **GIVEN** все четыре места называют одно число
|
||||
- **WHEN** запускают `task gate`
|
||||
- **THEN** шаг сверки проходит с кодом 0
|
||||
- **AND** остальные шаги набора идут как прежде
|
||||
|
||||
#### Scenario: Инструмента сборки нет на машине
|
||||
|
||||
- **GIVEN** в `PATH` нет `go` вовсе
|
||||
- **WHEN** запускают шаг сверки
|
||||
- **THEN** исход и сообщение те же, что и при установленном `go`
|
||||
|
||||
#### Scenario: Ни docker, ни сети нет
|
||||
|
||||
- **GIVEN** docker недоступен и сети нет
|
||||
- **WHEN** запускают шаг сверки
|
||||
- **THEN** он отрабатывает и даёт тот же исход, что и при доступном docker
|
||||
|
||||
#### Scenario: Шаг запущен не из корня проекта
|
||||
|
||||
- **GIVEN** шаг запускают из подкаталога дерева
|
||||
- **WHEN** он ищет свои четыре места
|
||||
- **THEN** исход тот же, что и при запуске из корня
|
||||
|
||||
#### Scenario: Место существует, но не читается
|
||||
|
||||
- **GIVEN** файл одного из мест на диске есть, но прав на чтение нет
|
||||
- **WHEN** запускают шаг сверки
|
||||
- **THEN** он завершается кодом окружения и говорит о нечитаемости места
|
||||
- **AND** сообщения «версия не названа» не печатает
|
||||
|
||||
#### Scenario: Версия не названа там, где должна быть
|
||||
|
||||
- **GIVEN** одно из четырёх мест перестало называть версию Go
|
||||
- **WHEN** запускают шаг сверки
|
||||
- **THEN** он завершается отказом и называет место, где число не нашлось
|
||||
@@ -1,11 +1,12 @@
|
||||
// Package scripts — проверки скриптов репозитория. Рабочего кода на Go в нём
|
||||
// нет: пакет существует ради того, чтобы `go test ./...` гонял и shell.
|
||||
//
|
||||
// Норма шага сверки версий — openspec/specs/toolchain/spec.md. Каждый её
|
||||
// сценарий проверяется здесь мутацией: дерево-образец собирается во временном
|
||||
// каталоге, портится ровно одним способом, и от скрипта требуется объявленный
|
||||
// исход. Прежде сценарии подтверждались разовыми ручными прогонами — после
|
||||
// первой правки образца они перестали бы выполняться молча.
|
||||
// Норма шага сверки версий живёт здесь и в комментариях самого скрипта: спека
|
||||
// toolchain, бывшая её домом, упразднена 2026-08-13 — инструментарий спеками не
|
||||
// нормируется. Каждый сценарий проверяется мутацией: дерево-образец собирается
|
||||
// во временном каталоге, портится ровно одним способом, и от скрипта требуется
|
||||
// объявленный исход. Прежде сценарии подтверждались разовыми ручными прогонами —
|
||||
// после первой правки образца они перестали бы выполняться молча.
|
||||
package scripts
|
||||
|
||||
import (
|
||||
|
||||
Reference in New Issue
Block a user