O.G.A.S. English

Форматы файлов

Форматы файлов платформы: программа, пульт, память, контрольная точка, настройки, манифест модуля, экспорт, витрина и другие — что в каждом поле и кто файл пишет.

Введение

Документ описывает файлы, которые пишет платформа, и их содержимое. Назначение документов изложено в описаниях частей: граф — Программа: граф и запуски, модули — Модули, пульт — Мастерская, раздел 6, настройки — Настройки, папка данных целиком — Устройство платформы, 3.8.

1 Общие правила

2 Идентификаторы

Таблица 1 — Идентификаторы

Идентификатор Что обозначает
function_id функция платформы из реестра
module_id модуль; совпадает с именем папки modules/<module_id>/: [a-z0-9][a-z0-9_-]{0,63} — строчные латинские буквы, цифры, _ и -, первый знак — буква или цифра; runtime — папка общего кода модулей, а не модуль. Другой module_id функция модулей отклоняет, не читая файлов
process_id рабочий процесс, [a-z0-9-]{1,64} (Программа: граф и запуски, раздел 1)
node_id, edge_id, group_id, port_id части графа
object_id сквозной объект
surface_id имя вида, которое функция объявила для диагностики
run_id логический прогон: местные дата и время его начала, 2026-10-08_07-29-12, при совпадении — -2, -3; единственный среди прогонов всех процессов. Имя папок прогона runs/<run_id>/ и results/<run_id>/ в папке процесса он даёт, только если состоит из латинских букв, цифр, - и _ и не длиннее 128 знаков; другой run_id остаётся лишь в общем журнале
attempt_id попытка прогона; после сбоя новая, run_id прежний
operation_id логический шаг узла: прогон + узел + packet_id + итерация. Повтор той же итерации сохраняет его, новая итерация цикла — новый
execution_id конкретный вызов модуля; у повтора новый
packet_id логический пакет; при разветвлении один на всех получателей. Пакет внутри рамки, в которую он вошёл из круга другой рамки, носит прежний packet_id и номер того круга через «/» (Программа: граф и запуски, раздел 11)
delivery_id конкретная доставка пакета одному получателю
artifact_handle файл результата прогона: его имя в results/<run_id>/, без / и \, не начинается с точки
command_id стабильный ключ изменяющей команды при повторной доставке (Обмен с ядром, раздел 3)
process_handle конкретный OS-процесс модуля; смысл знает функция модулей
event_id монотонный номер события ядра
trace_id связь всех записей одного действия человека
problem_id проблема в списке функции observe

3 Реестр функций

Сведения о функции содержатся в двух файлах. Реестр экземпляра определяет размещение её программы, включение и выданные права. Сама функция в своей папке описывает свои свойства: зависимости, версию договора, работу с окном и перезапуск (правило 2.10). Ядро читает оба файла и соединяет их по id.

Файл реестра: data/functions.json. Формат: ogas.functions/2.

{
  "format": "ogas.functions/2",
  "cli": {
    "run": {
      "args": {
        "process": { "required": true },
        "text": { "required": false, "default": "hello from O.G.A.S." }
      },
      "before": [
        { "method": "process.program.on", "params": { "command_id": "cli-run-on", "process_id": "$process" } }
      ],
      "method": "process.event.fire",
      "params": {
        "command_id": "cli-run",
        "process_id": "$process",
        "data": { "text": "$text" }
      },
      "wait": {
        "method": "process.run.status",
        "params": { "run_id": "$run_id" },
        "field": "status",
        "success": ["completed"],
        "failure": ["failed", "cancelled", "stopped", "interrupted", "unknown"]
      }
    },
    "install": {
      "args": { "process": { "required": true } },
      "method": "module.install",
      "params": { "process_id": "$process" }
    }
  },
  "functions": [
    {
      "id": "settings",
      "path": "bin/ogas-settings",
      "enabled": true
    }
  ]
}

cli — необязательные глаголы командной строки, кроме глаголов ядра (start, ui, doctor), в виде { "<глагол>": описание } (Устройство платформы, раздел 5):

Глагол с именем глагола ядра, имя глагола или аргумента, не отвечающее этим требованиям, необязательный аргумент без умолчания, вызов без method, подстановка без аргумента и опрос wait у глагола, которому нужна мастерская, делают реестр недействительным (function_registry_invalid): ядро отказывает всем глаголам реестра и работает без функций (Устройство платформы, 3.4.1).

Записка повторного запуска — run/launch.json в папке данных, ogas.launch/1: { "format", "verb", "args": { "<имя>": "<значение>" }, "asked_ms" }. Её оставляет запуск глаголом, которому нужна мастерская, когда экземпляр уже работает, и читает разбуженный экземпляр (Устройство платформы, 3.6.3). asked_ms — время просьбы в миллисекундах от начала эпохи. Файл доступен только пользователю, записывается целиком и удаляется при чтении.

Запись функции в реестре — только решения экземпляра:

Таблица 2 — Поля записи функции в реестре

Поле Тип Умолчание Смысл
id string — id функции; её папка — functions/<id>/
path string — исполняемый файл относительно папки установки
enabled bool — запускать ли
capabilities string[] пусто права, которые handshake может запросить

Состояние функций во время работы в этот файл не входит.

Описание функции — файл functions/<id>/function.json в папке установки, формат ogas.function/1. Его пишет автор функции вместе с её кодом; в поставку описание входит вместе с функцией.

{
  "format": "ogas.function/1",
  "id": "ui",
  "requires": ["settings", "i18n", "graph", "modules", "canvas", "observe"],
  "optional": ["graph", "modules", "canvas", "observe"],
  "platform": { "min": 1, "max": 1 },
  "contract": 1,
  "restart": false,
  "interactive": true
}

Таблица 3 — Поля описания функции

Поле Тип Умолчание Смысл
format string — ogas.function/1
id string — та же функция, что в реестре; другое id — описание чужое
requires string[] пусто функции, договором которых пользуется данная
optional string[] пусто те из requires, без которых функция работает: запуск их не ожидает, отказ их её не останавливает
platform.min / max u32 1 поддерживаемые версии платформы
contract u32 — версия контракта
restart bool true перезапускать ли после выхода
interactive bool false нужна мастерская
checks object[] пусто проверки среды для ogas-core doctor

Функция ui описывает себя с interactive: true и restart: false; списка идентификаторов функций в ядре нет. Смысл полей — Устройство платформы, 3.4.1.

checks — проверки среды, которые функция объявляет для ogas-core doctor (Устройство платформы, раздел 5). Каждая — { "id", <вид> } из закрытого набора видов, которые умеет выполнять ядро:

id состоит из строчных латинских букв, цифр и _ и не повторяется в описании; у проверки ровно один вид. Иначе описание недействительно. Что означает итог, функция говорит в своём словаре ключами <id функции>.check.<id>.passed и <id функции>.check.<id>.failed на русском и английском языках.

"checks": [
  { "id": "wsl_interop", "file": ["/proc/sys/fs/binfmt_misc/WSLInterop", "/proc/sys/fs/binfmt_misc/WSLInterop-late"] },
  { "id": "window", "file": ["bin/ogas-window.exe", "functions/ui/window/target/x86_64-pc-windows-msvc/release/ogas-window.exe"] }
]

