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

Архитектура

Обзор архитектуры и основных концепций Крестьянство Среда Волнового Фронта.

Живое демо: wavefront.krestianstvo.org
Исходный код: github.com/NikolaySuslov/krestianstvo-wavefront-evaluator


Эвалюатор волнового фронта — не просто умный способ синхронизировать аватары; он глубоко укоренён в вычислительной физике и аппаратной архитектуре. Он имитирует то, как информация естественно распространяется через пространство-время.

Эвалюатор волнового фронта — это по сути «физический движок для информации». Он заменяет «линейный список» стандартного программирования законами классической механики и распространения волн.

Распространение волнового фронта. Каждая точка волнового фронта действует как источник вторичных волн. Каждый узел, получающий сообщение, становится «источником», который может генерировать новые сообщения (волны) для других узлов.

Причинность и световой конус. Каждый узел имеет локальную очередь. Сообщение может влиять только на будущее состояние. Это сохраняет причинность — эффект никогда не происходит до причины.

КонцепцияФизический эквивалентРеализация волнового фронта
ПульсУниверсальное времяСердцебиение рефлектора
Очередь узлаСостояние локальной частицыW.reduce локальный _Q
МикротикВзаимодействие частиц«Дренаж» / Цикл обратной связи
СтабильностьТепловое равновесиеКогда все очереди пусты

Формула системы:

S(t+1) = Стабильность ( Дренаж ( Пульс(t) + S(t) ) )

Где S = Состояние Вселенной, Пульс = «Энергия», инжектированная рефлектором, Дренаж = «Работа», выполняемая узлами, Стабильность = «Состояние наименьшей энергии».


От виртуальной машины к эвалюатору волнового фронта

Заголовок раздела «От виртуальной машины к эвалюатору волнового фронта»
ИзмерениеKrestianstvo VMКрестьянство Среда Волнового Фронта
Очередь сообщенийЦентрализованная — одна общая очередьДецентрализованная — каждый узел имеет свою локальную очередь
Авторитет времениЧасы VM управляют всеми узлами равномерноДвухслойное время: общий логический пульс + локальный микротик
ПричинностьОбеспечивается упорядочением очереди на уровне VMВозникает из распространения волнового фронта
Обнаружение стабильностиФлаг на уровне VMW.stable() проверяется после каждого вызова evaluate
Автономная работаТребует рефлектораЛокальные резервные часы через makeMeta.startAutonomous()

Всё время логическое — нет Date.now(), нет зависимости от настенных часов в модели. Рефлектор штампует каждый пульс:

logicalTime = lt (счётчик тиков, увеличивается на 1 за пульс)
wallTime = lt (чистый счётчик тиков — 1 логическая единица за тик)

ctx.future(delay, msg, payload) планирует msg, когда wallTime >= currentWallTime + delay:

future(1) → следующий тик рефлектора
future(0.5) → субтик: срабатывает в текущем дренажном проходе
future(0.001) → субтик: срабатывает немедленно в дренаже
future(60) → через 60 тиков

Пульс — фундаментальная единица общего времени, производимая внешним рефлектором и доставляемая всем участникам.

Волна — полный жизненный цикл вычислений, запущенных одним логическим пульсом. Волна начинается, когда пульс приходит в мир, и заканчивается, когда мир достигает стабильности.

Волновой фронт — распространяющаяся граница устоявшихся вычислений внутри волны.

Warp обрабатывает случай, когда новый общий пульс приходит с logicalTime > lastLT + 1 — участник пропустил один или несколько пульсов.

Дренаж исчерпывает все готовые записи очереди внутри микрофазы.

Мир стабилен, когда выполняются три условия:

  1. Все очереди узлов содержат только записи с fireAt > wallTime
  2. Ни один узел не находится в середине цикла обратной связи
  3. Общий исходящий ящик пуст

