Перейти к основному содержимому

Часть II. Объекты формата

4. Φ — лог событий как единственный источник истины

Φ (phi) — это упорядоченная по времени последовательность эффектов, каждый из которых достиг состояния confirmed. Она одна содержит всё изменение мира приложения.

Каждый эффект — это запись вида:

  • α — вид изменения: create, replace, remove, transition, commit
  • entity — тип сущности, которую эффект затрагивает
  • fields — полезная нагрузка (значения полей)
  • context — метаданные: кто инициировал, к какой сессии относится, какая степень необратимости (см. 23), ссылки на другие эффекты

Мир не хранится отдельно. Состояние любой сущности в любой момент — результат fold(Φ) (см. 11), применённого к эффектам, видимым к этому моменту. Это свойство даёт три следствия, которые проходят через весь формат:

  1. Audit trail бесплатный: каждое изменение в мире имеет свидетеля в Φ. Нет in-place мутаций, которые обошли бы журнал.
  2. Rebuild from scratch — первоклассная операция. Тесты, дебаг, миграция — всё это частные случаи перевычисления мира от Φ.
  3. Причинность сохраняется: rejected эффекты тоже остаются в журнале (в отдельной зоне), чтобы можно было понять, что именно было отвергнуто и почему.

Жизненный цикл эффекта: proposed → { confirmed | rejected }. Переход — отдельный шаг валидации, в котором проверяются инварианты онтологии, препятствия типа irreversibility и условия намерения. Confirmed эффекты попадают в Φ и становятся частью мира; rejected — не попадают, но сохраняются отдельно.

5. Δ — черновики, session-scoped namespace

Δ (delta) — это пространство черновиков: эффектов, инициированных, но не достигших статуса confirmed. Черновики видны только инициатору и живут до момента commit, cancel или истечения сессии.

Структурная функция Δ в формате — позволить автору намерения накапливать состояние до решения его зафиксировать. Форма-wizard с четырьмя шагами — череда черновиков, где каждый шаг добавляет поля; финальный шаг превращает accumulated draft в confirmed effect. До этого момента ни один другой viewer не видит промежуточное состояние.

Промоция Δ → Φ происходит атомарно при подтверждении намерения. Rejected черновики уничтожаются (не становятся частью Φ, не остаются в rejected-зоне — это чистый рабочий процесс автора, не свидетельство в мире).

Множественные черновики одного инициатора могут существовать параллельно: пользователь может работать одновременно над несколькими намерениями, и черновики не мешают друг другу, потому что каждый привязан к session-context внутри инициатора.

6. Intent — конструктивные частицы

Intent — это декларативное описание возможности изменить мир, которая может быть предложена viewer'у.

Намерение — не функция и не handler. Оно — запись формата:

  • id — стабильный идентификатор
  • ownerRole — какая роль авторизована его инициировать
  • requiredFields — какие поля должны быть заполнены до подтверждения
  • conditions — предикаты над миром, которые должны выполняться
  • effects — список эффектов, которые будут эмитены при подтверждении

Пять первичных видов намерений (α / β / χ / τ / ω), соответствующих пяти видам эффектов: создание, замена, удаление, переход состояния, commit workflow. Шестой вид — системные намерения: schedule_timer, revoke_timer — конструкты темпорального слоя (см. 8.5).

Generic effect handler формата механически применяет объявленные effects к Φ. Это свойство — ключевое: намерения не несут императивный код. Domain-автор описывает, что должно произойти; движок гарантирует, как это произойдёт.

Намерение не знает о пользовательском интерфейсе; интерфейс не знает о намерении напрямую — только через проекцию, которая связывает намерения в логически связный вид. Это разделение делает намерения переиспользуемыми между рендерами: одно и то же create_appointment показывается в pixel-форме, voice-диалоге, agent-API schema и document-варианте без модификации.

7. Effect — атомы изменения мира

Эффект — квант изменения: минимальная единица, которая может быть записана в Φ. Каждый эффект порождается намерением и подчиняется формату:

{ α, entity, fields, context }

Поле α принимает одно из пяти значений:

  • create — добавить новую сущность
  • replace — заменить поля существующей сущности
  • remove — удалить сущность (с ограничением irreversibility)
  • transition — изменить состояние workflow'а
  • commit — зафиксировать завершение сложной частицы (wizard, batch)

Поле context несёт метаданные, важные для валидации и интерпретации:

  • __irr: { point, at, reason } — степень необратимости: point = "high" блокирует последующие remove после at
  • ссылки на инициирующее намерение, инициатора, session-id
  • external refs — если эффект отражает вовне-мировое событие (платёж, сообщение в мессенджер)