Если описание отсутствует, не является JSON, имеет другой формат или другое id, ядро функцию не запускает, так как не знает её требований и договора. Запуск отказывает с function_description_invalid и называет файл, остальные функции работают, а зависимые от неё остаются без неё, как без любой недоступной. Реестр другого формата ядро не читает, а называет его версию: молча выбросить из него, например, restart: false значило бы поменять поведение экземпляра без слова.

4 Манифест модуля

Файл: modules/<module_id>/manifest.json. Формат: ogas.module/1.

{
  "format": "ogas.module/1",
  "id": "echo",
  "version": "1.0.0",
  "name_key": "module.echo.name",
  "description_key": "module.echo.description",
  "runtime": "python",
  "entrypoint": "main.py",
  "inputs": [
    { "name": "input", "required": true, "type": "text" }
  ],
  "outputs": [
    { "name": "success", "type": "text" }
  ],
  "input_policy": "all",
  "parallelism": 1,
  "process": "step",
  "resources": { "gpu_mb": 0 },
  "suspend": false,
  "execution_semantics": "idempotent",
  "retry": { "max_attempts": 1, "delay_ms": 0, "exponential": false },
  "parameters": {
    "suffix": { "type": "string", "default": "" }
  },
  "permissions_info": { "network": false, "filesystem": "module-and-run-only" },
  "timeout_ms": 10000
}

Таблица 4 — Манифест модуля

Поле Тип Обязательно
format "ogas.module/1" да
id string да
version string да
name_key string да
description_key string нет
runtime "python" | "native" да
entrypoint string относительно папки модуля да
inputs / outputs массив портов да, может быть пустым для outputs
input_policy all | any да
parallelism целое ≥ 1 да
process step | long | service да
resources.gpu_mb целое ≥ 0: сколько видеопамяти нужно поднятому модулю нет, по умолчанию 0
suspend bool: умеет ли модуль сохранить промежуточное состояние перед выгрузкой и продолжить с него нет, по умолчанию false
execution_semantics idempotent | non_idempotent | unknown да
retry.max_attempts целое ≥ 1 да
retry.delay_ms целое ≥ 0 да
retry.exponential bool нет
timeout_ms целое ≥ 1 да
parameters объект: имя параметра → { type, default?, min?, max?, choices? }, у нейросети — { type: "model", kind, default? } нет
permissions_info { network, filesystem } нет
role assistant_network — модуль служит сетью помощника мастерской: вход request, выход reply нет
secrets имена секретов, которые модуль читает из .env своей папки: заглавные буквы, цифры и _; окно спрашивает их у человека нет
runtime_python string, например ">=3.11" нет

Порт: name, type — имя вида данных из таблицы 11 (16.1), required. У входа может быть join_key — путь через точку. Входы и выходы манифеста — это порты узла на графе: рёбра соединяют их по имени, а имя выхода модуль называет в поле port ответа (Методы модулей, раздел 1).

Параметр:

Поля models — списка нейросетей, которые модуль берёт всегда, — у манифеста нет: нейросеть берут параметром, и выбирает её узел. Что такое параметр и где его тексты — Модули, раздел 10.

Тексты в манифесте отсутствуют: название, пояснение и подсказки хранятся в словарях модуля.

permissions_info — только сведения для человека: системные вызовы по ним не ограничиваются.

5 Рабочий процесс

Папка data/processes/<process_id>/ — всё, что относится к процессу: process.json, workspace.json, settings.json, state.json, запомненные списки kept/<id переменной>/, modules.lock.json, generation.json, память узлов state/<имя>/, рисунки пульта и виды его элементов pulpit/, файлы человека inputs/, файлы постоянных и переменных files/ (16.3), прогоны runs/<run_id>/, их результаты results/<run_id>/ и окружение .venv. Кто чем владеет — Программа: граф и запуски, раздел 1.

5.1 process.json — ogas.process/4

{
  "format": "ogas.process/4",
  "generation": 1,
  "id": "chat",
  "name": "Chat",
  "description": "",
  "variables": [
    { "id": "history", "type": "list", "initial": [], "remember": true },
    { "id": "style", "type": "text", "initial": "watercolor", "remember": true }
  ],
  "nodes": [
    {
      "id": "send",
      "kind": "event",
      "x": 40, "y": 80,
      "parameters": { "source": "pult", "overlap": "queue" }
    },
    {
      "id": "reply",
      "kind": "module",
      "module_id": "llm",
      "x": 240, "y": 80,
      "parameters": { "temperature": { "variable": "temperature" } }
    },
    {
      "id": "remember_reply",
      "kind": "write",
      "x": 440, "y": 80,
      "parameters": { "variable": "history", "mode": "append" }
    },
    {
      "id": "history_now",
      "kind": "variable",
      "x": 240, "y": 200,
      "parameters": { "variable": "history" }
    },
    {
      "id": "retry_image",
      "kind": "repeat",
      "x": 240, "y": 320,
      "parameters": { "max_iterations": 3, "max_loop_ms": 600000 }
    },
    {
      "id": "draw",
      "kind": "module",
      "module_id": "image_gen",
      "region": "retry_image",
      "x": 280, "y": 360
    }
  ],
  "edges": [
    {
      "id": "e1",
      "source_node": "send",
      "source_port": "event",
      "target_node": "reply",
      "target_port": "input",
      "parts": null,
      "join_key": null
    },
    {
      "id": "e2",
      "source_node": "history_now",
      "source_port": "value",
      "target_node": "reply",
      "target_port": "history"
    }
  ],
  "groups": []
}

Группа:

{
  "group_id": "g1",
  "name": "Зажигание",
  "node_ids": ["reply"],
  "group_id_parent": null,
  "x": 120.0,
  "y": 40.0,
  "collapsed": true,
  "ports_in": [{ "node_id": "reply", "port": "input", "name": "Картинка" }],
  "ports_out": [{ "node_id": "reply", "port": "success", "name": "Готово" }],
  "variables": ["style"]
}

5.2 state.json — ogas.state/2 и запомненные списки

Значения переменных с отметкой remember, хозяин — функция графа. Читаются при включении программы и попадают на диск при каждой записи такой переменной:

{
  "format": "ogas.state/2",
  "values": { "style": "watercolor" },
  "lists": { "history": 3 }
}

Значение переменной, которой больше нет в process.json или тип которой не совпадает, при включении не берётся: переменная получает initial. Переменная, переименованная после последней записи, находит своё значение под прежним именем — по записи renamed_objects документа процесса; следующая её запись кладёт значение уже под новым, а список — целиком в папку нового имени. state.json и kept/ принадлежат человеку, который работает с программой: в экспорт процесса они не входят.

5.3 Память узла

state/<имя>/ — память узла: то, что модуль узла сохраняет перед выгрузкой (Модули, раздел 4). Память принадлежит узлу, а не модулю: модуль один на все свои узлы. Имя — идентификатор узла или имя общей памяти из поля memory узла, которую называют несколько узлов одного модуля. Что в ней, решает модуль; путь к ней он получает с каждым шагом узла в поле state_dir. Платформа её не читает, переносит в экспорт, только если человек попросил (10.1), и удаляет, когда её не называет ни один узел.

Рядом с папкой лежит отметка о сохранённой памяти state/<имя>.saved.json — ogas.module-state/1: она называет модуль, который сохранил память. Её пишет функция модулей, а не модуль: целиком, после того как модуль ответил, что сохранил память, и убирает перед тем, как попросить его сохраниться снова. Имя папки — латинские буквы, цифры, - и _; у узла с другим идентификатором и без memory памяти нет.

