92 lines
12 KiB
Markdown
92 lines
12 KiB
Markdown
# 18 — Онтология банка памяти: роли носителей, писатели, свежесть
|
||
|
||
> **СТАТУС: РАТИФИЦИРОВАНО D39.158 (27.08.2026).** Топикальный вход (D39.126): НЕ источник истины,
|
||
> при конфликте побеждает журнал решений. Собрано оркестратором №19 по консилиуму со сторонним
|
||
> архитектором при приёмке четырёх паков входной двери шва.
|
||
>
|
||
> **Зачем страница.** Вокруг одного понятия — «состояние банка этой книги» — живут десять носителей,
|
||
> выросших пак за паком. Форма при этом СТРОГАЯ: поток однонаправленный, у каждого источника
|
||
> единственный писатель, вид пересобирается полностью на каждой границе прогона. Но эта строгость не
|
||
> была записана нигде — каждый файл документировал свою роль, ни одно место не документировало поток.
|
||
> Из-за этого приёмка сначала прочитала девять носителей как девять заплаток и едва не заказала
|
||
> рефактор ради стройности. Страница дешевле рефактора и снимает причину, а не симптом.
|
||
|
||
## Четыре роли, и они не смешиваются
|
||
|
||
| Роль | Носители | Писатель | Момент фиксации |
|
||
|---|---|---|---|
|
||
| **ИСТОЧНИКИ** — то, из чего банк собирается | `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`), потому что это перенос базового снапшота и пере-оплата черновой волны — другое решение (щель ратифицирована, строка 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` | стоп | ПОСЛЕ карты, никогда до |
|
||
|
||
**Поток однонаправленный: источники → вид → проекции.** Отсюда главное свойство, из-за которого
|
||
рефактор не нужен: **расхождение источников с видом структурно невозможно дольше одной границы
|
||
прогона**, потому что вид не патчится, а пересобирается целиком.
|
||
|
||
⚠ **Единственная петля — авто-провод, и она названа здесь нарочно:** прогон пишет собственный ИСТОЧНИК
|
||
(`auto-bank`) и пере-сидит вид в той же границе. Это первое, куда ткнёт проверяющий однонаправленности.
|
||
Петля реальна и защищена с двух сторон — `unsignedEngineSurfaces` держит границу подписанного, а
|
||
`loadAutoBank` отказывает строке со статусом `approved`, — то есть слово движка не может присвоить себе
|
||
слово владельца. Однонаправленность формулируется точно так: **петля есть, но она не может изменить
|
||
подписанное.**
|
||
|
||
## Почему слово владельца и слово движка не сливаются
|
||
|
||
Соблазн понятный: одобрения владельца и авто-строки движка — одинаковые по форме строки банка. Но
|
||
слитые, они делают неразличимым то, ради чего банк существует: **какие переводы человек действительно
|
||
одобрил.** Поэтому источники разнесены и по писателю, и по каталогу — решения владельца едут с книгой,
|
||
состояние движка сидит при базе.
|
||
|
||
## Дисциплина проекции — норма, а не стиль
|
||
|
||
Три правила, каждое куплено дефектом:
|
||
|
||
1. **У проекции обязан быть НАЗВАННЫЙ читатель.** Машинная таблица стопа `.bank-stop.json` была
|
||
написана для пер-термного экрана подписи; экран упразднён D39.144, читателя не осталось ни в одной
|
||
зоне — снесена D39.158. Свип наследия отменённой модели шёл по коду, гейтам и текстам, а её
|
||
АРТЕФАКТ пережил его, потому что никто не смотрел на множество публикаций.
|
||
2. **У проекции обязан быть якорь свежести ВНУТРИ документа.** Отказ записи банк-экспорта — «громко,
|
||
но не фатально» (деньги дороже проекции), и это верно; но «может быть устаревшим» жило только в
|
||
ЛОГЕ. Потребитель не мог отличить проекцию этой границы от прошлой. Закрыто конвертом с меткой
|
||
границы и идентификатором прогона.
|
||
3. **Порядок между носителями — инвариант, а не деталь.** Память флажка пишется ПОСЛЕ карты: падение
|
||
между ними даёт лишний доброкачественный стоп, обратный порядок — запомненную поверхность, чьей
|
||
карты не существует, то есть молчаливую потерю навсегда. Инвариант, живущий в комментарии, не
|
||
держится ничем — держит его пин.
|
||
|
||
⚠ **КЛАСС A, названный этой страницей: проекция без контракта потребителя и без якоря свежести
|
||
в самой себе.** Два известных члена: снесённая таблица стопа · банк-экспорт до конверта. Третий живёт
|
||
строкой бэклога 224: банк-экспорт на стопе ПУСТ — проекция, наиболее пустая ровно в тот момент, когда
|
||
её читает экран подписи.
|
||
|
||
⚠ **КЛАСС B — другой, и путать их нельзя: межносительный инвариант, живущий комментарием без пина.**
|
||
Член — порядок «карта → память» до фикс3. Он НЕ подпадает под класс A: там дефект в том, что документ
|
||
не несёт контракта, здесь — в том, что связь ДВУХ носителей держится только текстом, который ничего не
|
||
проверяет. Разделено 27.08 по вычитке старшего: в одном классе они были бы неподсудны — первый же
|
||
судья отклонил бы членство порядка, и вместе с ним ушёл бы весь класс.
|
||
|
||
⚠ **Второй ярус КЛАССА A, дописан 27.08 по замечанию платформенной сессии при приёмке
|
||
`D39.159`: носитель с ДВУМЯ писателями и НОЛЬ читателей.** Здесь опасность не в отсутствии
|
||
потребителя — она в том, что расхождение писателей ничем не судится, пока читателя нет, а в день,
|
||
когда читатель появится, разница СТАНЕТ семантикой, и разрешать её придётся задним числом по уже
|
||
накопленной истории. Отсутствие потребителя из симптома делается отсрочкой платежа. Живой член —
|
||
`books.chunker_version` в платформе (`PD-396`); родня по эту сторону шва — мёртвые поля шва и
|
||
`ingest.StatusReport.UnsignedBankTerms`. Отсюда правило таблицы выше — «у каждого источника РОВНО
|
||
один писатель» — читается в обе стороны: **два писателя без читателя судятся так же строго, как
|
||
проекция без потребителя, и чинятся раньше, а не когда читатель придёт.**
|
||
|
||
## Чего эта форма НЕ несёт
|
||
|
||
Джойн «предложено × решено × нерешено» существует только внутри движка. Читаемый банк несёт итоги без
|
||
предложений, карта — предложения без решений. Экран подписи при разморозке фронта заставит платформу
|
||
пере-реализовать движковый закон у себя, что запрещено п.6 закона шва. Лечение — публиковать
|
||
нерешённость движком, когда экран закажут; сейчас это ноль кода и строка бэклога, а не рефактор под
|
||
несуществующий экран.
|
||
|
||
## Если проектировать с нуля
|
||
|
||
То же самое, с одним отличием: дельта и список отказов — **один документ с двумя секциями**. Это
|
||
правильнее с нуля (одна запись, одна точка фиксации, невозможность указать двумя ключами на один
|
||
файл), но не стоит миграции схемы в полёте: снятие объявляемых ключей D39.158 уже закрыло тот дефект,
|
||
ради которого слияние в первую очередь понадобилось бы.
|