Честная граница (particle uniformity): generic effect handler формата покрывает большинство намерений, но не все. Domain-автор может поставить custom effect builder для доменно-специфичных инвариантов (например, real-time mirror в messenger или cascade cleanup в workflow). Это свойство реализации, не формата: формат гарантирует, что эффекты всегда имеют форму {α, entity, fields, context} — а путь их порождения может быть generic или custom.

8. Ontology — тип данных домена

Онтология — центральный объект формата. Она определяет, что такое «домен»: какие сущности существуют, какие роли ими манипулируют, какие инварианты должны выполняться, какие правила автоматики движок исполняет.

8.1 Entities

Сущности — типы данных домена. Каждая имеет:

  • fields — типизированные поля с read/write matrix по ролям
  • ownerField — поле, указывающее single-owner (foreign key на роль)
  • kind — таксономический маркер:
    • internal (implicit default) — обычная сущность, принадлежит одному viewer'у
    • reference — справочная сущность без owner'а (видна всем с правильным role.visibleFields)
    • assignment — bridge-сущность для m2m-связей через role.scope

Приоритет row-filter: role.scope > entity.kind:"reference" > entity.ownerField > none.

8.2 Roles и base-таксономия

Роли — это viewer-типы. Каждая роль имеет:

  • base — семантическая таксономия: owner | viewer | agent | observer | admin
  • visibleFields — какие поля каждой сущности она видит
  • canExecute — какие намерения она может инициировать
  • scope — декларативное m2m-присоединение через bridge-сущность:
role.advisor.scope.Portfolio = {
via: "Assignment", // bridge
viewerField: "advisorId", // поле в bridge, сопоставляемое с viewer
joinField: "portfolioId", // поле в bridge, ссылающееся на target
localField: "id" // поле в target, сопоставляемое с joinField
}

Base-таксономия не заменяет доменные имена; она даёт cross-domain инструментам (SDK defaults, авторские линтеры, тесты) возможность узнавать структурный паттерн: «все agent-роли обязаны иметь preapproval», «observer-роли не могут эмитить α-эффекты», «admin-роли видят все записи независимо от ownerField (row-override в filterWorldForRole)».

Базы устроены как открытое множество прецедентов, не closed enum: пятый класс admin появился post-v2.0 после стресс-теста spec-v0.1 на library-домене (librarian не вписался в существующие четыре). Конформная реализация MUST принимать любую строку в role.base; нормативную семантику задают только перечисленные классы.

8.3 Invariants — ∀-свойства

Инварианты — декларативные предикаты, которые должны выполняться для состояния мира всегда. Шесть видов:

  • role-capability — какие роли могут инициировать какие намерения (observer не может replace)
  • referential — referential integrity (foreign keys, ссылочная целостность)
  • transition — допустимые переходы workflow (state machine)
  • cardinality — N-to-M кардинальности (Portfolio имеет ровно один риск-профиль), composite groupBy поддерживается
  • aggregate — свойства агрегатов (sum(portfolio.positions.weight) = 1.0)
  • expression — row-level predicate с доступом к world / viewer / context: авторская функция или строковое JS-выражение; служит для cross-entity предикатов (SoD: approver≠preparer через lookup в world.approvals), dynamic-threshold (нужное число подписей зависит от row.amount) и viewer-aware блокировок (auditor не мутирует). Добавлен после 13-го полевого теста (compliance/SOX ICFR); predicate — trusted authored code, не пользовательский input.

Инварианты проверяются при каждом confirm effect. Нарушение блокирует эффект и каскадно отклоняет зависимые — то есть инвариант не «проверяется позже», а формирует барьер между proposed и confirmed.

8.4 Rules — Reactive Rules Engine

Правила — декларативные event-condition-action автоматы. Каждое правило имеет триггер (событие в Φ), условие (предикат над миром), действие (список эффектов).

Четыре расширения базовой event→action модели:

  • aggregation: счётчик per-user, срабатывает на каждое N-е событие
  • threshold: предикат над последними N записями (lookback window)
  • schedule: темпоральный триггер — частный случай 8.5
  • condition: JS-выражение (whitelisted Math), evaluator для сложных предикатов

Состояние правил (rule_state: counter, last_fired_at) хранится per (rule, user).

8.5 Scheduler — темпоральный слой

Расписание — частный случай rule. Декларация:

rule.schedule = { after: <duration> }
| { at: <ISO timestamp> }
| { after: ..., revokeOn: <effect patterns> }