{
  "format": "ogas.module-state/1",
  "module_id": "painter",
  "version": "1.0.0",
  "digest": "sha256:…",
  "saved_at": "2026-10-07T17:30:00Z"
}

version и digest — версия и отпечаток модуля, сохранившего состояние (Модули, раздел 3). Модуль, поднятый с теми же идентификатором, версией и отпечатком, получает resumed: true; без отметки или при расхождении — resumed: false, даже если папка не пуста.

6 Сквозной объект

Сквозные объекты не хранятся отдельным списком: их задают узлы и переменные графа (Программа: граф и запуски, раздел 16).

Таблица 5 — Сквозной объект

object_id Откуда берётся
event:<node_id>, cancel:<node_id>, retry:<node_id>, status:<node_id> узел event с source: pult
var:<variable_id> переменная из variables
ask:<node_id> узел ask
program сама программа

Пульт хранит только object_id в своих привязках (раздел 7).

7 Пульт

workspace.json — ogas.workspace/3: граф интерфейса программы (Мастерская, 6.8). Владелец — функция canvas, смысл объектов — в process.json.

{
  "format": "ogas.workspace/3",
  "generation": 8,
  "process_id": "comic",
  "pulpit_id": "main",
  "theme": { "accent": "#c8892b" },
  "bindings": { "open": "var:screen" },
  "groups": [
    { "id": "window_1", "name": "Комикс", "holds": "tabs" },
    { "id": "tab_1", "name": "Рисовать", "parent": "window_1" },
    { "id": "tab_2", "name": "Галерея", "parent": "window_1", "bindings": { "shown": "var:has_frames" } },
    { "id": "group_1", "name": "Сцена", "parent": "tab_1" }
  ],
  "elements": [
    { "id": "field_1", "kind": "field", "group": "group_1", "bindings": { "value": "var:scenario" },
      "label": "Сценарий", "parameters": { "lines": 6 } },
    { "id": "file_1", "kind": "file", "group": "group_1", "bindings": { "value": "var:hero" },
      "label": "Герой", "parameters": { "kind": "image" } },
    { "id": "button_1", "kind": "button", "group": "group_1",
      "bindings": { "act": "event:draw", "carries": { "scenario": "var:scenario", "hero": "var:hero" }, "opens": "tab_2" },
      "label": "Нарисовать" },
    { "id": "view_1", "kind": "view", "group": "tab_2", "bindings": { "value": "show:comic" } }
  ]
}

Таблица 6 — Первый набор элементов пульта

kind Элемент Род Привязки Параметры
blank пустой элемент — holds — что держит: любой объект программы — событие, вопрос, «Показать», выход, вход, связь, ход шага, переменная. Пустой элемент — графический узел, вид которого ещё не выбран: функция пульта пишет ему placed: false, на лист он не ложится, а canvas.snapshot помечает его no_kind, пока он к чему-то привязан (Мастерская, 6.8) —
button кнопка действие act — событие, его остановка или повтор, или сигнал, которого ждёт узел (signal:<node_id>); carries — необязательные переменные, значения которых кнопка несёт событию, каждая под именем поля пакета (Программа: граф и запуски, раздел 5); допустима только у кнопки события и сигнала: сигналу они уходят его данными; opens — необязательное вместилище этого же графа: кнопка открывает вкладку или окно, а при act ещё и нажимает событие; resets — необязательное вместилище этого же графа: кнопка возвращает к начальному значению каждую переменную, которую пишут элементы ввода в нём на любой глубине (process.variable.reset), — так у настроек есть «Вернуть как было». Кнопка называет хотя бы одну из act, opens, resets —
toggle выключатель ввод value — переменная типа boolean или включение программы —
rows строки ввод value — переменная типа list: человек правит её строками — меняет клетку, добавляет строку под последней и убирает строку; поля записи — столбцами, у списка не из записей — один столбец. Клетка берёт то, что держит её столбец в первой строке, где он задан: «да» или «нет» — выключателем, число — числом, текст — строкой; столбец, которого нет ни в одной строке, — строкой; иное показано по правилам показа (16.5) и здесь не правится. Добавленная строка — запись из столбцов, каждый пустой своего вида: пустая строка, «нет»; число не ставится, пока его не набрали. Переменная получает весь список, когда набор клетки закончен, строка добавлена или убрана fields — список полей, которые видны столбцами, по порядку; пусто — поля, которые есть в записях, в порядке появления; titles — слова над столбцами, по порядку; пустая строка или её нехватка — имя поля; lines — сколько строк текста видно в ячейке, целое от 1 до 12, по умолчанию 1: больше одной — ячейка многострочная, и Enter переводит строку
field поле ввод value — переменная типа text, time, json или list; время выбирают выбором даты и времени системы, значение json и list набирают текстом JSON lines — сколько строк видно, целое от 1 до 40, по умолчанию 1; больше одной — поле многострочное; writes — когда поле пишет переменную: done — когда набор закончен, по Enter или уходу из поля, по умолчанию; typing — ещё и на каждой паузе в наборе, только у текста: данные, набранные наполовину, значением не стали
file файл ввод value — переменная картинки, звука, видео, файла или json: выбранный файл ложится в файлы процесса, а переменная получает ссылку на него (Программа: граф и запуски, раздел 24) kind — вид файла: image, audio, video или file (по умолчанию)
number число ввод value — переменная типа number min, max, step — необязательные числа
choice выбор ввод value — переменная типа text options — список значений; пока он пуст, выбирать не из чего; titles — слова, которыми значения показаны человеку, по порядку; пустая строка или её нехватка — само значение: так переменная держит код параметра модуля, а человек видит слово; models — вид нейросетей: тогда выбирают из нейросетей этого вида в библиотеке, и options не нужен
ask вопрос ввод question — вопрос человеку; ответ — того вида, какой просит узел вопроса: текст, число, выбор, да или нет, область, точки или закрашенное кистью на картинке вопроса, файл своего вида (Программа: граф и запуски, раздел 9) —
value значение показ value — переменная любого типа, выход узла (out:<node_id>/<выход>), вход узла (in:<node_id>/<вход>) или связь (edge:<edge_id>) —
view просмотр показ value — узел «Показать» (show:<node_id>), выход узла (out:<node_id>/<выход>), вход узла, связь или переменная: показывает так же, как узел «Показать» на холсте — текст, число, список, картинку, галерею, проигрыватель звука и видео (16.5) —
table таблица показ value — переменная типа list, узел «Показать», выход узла, вход узла или связь: записи списка строками, поля столбцами, ячейка — по правилам показа (16.5), картинка — картинкой; picked — необязательная переменная, в которую щелчок по строке пишет её ключ; выбранная строка — та, чей ключ равен значению переменной; act — необязательное событие: щелчок по строке после выбора нажимает его, как кнопка, у выключенной программы только выбирает; carries — как у кнопки, допустима только при act; переменная выбора в нём уже держит ключ этой строки; only — необязательная переменная: видны только записи, у которых поле by равно её значению, а пока она пуста — ни одной. Длинный список стоит частями по 200 строк: следующая часть приходит, когда человек прокрутил таблицу к концу нарисованного, или по кнопке «Показать ещё» с числом оставшихся (лента из тысяч снимков, нарисованная целиком, задерживает каждую перерисовку окна на 0,7 с) fields — список полей, которые видны столбцами, по порядку; пусто — все поля первой записи; titles — слова над столбцами, по порядку; пустая строка или её нехватка — имя поля (проверка пульта пустую строку принимает только здесь, в fields — нет); sort — поле, по которому строки стоят по порядку: числа по величине, остальное как текст, запись без поля — после остальных; пусто — в порядке списка, а сам список порядка не меняет; order — up по возрастанию или down по убыванию, по умолчанию up; key — поле записи, которое пишется в picked; пусто — вся запись; pick — one: щелчок выбирает одну строку, по умолчанию; many: у каждой строки метка, щелчок отмечает строку или снимает отметку, picked держит список ключей отмеченных строк, а событие щелчок не нажимает; by — поле записи, которое сравнивают со значением only; lines — one: ячейка в одну строку, длинное обрезается, по умолчанию; all: текст читается целиком, ячейка растёт; follow — no: таблица стоит, где её оставили, по умолчанию; end: новая строка внизу сама уходит в вид, как реплика разговора
bar полоса показ value — переменная типа number или ход шага узла модуля (progress:<node_id>): доля от нуля до целого min, max — границы полосы для переменной; по умолчанию 0 и 100
indicator индикатор показ state — состояние прогона события shows — color (по умолчанию) или words: состояние цветом или словами
label надпись украшение — text — текст надписи, необязательный: без него надпись называет себя; size — необязательная высота букв в единицах листа; align — left (по умолчанию), center или right
picture рисунок украшение — image — необязательное имя файла рисунка (7.2): без него на листе пустое место; fit — contain (по умолчанию), cover или stretch: рисунок целиком, во всю площадь или растянут

