textmachine/docs/architecture/18-bank-ontology.md

122 lines
17 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# 18 — Онтология банка памяти: роли носителей, писатели, свежесть
> **СТАТУС: РАТИФИЦИРОВАНО D39.158 (27.08.2026).** Топикальный вход (D39.126): НЕ источник истины,
> при конфликте побеждает журнал решений. Собрано оркестратором №19 по консилиуму со сторонним
> архитектором при приёмке четырёх паков входной двери шва.
>
> **Зачем страница.** Вокруг одного понятия — «состояние банка этой книги» — живут одиннадцать носителей.
> Форма СТРОГАЯ: поток однонаправленный, у каждого источника единственный писатель, вид пересобирается
> полностью на каждой границе прогона (D39.158 п.8).
## Пять ролей, и они не смешиваются
**Было ЧЕТЫРЕ до 17.09.** Пятую — «ПАМЯТЬ РЕШЕНИЙ» — завела эррата 17.09-д и построил пак базиса
решённого. Заводить новый класс пришлось именно потому, что подпись существующего у́же: «ПАМЯТЬ ФЛАЖКА»
определена как «что стоп уже предъявлял», писатель — стоп, а базис пишет ПРОГОН на своих границах и читает
его денежный предикат ДО первой траты. Расширить чужую подпись значило бы сделать одну строку таблицы
двузначной, чего эта страница не допускает нигде.
| Роль | Носители | Писатель | Момент фиксации |
|---|---|---|---|
| **ИСТОЧНИКИ** — то, из чего банк собирается | `glossary_seed` · `<book_id>.mined-delta.yaml` · `<book_id>.mined-rejects.yaml` (слово ВЛАДЕЛЬЦА, рядом с `book.yaml`, едут с книгой в бэкапе и экспорте) · `<project_db>.auto-bank.yaml` (слово ДВИЖКА, сидит при базе) · ruby-чтения в хранилище | у каждого РОВНО один. ⚠ Дверь `bank-apply` пишет ТОЛЬКО два файла решений: правка сид-терма ею ОТКЛОНЯЕТСЯ по имени (`internal/membank/decisions.go:359`=`Scoped to APPROVE`), потому что это перенос базового снапшота и пере-оплата черновой волны — другое решение (щель ратифицирована, строка 192). `glossary_seed` — рука владельца · `auto-bank` — прогон · ruby — хранилище | запись двери — под эксклюзивным флоком проекта; рука владельца флока не берёт (остаток — строка 222) |
| **ВИД** — банк, каким его видят роли | строки глоссария в хранилище | только `seedGlossary`, и только полным пересбором | каждая граница прогона; один загрузчик, все гарды |
| **ПРОЕКЦИИ** — то, что банк рассказывает наружу | `<project_db>.bank.json` (единственный канал банка наружу) · карта подписи `<project_db>.mined-signature.yaml` · человеческая таблица стопа `.bank-stop.txt` | прогон, на границе | ⚠ не одинаков: `bank.json` — ПОСЛЕ смены вида; карта подписи и `.bank-stop.txt` — при вычислении стопа, ДО пере-сида, а на стоп-границе вид вообще не меняется (остановившийся прогон авто-банк не пишет) |
| **ПАМЯТЬ ФЛАЖКА** — что стоп уже предъявлял | таблица `bank_stop_presented` | стоп | ПОСЛЕ карты, никогда до |
| **ПАМЯТЬ РЕШЕНИЙ** — что книга уже решила и на каких уликах | таблица `bank_basis` (отпечаток улик + консолидированный ответ) | **прогон**, и границ у него ДВЕ: `run-finished` и ветка стопа подписи | на выходной границе прогона, ПЕРЕД памятью флажка |
**Поток однонаправленный: источники → вид → проекции.** Отсюда главное свойство, из-за которого
рефактор не нужен: **расхождение источников с видом структурно невозможно дольше одной границы
прогона**, потому что вид не патчится, а пересобирается целиком.
**Единственная петля — авто-провод, и она названа здесь нарочно:** прогон пишет собственный ИСТОЧНИК
(`auto-bank`) и пере-сидит вид в той же границе. Это первое, куда ткнёт проверяющий однонаправленности.
Петля реальна и защищена с двух сторон — `unsignedEngineSurfaces` держит границу подписанного, а
`loadAutoBank` отказывает строке со статусом `approved`, — то есть слово движка не может присвоить себе
слово владельца. Однонаправленность формулируется точно так: **петля есть, но она не может изменить
подписанное.**
**ВТОРАЯ ПЕТЛЯ (пак базиса решённого, 17.09): базис → предикат → авто-банк.** Прежняя редакция называла
авто-провод ЕДИНСТВЕННОЙ петлёй, и с этого дня это неверно: прогон пишет память решений на своей границе,
а СЛЕДУЮЩАЯ покупка читает её предикатом до первого платного вызова и подставляет оттуда ответ, который
уезжает в авто-банк. Защищена она тем же самым — слово движка не может присвоить себе слово владельца:
подписанная строка записи в базис не получает (предикат отвергает её по статусу) и её передача базисом НЕ
подменяется никогда. Формулировка однонаправленности не меняется, меняется число её членов: **петель две,
и ни одна не может изменить подписанное.**
**Порядок на границе стопа — карта → таблица стопа → проекция банка → БАЗИС → память флажка**, и базис
стоит ПЕРЕД памятью флажка по тому же правилу, которым правило 3 ниже объясняет саму асимметрию: последней
пишется запись, чья потеря ДЕШЕВЛЕ. Потеря памяти флажка стоит одного доброкачественного лишнего стопа;
потеря базиса стоит пере-покупки обеих банк-ролей из ПОЖИЗНЕННОГО потолка книги, исчерпание которого
необратимо (ряд 356). ⛔ И писать базис РАНЬШЕ развилки нельзя: базис, оказавшийся на краш-резюме, сжимает
состав батчей, чекпойнты по хешу запроса не находятся, и резюм перекупает уже оплаченное.
## Почему слово владельца и слово движка не сливаются
Соблазн понятный: одобрения владельца и авто-строки движка — одинаковые по форме строки банка. Но
слитые, они делают неразличимым то, ради чего банк существует: **какие переводы человек действительно
одобрил.** Поэтому источники разнесены и по писателю, и по каталогу — решения владельца едут с книгой,
состояние движка сидит при базе.
## Дисциплина проекции — норма, а не стиль
Три правила, каждое куплено дефектом:
1. **У проекции обязан быть НАЗВАННЫЙ читатель.** Машинная таблица стопа `.bank-stop.json` была
написана для пер-термного экрана подписи; экран упразднён D39.144, читателя не осталось ни в одной
зоне — снесена D39.158. Свип наследия отменённой модели шёл по коду, гейтам и текстам, а её
АРТЕФАКТ пережил его, потому что никто не смотрел на множество публикаций.
2. **У проекции обязан быть якорь свежести ВНУТРИ документа.** Отказ записи банк-экспорта — «громко,
но не фатально» (деньги дороже проекции), и это верно; но «может быть устаревшим» жило только в
ЛОГЕ. Потребитель не мог отличить проекцию этой границы от прошлой. Закрыто конвертом с меткой
границы и идентификатором прогона.
3. **Порядок между носителями — инвариант, а не деталь.** Память флажка пишется ПОСЛЕ карты: падение
между ними даёт лишний доброкачественный стоп, обратный порядок — запомненную поверхность, чьей
карты не существует, то есть молчаливую потерю навсегда. Инвариант, живущий в комментарии, не
держится ничем — держит его пин.
⚠ **КЛАСС A, названный этой страницей: проекция без контракта потребителя и без якоря свежести
в самой себе.** Два известных члена: снесённая таблица стопа · банк-экспорт до конверта. Третий живёт
строкой бэклога 224: банк-экспорт на стопе ПУСТ — проекция, наиболее пустая ровно в тот момент, когда
её читает экран подписи.
**КЛАСС B — другой, и путать их нельзя: межносительный инвариант, живущий комментарием без пина.**
Член — порядок «карта → память» до фикс3. Он НЕ подпадает под класс A: там дефект в том, что документ
не несёт контракта, здесь — в том, что связь ДВУХ носителей держится только текстом, который ничего не
проверяет.
**Второй ярус КЛАССА A (D39.159): носитель с ДВУМЯ писателями и НОЛЬ читателей.** Здесь опасность не в отсутствии
потребителя — она в том, что расхождение писателей ничем не судится, пока читателя нет, а в день,
когда читатель появится, разница СТАНЕТ семантикой, и разрешать её придётся задним числом по уже
накопленной истории. Отсутствие потребителя из симптома делается отсрочкой платежа. Живой член —
`books.chunker_version` в платформе (`PD-396`); родня по эту сторону шва — мёртвые поля шва и
`ingest.StatusReport.UnsignedBankTerms`. Отсюда правило таблицы выше — «у каждого источника РОВНО
один писатель» — читается в обе стороны: **два писателя без читателя судятся так же строго, как
проекция без потребителя, и чинятся раньше, а не когда читатель придёт.**
⚠ **ЭРРАТА 07.09 (оркестратор, акт лендинга пака «гейт вместо прозы»): ТРЕТИЙ ЧЛЕН КЛАССА A ЗАКРЫТ СО
СТОРОНЫ ДВИЖКА.** Стоп-граница теперь публикует свои предложения отдельной секцией того же сайдкара,
который экран подписи уже читает, — то есть исполнено ровно то, чего требует правило этой страницы
(«чинятся раньше, а не когда читатель придёт»), а не рефактор под несуществующий экран. Следствия для
текста ниже: клауза «на стоп-границе вид вообще не меняется» тоже стала неточной — секция едет в проекцию, не проходя
через вид (⚠ при этом правило однонаправленного потока НЕ нарушено: глоссарий не тронут, снапшот байт-равен);
фраза «читаемый банк несёт итоги БЕЗ предложений» с этого дня ЛОЖНА и читается как описание
до-паковой формы; оговорка «когда экран закажут» относится к полному ДЖОЙНУ «предложено × решено ×
нерешено», который по-прежнему живёт только внутри движка и наружу не выносится. ⛔ **Долг, названный
вслух:** у новой секции сегодня НОЛЬ читателей — платформа разбирает сайдкар аллоулистом и поле
игнорирует; носитель обязательства сделать читателя названным — платформенная половина строки **224** (⚠ испр. 08.09: первая редакция эрраты называла 253, но её половина (а) ЗАКРЫВАЕТСЯ лендингом 224, а живая (б) — другой предмет; адрес, не разрешающийся в обязательство, которое он называет, — ровно класс, которым куплено правило 1 этой страницы).
Пока она открыта, это проекция без потребителя, то есть класс A, заведённый сознательно и с адресом.
## Чего эта форма НЕ несёт
Джойн «предложено × решено × нерешено» существует только внутри движка. Читаемый банк несёт итоги без
предложений, карта — предложения без решений. Экран подписи при разморозке фронта заставит платформу
пере-реализовать движковый закон у себя, что запрещено п.6 закона шва. Лечение — публиковать
нерешённость движком, когда экран закажут; сейчас это ноль кода и строка бэклога, а не рефактор под
несуществующий экран.
## Если проектировать с нуля
То же самое, с одним отличием: дельта и список отказов — **один документ с двумя секциями**. Это
правильнее с нуля (одна запись, одна точка фиксации, невозможность указать двумя ключами на один
файл), но не стоит миграции схемы в полёте: снятие объявляемых ключей D39.158 уже закрыло тот дефект,
ради которого слияние в первую очередь понадобилось бы.