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

12 KiB
Raw Blame History

18 — Онтология банка памяти: роли носителей, писатели, свежесть

СТАТУС: РАТИФИЦИРОВАНО D39.158 (27.08.2026). Топикальный вход (D39.126): НЕ источник истины, при конфликте побеждает журнал решений. Собрано оркестратором №19 по консилиуму со сторонним архитектором при приёмке четырёх паков входной двери шва.

Зачем страница. Вокруг одного понятия — «состояние банка этой книги» — живут десять носителей, выросших пак за паком. Форма при этом СТРОГАЯ: поток однонаправленный, у каждого источника единственный писатель, вид пересобирается полностью на каждой границе прогона. Но эта строгость не была записана нигде — каждый файл документировал свою роль, ни одно место не документировало поток (D39.158 п.8).

Четыре роли, и они не смешиваются

Роль Носители Писатель Момент фиксации
ИСТОЧНИКИ — то, из чего банк собирается 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 (D39.159): носитель с ДВУМЯ писателями и НОЛЬ читателей. Здесь опасность не в отсутствии потребителя — она в том, что расхождение писателей ничем не судится, пока читателя нет, а в день, когда читатель появится, разница СТАНЕТ семантикой, и разрешать её придётся задним числом по уже накопленной истории. Отсутствие потребителя из симптома делается отсрочкой платежа. Живой член — books.chunker_version в платформе (PD-396); родня по эту сторону шва — мёртвые поля шва и ingest.StatusReport.UnsignedBankTerms. Отсюда правило таблицы выше — «у каждого источника РОВНО один писатель» — читается в обе стороны: два писателя без читателя судятся так же строго, как проекция без потребителя, и чинятся раньше, а не когда читатель придёт.

Чего эта форма НЕ несёт

Джойн «предложено × решено × нерешено» существует только внутри движка. Читаемый банк несёт итоги без предложений, карта — предложения без решений. Экран подписи при разморозке фронта заставит платформу пере-реализовать движковый закон у себя, что запрещено п.6 закона шва. Лечение — публиковать нерешённость движком, когда экран закажут; сейчас это ноль кода и строка бэклога, а не рефактор под несуществующий экран.

Если проектировать с нуля

То же самое, с одним отличием: дельта и список отказов — один документ с двумя секциями. Это правильнее с нуля (одна запись, одна точка фиксации, невозможность указать двумя ключами на один файл), но не стоит миграции схемы в полёте: снятие объявляемых ключей D39.158 уже закрыло тот дефект, ради которого слияние в первую очередь понадобилось бы.