Привязка, не названная необязательной, обязательна. Набор пополняет платформа: новый вид элемента формат не меняет. Рамки в наборе нет: собрать элементы вместе — дело группы.

Что функция пульта отклоняет (canvas_invalid, с названием элемента или вместилища и поля): документ без вместилищ; повторяющийся id; parent или group, которых нет; вместилище, лежащее само в себе прямо или через другие; holds вне перечня; привязку вместилища, кроме shown и open, open у вместилища без вкладок и привязку вместилища не к переменной; opens, который называет не вместилище; kind вне набора; привязку, которой нет у вида элемента, отсутствие обязательной привязки, несколько объектов там, где объект один, и наоборот; opens или resets, которые называют не вместилище этого пульта; параметр, которого нет у вида элемента, или его значение вне допустимого; пустую hint; place и size у того, что лежит не на странице; лист у вместилища, которое само стоит на листе другого; size у вместилища; элемент на листе, выходящий за лист или меньше наименьшего размера; placed, который не true и не false, и placed: false у того, что не лежит на листе; anchor, который называет что-то, кроме x и y, или значение вне их перечня; отражение без objects или с пустым списком, group отражения, которого нет, и повторяющийся id отражения; label, hint или привязку у украшения; ключ темы вне перечня или с недопустимым значением; имя рисунка, которое не является именем файла рисунка (7.2); два элемента одного вида с одними и теми же привязками в одном вместилище (Мастерская, 6.2) — кроме украшений.

Что функция пульта не отклоняет, а помечает. Объект, которого в графе нет, и объект, вид или тип которого элементу или вместилищу не подходит, отказом записи не являются: граф меняется после пульта, и пульт не должен из-за этого терять документ. Такой элемент или вместилище canvas.snapshot отдаёт помеченным, и мастерская показывает его на месте (С чего начать, 4); помеченный элемент ничего не отправляет и не записывает, а вместилище с помеченной привязкой показывается, как без неё. Так же помечается то, рисунка которого в папке процесса нет (7.2): why — image_gone; подложка такого листа показана одним цветом.

Что функция пульта дополняет при записи:

Место и размер, записанные в документе, функция пульта иначе не меняет. Пульт без листов при чтении раскладывается так же.

Документ читают canvas.get; canvas.snapshot — поверхность для окна, а не документ.

7.1 Раскладка окон мастерской

data/config/layout.json — ogas.layout/1. Владелец — функция ui, записывает его по запросу страницы (ui.window.layout.set, Методы мастерской и пульта, раздел 2). Документ хранит расположение окон, оставленное человеком, и настройкой не является: в окне настроек его нет. Как и user.json, он принадлежит человеку, который здесь работает, и в репозиторий и поставку не входит.

{
  "format": "ogas.layout/1",
  "host": [1180, 758],
  "windows": [
    { "kind": "graph", "x": 0, "y": 0, "w": 1180, "h": 379, "z": 4, "maximized": false, "folded": false, "minimized": 0, "restore": null },
    { "kind": "journal", "x": 0, "y": 379, "w": 1180, "h": 379, "z": 3, "maximized": false, "folded": false, "minimized": 0, "restore": null },
    { "kind": "settings", "x": 40, "y": 40, "w": 614, "h": 417, "z": 2, "maximized": false, "folded": false, "minimized": 1, "restore": null }
  ],
  "panels": { "graph": [573, 0, 340, 703] }
}

7.2 Рисунки пульта и вид элемента

Рисунки пульта и свои виды его элементов лежат в папке процесса, в папке pulpit/; хозяин — функция canvas. Они принадлежат процессу: удаление папки процесса уносит их, передача процесса переносит.

processes/<process_id>/pulpit/
  images/<файл>                рисунки подложек и украшений
  looks/<look_id>/look.json    свой вид элемента
  looks/<look_id>/<файл>       рисунки этого вида

Папка pulpit/ переносится с процессом (10.1).

look.json — ogas.look/1. Вид — данные: сценариев и ссылок за пределы своей папки в нём нет, поле вне перечня — отказ.

{
  "format": "ogas.look/1",
  "look_id": "brass",
  "kind": "button",
  "name": "Латунь",
  "size": [200, 60],
  "states": { "rest": "rest.svg", "hover": "hover.svg", "pressed": "down.svg", "disabled": "off.svg" },
  "slice": [18, 18, 18, 18],
  "content": [0, 14, 4, 14],
  "words": "#2a1c05"
}

Вид может быть и нарисован, и составлен из рисунков: рисунок состояния ложится поверх нарисованного. Каждый рисунок, названный в states и в value, лежит в папке вида и проходит ту же проверку, что рисунок пульта; в папке своего вида нет ничего, кроме look.json и названных им рисунков. Общий размер вида — не больше canvas.image_max_bytes.

Таблица 7 — Состояния элементов для вида

kind Состояния Когда
button rest, hover, pressed, disabled покой; под указателем; нажата; команду сейчас не выполнить: событие — программа выключена, остановка — прогон не идёт, повтор — последний прогон события не упал
toggle off, on выключен; включён
field, rows, number, choice, file rest, focus покой; в поле или клетке стоит курсор или выбор файла в фокусе
ask rest, asked никого не спрашивают; вопрос открыт
value, view, table rest —
bar rest; показывает количество рисунок подложки; доля — поле value
indicator idle, running, completed, failed, stopped запуска не было; идёт; прошёл; сбой; остановлен, прерван или отменён
group — вместилище rest —
label, picture нет видов у них нет

Состояния hover, pressed и focus окно узнаёт само — по указателю и курсору — и показывает поверх состояния, в котором элемент находится. Встроенные виды первого набора: button — key, toggle — lever, indicator — lamp, bar — tube (заполнение) и dial (стрелка), вместилище — plate. Вид вместилища описывают так же, с kind: "group".

7.3 Библиотека мастерской