Движок поддерживает priority-queue таймеров. Таймеры — обычные эффекты (τ=scheduled_timer) в Φ, не отдельный state: hydration из мира при рестарте происходит автоматически. Revoke — удаление таймера по id, эмитируется системным намерением.

Системные намерения темпорального слоя:

  • schedule_timer(afterMs | atISO, target, revokeOn?) — создать таймер
  • revoke_timer(timerId) — отменить

Любое доменное правило со schedule разворачивается во внутренний schedule_timer при fire'е, с автоматическим self-rescheduling при повторяемости.

8.6 Field roles — семантические типы

Поле сущности имеет тип (string, number, enum, ...) и, опционально, семантическую роль:

  • pure-data: money, percentage, trend, ticker
  • spatial: coordinate, address, zone
  • temporal: datetime, duration

Семантические роли — advisory hints для читателей формата. Pixel-материализатор консультируется с adapter capability surface: если адаптер поддерживает нативный рендер money (форматирование с валютой, выравнивание), он использует его; если нет — fallback на text.

Честная граница: нативный рендер семантических ролей зависит от адаптера. Некоторые адаптеры реализуют fallback тонко, другие — грубо. Формат гарантирует, что роль будет prosledeна в артефакт; качество рендера — свойство читателя.

9. Projection — авторский контракт

Projection — декларация автора о том, какие намерения и сущности образуют один «экран», «диалог», «страницу». Она содержит:

  • список намерений, которые должны быть доступны в этой проекции
  • предпочтительный архетип (catalog, detail, form, feed, canvas, dashboard, wizard) или auto
  • preference по паттернам Pattern Bank'а: patterns: { enabled: [...], disabled: [...] }
  • опциональный slot-override для конкретных мест в артефакте

Projection — это input для кристаллизации; artifact — output. Автор влияет на результат через два механизма:

  • Projection.patterns — preference, модификатор входа. Артефакт остаётся перегенерируемым из (intents, ontology, projection, patterns, features): тот же вход → тот же выход.
  • Slot-override (через mergeProjections) — freezing output. Автор фиксирует конкретный слот, bypass'а кристаллизацию для этой части. Потеря: артефакт больше не чистая функция от входа.

Разница принципиальная. Preference сохраняет инвариант «артефакт = f(input)»; slot-override жертвует им ради локального контроля. Рекомендация формата: preference first, slot-override только когда preference принципиально не выражает нужное поведение.

10. Artifact — кристаллизованный результат

Артефакт v2 — это тип данных, не результат рендеринга.

Структура артефакта:

  • archetype — один из семи: feed, catalog, detail, form, canvas, dashboard, wizard
  • slots — именованные контейнеры содержимого (header, body, footer, toolbar, sidebar, ...)
  • witnesses — structured findings о свойствах артефакта, см. ниже
  • shape — деривационный слой над архетипом (timeline, directory, default)
  • pattern annotations — матченные паттерны Pattern Bank'а с basispattern-bank

Witnesses — свидетельства свойств артефакта. Каждый witness — запись вида:

{ basis, reliability, pattern?, requirements?, ... }

Три основных basis:

  • heuristic — вывод через эвристику, например inferFieldRole определяющую семантическую роль поля. reliability: "heuristic", требует promotion через анкеринг для продвижения в надёжное знание.
  • pattern-bank — formal match паттерна банка. reliability: "rule-based": trigger и structure/apply — декларативные функции, результат детерминированный.
  • anchored — constructive proof через witness-of-proof (частица 15 field-теста). Самый сильный класс; anchoring promotion writer — открытая epistemic задача.

Артефакт не рендерится напрямую. Его читают разные материализации (часть IV): pixel-рендерер собирает DOM, voice-материализатор строит speech-script, agent-API сериализует в JSON-schema, document-генератор строит HTML-граф. Все четыре читают один и тот же артефакт.

Семь структурных архетипов описывают скелет артефакта (какие слоты есть, как они организованы); пять behavioral паттернов (monitoring, triage, execution, exploration, configuration) — перпендикулярны архетипу и описывают поведение (что делают viewer'ы на этой проекции). Signal Classifier выводит behavioral pattern из группы намерений через взвешенный scoring; rendering strategy определяет itemLayout, emphasisFields, preferControl.

Артефакт — компактное, сериализуемое, машинно-читаемое описание проекции. Это делает возможным сравнение артефактов (diff для code review), перегенерацию (rebuild from input), кеширование (content-addressable storage) и audit (stable reference для инвариантов).