Apply the three conditions of the senior sign-off: split the book_id checks, widen the vocabulary anchor to carry the depth field, and give the signature contract its positive half

This commit is contained in:
heaven 2026-08-27 17:35:08 +03:00
parent eec0947b00
commit b5b2ab6eb2

View file

@ -52,9 +52,13 @@ $0-глагол со своим словарём, кодами отказа и
1. **`docs/architecture/14-api-contract/README.md`** — компаньон, 1414 строк. Он и есть карта канона:
читается целиком, объясняет, ЗАЧЕМ канон устроен так. Начни с него, не с YAML.
2. **`openapi.yaml`, только нужные места** — 2592 строки, целиком НЕ читать. Отправные точки в §3.
3. **Словарь глагола — в КОДЕ, и он первичен:** `backend/internal/membank/decisions.go`, комментарий
к типу `Decision` (строки 55120). Он написан развёрнуто НАРОЧНО и прямо предупреждает, что
короткий лозунг «входной словарь = выходной» про него НЕВЕРЕН. Это твой источник тела двери.
3. **Словарь глагола — в КОДЕ, и он первичен:** `backend/internal/membank/decisions.go`, **строки
51117** — это НЕ только комментарий к типу `Decision` (он начинается на `:65`). Читай с `:51`, потому
что там `DecisionDepth`, и он сделан ПОЛЕМ, а не комментарием, ровно потому, что ответ не тот, какой
пользователь предполагает: принятое решение доезжает до РЕДАКТОРА, а не пере-формирует черновик
(дельта — `Source:"mined"` и в БАЗОВЫЙ банк черновой волны не входит). Комментарий к `Decision`
написан развёрнуто НАРОЧНО и прямо предупреждает, что короткий лозунг «входной словарь = выходной»
про него НЕВЕРЕН. Это твой источник тела двери.
4. **`backend/internal/pipeline/bankdecisions.go`** — форма отчёта (`BankDecisionsReport`) и шесть
исходов; `backend/cmd/tmctl/main.go:69-75` — полоса отказов 1019.
5. **Две ратифицированные НОРМЫ — читать обе, они короткие и обе про твой предмет:**
@ -123,10 +127,15 @@ $0-глагол со своим словарём, кодами отказа и
`decline` **снимает ВСЕ окна поверхности** (`decisions.go:85-87`). Расширение или сдвиг окна —
операция в два вызова. Это ратифицированное свойство, а не дефект: предупреждением, не умолчанием.
- **Конверт документа — тоже словарь, и его нельзя изобретать заново:** `decisions_version` со
значением `tm-bank-decisions-v1` (`decisions.go:47`) · `book_id` **обязателен и сверяется с книгой**
(`:142`), потому что решения — единственный вход, несущий слова пользователя в чужую книгу незаметно
для даунстрима · **неизвестное поле — громкий отказ** (`DisallowUnknownFields`, `:133`) — зеркало
значением `tm-bank-decisions-v1` (`decisions.go:47`) · `book_id` **обязателен** (`decisions.go:142`, «names no book_id») **и отдельно СВЕРЯЕТСЯ с книгой**
(`pipeline/bankdecisions.go:267`, `openDecisionRequest`: `doc.BookID != book.BookID` — отказ). Два
разных места и две разные проверки; путать их не надо. Причина сверки: решения — единственный вход,
несущий слова пользователя в чужую книгу незаметно для даунстрима · **неизвестное поле — громкий отказ** (`DisallowUnknownFields`, `:133`) — зеркало
**п.4 закона входной двери шва** (`docs/architecture/17-seam-inbound-law.md`, позиция 5 карты).
- **`depth` — поле ОТЧЁТА, и оно обязано доехать до фронта с правильным смыслом.** `edit_wave`:
принятое решение доезжает до редакторской волны и **НЕ пере-формирует черновик**
(`bankdecisions.go:49-52` говорит это прямо: «what it must not do is assume the corrected term
re-forms the draft»). Это первое, о чём экран соврёт пользователю, если канон промолчит.
- **Два потолка, оба объявляются:** **1 МиБ** на чтение документа и **5000 решений на один акт**
(`bankdecisions.go:647`, `maxDecisions`; за ним — отказ КЛАССОМ 14 с текстом «split it», потому что
дальше вызов перестаёт влезать в таймаут вызывающего и умирает на каждом ретрае). Опубликованная
@ -146,6 +155,12 @@ $0-глагол со своим словарём, кодами отказа и
пер-термная модель, вернувшаяся через чёрный ход тем же минором, который её сносит. **Публикуешь
поле — публикуешь и запрет; не готов опубликовать запрет — не публикуй поле.**
**И неси ОБЕ половины контракта.** У него есть положительная (`bankdecisions.go:101-104`), и без
неё блок кренит к «проще не публиковать», а поле экрану полезно: числа отвечают на вопрос «из
поверхностей, которые предложил последний стоп, о скольких владелец ещё не высказался», и считаются
ТЕМ ЖЕ правилом, каким прогон сворачивает решения в банк, — поэтому счёт согласован с тем, что
следующий прогон сочтёт решённым содержанием.
**Отправные точки модели ошибки — держи их под рукой прежде, чем раскладывать коды:** конверт отказа
— схема `Problem` (`openapi.yaml:2395`, RFC 9457 плюс расширения); **машинный идентификатор — `code`**
(`:2432`), его словарь — `ErrorCode` (`:2462`); `errors[]` (`:2444`) несёт, ЧТО именно в запросе не так,