data/config/library.json — ogas.library/1. Владелец — функция ui, записывает его целиком по запросу страницы после каждой правки (ui.window.library.set, Методы мастерской и пульта, раздел 2). Документ хранит, что человек держит на виду из своих программ и модулей (Мастерская, 5.6): панели программ справа и то, чего колонка графа не предлагает. Как и раскладка (7.1), он принадлежит человеку, настройкой не является и в репозиторий и поставку не входит.

{
  "format": "ogas.library/1",
  "bars": [
    { "id": "programs", "name": "", "programs": ["telegram", "process-5"] },
    { "id": "bar-2", "name": "Игры", "programs": [] }
  ],
  "hidden": { "programs": ["process-3"], "modules": ["echo"] },
  "views": { "programs": "tiles", "models": "table" },
  "groups": { "programs": true, "models": false },
  "fits_only": true
}

7.4 Заготовка интерфейса

data/library/pieces/<piece_id>.json — ogas.piece/1: вместилище пульта со всем, что в нём лежит, сохранённое в библиотеке, чтобы поставить его в другую программу (Мастерская, 6.8). Владелец — функция canvas: делает заготовку из записанного пульта процесса (canvas.piece.save, Методы мастерской и пульта, раздел 3), отдаёт и удаляет её. Заготовка принадлежит человеку, как библиотека (7.3), и в репозиторий и поставку не входит.

{
  "format": "ogas.piece/1",
  "piece_id": "razgovor",
  "name": "Разговор",
  "groups": [
    { "id": "talk", "name": "Разговор", "holds": "together", "layer": [640, 120] },
    { "id": "more", "parent": "talk", "holds": "together" }
  ],
  "elements": [
    { "id": "field_1", "kind": "field", "group": "talk", "label": "Сообщение", "parameters": { "lines": 3 }, "layer": [660, 180] },
    { "id": "button_1", "kind": "button", "group": "talk", "label": "Ещё", "bindings": { "opens": "more" } }
  ]
}

8 Настройки

Файлы: data/config/core.json (только core.*), data/config/system.json, data/config/user.json, processes/<id>/settings.json. Уровень сессии в файле не хранится. Формат ogas.settings/1.

{
  "format": "ogas.settings/1",
  "generation": 1,
  "values": {
    "core.health_interval_ms": 5000,
    "i18n.language": "ru"
  }
}

Уровни, порядок чтения, схема ключей и их перечень — Настройки. Секретов в этих файлах нет.

Схема настроек хозяина — файл settings.schema.json рядом с кодом хозяина, формат ogas.settings-schema/1. Программа хозяина встраивает его при сборке.

{
  "format": "ogas.settings-schema/1",
  "owner": "graph",
  "group": "other",
  "sections": [
    {
      "id": "graph.run",
      "keys": {
        "graph.max_iterations": { "type": "integer", "default": 1000, "min": 1, "max": 1000000, "restart": false },
        "graph.runs_keep": { "type": "integer", "default": 20, "min": 0, "max": 10000, "restart": false }
      }
    }
  ]
}

Таблица 8 — Настройки

Поле Смысл
owner хозяин; каждый ключ начинается с <owner>.
group крупный раздел окна настроек: core, ui или other
sections подразделы в том порядке, в каком их показывает окно; id подраздела начинается с <owner>.
keys ключи подраздела; порядок в окне — по имени ключа
type string, integer, number, string[] или color
default значение по умолчанию; обязательно и само проходит проверку по схеме
default_by необязательно: { "key": "<ключ того же хозяина>", "values": { "<значение того ключа>": <умолчание> } } — умолчание, когда тот ключ принял указанное значение; иначе действует default
restart нужен ли перезапуск, чтобы значение подействовало
min, max для integer и number — допустимые границы включительно
choices закрытый набор допустимых строк
pick необязательно, только для string: folder или file — путь, который человек может выбрать в системном окне Windows, а не печатать; значение — путь так, как его пишет Windows

Названия и пояснения в схеме отсутствуют: они хранятся в словарях хозяина под ключами setting.<ключ>.title, setting.<ключ>.help, setting.<ключ>.choice.<значение> и setting.section.<id> (Настройки, раздел 2).

9 Версии модулей и поколение документов

modules.lock.json — ogas.modules-lock/1:

{
  "format": "ogas.modules-lock/1",
  "generation": 1,
  "modules": [
    {
      "id": "echo",
      "version": "1.0.0",
      "digest": "sha256:9f2b…"
    }
  ]
}

generation.json — ogas.generation/1. Владелец — функция графа; в files только документы, которые она пишет:

{
  "format": "ogas.generation/1",
  "generation": 1,
  "files": ["process.json"]
}

workspace.json, settings.json и modules.lock.json принадлежат функциям canvas, settings и modules. Полноту поколения граф проверяет только по своим файлам; записанные версии модулей он сверяет запросом module.lock.get.

После сбоя принимается поколение, для которого все files существуют, имеют то же generation и проходят разбор. Незавершённое поколение откатывается к предыдущему .bak набору, если он полный.

Истории версий сверх нынешнего поколения и предыдущего нет: правку в мастерской возвращают шагами истории правок, а сохранённое берегут передачей процесса папкой.

10 Пакет на ребре и артефакт

{
  "packet_id": "packet-1",
  "run_id": "run-1",
  "iteration_id": 0,
  "delivery_id": "delivery-1",
  "source": { "node_id": "echo_one", "port": "success" },
  "parts": { "text": "пример" },
  "artifacts": [
    {
      "artifact_handle": "sheet-1.svg",
      "kind": "file",
      "size": 1234,
      "media_type": "application/octet-stream"
    }
  ]
}

Файл результата — data/processes/<process_id>/results/<run_id>/<artifact_handle>, размер по умолчанию до 64 МиБ (modules.artifact_max_bytes). Ссылка — имя файла среди результатов прогона, которое дал модуль: без папок, не начинается с точки, занятое в прогоне получает номер (Модули, раздел 6). В JSON абсолютных путей нет. Поле name — путь, под которым файл создал модуль в рабочей папке.

10.1 Экспорт процесса

Экспорт процесса — папка data/exports/<process_id>/ формата ogas.export/3. Документы процесса хранятся в виде JSON, файлы модулей — как есть, без base64 и без предела размера документа. Вместе с процессом в экспорт входят процессы, которые он вызывает, на любой глубине (Программа: граф и запуски, раздел 18): вызов — ссылка, и без них процесс там, куда его перенесли, не работал бы.

exports/workshop/
  package.json               что внутри
  documents/process.json
  documents/workspace.json
  documents/settings.json
  documents/modules.lock.json
  calls/resize/documents/process.json
  calls/resize/documents/modules.lock.json
  modules/echo/manifest.json
  modules/echo/main.py
  modules/thumb_image/…
  pulpit/images/face.svg     рисунки и виды пульта, если они есть
  files/7f3a91c2-кот.png     файлы постоянных и переменных, если они есть
  state/paint/…              сохранённая память узла, если её просили
  state/paint.saved.json     и её отметка

package.json:

{
  "format": "ogas.export/3",
  "process_id": "workshop",
  "name": "Workshop pack",
  "exported_at": "2026-09-17T10:15:30.123Z",
  "documents": ["process.json", "workspace.json", "settings.json", "modules.lock.json"],
  "calls": [
    { "process_id": "resize", "name": "Resize", "documents": ["process.json", "modules.lock.json"] }
  ],
  "modules": [
    {
      "id": "echo",
      "version": "1.0.0",
      "digest": "sha256:9f2b…",
      "files": 4,
      "bytes": 3812,
      "links_left_out": []
    }
  ]
}