┌─────────────────────────────────────────────────────┐
│ Рефлектор │
│ Штампует пульс один раз. Доставляет всем. │
└────────────────────┬────────────────────────────────┘
│ pulse { lt, wallTime=lt }
┌────────────────────▼────────────────────────────────┐
│ Мета-программа │
│ Оркестрирует миры. Управляет волновым фронтом. │
│ Warp · Дренаж · Проверка стабильности · UI-синхр. │
└────────────────────┬────────────────────────────────┘
│ registerEvent / evaluate
┌────────────────────▼────────────────────────────────┐
│ Мир (ProgramState) │
│ Хостит W-узлы: Behaviors.collect + W.reduce │
└────────────────────┬────────────────────────────────┘
│ handler(state, payload, ctx)
┌────────────────────▼────────────────────────────────┐
│ W.reduce(state, pulse, nodeId, handlers) │
│ ctx: future · send · feedback · futureInf │
│ localReflector │
└─────────────────────────────────────────────────────┘

META_PROGRAM — программа Renkon, работающая выше программ мира. Для каждого пульса × мира по порядку:

  1. WARP — срабатывает только когда участник пропустил тики и предыдущий тик не устоялся
  2. MACRO — срабатывает на каждом новом пульсе
  3. DRAIN — цикл пока !world.isStable. Предохранитель: 10000 итераций
  4. Очистка исходящего ящика — одна дополнительная evaluate, если world._outbox непуст после дренажа

W — функциональное ядро каждого узла. Его функция reduce принимает (state, pulse, nodeId, handlers) и возвращает новое состояние.

const counter = Behaviors.collect(
{ count: 0, started: false },
reflector,
(state, pulse) => W.reduce(state, pulse, "counter", {
__macro: (s, p, ctx) => { ... }, // срабатывает один раз за logicalTime
newCycle: (s, p, ctx) => { ... }, // срабатывает когда приходит future
})
);

Логическое время T ──────────────────────────────────────▶
│ │ │
pulse(lt=1) pulse(lt=2) pulse(lt=3) общее, дискретное
├── субтик 0 (макрофаза)
├── субтик 0.5 (шаг Зенона)
├── субтик 0.75
├── ...
└── стабильно (все fireAt ≥ wallTime+1, глубины 0, исходящий ящик пуст)

Инварианты распределённого детерминизма

Заголовок раздела «Инварианты распределённого детерминизма»

Эти инварианты должны выполняться, чтобы два участника оставались синхронизированными:

  1. wallTime = lt — чистый счётчик логических тиков. Никакого Date.now() в модели.
  2. Канонический пульс заморожен и доставляется без изменений.
  3. Warp использует wallTime, производный от очереди.
  4. Никаких замыканий в полезных нагрузках очереди.
  5. Стабильность определяется локально.
  6. Очередной приёмник пульсов — используется {queued: true}.
  7. __macro срабатывает не более одного раза за logicalTime.

На отключении. meta.startAutonomous() запускает локальный setInterval(REFLECTOR_MS), инжектирующий пульсы. Все миры продолжают анимироваться, используя чисто логические тики.

На переподключении. Анимация возобновляется плавно. Если какой-либо мир разошёлся, warp срабатывает и воспроизводит авторитетное состояние.


РешениеОбоснование
wallTime = lt, а не Date.now()Чистый детерминизм — устойчив к джиттеру реального времени
Единый рефлектор для всех мировОдни часы, все участники
Задержки будущих событий в логических тикахНет путаницы единиц, независимость от масштаба
Граница SUBTICK_MS = 1Чистые двухуровневые часы без дополнительного механизма

npm install
npm start

Откройте браузер: http://localhost:3000 — список демо-приложений.

URL-параметры для демо-страницы: ?app=appName&k=seloID

Загрузите kwe-index.renkon в локально/удалённо запущенный экземпляр Renkon Pad. Эвалюатор работает непосредственно в Renkon Pad без шага сборки.