11 Контрольная точка

data/processes/<process_id>/runs/<run_id>/checkpoint.json — ogas.checkpoint/2: голова контрольной точки; рядом с ней — запечатанные части checkpoint.part-<n>.json (ниже).

{
  "format": "ogas.checkpoint/2",
  "run_id": "run-1",
  "attempt_id": "attempt-1",
  "process_id": "demo",
  "process_generation": 1,
  "status": "running",
  "updated_ms": 1789640130123,
  "queued": [
    {
      "node_id": "echo_two",
      "port": "input",
      "delivery_id": "delivery-2",
      "packet_id": "packet-1",
      "iteration_id": 0,
      "payload": { "text": "x" },
      "artifacts": []
    }
  ],
  "executions": [
    {
      "node_id": "echo_one",
      "packet_id": "packet-1",
      "delivery_id": "delivery-1",
      "operation_id": "run-1-operation-echo_one-packet-1-0",
      "execution_id": "run-1-operation-echo_one-packet-1-0-execution-1",
      "attempt": 1,
      "iteration": 0,
      "status": "completed",
      "port": "success",
      "input_port": "input"
    }
  ],
  "outputs": [],
  "resume": { "allowed": true, "reason": null }
}

Отметка «Хранить» — runs/<run_id>/keep.json в папке процесса, формат ogas.run-keep/1. Пишет и удаляет её функция графа (Программа: граф и запуски, 12.6); уборка прогонов отмеченный прогон не удаляет.

{ "format": "ogas.run-keep/1", "run_id": "run-1", "kept_at": "2026-09-17T10:15:30.123Z" }

12 Замок экземпляра

data/ogas.lock, права 0600, действующий замок — flock на открытом дескрипторе:

{
  "pid": 1234,
  "started_at": "2026-08-30T10:15:30.123Z",
  "nonce": "n-3f9a1c0b7e2d4a65"
}

nonce — случайная метка этого запуска экземпляра: восемь байт случайности системы в шестнадцатеричной записи.

13 Журнал и проблема

Запись общего журнала событий data/logs/events-<ГГГГ-ММ>.jsonl — по месяцу времени записи — и журнала прогона runs/<run_id>/events.jsonl в папке процесса:

{
  "time": "2026-08-30T10:15:30.123Z",
  "level": "info",
  "source": "graph",
  "trace_id": "trace-1",
  "run_id": "run-1",
  "node_id": null,
  "event_id": 42,
  "event_type": "run.changed",
  "payload": { "run_id": "run-1", "status": "running" }
}

Запись — событие шины, как его разослало ядро: event_id, event_type и payload. К нему добавлены уровень level (info, warn или error; уровень, названный в payload, или error у отказа) и поля, по которым журнал ищут: source, trace_id, run_id, node_id. Своего ключа словаря у записи нет: человеку событие называет текст event.<event_type> из словаря его хозяина.

Журнал ядра data/logs/core.jsonl пишет само ядро — отказы функций, знакомство, перезапуски; функция observe его не записывает:

{
  "time": "2026-08-30T10:15:30.123Z",
  "source": "graph",
  "event": "function.health_failed",
  "error_code": "rpc_timeout",
  "message": "Function did not answer the health check in time"
}

Поля записи: time, source (ядро или id функции, о которой запись), event, error_code (или null) и message. Строка, которую функция написала в stderr, лежит здесь же записью function.stderr — не длиннее 4 КиБ, длинная обрезается. message — короткая подсказка тому, кто разбирает отказ по журналу; это не текст для человека в мастерской, поэтому он не переводится и ключа словаря у него нет. Человеку то же самое объясняет проблема из problems.json по своему code.

Список проблем — data/problems.json, формат ogas.problems/1: { "format", "problems": [проблема, …] }; пишет его только функция наблюдения. Проблема описывается полями problem_id, code, severity (info, warn или error), указателем на место pointer (function_id, process_id, run_id, node_id, trace_id; у пропавшего текста ещё key), признаком open, счётчиком count, временами first_seen и last_seen, а также событием, которое её открыло: event_type и payload. Закрытая проблема несёт open: false и время закрытия resolved_at. Повтор того же отказа увеличивает count, а новой строки не добавляет; тот же отказ — то же событие с тем же кодом в том же месте: у той же функции или в том же узле того же процесса, а у пропавшего текста — с тем же ключом, на каком бы языке его ни искали. Повтор закрытой проблемы открывает её снова: open становится true, resolved_at убирается. Список проблем отдаёт observe.problems.list, события журнала — observe.logs.query.

14 Связи

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

Таблица 9 — Связи

Целое Сколько частей Часть
рабочий процесс сколько угодно узел
рабочий процесс сколько угодно ребро
рабочий процесс сколько угодно группа
рабочий процесс сколько угодно переменная
рабочий процесс сколько угодно сквозной объект — из узлов и переменных
рабочий процесс ровно один файл запомненных значений (state.json)
рабочий процесс по одной на имя памяти, которую сохранил модуль: узла или общую нескольких узлов память узла (state/<имя>/)
рабочий процесс по одной на прогон папка прогона (runs/<run_id>/) и папка его результатов (results/<run_id>/)
включённая программа сколько угодно прогон
рабочий процесс ровно один пульт (workspace.json)
рабочий процесс ровно один свои настройки (settings.json)
рабочий процесс ровно один окружение Python (.venv)
рабочий процесс сколько угодно, и наоборот версия модуля — через modules.lock.json
прогон сколько угодно выполнение шага
прогон сколько угодно пакет
прогон сколько угодно артефакт
прогон ровно одна текущая контрольная точка

15 Хранение

База данных не используется.

Запись документа выполняется в следующем порядке:

1) хозяин документа проверяет его по схеме; 2) ядро проверяет путь, размер, UTF-8 и format, если он есть на верхнем уровне; 3) временный файл, fsync файла, текущий файл переименовывается в .bak, временный встаёт на его место, fsync папки; 4) в наборе процесса generation.json обновляется последним.

Документ другой версии формата не читается. Ядро при записи проверяет только вид строки — <имя>/<номер>, — потому что смысла документа не знает; какую версию понимать, решает хозяин документа при чтении. Хозяин отвечает document_invalid, называя найденную и ожидаемую версию. Хозяева форматов:

Имена форматов объявлены в файлах констант их хозяев; make ci проверяет, что в коде нет их строковых копий и что каждый записан здесь.

16 Виды данных, файлы процесса и показ

Раздел описывает виды данных, файлы процесса и то, как данные показаны человеку (Программа: граф и запуски, раздел 24; Мастерская, 5.5).

16.1 Имена видов данных

В форматах вид данных называют именем из таблицы 11: у порта модуля (type, раздел 4), у переменной (type, 5.1), у постоянной, у события и у вопроса (16.6).

Таблица 11 — Имена видов данных

Вид Имя Значение в JSON
текст text строка
число number число
да/нет boolean true или false
дата и время time строка ISO 8601 — 2026-10-17T09:00, с секундами или без, с поясом Z или +03:00 или без него — тогда по часам этой машины; пустая строка — время не задано. Поле ввода — выбор даты и времени системы
список list массив
картинка image ссылка на файл (16.2)
звук audio ссылка на файл
видео video ссылка на файл
файл file ссылка на файл
что угодно json любое значение

Ребро соединяет порты, когда виды одинаковые, когда один из них json и когда картинка, звук или видео идут на порт file: картинка — тоже файл. Обратно — файл на порт картинки — ребро не соединяет: что в файле, неизвестно. Других превращений нет: текст на порт числа не идёт.

16.2 Ссылка на файл

Картинка, звук, видео и файл в данных — ссылка, а не содержимое:

{ "file": "files/7f3a91c2-кот.png", "name": "кот.png", "media_type": "image/png", "size": 48213 }

Ссылка идёт в пакете, лежит в переменной и в постоянной, как любое значение. Модуль получает файл по ссылке так же, как файл результата: путём в artifact_files (Модули, раздел 6). Отдаёт модуль файл той же ссылкой: в file — путь в рабочей папке, тот же, что в artifacts; функция модулей, перенеся файл, ставит в file его имя среди результатов и дописывает остальные поля (Модули, раздел 6).

16.3 Где лежат файлы

Файлы лежат в папке процесса, в двух местах:

Файл после появления не изменяется (Программа: граф и запуски, 24.4). Поэтому, когда узел «Запись» кладёт в переменную ссылку на файл прогона, функция графа копирует файл в files/ — на том же диске жёсткой ссылкой, без второй копии содержимого, — и в переменную ложится ссылка на копию: прогон уберут, а переменная держит файл дольше.

Уборка файлов процесса. Файл из files/ живёт, пока его называет что-то из: значение постоянной в записанном документе процесса, начальное значение переменной, нынешнее значение переменной включённой программы, запомненное значение (state.json). Функция графа убирает файл, который ничего не называет и который старше суток: сутки покрывают файл, данный в несохранённую правку графа. Убирает при включении программы и после записи документа процесса.

Экспорт процесса уносит папку files/ вместе с процессом, как папку рисунков пульта (10.1). Данные, которые узел «Отправить» передаёт другой программе, несут её файлы с собой: каждый файл, который они называют, копируется в files/ получателя тем же способом, и ссылка называет копию (Программа: граф и запуски, раздел 23).

16.4 Как файл попадает в процесс

Файл Windows человек даёт двумя способами: выбирает в системном окне выбора — оно открывается по нажатию поля для файла с папки настройки ui.open_dir и показывает сначала файлы нужного вида, потом все, — или отпускает над полем файл, перетащенный из Проводника. В обоих случаях окно получает путь, а не содержимое: функция ui переводит путь Windows в путь Linux (ui.window.path), и функция графа копирует файл сама (process.file.take с process_id, path, place и run_id) — целиком, один раз, рядом с местом назначения и затем на место, под своим именем; предел размера и место на диске проверяются до копирования. Перетащенный файл, отпущенный там, где файл не берут, не теряется молча: окно говорит, куда его отпустить.

Файл, который сделала сама страница (маска рисунка), она передаёт функции графа содержимым, частями: строка обмена ограничена (MAX_LINE_BYTES, раздел 1), а видео бывает большим. Запрос process.file.put несёт process_id, name, media_type, часть содержимого в base64 (data), upload_id — один на весь файл, offset — с какого байта эта часть, и last — последняя ли она. Части складываются в файл .<upload_id>.part рядом с местом назначения; последняя часть переименовывает его в постоянное имя, и ответ несёт ссылку (16.2). Пропущенная или повторная часть — отказ с причиной; недописанный файл старше суток убирается. Куда ложится файл, говорит place: files — для постоянной и переменной, run с run_id — для ответа на вопрос идущего прогона. Предел размера — настройка функции графа, по умолчанию 1 ГиБ.

16.5 Узел «Показать»

Вид узла show (Программа: граф и запуски, 24.3):

Узел «Показать» проверка графа не требует ни к чему подключать: без входа он не сработает, как любой узел, и process.validate назовёт его предупреждением.

16.6 Поле на узле

Что задаёт поле на узле холста и где это хранится:

16.7 Отдельно запущенная часть

Узел или группу запускают отдельно (process.run.start, Программа: граф и запуски, 12.1). Вход части, к которому ведёт ребро снаружи, получает:

Окно передаёт набранное во всех событиях графа (events: { <id события>: пакет }, у события без полей — null), кладя в пакет только поля, которые читаются как их вид. Какие из событий ведут в часть, знает функция графа, и только их набранное она сверяет с takes: поле, которого нет или которое не того вида, — отказ (graph_no_entry, message_key graph.part.event_unfit, в names — «событие: поле»). Событие, которое в часть не ведёт, ни о чём не спрашивают: недонабранное поле в соседней ветке проверке не мешает.

Узел части, к которому не ведёт ни одно горячее ребро — ни изнутри, ни от события снаружи, — начинает прогон с пустого пакета {} и читает свои холодные входы: так проверяют узел, у которого на входе только постоянная.

Общего ввода у окна нет.

17 Источники

17.1 Витрина — ogas.catalog/1

Витрина — документ JSON, который источник O.G.A.S. отдаёт по своему адресу: по умолчанию https://ogas.space/catalog.json. Её читает функция источников (Мастерская, 5.6).

{
  "format": "ogas.catalog/1",
  "name": "O.G.A.S.",
  "items": [
    {
      "id": "sobesednik",
      "what": "program",
      "title": "Собеседник",
      "description": "Разговор с локальной сетью в манере образа",
      "version": "1.0.0",
      "author": "Виктор Овчинников",
      "license": "Apache-2.0",
      "files": [
        { "path": "process.json", "url": "https://ogas.space/files/sobesednik/1.0.0/process.json", "size": 298115, "sha256": "…" }
      ]
    }
  ]
}

Таблица 12 — Вещь витрины

Поле Тип Обязательно Что значит
id string да имя вещи в витрине: строчные латинские буквы, цифры, _, - и .; под ним вещь ложится в downloads/
what string да program — программа, папка экспорта процесса (Форматы файлов, 10.1); module — папка модуля; network — нейросеть; piece — заготовка интерфейса: ровно один файл .json, документ ogas.piece/1 (7.4)
title, description string title — да название и описание словами человека
kind string у нейросети вид нейросети — подпапка папки нейросетей, куда она встанет
version, author, license string нет версия, автор, лицензия как её называют
profile integer ≥ 1 нет номер профиля автора на ogas.space (21.5): по нему библиотека показывает автора и говорит, тот ли автор у новой версии, что у прежней
category string нет раздел витрины, в котором стоит вещь, словами витрины: по нему библиотека показывает найденное группами
gpu_mb integer ≥ 0 нет сколько видеопамяти нужно программе или модулю, в МиБ: по нему библиотека говорит, запустится ли вещь на этом компьютере
files object[] да файлы вещи: path — относительный путь внутри её папки, url — откуда скачать (https; у витрины-файла на этом компьютере — file:), size — байты, sha256 — контрольная сумма; необязательные role — чем файл приходится вещи (weights, part:<папка>, adapter, config, tokenizer, vae, docs, picture, other) и variant — чем этот вариант отличается от других (fp16, Q4_K_M, pruned…); без них роль и вариант читаются по имени файла
preview object нет картинка вещи для плитки: url, size, sha256, как у файла; PNG, JPEG, WebP или GIF не крупнее 2 МиБ

Витрина другого формата, вещь без обязательного поля, заготовка не из одного файла .json, путь файла, выходящий из папки вещи, файл без size или sha256, gpu_mb не целым числом, роль файла, которой нет в списке, не читаются: источник отказывает source_answer_bad и называет, что не так.

Витрина O.G.A.S. может назвать и новую версию платформы: поле platform — { "version": "1.0.1", "page": "https://ogas.space/…" }; номер — числа через точку, страница — только страница ogas.space. Его читает только проверенная витрина (Методы служб платформы, раздел 4).

Витрина ogas.space лежит рядом со своей подписью catalog.json.sig (21.5); без верной подписи она не читается (source_signature_bad). Программы, модули и заготовки на ней — все файлы лежат на самом ogas.space; нейросетей на ней нет, их библиотека берёт с Hugging Face и Civitai.

17.2 Загрузки

Функция источников пишет скачанное в папку данных, в downloads/:

Остановленная или отказавшая загрузка убирает свою папку целиком: недокачанного на диске не остаётся. Список загрузок живёт, пока работает функция, и в файл не пишется.

18 Вход для программ — ogas.gate/1

data/gate.json. Владелец — функция gate (Методы служб платформы, раздел 5). Программа человека читает его, чтобы войти.

{ "format": "ogas.gate/1", "port": 50123, "key": "9f…e1" }

19 Помощник

Владелец — функция assistant (Методы служб платформы, раздел 6).

20 Места частей — ogas.places/1

data/places.json пишет ядро, когда часть называет свои папки вне папки данных (core.space.places, Обмен с ядром, 5.19):

{ "format": "ogas.places/1", "parts": { "modules": [
  { "path": "/opt/ogas/modules", "backup": true },
  { "path": "/opt/ogas/models", "backup": false }
] } }

parts — по части список её папок; backup: true — папку берёт резервная копия (Сборка, установка и обслуживание, 5.6). Документ нужен, когда платформа остановлена: по нему ядро знает, что взять в копию.

21 Профиль, посылки и файлы сайта

Владелец — функция profile (Методы служб платформы, раздел 7); что от чего защищает — Защита, раздел 8. Строки base64 — стандартный алфавит с =.

21.1 Код восстановления и файл ключа — ogas.key/1

Код — 55 знаков алфавита 0123456789ABCDEFGHJKMNPQRSTVWXYZ группами по пять через -: 34 байта — зерно главного ключа (32 байта) и первые два байта его SHA-256 — с тремя нулевыми битами в конце. При чтении пробелы, переводы строк и - пропускаются, строчные буквы читаются как прописные, O — как 0, I и L — как 1.

Файл ключа — документ JSON там, где его сохранил человек:

{ "format": "ogas.key/1", "code": "T2RBT-8P06Y-…-JMAWR" }

или, под паролем:

{ "format": "ogas.key/1",
  "kdf": { "name": "argon2id", "salt": "…", "m": 65536, "t": 3, "p": 1 },
  "sealed": "…" }

sealed — 24 байта nonce и шифр кода (XChaCha20-Poly1305) ключом 32 байта, который Argon2id выводит из пароля с salt (16 байт) и параметрами m (КиБ), t, p.

21.2 Профиль на компьютере

Папка data/profile/; файлы пишет функция profile.

21.3 Посылка — ogas.parcel/1

{ "format": "ogas.parcel/1",
  "key": "…", "device": "…", "vouch": "…",
  "body": "{\"what\":\"review\",\"lang\":\"ru\",\"made\":\"2026-11-06T12:00:00Z\",\"thing\":\"rask\",\"version\":\"1.0\",\"works\":true}",
  "sign": "…" }

Таблица 13 — Виды посылок

what Поля Подписывает
profile name (до 80 знаков), about?, links? — до пяти адресов https://, picture? — { type: ".png" \| ".jpg" \| ".webp", base64 } до 2 МиБ, box — открытая часть ключа писем, device — открытая часть ключа компьютера, с которого пришла карточка: сайт принимает подпись только названных так компьютеров, shown? — показывать ли страницу главный ключ
review thing, version, works (boolean), platform?, gpu?, text?, incognito? компьютер
request title, wants, input?, output?, network?, gpu?, example?, incognito? компьютер
take request — номер обращения, about?, incognito? компьютер
offer request?, title, about?, note?, incognito?, things — до 20 вещей { what: "program" \| "module" \| "piece", id, version, files: [{ path, text } \| { path, base64 }] } компьютер
bug where — platform или id вещи, version?, did?, expected?, happened, doctor?, journal?, box компьютер
comment bug — номер, text компьютер
solved bug, version, note? компьютер
reply review — номер отзыва о своей вещи, text компьютер
withdraw parcel — SHA-256 своей посылки компьютер
revoke keep — открытая часть ключа этого компьютера: остальные компьютеры профиля отзываются главный ключ
delete — главный ключ

Пределы: посылка — до 28 МиБ; файлы вещей — до 20 МиБ и 500 штук, путь — до 200 знаков, относительный, из обычных имён, без .., скрытых и \, один путь — один раз без учёта регистра; base64 — только у картинок .png, .jpg, .jpeg, .webp, .gif, и первые байты должны быть картинкой этого вида; заготовка — ровно один файл .json текстом. Тексты: имя — до 80 знаков, строка — до 500, текст — до 20 000, doctor и journal — до 100 000.

Посылку отправляют запросом POST https://ogas.space/api/send с заголовком X-OGAS-Work: <день>:<число>: SHA-256 от строки <день>:<число>:<hex SHA-256 посылки> должен начинаться с 20 нулевых бит, у посылки profile — с 24; <день> — сегодня или вчера по UTC, YYYY-MM-DD. Ответ — { "ok": true, "id": "<hex SHA-256 посылки>" } или { "ok": false, "error", "detail" }; коды: bad_format, bad_kind, bad_path, not_a_picture, missing, too_large, main_key_only, no_work, blocked, too_often, full.

21.4 Письмо — ogas.letter/1

Письмо — запечатанный ящик libsodium (crypto_box_seal: X25519 и XSalsa20-Poly1305) для открытой части ключа писем получателя; внутри — объект JSON { "format": "ogas.letter/1", "kind", … }.

Таблица 14 — Письма

kind Поля Кому
answer parcel — SHA-256 сообщения об ошибке, text сообщившему
bug bug — номер, thing, version, did, expected, happened, doctor, journal автору вещи
review review — номер отзыва, thing автору вещи, когда отзыв встал на сайт

21.5 Файлы сайта и их подпись

Таблица 15 — Что платформа читает с ogas.space

Файл Формат Что в нём
catalog.json ogas.catalog/1 витрина (17.1)
requests.json ogas.requests/1 requests: { number, made, by, title, wants, input, output, network, gpu, example, takes, results, state }; takes — { number, by, about, made }; results — { number, title, by, note, where }; state — open или done; by — номер профиля или null
reviews.json ogas.reviews/1 reviews — по id вещи список { number, works, made, by, version, platform, gpu, text, reply? }, reply — ответ автора вещи; bugs — по id вещи известные ошибки { number, text, version, made, solved?, solved_note?, comment? }
profiles.json ogas.profiles/1 profiles: { number, name, about, links, picture?, things, results, reviews, of_things }; of_things — по своей вещи её отзывы и ошибки
states.json ogas.states/1 states — по SHA-256 посылки { state, number, reason?, profile? }; state — waiting, shown, accepted, done, rejected, withdrawn, answered, refused
mail.json ogas.mail/1 letters — запечатанные письма base64 (21.4) за последние 30 дней

Рядом с каждым — <имя>.sig: строка base64 подписи Ed25519, 64 байта, над байтами ogas.site/1\n<имя>\n и байтами файла. Открытые части ключей сайта — в общем коде платформы.