File formats
The file formats of the platform: the program, the pulpit, memory, the checkpoint, settings, the manifest of a module, the export, the showcase and others — what is in each field and who writes the file.
Introduction
The document describes the files the platform writes and their content. The purpose of the documents is set out in the descriptions of the parts: the graph — The program: graph and runs, modules — Modules, the pulpit — The workshop, section 6, settings — Settings, the data folder as a whole — The make-up of the platform, 3.8.
1 General rules
- A document is JSON in UTF-8, without comments and without a comma before a closing bracket.
- Each format has a field
format, for exampleogas.process/4. An unknown value makes the document invalid, and a program of an earlier version does not open a document of a newer one. - An unknown optional field is not read by the current version.
- Identifiers are strings. An identifier of an execution is not given twice within an instance.
- Time is written in UTC as ISO 8601 with milliseconds and the letter
Z, for example2026-08-30T10:15:30.123Z. - Binary data are not put into JSON: an artifact and the reference to it,
artifact_handle, serve for them. - A path inside a document is counted from the folder of its owner and does not go beyond it.
- A kilobyte in limits is 1024 bytes.
2 Identifiers
Table 1 — Identifiers
| Identifier | What it stands for |
|---|---|
function_id |
a function of the platform from the register |
module_id |
a module; the same as the name of the folder modules/<module_id>/: [a-z0-9][a-z0-9_-]{0,63} — small Latin letters, digits, _ and -, the first sign a letter or a digit; runtime is the folder of the common code of modules, not a module. The function of modules refuses another module_id without reading files |
process_id |
a working process, [a-z0-9-]{1,64} (The program: graph and runs, section 1) |
node_id, edge_id, group_id, port_id |
parts of the graph |
object_id |
a shared object |
surface_id |
the name of a view a function declared for diagnostics |
run_id |
a logical run: the local date and time of its start, 2026-10-08_07-29-12, on a clash -2, -3; unique among the runs of all processes. It gives the name of the run folders runs/<run_id>/ and results/<run_id>/ in the process folder only if it consists of Latin letters, digits, - and _ and is not longer than 128 signs; another run_id stays only in the common journal |
attempt_id |
an attempt of a run; new after a failure, the run_id the same |
operation_id |
a logical step of a node: run + node + packet_id + iteration. A retry of the same iteration keeps it, a new iteration of a loop gets a new one |
execution_id |
a particular call of a module; a retry has a new one |
packet_id |
a logical packet; on a fan-out one for all receivers. A packet inside a frame it entered from a round of another frame carries its former packet_id and the number of that round after «/» (The program: graph and runs, section 11) |
delivery_id |
a particular delivery of a packet to one receiver |
artifact_handle |
a result file of a run: its name in results/<run_id>/, without / and \, not starting with a dot |
command_id |
the stable key of a changing command on repeated delivery (Exchange with the kernel, section 3) |
process_handle |
a particular OS process of a module; its meaning is known to the function of modules |
event_id |
the monotonic number of a kernel event |
trace_id |
the tie of all records of one action of the person |
problem_id |
a problem in the list of the function observe |
3 The register of functions
What is known of a function is held in two files. The register of the instance sets where its program lies, whether it is on and the rights it is given. The function itself describes its properties in its folder: dependencies, the version of the contract, work with the window and restart (rule 2.10). The kernel reads both files and joins them by id.
The register file: data/functions.json. Format: 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 — optional verbs of the command line besides the verbs of the kernel (start, ui, doctor), as { "<verb>": description } (The make-up of the platform, section 5):
- the description of a verb is
{ "args", "before", "method", "params", "wait", "interactive" }; interactiveis an optional sign «the verb needs the workshop»,falseby default: the instance is started together with the functions that need the workshop and stays working after the calls of the verb, and a working instance carries out the calls itself (The make-up of the platform, 3.6.3 and 5.3). Such a verb has nowait: there is no end of work for it to wait for;args— the arguments of the verb:{ "<name>": { "required", "default" } },requiredisfalseby default; an argument is passed by the flag--<name> VALUE. Without a required argument the verb ends with code 1 without starting the instance; an optional argument without its flag takes the valuedefault(a string), so an optional argument withoutdefaultis not allowed;- the name of a verb and the name of an argument consist of small Latin letters, digits,
_and-and begin with a letter;data-dirandhelpare flags of the kernel and are not names of arguments; before— calls before the main one, each{ "method", "params" }: actions the person would take beforehand, for example switching a program on before pressing a button of its pulpit. The answers of these calls are not read; a refusal of any of them is a refusal of the verb;- substitutions in the
paramsof the main call and of the calls ofbefore: a string$<name>as a whole is replaced by the value of the argument with that name; a string with other signs besides$<name>is not replaced. A name that is not among the arguments of the verb is not allowed; wait— an optional polling after the call:method,params,field,success,failure. In theparamsof the polling the arguments of the verb and the string fields of the answer of the first call ($run_id) are available; a name that is neither among them nor in the answer is a refusal of the verb with code 1. A value offieldfromsuccessgives exit code 0, fromfailure— 1.
A verb with the name of a kernel verb, a name of a verb or argument that does not meet these requirements, an optional argument without a default, a call without method, a substitution without an argument and a wait at a verb that needs the workshop make the register invalid (function_registry_invalid): the kernel refuses all verbs of the register and works without functions (The make-up of the platform, 3.4.1).
The note of a repeated start — run/launch.json in the data folder, ogas.launch/1: { "format", "verb", "args": { "<name>": "<value>" }, "asked_ms" }. It is left by a start with a verb that needs the workshop when the instance is already working, and is read by the instance woken up (The make-up of the platform, 3.6.3). asked_ms is the time of the request in milliseconds from the epoch. The file is open only to the user, is written whole and is deleted when read.
The entry of a function in the register — only choices of the instance:
Table 2 — Fields of the entry of a function in the register
| Field | Type | Default | Meaning |
|---|---|---|---|
id |
string | — | the id of the function; its folder is functions/<id>/ |
path |
string | — | the executable file relative to the installation folder |
enabled |
bool | — | whether to start it |
capabilities |
string[] | empty | the rights a handshake may ask for |
The state of functions during work is not part of this file.
The description of a function — the file functions/<id>/function.json in the installation folder, format ogas.function/1. It is written by the author of the function together with its code; the description comes in the delivery together with the function.
{
"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
}
Table 3 — Fields of the description of a function
| Field | Type | Default | Meaning |
|---|---|---|---|
format |
string | — | ogas.function/1 |
id |
string | — | the same function as in the register; another id — the description is someone else's |
requires |
string[] | empty | the functions whose contract this one uses |
optional |
string[] | empty | those of requires without which the function works: the start does not wait for them, their failure does not stop it |
platform.min / max |
u32 | 1 |
the supported versions of the platform |
contract |
u32 | — | the version of the contract |
restart |
bool | true |
whether to restart it after it exits |
interactive |
bool | false |
needs the workshop |
checks |
object[] | empty | checks of the environment for ogas-core doctor |
The function ui describes itself with interactive: true and restart: false; there is no list of function identifiers in the kernel. The meaning of the fields — The make-up of the platform, 3.4.1.
checks — checks of the environment a function declares for ogas-core doctor (The make-up of the platform, section 5). Each is { "id", <kind> } of a closed set of kinds the kernel can carry out:
file— a list of paths: the check passes if at least one file or folder exists; a relative path is counted from the installation folder;program— a program and its arguments: the check passes if the program ended with code 0 within the inner term of the kernel; the program is started from the installation folder, its output is not read.
id consists of small Latin letters, digits and _ and does not repeat within the description; a check has exactly one kind. Otherwise the description is invalid. What the outcome means, the function says in its dictionary with the keys <function id>.check.<id>.passed and <function id>.check.<id>.failed in Russian and English.
"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"] }
]
If the description is missing, is not JSON, has another format or another id, the kernel does not start the function, since it does not know its requirements and contract. The start refuses with function_description_invalid and names the file, the other functions work, and those depending on it are left without it, as without any unavailable one. A register of another format is not read by the kernel, which names its version: silently dropping, say, restart: false from it would change the behaviour of the instance without a word.
4 The manifest of a module
The file: modules/<module_id>/manifest.json. Format: 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
}
Table 4 — The manifest of a module
| Field | Type | Required |
|---|---|---|
format |
"ogas.module/1" |
yes |
id |
string | yes |
version |
string | yes |
name_key |
string | yes |
description_key |
string | no |
runtime |
"python" | "native" |
yes |
entrypoint |
string relative to the module folder | yes |
inputs / outputs |
an array of ports | yes, may be empty for outputs |
input_policy |
all | any |
yes |
parallelism |
integer ≥ 1 | yes |
process |
step | long | service |
yes |
resources.gpu_mb |
integer ≥ 0: how much video memory a module that is up needs | no, 0 by default |
suspend |
bool: whether the module can save its intermediate state before unloading and go on from it | no, false by default |
execution_semantics |
idempotent | non_idempotent | unknown |
yes |
retry.max_attempts |
integer ≥ 1 | yes |
retry.delay_ms |
integer ≥ 0 | yes |
retry.exponential |
bool | no |
timeout_ms |
integer ≥ 1 | yes |
parameters |
an object: the name of a parameter → { type, default?, min?, max?, choices? }, for a neural network — { type: "model", kind, default? } |
no |
permissions_info |
{ network, filesystem } |
no |
role |
assistant_network — the module serves as a network of the assistant of the workshop: the input request, the output reply |
no |
secrets |
the names of the secrets the module reads from .env of its folder: capital letters, digits and _; the window asks the person for them |
no |
runtime_python |
string, for example ">=3.11" |
no |
A port: name, type — the name of a kind of data from table 11 (16.1), required. An input may have join_key — a path through dots. The inputs and outputs of the manifest are the ports of the node on the graph: links join them by name, and the module names the output in the field port of its answer (Methods of modules, section 1).
A parameter:
type—string,integer,number,string[]orcolor, as for settings (Settings, section 2);boolean— yes or no, withoutmin,maxandchoices, a pulpit switch gives it as it is;model— a neural network of one kind;default— the value the module gets if the node did not set the parameter; withoutdefaultthe parameter is optional, and the module does not get it;minandmax— for numbers,choices— for a closed set;- for a neural network,
kindis the kind, the name of a subfolder of the folder of networks: small Latin letters, digits,_and-;default— the name of the file or folder of the network in it; it has no limits and no closed set — the choice is among what lies there (Modules, section 11); - the optional
sourcesof a neural network — where to get itsdefault: a list{ "source", "id", "files" }, wheresourceis the kind of source (huggingface,civitaiorogas),id— what the source calls it (unsloth/Qwen2.5-7B-Instruct-bnb-4bit), and the optionalfiles— which files to take; without it, those the source offers itself (section 17).
The manifest has no field models — a list of neural networks the module always takes: a network is taken by a parameter, and the node chooses it. What a parameter is and where its texts are — Modules, section 10.
There are no texts in the manifest: the name, the explanation and the hints are kept in the dictionaries of the module.
permissions_info is only information for the person: system calls are not limited by it.
5 The working process
The folder data/processes/<process_id>/ holds everything that belongs to the process: process.json, workspace.json, settings.json, state.json, the remembered lists kept/<variable id>/, modules.lock.json, generation.json, the memory of nodes state/<name>/, the pictures of the pulpit and the looks of its elements pulpit/, the person's files inputs/, the files of constants and variables files/ (16.3), the runs runs/<run_id>/, their results results/<run_id>/ and the environment .venv. Who owns what — The program: graph and runs, section 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": []
}
kindof a node is a kind from the catalogue of the node system (Kinds of nodes, Appendix A); a kind the program does not know is refused withgraph_node_not_supported. A group is never a kind of node. The parameters of each kind — The program: graph and runs, sections 5, 11, 18, 22.name— the name of the node given by the person: plain text, like the name of a group. Without the field the node is called by default — by its kind, and a module node by the name of the module (The program: graph and runs, section 4). The field is optional.description— the description of the node in the person's words: what the node does and why it is here; plain text, may take several lines. It does not affect a run (The program: graph and runs, section 4). The field is optional.region— the id of the frame the node lies in; a node outside frames has no such field.collapsed— for a frame: whether it is folded into one node (The workshop, 5.3); without the field the frame is unfolded. A run does not read the field.shown_parameters— optional: the parameters the node shows on the canvas as rows, in the order they were marked — for a module node the names of the parameters of the manifest, for a node of the platform the paths of the fields of its kind (The workshop, 5.3). A run does not read the field, and the function of the graph writes it with the requestprocess.node.showeven for a program that is on, without changing the generation (Methods of the graph).face_marks— optional, for a node of the top level: marks ahead — for the face of the group that will be built of it —inputsandoutputs— the names of its ports,variables— the variables it works with (The program: graph and runs, 17.1). When the node ends up in a group, the marks move to its face and the field goes.memory— for a module node that shares memory with other nodes of its module: the name of the shared memory, Latin letters, digits,-and_. Without the field the memory of the node is named by its identifier (The program: graph and runs, section 13).overlap— for a node of a service that gives packets itself: the overlap rule of its packets —queue,skip,replaceorparallel; without the field —queue. Other nodes have no such field: for an event the overlap rule is its parameter (The program: graph and runs, section 5).- The parameters of events and nodes are set by their kind (Kinds of nodes, Appendix A). A node
notifyhastitle, the title of the notification, andpath, the field of its text (The program: graph and runs, 24.6). An event withsource: "message"hasname, the name of the message; withsource: "change"—variable, the variable it watches; a nodesendhasprocess_id,mode(message|signal),nameand, for a signal,key(The program: graph and runs, section 23). An event withsource: "call"and a noderesulthave an optionalname— the name of the input and the name of the output under which they stand as ports at the node that calls the process; without a name —inputandsuccess. A nodeprocesshasprocess_idand an optionalvalues: the values of the variables of the called process at this place of the call,{ "<variable id>": <a value of its type> }(The program: graph and runs, section 18). The fields are optional. - A node keeps only its own values. The ports of a node of the platform are set by its kind (The program: graph and runs, section 4), the ports and the schema of parameters of a module node by the manifest, the version of the module by
modules.lock.json; they are not copied into the node. A module node keepsmodule_id, the parameters set, its place, frame and group. A parameter missing fromparametersgets the default of the manifest.input_policyandretryof a node, if set, override the same fields of the manifest (The program: graph and runs, 10.3, 12.4). - The value of a parameter is the value itself, a substitution of a setting
"${name}"or a variable{ "variable": "<id>" }(The program: graph and runs, sections 6, 15). variables— the variables of the program:id(an identifier[A-Za-z_][A-Za-z0-9_]*),type— the name of a kind of data from table 11 (16.1),initial— a value of this type ornull: for a picture, sound, video and file — while there is no file,remember— whether the value is kept after the program is switched off,scope— optional,run— a variable of the run: each run has its own value, withoutremember; without the field — a variable of the program (The program: graph and runs, section 7).x,yof a node — its place on the canvas of the graph, any numbers, negative ones too: the canvas has no edges; the layout of the graph is a part of the document of the process.- A link must have
source_node,source_port,target_node,target_port. Theidof a link is optional; if it is missing, the function of the graph gives one on saving. A cold link differs not by a field but by its source: it comes from a nodevariableorconstant. partsof a link — an array of names of parts to pick, ornull(pass the whole content of the packet). A name is looked for first among the parts of the packet (its fieldparts), then in the packet itself — as a path (The program: graph and runs, section 8). On a cold link the picking acts on the value of the variable or constant.viaof a link — optional: the points on the canvas the link is led through, in order, each a pair of numbers[x, y](The workshop, 5.1). A run does not read the field: data go along the link as without it.- A note is a record among the nodes with
kind: "note", a placex,y,group_idorregion, as for a node, and the parametertext— the person's words. It has no ports, no links come to it, and a run never comes to it: it is the shorthand kind УС-06 with no meaning for the work (Kinds of nodes, Appendix A).
A group:
{
"group_id": "g1",
"name": "Ignition",
"node_ids": ["reply"],
"group_id_parent": null,
"x": 120.0,
"y": 40.0,
"collapsed": true,
"ports_in": [{ "node_id": "reply", "port": "input", "name": "Picture" }],
"ports_out": [{ "node_id": "reply", "port": "success", "name": "Done" }],
"variables": ["style"]
}
name— the name of the group as plain text: the person writes it, and it has no translation. A dictionary key and a folder of texts of its own belong to elements delivered ready — to a module (The program: graph and runs, 17.1).description— the description of the group in the person's words, as for a node: what it does and why. The field is optional.node_ids— the nodes lying directly in the group. The fieldgroup_idof a node says the same; if a node is named in both, it is one and the same group, otherwise —graph_invalid(The program: graph and runs, 17.1).group_id_parent— the group inside which this one lies;nullor no field — a group of the top level. Nesting is not limited (The program: graph and runs, 17.1).x,y— the place of a folded group on the canvas: the top left corner of what lies in it (The program: graph and runs, 17.1); an unfolded one takes the place of its area, as a frame does. A group without these fields stands at the corner of its nodes.collapsed— whether the group is folded. Without the field the group is unfolded.ports_in,ports_out— the face: a port of an inner node put outside, with a name of its own. A link from outside still goes to the node in the document, not to the group: folding is a way of showing, and a run does not change from it. Thenameof a row is optional: without it the row is called by the port.variables— the identifiers of the variables of the program shown on the face. The group does not own them (The program: graph and runs, section 7).- Marks ahead at a group of the top level (The program: graph and runs, 17.1):
marked: trueat a row ofports_inorports_out— the row will stand on the face of the group built of this one, andface_marks.variables— the variables of the face marked the same way. When the group ends up in another, the marks move to the face of that one and go.
5.2 state.json — ogas.state/2 and remembered lists
The values of variables marked remember; the owner is the function of the graph. They are read when the program is switched on and go to disk at every write of such a variable:
state.jsonkeeps the values of remembered variables that are not lists, and the generation of each remembered list;- a remembered list keeps its elements in the folder
kept/<variable id>/<generation>/: a list written whole — as one documentall.json(ogas.state-items/1, the fielditems, the elements are numbered from 1 in order), an element added after it or changed — as a document of its own<number>.json(ogas.state-item/1, the fieldvalue), which stands over the element with the same number; the order of the list is the order of the numbers; - writing an added letter is one small document, writing by key is the document of that element; an element added after the whole one and removed — its document is deleted together with the
.bakcopy the kernel keeps beside a rewritten document; a removed element of the whole one, an element inserted not at the end, and a list replaced whole are written whole as a new generation; so is a batch: a write that added or changed more than 64 elements at once (a folder of thousands of pictures is one document, not thousands of small ones, each with its own wait for the disk). The new generation is written beforestate.jsonnames it, and the former one is deleted after: should the writing break between them, the program begins with the former list or the new one, but not with half of each. What is removed does not stay on disk; - the writes of the remembered values of one program go to disk in the order the values changed.
{
"format": "ogas.state/2",
"values": { "style": "watercolor" },
"lists": { "history": 3 }
}
The value of a variable that is no longer in process.json or whose type does not match is not taken when the program is switched on: the variable gets initial. A variable renamed after the last write finds its value under its former name — by the record renamed_objects of the document of the process; its next write puts the value under the new name, and a list — whole into the folder of the new name. state.json and kept/ belong to the person who works with the program: they are not part of an export of the process.
5.3 The memory of a node
state/<name>/ is the memory of a node: what the module of the node saves before unloading (Modules, section 4). The memory belongs to the node, not to the module: a module is one for all its nodes. The name is the identifier of the node or the name of a shared memory from the field memory of the node, named by several nodes of one module. What is in it, the module decides; it gets the path to it with every step of the node in the field state_dir. The platform does not read it, carries it into an export only if the person asked (10.1), and deletes it when no node names it.
Beside the folder lies the mark of the saved memory state/<name>.saved.json — ogas.module-state/1: it names the module that saved the memory. It is written by the function of modules, not by the module: whole, after the module answered that it saved its memory, and removed before the module is asked to save again. The name of the folder is Latin letters, digits, - and _; a node with another identifier and without memory has no memory.
{
"format": "ogas.module-state/1",
"module_id": "painter",
"version": "1.0.0",
"digest": "sha256:…",
"saved_at": "2026-10-07T17:30:00Z"
}
version and digest are the version and print of the module that saved the state (Modules, section 3). A module brought up with the same identifier, version and print gets resumed: true; without the mark or on a mismatch — resumed: false, even if the folder is not empty.
6 The shared object
Shared objects are not kept as a separate list: they are set by the nodes and variables of the graph (The program: graph and runs, section 16).
Table 5 — The shared object
object_id |
Where it comes from |
|---|---|
event:<node_id>, cancel:<node_id>, retry:<node_id>, status:<node_id> |
a node event with source: pult |
var:<variable_id> |
a variable from variables |
ask:<node_id> |
a node ask |
program |
the program itself |
The pulpit keeps only the object_id in its bindings (section 7).
7 The pulpit
workspace.json — ogas.workspace/3: the graph of the interface of the program (The workshop, 6.8). The owner is the function canvas, the meaning of the objects is in 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": "Comic", "holds": "tabs" },
{ "id": "tab_1", "name": "Draw", "parent": "window_1" },
{ "id": "tab_2", "name": "Gallery", "parent": "window_1", "bindings": { "shown": "var:has_frames" } },
{ "id": "group_1", "name": "Scene", "parent": "tab_1" }
],
"elements": [
{ "id": "field_1", "kind": "field", "group": "group_1", "bindings": { "value": "var:scenario" },
"label": "Script", "parameters": { "lines": 6 } },
{ "id": "file_1", "kind": "file", "group": "group_1", "bindings": { "value": "var:hero" },
"label": "Hero", "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": "Draw" },
{ "id": "view_1", "kind": "view", "group": "tab_2", "bindings": { "value": "show:comic" } }
]
}
generation— the generation of the document of the pulpit: each write of the functioncanvasis the next generation after the one written;canvas.snapshotcalls itrevision.pulpit_id— the name of the pulpit, an identifier. A process has one pulpit, its name ismain; the identifiers of containers and elements are unique within the pulpit.theme— the optional theme of the pulpit:{ "<key>": value }. The keys are a closed list of the functioncanvas:background,surface,text,accent,ok,stop— colours of the form#rrggbbor#rgb;font—bundled,system,seriformono;letters— the height of letters, an integer from 8 to 48 units of the sheet;radius— the rounding, an integer from 0 to 40 units of the sheet. The list and the allowed value of each key are the sectioncanvas.themeof the settings schema of the function of the pulpit: the key<key>is described there ascanvas.theme_<key>(Settings, section 8). A key outside the list and a value the key does not take are refused. A key missing from the document is taken from the settings; without the field the pulpit is drawn with the default look.bindings— optional bindings of the top level:open— a variable of typetext: which window is open, by theidof the window. Without it the program opens on the first window.groups— the containers, at least one. A window is a container withoutparent; a tab is a container in one that shows its content one at a time; a group and a subgroup are containers in one that shows everything at once. Windows are shown one at a time, the program begins with the first. A container has:id— an identifier, unique in the pulpit among containers and elements; given by the function of the pulpit;name— the name set by the person; optional: a window without a name is called by the name of the process, a tab by the text «Main» of the dictionary of the function of the pulpit, a group stays without a title;parent— theidof the container it lies in; a window has no such field;holds— how the container shows what lies in it:together(the default) — everything at once,tabs— one at a time, with a switcher;bindings— optional bindings to variables of the program:shown— a variable of typeboolean: atfalsethe container with everything in it is not shown;open— only for a container withholds: tabs— a variable of typetext: which of the nested ones is open, by itsid; switching a tab by hand, the person writes this variable, as a field writes its own. So a process opens a tab and hides a group by writing a variable (The workshop, 6.8);look— the optional name of a look of the container (7.2);screen— the sheet of a page — a window without tabs or a tab of a window:sheet—[width, height]in units of the sheet,background— the underlay:colorandimage, both optional. A page always has a sheet: a page without one gets it when written and when read (The workshop, 6.3). The tabs of one window have one sheet: the function of the pulpit gives them the widest and the tallest of their sheets. A container inside a page is a frame around what lies in it: the function of the pulpit counts it (boxincanvas.snapshot), it has no sheet and size of its own;place— only for an empty one, where it stands;placed—falsefor a frame the person took off the sheet: it and everything that lies in it do not stand on the sheet, and the place they had is kept (The workshop, 6.3). Only for what lies on the sheet of a page; without the field — on the sheet;layer— the place of the container on the canvas of the graph of the interface[x, y],collapsed— whether it is folded there (The workshop, 6.8). An unfolded container is an area around what lies in it;layeris the place where a folded or empty container stands; it is written by the hand that moves the container by its head;reflections— optional reflections: what the working graph gives the interface, as nodes of the graph of the interface (The workshop, 6.4 and 6.8). A reflection has:id— the identifier, the only one in the pulpit among containers, elements and reflections; the function of the pulpit gives it:reflection_<n>;objects— its rows: theobject_idof shared objects, at least one. An element is tied to a reflection by a shared object;source— what is reflected:node:<node_id>— a node as a whole,in:<node_id>/<input>,out:<node_id>/<output>,param:<node_id>/<parameter>— a parameter that takes the variable of the row,var:<variable>,group:<group_id>— the face of an assembled node,program— switching the program on; the reflection is named by it and from it one goes to the original;group— an optional container the reflection lies in on the graph of the interface; without it — in the first window. A container in which at any depth only reflections lie and no element does not stand on the sheet;layer— the place on the canvas of the graph of the interface[x, y]; the hand writes it;elements— the elements. The order in the list is the order inside the container, the order of drawing on the sheet (the last on top) and the order of going round with the keyTab. An element has:id— an identifier, unique in the pulpit; given by the function of the pulpit: the kind and a number;kind— the kind of the element from the set (table 6);group— theidof the container the element lies in;bindings— bindings to shared objects (The program: graph and runs, section 16):{ "<binding name>": "<object_id>" }; a binding the kind requires may be missing: such an element is written and markedunbound— it was put on the graph of the interface and not yet linked; a binding to several objects names each by its own name —{ "<name>": "<object_id>", … }, the name is an identifier. The names of bindings and the allowed kinds of objects are named by the kind of the element (table 6). A decoration has no such field;label— the label set by the person; optional and not empty: without it the window names the element by its object — with the text of the dictionary of the graph for the kind of the object. A decoration has no such field;hint— the hint set by the person: what the element sets and which way to turn it; optional and not empty. The window shows it over the element when the pointer is held over it and tells it to a screen reader. A decoration has no such field;screen—place—[x, y]of the top left corner andsize—[width, height], integers in units of the sheet: only for an element that lies on the sheet of a container at any depth; there the element lies on the sheet whole and is not smaller than the smallest size of its kind;anchor— optional: how the element holds on in a window bigger than the sheet as drawn (The workshop, 6.3):x—left,right,middleorstretch,y—top,bottom,middleorstretch; what is missing is said by the kind of the element;placed—falsefor an element that is not placed: the person took it off the sheet or has not yet laid it on it. It works like any other but is not drawn, the function of the pulpit gives it no place, and thescreenit had is kept as it is — numbers that need not lie on the present sheet. Only for what lies on the sheet of a page; without the field — on the sheet;layer— the place of the graphic node on the canvas of the graph of the interface[x, y], in the measures of the working graph; written by the hand that places and moves the node. Without it the node stands where the initial layout puts it: windows one under another to the right of the working graph, the elements of a container in a column in it;look— the optional name of a look of the element (7.2); without it the element is drawn with the default look of the set;parameters— optional parameters of the kind of the element (table 6).
Table 6 — The first set of pulpit elements
kind |
Element | Family | Bindings | Parameters |
|---|---|---|---|---|
blank |
empty element | — | holds — what it holds: any object of the program — an event, a question, «Show», an output, an input, a link, the progress of a step, a variable. An empty element is a graphic node whose kind is not chosen yet: the function of the pulpit writes placed: false for it, it is not laid on the sheet, and canvas.snapshot marks it no_kind while it is bound to something (The workshop, 6.8) |
— |
button |
button | action | act — an event, its stop or retry, or a signal a node waits for (signal:<node_id>); carries — optional variables whose values the button carries to the event, each under the name of a field of the packet (The program: graph and runs, section 5); allowed only for a button of an event and of a signal: to a signal they go as its data; opens — an optional container of the same graph: the button opens a tab or a window, and with act also presses the event; resets — an optional container of the same graph: the button returns to its initial value each variable written by the input elements in it at any depth (process.variable.reset) — so settings have «Return as it was». A button names at least one of act, opens, resets |
— |
toggle |
switch | input | value — a variable of type boolean or switching the program on |
— |
rows |
rows | input | value — a variable of type list: the person edits it by rows — changes a cell, adds a row under the last and removes a row; the fields of a record are columns, a list not of records has one column. A cell takes what its column holds in the first row where it is set: «yes» or «no» — by a switch, a number — by a number, a text — by a line; a column missing from all rows — by a line; anything else is shown by the rules of showing (16.5) and is not edited here. An added row is a record of the columns, each empty of its kind: an empty line, «no»; a number is not set until it is typed. The variable gets the whole list when typing in a cell is done, a row is added or removed |
fields — the list of fields seen as columns, in order; empty — the fields there are in the records, in the order they appear; titles — the words over the columns, in order; an empty line or its lack — the name of the field; lines — how many lines of text are seen in a cell, an integer from 1 to 12, 1 by default: more than one — the cell has several lines, and Enter breaks the line |
field |
field | input | value — a variable of type text, time, json or list; a time is chosen with the date and time picker of the system, a value of json and list is typed as JSON text |
lines — how many lines are seen, an integer from 1 to 40, 1 by default; more than one — the field has several lines; writes — when the field writes the variable: done — when typing is done, on Enter or leaving the field, the default; typing — also at each pause in typing, only for text: data typed halfway have not become a value |
file |
file | input | value — a variable of a picture, sound, video, file or json: the chosen file goes into the files of the process, and the variable gets a reference to it (The program: graph and runs, section 24) |
kind — the kind of file: image, audio, video or file (the default) |
number |
number | input | value — a variable of type number |
min, max, step — optional numbers |
choice |
choice | input | value — a variable of type text |
options — the list of values; while it is empty, there is nothing to choose from; titles — the words the values are shown to the person with, in order; an empty line or its lack — the value itself: so the variable keeps the code of a parameter of a module, and the person sees a word; models — a kind of neural networks: then the choice is among the networks of this kind in the library, and options is not needed |
ask |
question | input | question — a question to the person; the answer is of the kind the question node asks for: text, number, choice, yes or no, an area, points or what is painted with a brush on the picture of the question, a file of its kind (The program: graph and runs, section 9) |
— |
value |
value | showing | value — a variable of any type, an output of a node (out:<node_id>/<output>), an input of a node (in:<node_id>/<input>) or a link (edge:<edge_id>) |
— |
view |
view | showing | value — a node «Show» (show:<node_id>), an output of a node (out:<node_id>/<output>), an input of a node, a link or a variable: shows the same way as the node «Show» on the canvas — text, number, list, picture, gallery, a player of sound and video (16.5) |
— |
table |
table | showing | value — a variable of type list, a node «Show», an output of a node, an input of a node or a link: the records of the list as rows, the fields as columns, a cell by the rules of showing (16.5), a picture as a picture; picked — an optional variable into which a click on a row writes its key; the chosen row is the one whose key equals the value of the variable; act — an optional event: a click on a row after choosing presses it, like a button; in a program that is off it only chooses; carries — as for a button, allowed only with act; the choice variable in it already holds the key of this row; only — an optional variable: only the records whose field by equals its value are seen, and while it is empty — none. A long list stands in parts of 200 rows: the next part comes when the person has scrolled the table to the end of what is drawn, or by the button «Show more» with the number left (a strip of thousands of pictures drawn whole delays each redraw of the window by 0.7 s) |
fields — the list of fields seen as columns, in order; empty — all fields of the first record; titles — the words over the columns, in order; an empty line or its lack — the name of the field (the check of the pulpit accepts an empty line only here, not in fields); sort — the field the rows stand in order by: numbers by size, the rest as text, a record without the field after the others; empty — in the order of the list, and the list itself does not change its order; order — up ascending or down descending, up by default; key — the field of the record written into picked; empty — the whole record; pick — one: a click chooses one row, the default; many: each row has a mark, a click marks the row or takes the mark off, picked keeps the list of keys of the marked rows, and a click does not press the event; by — the field of the record compared with the value of only; lines — one: a cell of one line, the long cut off, the default; all: the text is read whole, the cell grows; follow — no: the table stays where it was left, the default; end: a new row at the bottom comes into view by itself, like a line of a conversation |
bar |
bar | showing | value — a variable of type number or the course of a step of a module node (progress:<node_id>): a share from zero to whole |
min, max — the bounds of the bar for a variable; 0 and 100 by default |
indicator |
indicator | showing | state — the state of the run of an event |
shows — color (the default) or words: the state by colour or by words |
label |
label | decoration | — | text — the text of the label, optional: without it the label names itself; size — an optional height of letters in units of the sheet; align — left (the default), center or right |
picture |
picture | decoration | — | image — an optional name of a picture file (7.2): without it an empty place on the sheet; fit — contain (the default), cover or stretch: the whole picture, over the whole area, or stretched |
A binding not named optional is required. The set is extended by the platform: a new kind of element does not change the format. There is no frame in the set: gathering elements together is the business of a group.
What the function of the pulpit refuses (canvas_invalid, naming the element or container and the field): a document without containers; a repeated id; a parent or group that is not there; a container lying in itself directly or through others; holds outside the list; a binding of a container other than shown and open, open at a container without tabs, and a binding of a container not to a variable; opens that names something other than a container; kind outside the set; a binding the kind of the element does not have, a missing required binding, several objects where there is one, and the other way round; opens or resets that name something other than a container of this pulpit; a parameter the kind of the element does not have, or its value out of the allowed; an empty hint; place and size at what does not lie on a page; a sheet at a container that itself stands on the sheet of another; size at a container; an element on a sheet that goes beyond the sheet or is smaller than the smallest size; placed that is neither true nor false, and placed: false at what does not lie on a sheet; anchor that names anything but x and y, or a value outside their list; a reflection without objects or with an empty list, a group of a reflection that is not there, and a repeated id of a reflection; label, hint or a binding at a decoration; a key of the theme outside the list or with a value not allowed; a picture name that is not the name of a picture file (7.2); two elements of one kind with the same bindings in one container (The workshop, 6.2) — except decorations.
What the function of the pulpit does not refuse but marks. An object that is not in the graph, and an object whose kind or type does not fit the element or container, are not a refusal of writing: the graph changes after the pulpit, and the pulpit must not lose its document because of that. canvas.snapshot gives such an element or container marked, and the workshop shows it in its place (Getting started, 4); a marked element sends and writes nothing, and a container with a marked binding is shown as without it. Marked the same way is what has its picture missing from the process folder (7.2): why — image_gone; the underlay of such a sheet is shown in one colour.
What the function of the pulpit adds on writing:
- an element or a container without
idgets one; an element withoutgroupgoes into the first container that has none nested; a container withoutholdsshows everything at once; - a page without a sheet gets a sheet of the size of a new sheet;
- an object an element is bound to and no reflection holds gets a reflection of its own (
source— the object itself); a reflection withoutidgets one. The same on reading: a pulpit built earlier or by the assistant is read with reflections; - what lies on a page without a place and is not taken off the sheet (
placed: false) gets a place where the page would put it itself (The workshop, 6.8): the elements of a container from top to bottom, under what already stands in it — what is read and typed in at full width, buttons one after another in a row, the rest at the width of its kind; then its containers — as a frame with a head 32 units high and margins of the gap of the sheet; the tabs of a container of tabs — one above another. The places are on the step of the sheet, with the margin from the edges and the gap set by the settings of the function of the pulpit (Settings, section 8); - when what is put into a standing frame makes it taller, what stands under it goes down by as much; the sheet grows down to what stands on it;
- a sheet at a container inside a page is taken off, and what stood on it gets places anew.
The place and size written in the document the function of the pulpit does not change otherwise. A pulpit without sheets is laid out the same way when read.
The document is read with canvas.get; canvas.snapshot is a surface for the window, not the document.
7.1 The layout of the windows of the workshop
data/config/layout.json — ogas.layout/1. The owner is the function ui, which writes it at the request of the page (ui.window.layout.set, Methods of the workshop and the pulpit, section 2). The document keeps the arrangement of windows the person left and is not a setting: it is not in the settings window. Like user.json, it belongs to the person who works here and is part of neither the repository nor the delivery.
{
"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] }
}
host— the size of the host the layout was written on,[width, height]in CSS pixels;nullwhile nothing is written.windows— the open windows on the host, no more than 96. A window has:kind— the kind of the window;process— for a window of a process (graph, pulpit, program journal) the identifier of its process (The workshop, section 5); a window without it shows the process open at the start;x,y,w,h— the rectangle on the host;z— the order of stacking;maximizedandfolded— maximized and folded in place;minimized—0or the place in the bottom bar;restore— the rectangle before maximizing, ornull. The fieldstiled(yes or no) andsnap({ kind, side }ornull) are accepted and kept by the functionuiand not read by the page: a window stands where it was put (The workshop, 5.1).panels— where the person put the panel of the chosen in the window of each kind:{ "<kind of window>": [x, y, w, h] }— a rectangle in the work area of the window, in CSS pixels, no more than 32 kinds. A kind whose panel stands in its own place at the bottom of the area is not inpanels(The workshop, 5.1). The field is optional. A kind of window the page does not know and a place without a size are skipped; inside the area the page keeps the panel, whatever its size.- At the start the page applies the layout to the host of this start: the rectangles are recounted in proportion to the host the layout was written on and stay inside the new one. A kind of window the page does not know and a repeated kind are skipped; a pair whose second half did not come back falls apart.
7.2 Pictures of the pulpit and the look of an element
The pictures of the pulpit and its own looks of its elements lie in the process folder, in the folder pulpit/; the owner is the function canvas. They belong to the process: deleting the process folder takes them along, handing the process over carries them.
processes/<process_id>/pulpit/
images/<file> pictures of underlays and decorations
looks/<look_id>/look.json a look of an element of its own
looks/<look_id>/<file> the pictures of this look
- The document of the pulpit names a picture by the name of its file in
images/: without folders, the name does not begin with a dot, is no longer than 120 bytes and ends in.png,.jpg,.jpeg,.gif,.webpor.svg. - A picture is a PNG, JPEG, GIF, WebP or SVG file: the kind is named by the ending of the name, and the file must begin the way a file of this kind begins. The size is no more than the setting
canvas.image_max_bytes(Settings, section 8). The window shows a picture only as an image: scripts inside SVG are not run, outside links are not loaded. - A picture is put into the folder by the function of the pulpit: the window gives it the file itself, chosen by the person, in one message (Methods of the workshop and the pulpit, section 3). The file is written beside and gets its name when written whole; a file with the same name is replaced. A file put into the folder by hand is seen by the function the same way, and an unfit one is not given out. Links in the folder are not read and not carried.
lookof an element and of a container names a look by itslook_id. A look is looked for first among the process's own looks, then among the built-in looks of this element at the functioncanvas. A look that is not there (look_gone), a look made for another element (look_unfit), and an own look whose description does not pass the check (look_broken) do not stop the element from working: the element is drawn with the default look of the set, and the surface names the cause inlook_why.- A built-in look is the same kind of document with pictures in the folder of the element at the function
canvas:elements/<kind of element>/looks/<look_id>/(The workshop, 6.2). The name of a built-in look for the person is in the dictionary of the element:canvas.element.<kind of element>.look.<look_id>.
The folder pulpit/ is carried with the process (10.1).
look.json — ogas.look/1. A look is data: there are no scripts and no links beyond its own folder in it; a field outside the list is refused.
{
"format": "ogas.look/1",
"look_id": "brass",
"kind": "button",
"name": "Brass",
"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"
}
look_id— the identifier, which is also the name of the folder of the look;kind— the kind of element the look is made for;name— an optional name for the person; without it the look is called by itslook_id;size— an optional size[width, height]the look is drawn for, in units of the sheet, no less than the smallest size of the element: an element given the look takes this size — so a round lamp stays round;states— the pictures by the states of the element:{ "<state>": "<file>" }. The states are named by the kind of the element (table 7). The picture of the first state of the kind is required when the look is not painted (paint); a state without a picture is shown with the picture of the first;slice— optional four integers: the insets from the top, right, bottom and left, in points of the picture, by which the picture is cut into nine parts. The corners keep their size, the edges stretch along, the middle in both directions. Without the field the picture is stretched over the whole element. One point of the picture is one unit of the sheet;content— optional four integers: the insets of the words and fields of the element from its edges, in units of the sheet;words— optional: the colour of the words of the element over the picture,#rrggbb, orfalse— the look says everything with pictures, and the element shows no words of its own;value— optional and only for an element that shows a quantity (table 7): how the look draws the share between the bounds. The way is one of three:{ "fill": "<file>", "slice": […], "inset": […], "from": "left" }— a fill picture stretched over the share:inset— the insets of the fill area from the edges of the element,from—left(the default) orbottom;{ "frames": "<file>", "count": 11, "along": "row" }— a strip ofcountequal frames in a row (row, the default) or in a column (column); the frame is chosen by the share. From 2 to 256 frames;-
{ "pointer": "<file>", "turn": [-120, 120], "pivot": [0.5, 0.5] }— a pointer: a picture over the whole element, turned by an angle betweenturn[0]andturn[1]degrees by the share around the pointpivot— in shares of the width and height of the element, the middle by default. -
paint— optional: the look is painted, not put together from pictures (The workshop, 6.5). It is made by eye in the panel of the element, and the document of the look is onelook.json. The fields: states— colours by state:{ "<state>": { "fill", "stroke", "words" } }— background, frame and words, each#rrggbband optional; the first state of the kind is required, the others take what they lack from it;radius— the rounding, an integer from 0 to 64 units of the sheet;stroke_width— the width of the frame, from 0 to 16;pattern— a pattern over the background:{ "kind": "stripes" | "checks" | "dots", "color": "#rrggbb", "size": 2…64 }— stripes, checks or dots, the step in units of the sheet;font—bundled,system,seriformono, as in the theme of the pulpit;letters— the height of letters, from 8 to 48;value— the colour the quantity is filled with, only for an element that shows one.
A look may be both painted and put together from pictures: the picture of a state lies over what is painted.
Each picture named in states and in value lies in the folder of the look and passes the same check as a picture of the pulpit; there is nothing in the folder of an own look but look.json and the pictures it names. The whole size of a look is no more than canvas.image_max_bytes.
Table 7 — The states of elements for a look
kind |
States | When |
|---|---|---|
button |
rest, hover, pressed, disabled |
at rest; under the pointer; pressed; the command cannot be carried out now: an event — the program is off, a stop — no run is going, a retry — the last run of the event did not fail |
toggle |
off, on |
off; on |
field, rows, number, choice, file |
rest, focus |
at rest; the cursor stands in the field or the cell, or the file choice has the focus |
ask |
rest, asked |
nobody is asked; the question is open |
value, view, table |
rest |
— |
bar |
rest; shows a quantity |
the underlay picture; the share — the field value |
indicator |
idle, running, completed, failed, stopped |
there was no run; going; went through; a failure; stopped, interrupted or cancelled |
group — a container |
rest |
— |
label, picture |
none | they have no looks |
The states hover, pressed and focus the window learns itself — by the pointer and the cursor — and shows over the state the element is in. The built-in looks of the first set: button — key, toggle — lever, indicator — lamp, bar — tube (fill) and dial (pointer), a container — plate. The look of a container is described the same way, with kind: "group".
7.3 The library of the workshop
data/config/library.json — ogas.library/1. The owner is the function ui, which writes it whole at the request of the page after each change (ui.window.library.set, Methods of the workshop and the pulpit, section 2). The document keeps what the person keeps in view of their programs and modules (The workshop, 5.6): the panels of programs on the right and what the column of the graph does not offer. Like the layout (7.1), it belongs to the person, is not a setting and is part of neither the repository nor the delivery.
{
"format": "ogas.library/1",
"bars": [
{ "id": "programs", "name": "", "programs": ["telegram", "process-5"] },
{ "id": "bar-2", "name": "Games", "programs": [] }
],
"hidden": { "programs": ["process-3"], "modules": ["echo"] },
"views": { "programs": "tiles", "models": "table" },
"groups": { "programs": true, "models": false },
"fits_only": true
}
bars— the panels of programs in their order from top to bottom, no more than 32. A panel has:id— small Latin letters, digits and-, no longer than 40 and not repeated;name— the name the person gave, no longer than 80 letters; an empty name is shown by the window with the word of the section «Programs»;programs— the identifiers of the programs on the panel in their order, each once.hidden.programsandhidden.modules— programs and modules the column of the graph does not offer, each once. What is hidden stays installed and works where it already stands.views— in which view the person looks at a section of the library: the key is the section (programs,modules,models,pieces,sources), the value istilesortable. No section, no field or another value — tiles.groups— whether the person shows a section in groups: the key is the section, as forviews, the value istrueorfalse. No section or no field — neural networks in groups by kind, the rest as one list.fits_only— the switch «Only what will run»:truehides things that need more video memory than the video card of the computer has. No field —false.- Each list holds no more than 1024 identifiers. A document that does not agree with this the function
uidoes not write and does not give out:document_invalidnaming the field. - Before the first write
ui.window.library.getgives one empty panelprogramswith an empty name and an emptyhidden. Which programs and modules there are, their owners say: an identifier that is no longer there the document keeps and the window does not show; a program and a module deleted from the workshop the window removes from the document itself.
7.4 A piece of interface
data/library/pieces/<piece_id>.json — ogas.piece/1: a container of the pulpit with everything in it, kept in the library to put it into another program (The workshop, 6.8). The owner is the function canvas: it makes a piece of the written pulpit of a process (canvas.piece.save, Methods of the workshop and the pulpit, section 3), gives it out and deletes it. A piece belongs to the person, like the library (7.3), and is part of neither the repository nor the delivery.
{
"format": "ogas.piece/1",
"piece_id": "razgovor",
"name": "Conversation",
"groups": [
{ "id": "talk", "name": "Conversation", "holds": "together", "layer": [640, 120] },
{ "id": "more", "parent": "talk", "holds": "together" }
],
"elements": [
{ "id": "field_1", "kind": "field", "group": "talk", "label": "Message", "parameters": { "lines": 3 }, "layer": [660, 180] },
{ "id": "button_1", "kind": "button", "group": "talk", "label": "More", "bindings": { "opens": "more" } }
]
}
piece_id— the name of the piece, which is also the name of the file: small Latin letters, digits and-, no longer than 40. The function of the pulpit gives it from the name in Latin letters; a name without Latin letters givespiece; a taken one gets a number after-.name— the name: the one sent when saving, otherwise the name of the container, otherwise itsid.groups— the saved container first, then those nested in it at any depth, in the order of the pulpit;elements— the elements lying in them, in the order of the pulpit. The fields are the same as in the pulpit (section 7), with these taken off:- the saved container has no
parent, and itsscreenhas noplaceandsize: the place on the sheet of what it lay in belongs to that; - containers have no
bindings: the variables that show and open them are variables of their own program; - of the
bindingsof an element only the bindings to a container stay —opensandresets— if they name a container of the piece itself; the rest is taken off, and an element put into another program is markedunbounduntil a link is drawn to it; - a
lookthat names an own look of the process is taken off; a built-in look stays. - A piece is put by the window: the containers get new
ids free in the pulpit, the saved container goes into the container the person chose, the elements come withoutidand get one from the function of the pulpit when written,opensandresetsare moved to the new names, the placeslayershift together. What is put is a part of the pulpit of the program: it is no longer tied to the piece.
8 Settings
Files: data/config/core.json (only core.*), data/config/system.json, data/config/user.json, processes/<id>/settings.json. The session level is not kept in a file. Format ogas.settings/1.
{
"format": "ogas.settings/1",
"generation": 1,
"values": {
"core.health_interval_ms": 5000,
"i18n.language": "ru"
}
}
The levels, the order of reading, the schema of keys and their list — Settings. There are no secrets in these files.
The settings schema of an owner — the file settings.schema.json beside the code of the owner, format ogas.settings-schema/1. The program of the owner builds it in.
{
"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 }
}
}
]
}
Table 8 — Settings
| Field | Meaning |
|---|---|
owner |
the owner; each key begins with <owner>. |
group |
the large section of the settings window: core, ui or other |
sections |
the subsections in the order the window shows them; the id of a subsection begins with <owner>. |
keys |
the keys of the subsection; the order in the window is by the name of the key |
type |
string, integer, number, string[] or color |
default |
the default value; required, and itself passes the check by the schema |
default_by |
optional: { "key": "<a key of the same owner>", "values": { "<a value of that key>": <default> } } — the default when that key has taken the given value; otherwise default holds |
restart |
whether a restart is needed for the value to take effect |
min, max |
for integer and number — the allowed bounds, inclusive |
choices |
a closed set of allowed strings |
pick |
optional, for a string only: folder or file — a path the person may choose in the dialog of Windows rather than type; the value is the path as Windows writes it |
There are no names and explanations in the schema: they are kept in the dictionaries of the owner under the keys setting.<key>.title, setting.<key>.help, setting.<key>.choice.<value> and setting.section.<id> (Settings, section 2).
9 Versions of modules and the generation of documents
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. The owner is the function of the graph; files holds only the documents it writes:
{
"format": "ogas.generation/1",
"generation": 1,
"files": ["process.json"]
}
workspace.json, settings.json and modules.lock.json belong to the functions canvas, settings and modules. The graph checks the completeness of a generation only by its own files; it compares the recorded versions of modules with the query module.lock.get.
After a failure the generation is accepted for which all files exist, have the same generation and can be parsed. An unfinished generation is rolled back to the previous .bak set, if it is complete.
There is no history of versions beyond the current generation and the previous one: an edit in the workshop is taken back by the steps of the history of edits, and what is saved is guarded by handing the process over as a folder.
10 The packet on a link and the artifact
{
"packet_id": "packet-1",
"run_id": "run-1",
"iteration_id": 0,
"delivery_id": "delivery-1",
"source": { "node_id": "echo_one", "port": "success" },
"parts": { "text": "example" },
"artifacts": [
{
"artifact_handle": "sheet-1.svg",
"kind": "file",
"size": 1234,
"media_type": "application/octet-stream"
}
]
}
The result file is data/processes/<process_id>/results/<run_id>/<artifact_handle>, up to 64 MiB by default (modules.artifact_max_bytes). The reference is the name of the file among the results of the run, given by the module: without folders, not beginning with a dot, a name taken in the run gets a number (Modules, section 6). There are no absolute paths in JSON. The field name is the path under which the module made the file in the work folder.
10.1 The export of a process
The export of a process is the folder data/exports/<process_id>/ of the format ogas.export/3. The documents of the process are kept as JSON, the files of modules as they are, without base64 and without the limit of the document size. Together with the process, the processes it calls at any depth go into the export (The program: graph and runs, section 18): a call is a reference, and without them the process would not work where it was carried.
exports/workshop/
package.json what is inside
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 pictures and looks of the pulpit, if there are any
files/7f3a91c2-cat.png files of constants and variables, if there are any
state/paint/… the saved memory of a node, if it was asked for
state/paint.saved.json and its mark
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": []
}
]
}
- The export of a module holds the same as the print counts: without
.venv,__pycache__,*.pyc,requirements.freeze.txtand.git. So the copy has the print of the source, and the import checks it: on a mismatch the module is deleted, the answer ismodule_changed. - Symbolic links are not carried. On export a link inside a module is not copied and is listed in
links_left_out; an export with a link is refused when added (module_invalid) — otherwise copying could carry any file of the receiving machine intomodules/. calls— the processes the exported one calls, each once, with its own documents incalls/<process_id>/documents/. The modules of all processes of the pack lie in the commonmodules/. On import each called process becomes a new process with a free id, the calls are moved to the new ids, and the called ones are written before the caller.- The folder
pulpit/— the pictures of the pulpit and its own looks of its elements (7.2) — goes into the pack when there are files in it: it is copied by its owner, the function of the pulpit, without links and without half-written files, andpackage.jsonnamespulpit—{ files, bytes }. On import it becomes the folderpulpit/of the new process. The pulpit of the called processes of the pack is not carried, and there is no such folder. - The folder
files/— the files held by constants and variables (16.3) — goes into the pack when there are files in it: it is copied by the function of the graph, under the same names, without links and without half-written parts;package.jsonthen hasfiles—{ files, bytes }. The import puts them intofiles/of the new process, and the references in the documents go on naming them. The files of the called processes, like the pictures of their pulpits, are not part of the pack. generation.jsonis not part of the pack: the receiving instance writes its own generation.- The Python environment is not part of it: it is rebuilt on the spot (Modules, section 5).
- Saved memory goes in only if the person asked (
include_state): the foldersstate/<name>/with their marks beside, and inpackage.json—state(which memory lies there) andstate_left_out(which stayed at home: without a mark or at a module that is up). The import makes it the memory with the same names of the new process; a module that has other files here does not take it as its own — the mark names another print (5.3). - A repeated export of the same process replaces the former one whole.
11 The checkpoint
data/processes/<process_id>/runs/<run_id>/checkpoint.json — ogas.checkpoint/2: the head of the checkpoint; beside it are the sealed parts checkpoint.part-<n>.json (below).
{
"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 }
}
- Parts. The records of steps and the outputs pile up in the head; when a hundred records of steps have gathered in it — an inner quantity of the function of the graph — they are sealed together with the outputs into a part
checkpoint.part-<n>.jsonof the formatogas.checkpoint.part/1(run_id,part— the number from 1,executions,outputs), and the head piles up anew. A part is written once and before the head that names it: should the writing break between them, the former head still holds these steps, and the part is written again.parts— optional: how many parts lie beside the head. A reader — resume, retry,process.snapshot, recovery after a stop of the platform — gathers the whole: the steps and outputs of the parts in order, then of the head; the gathered one has no fieldpartsand is the same as a document with all the steps would be. A run broken off by a stop of the platform is marked interrupted in the head; the parts stay as they were. The reason: the head is rewritten at every step, and in one document with all the steps the writing would grow with the square of their number (sections 4 and 7). queued— the packets in queues: the node and the port, thedelivery_idof the delivery, thepacket_idanditeration_idof the packet, its datapayloadand the references to filesartifacts(section 10). By them the resume restores the queues.status:running|completed|failed|cancelled|interrupted.resume.allowedandresume.reasondecide whether the run may be resumed (The program: graph and runs, section 14).stopped_by— present only in a run with the outcomecancelled:person|replace|switched_off— who stopped it (The program: graph and runs, 12.5).error— present only in a run with the outcomefailed:{ error_code, message, node_id, message_key, category }— why the run failed;message_key— the words the refusal named (each refusal has at leasterror.<code>),category— whose refusal it is, for examplemodule(The program: graph and runs, 12.5).node_id— the node the run stopped on; there is no such field if the refusal happened not at a node. The refusal of a step here is the same as in the record of the step.event_node— optional: the id of the nodeeventthat began the run. Without the field the run was begun by starting a node or a group (The program: graph and runs, 12.1).event_port— optional, present only when the run did not begin from the outputevent: a run begun by a packet of a service begins from the node of its module and from the output the service named (Modules, section 7). The resume begins the run from the same place.asks— optional, present only when a question to the person is open in the run:{ node_id, packet_id, iteration_id, question }for each open question (The program: graph and runs, section 9). After a failure and a resume the question is open again, under a newask_id, and the term of the answer is counted anew: while the platform did not work, the person did not see the question.signals— optional, present only when a branch waits for a signal from outside:{ node_id, packet_id, iteration_id, payload, artifacts, key }for each waiting branch (The program: graph and runs, section 22).key— the key the branch waits with, when the node names a pathkeyand there is a value at it: by it the window lets the person choose which branch to send a signal to. The other parameters of the awaited signal are not part of the record: they are read from the node, as for a question, and on resume the key too is read anew.run_variables— optional, present only when the process declares variables of the run:{ "<id>": value }— what they hold in this run. The resume begins with them; a value not of the declared type is replaced by the initial one (The program: graph and runs, section 7).waits— optional, present only when a pause is going in the run:{ node_id, packet_id, iteration_id, until_ms, payload, artifacts }for each waiting branch, whereuntil_msis the moment of real time the branch waits until (The program: graph and runs, section 19). The resume waits out what is left; a moment already past lets the branch go at once.frames— optional, present only when a frame «For each» is working in the run:{ node_id, packet_id, items, results, done, sent, files, result_files }for each such frame, wherepacket_idis the one its elements go into the body with (The program: graph and runs, section 11),items— its list,results— what is gathered so far,done— which elements came back,sent— how many were sent into the body,files— the files that came with the list,result_files— the files of each result that came back; the two last fields, if missing, count as empty (The program: graph and runs, 11.2, 14). By this record the resume restores the frame and sends the remaining elements.outputs— packets that went into no link: an output of a node without links. A record —{ node_id, port, packet_id, payload, artifacts, code: "packet_absorbed" }; of each such record the function of the graph publishespacket.absorbedonce, and the journal of the run names it (The program: graph and runs, 10.2).dropped— optional, present only if there were dropped packets: packets the input ruleanyor the mergefirstdid not choose and that could not leave throughoverflow(The program: graph and runs, 10.3). A record —{ node_id, port, packet_id, delivery_id, iteration_id, reason }.reason—unselected(the input rule took another packet of the same round) orstalled(the run ended, and the packet still stood in the queue waiting for a partner that did not come — The program: graph and runs, 10.4), orwithdrawn— the wait of a question, a signal or a pause is taken off because the node that takes the first packet of a round took another (10.3 there); such a record hasdecided_by, the node that decided, instead ofport; orstopped— the node lies in a group the person stopped: the wait of a question, a signal or a pause is taken off, or a packet that came to the node is not taken (The program: graph and runs, 12.3).updated_ms— when the checkpoint was written, in milliseconds from the epoch; past runs are ordered by it (The program: graph and runs, 12.6). A run without the field is ordered by the time its folder was changed.- A branch that waited for a question, a signal or the end of a pause and went on is recorded as a step of its node:
status: completedand the output it went by —answer,declined,timeout,signalordone. By this record the waiting node is shown as done. - A step of a module going beside the run stands in
queuedof its node with the data it took, until it ends (The program: graph and runs, section 14). Data gathered by the ruleallfrom several inputs stand at each of their inputs. - The record of a step whose refusal went to the output
failedof a module node is the record of a finished step:status: completed,port: failedand the fieldcaughtwith the refusal itself (The program: graph and runs, 12.4). The resume does not repeat such a step. - The record of a step broken off by stopping the run or the group —
status: cancelled, with the fieldspayload,input_portanderror— what the module answered (The program: graph and runs, 12.3). The resume returns such a step to the queue if its operation was not done later. - The record of a finished step keeps identifiers, not the input data: the resume needs to know which operations are already done. The input data (
payload) are kept only by a refused or broken-off step — on resume they are returned to the queue. The checkpoint is rewritten at every step, and the data of every step would make it the size of all the data of the run. - The record of each step is kept, so the checkpoint grows with the number of steps, about 280 bytes per step: the document limit of 8 MiB comes at about 30,000 steps per run.
The mark «Keep» — runs/<run_id>/keep.json in the process folder, format ogas.run-keep/1. It is written and deleted by the function of the graph (The program: graph and runs, 12.6); the clearing of runs does not delete a marked run.
{ "format": "ogas.run-keep/1", "run_id": "run-1", "kept_at": "2026-09-17T10:15:30.123Z" }
12 The lock of the instance
data/ogas.lock, mode 0600, the lock that holds is a flock on the open descriptor:
{
"pid": 1234,
"started_at": "2026-08-30T10:15:30.123Z",
"nonce": "n-3f9a1c0b7e2d4a65"
}
nonce — a random mark of this start of the instance: eight bytes of the system's randomness in hexadecimal.
13 The journal and the problem
A record of the common journal of events data/logs/events-<YYYY-MM>.jsonl — by the month of the time of writing — and of the journal of a run runs/<run_id>/events.jsonl in the process folder:
{
"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" }
}
A record is an event of the bus as the kernel sent it out: event_id, event_type and payload. To it are added the level level (info, warn or error; the level named in payload, or error for a refusal) and the fields the journal is searched by: source, trace_id, run_id, node_id. A record has no dictionary key of its own: the person is told the event by the text event.<event_type> from the dictionary of its owner.
The kernel journal data/logs/core.jsonl is written by the kernel itself — refusals of functions, introductions, restarts; the function observe does not write it:
{
"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"
}
The fields of a record: time, source (the kernel or the id of the function the record is about), event, error_code (or null) and message. A line a function wrote to stderr lies here as well, as a record function.stderr — no longer than 4 KiB, a long one is cut. message is a short hint for whoever looks into a refusal by the journal; it is not a text for the person in the workshop, so it is not translated and has no dictionary key. To the person the same is explained by a problem from problems.json by its code.
The list of problems is data/problems.json, format ogas.problems/1: { "format", "problems": [problem, …] }; only the function of observation writes it. A problem is described by the fields problem_id, code, severity (info, warn or error), a pointer to the place pointer (function_id, process_id, run_id, node_id, trace_id; for a missing text also key), the sign open, the counter count, the times first_seen and last_seen, and also the event that opened it: event_type and payload. A closed problem carries open: false and the time of closing resolved_at. A repetition of the same refusal raises count and adds no new line; the same refusal is the same event with the same code in the same place: at the same function or in the same node of the same process, and for a missing text — with the same key, in whatever language it was looked for. A repetition of a closed problem opens it again: open becomes true, resolved_at is removed. The list of problems is given by observe.problems.list, the events of the journal by observe.logs.query.
- The kernel writes only
core.jsonlandboot.jsonl; the functionobserve—logs/events-<YYYY-MM>.jsonlandprocesses/<process_id>/runs/<run_id>/events.jsonl; the filelogs/events.jsonl, if there is one, it only reads. The function learns the process of a run from the first event of the run that names it — the beginning of the run. - The journal is read only by lines ended with
\n. - The level
warnof a record does not open a problem by itself.
14 Ties
The ties of belonging are given in the table. A tie «one to many» means that one working process may have any number of such items, and each of them belongs to one process.
Table 9 — Ties
| Whole | How many parts | Part |
|---|---|---|
| working process | any number | node |
| working process | any number | link |
| working process | any number | group |
| working process | any number | variable |
| working process | any number | shared object — from nodes and variables |
| working process | exactly one | the file of remembered values (state.json) |
| working process | one per name of a memory a module saved: of a node or shared by several nodes | memory of a node (state/<name>/) |
| working process | one per run | the folder of the run (runs/<run_id>/) and the folder of its results (results/<run_id>/) |
| program that is on | any number | run |
| working process | exactly one | pulpit (workspace.json) |
| working process | exactly one | its own settings (settings.json) |
| working process | exactly one | Python environment (.venv) |
| working process | any number, and the other way round | version of a module — through modules.lock.json |
| run | any number | execution of a step |
| run | any number | packet |
| run | any number | artifact |
| run | exactly one | the current checkpoint |
15 Storage
No database is used.
A document is written in the following order:
1) the owner of the document checks it by the schema;
2) the kernel checks the path, the size, UTF-8 and format, if it is at the top level;
3) a temporary file, fsync of the file, the current file is renamed to .bak, the temporary one takes its place, fsync of the folder;
4) in the set of a process generation.json is updated last.
A document of another version of its format is not read. On writing, the kernel checks only the form of the string — <name>/<number> — because it does not know the meaning of the document; which version to understand, the owner of the document decides when reading. The owner answers document_invalid, naming the version found and the one expected. The owners of formats:
- the function of the graph — the process
ogas.process/4, memoryogas.state/2,ogas.state-item/1,ogas.state-items/1, the generationogas.generation/1, the checkpointogas.checkpoint/2andogas.checkpoint.part/1, the exportogas.export/3, the mark «Keep»ogas.run-keep/1; canvas— the pulpitogas.workspace/3;settings— settingsogas.settings/1;modules— the versions of modulesogas.modules-lock/1;- the kernel — the register of functions
ogas.functions/2and the description of a functionogas.function/1; - the function of observation — the list of problems
ogas.problems/1; - the common code of the protocol — the settings schema
ogas.settings-schema/1.
The names of formats are declared in the constant files of their owners; make ci checks that there are no string copies of them in the code and that each is written here.
16 Kinds of data, files of a process and showing
The section describes the kinds of data, the files of a process and how data are shown to the person (The program: graph and runs, section 24; The workshop, 5.5).
16.1 Names of kinds of data
In the formats a kind of data is called by a name from table 11: at a port of a module (type, section 4), at a variable (type, 5.1), at a constant, at an event and at a question (16.6).
Table 11 — Names of kinds of data
| Kind | Name | Value in JSON |
|---|---|---|
| text | text |
a string |
| number | number |
a number |
| yes/no | boolean |
true or false |
| date and time | time |
an ISO 8601 string — 2026-10-17T09:00, with or without seconds, with a zone Z or +03:00 or without one — then by the clock of this machine; an empty string — the time is not set. The input field is the date and time picker of the system |
| list | list |
an array |
| picture | image |
a reference to a file (16.2) |
| sound | audio |
a reference to a file |
| video | video |
a reference to a file |
| file | file |
a reference to a file |
| anything | json |
any value |
A link joins ports when the kinds are the same, when one of them is json, and when a picture, sound or video goes to a port file: a picture is a file too. The other way — a file to a port of a picture — a link does not join: what is in the file is not known. There are no other conversions: text does not go to a port of a number.
16.2 A reference to a file
A picture, sound, video and file in data are a reference, not the content:
{ "file": "files/7f3a91c2-cat.png", "name": "cat.png", "media_type": "image/png", "size": 48213 }
file— where the file lies (16.3);name— the name under which it was given or made: it is shown to the person and offered when saving;media_type— the type of the content; by it the node «Show» decides how to show the file (16.5);size— the size in bytes.
A reference goes in a packet, lies in a variable and in a constant, like any value. A module gets the file by the reference the same way as a result file: as a path in artifact_files (Modules, section 6). A module gives a file with the same kind of reference: in file — the path in the work folder, the same as in artifacts; the function of modules, having moved the file, puts its name among the results into file and fills in the other fields (Modules, section 6).
16.3 Where files lie
Files lie in the process folder, in two places:
- files of a run —
results/<run_id>/(section 10): what a module made, and what the person gave to an event or a question of this run. The fieldfileof the reference is the name of the file among the results of the run, likeartifact_handle. They live as long as the run (clearing — The program: graph and runs, 12.6); - files of the process —
files/: what a constant or a variable holds. The fieldfileisfiles/<name>; the name is eight hexadecimal signs, a hyphen and the name under which the file was given, without folders and not beginning with a dot.
A file does not change after it appears (The program: graph and runs, 24.4). So when a node «Write» puts a reference to a file of a run into a variable, the function of the graph copies the file into files/ — on the same disk as a hard link, without a second copy of the content — and the reference to the copy goes into the variable: the run will be cleared, and the variable keeps the file longer.
Clearing the files of a process. A file from files/ lives while something names it: the value of a constant in the written document of the process, the initial value of a variable, the current value of a variable of a program that is on, a remembered value (state.json). The function of the graph removes a file nothing names that is older than a day: a day covers a file given to an unsaved edit of the graph. It clears when the program is switched on and after the document of the process is written.
An export of a process takes the folder files/ along with the process, like the folder of pictures of the pulpit (10.1). Data the node «Send» passes to another program carry their files with them: each file they name is copied into files/ of the receiver the same way, and the reference names the copy (The program: graph and runs, section 23).
16.4 How a file gets into a process
A file of Windows is given by the person in two ways: they choose it in the dialog of Windows — it opens at a press of a field for a file, at the folder of the setting ui.open_dir, and offers the files of the kind asked for first and any file second — or they let go over the field a file dragged from the Explorer. Either way the window gets the path, not the contents: the function ui turns the path of Windows into a path of Linux (ui.window.path), and the function of the graph copies the file itself (process.file.take with process_id, path, place and run_id) — whole, once, beside its place and then into it, under a name of its own; the limit of size and the room on the disk are checked before the copy. A dragged file let go where no file is taken is not lost silently: the window says where to let it go.
A file the page made itself (the mask of a picture) it gives to the function of the graph by its contents, in parts. A file the person chose is passed by the window page to the function of the graph as content, in parts: a line of the exchange is limited (MAX_LINE_BYTES, section 1), and a video may be large. The request process.file.put carries process_id, name, media_type, a part of the content in base64 (data), upload_id — one for the whole file, offset — from which byte this part goes, and last — whether it is the last. The parts are put together in a file .<upload_id>.part beside the place it is meant for; the last part renames it to its lasting name, and the answer carries the reference (16.2). A missed or repeated part is a refusal with its reason; a half-written file older than a day is removed. Where the file goes is said by place: files — for a constant and a variable, run with run_id — for the answer to a question of a run that is going. The size limit is a setting of the function of the graph, 1 GiB by default.
16.5 The node «Show»
The kind of node show (The program: graph and runs, 24.3):
- the input
value— anything (json), the outputsuccess— the same packet unchanged: the node is put at the end of a branch and in its middle alike, without re-hooking anything; - the parameter
path— which field of the packet to show, by the rules of paths (The program: graph and runs, section 8); without it the whole packet is shown. The node does not demand a field missing from the packet: it is shown that it is missing, and the run goes on — the node looks and does not change what it looks at; - the node keeps what came: the last shown value of each node
showof a program that is on, with the run that brought it. When the program is switched off, what was shown is forgotten; - showing chooses the look by the value: a string — as text, and an ISO 8601 time — as a date and a time by the person's clock, a number — as a number, a logical value — as the word «yes» or «no» in the person's language, an array — as a list, a reference to a file — by
media_type: a picture, a player of sound or video, the name and size of the file; the rest — as the structure of the data. An element of a list and a field of a record are shown by the same rules: a picture in a list and in a field as a picture, a file by its name and size, not by the structure of the reference; a list in which each element is a file or a record with one file — as a gallery: a tile shows the file, its hint the other fields of the record; so frames with captions — the result of «For each», which is always records — are seen as pictures; - a value over the limit — a setting of the function of the graph, 256 KiB by default — is kept by its beginning: the first signs of a text, the first elements of a list, and it is marked «not all is shown»;
- the shared object of the node is
show:<node_id>: an element of the interface that shows the same on the pulpit is bound to it (The workshop, 6.8); - the window learns of a new value from the event
show.changed(process_id,node_id,run_id) and reads the values with the requestprocess.show.getwithprocess_id: the answer is{ values: { <node_id>: { value, cut, run_id } } }.
The check of the graph does not demand that the node «Show» be connected to anything: without an input it will not fire, like any node, and process.validate names it as a warning.
16.6 The field on a node
What the field on a node of the canvas sets and where it is kept:
- constant — the parameter
type: the kind of its value (16.1); without it the kind follows from the value — a string, a number,true/false, an array, an object. The field editsvaluein the document of the process: it is an edit of the graph, taken back with a step back and written with «Save». For a picture, sound, video and file the field chooses a file, and a reference to a file of the process goes intovalue; - variable — the field shows the value, and in a program that is on also writes it (
process.variable.set), like a field of the pulpit. In a program that is off the field only shows the initial value: it is edited in the panel of the variable; - event — the parameter
takes: what the event takes, a list{ name, type }. The field on the node has a line for each name, and the sign «Run» starts the event with what is typed: the packet{ <name>: value }. Withouttakesan event of the pulpit, of a message and of a call has one linetextof the kind «text»: the packet{ "text": "…" }; an event of a timer, a clock, switching on and a change has no fields — its data are given by its source. What is typed is kept by the window until the workshop is closed, not by the document; - question — the parameter
kindtakes, besidestext,choiceandconfirm, alsonumber,area,points,mask,image,audio,videoandfile: - area (
area) — instead of the data of the packet a picture from them is shown, and the person draws an area on it: presses and drags; «Answer» is available when there is an area, and without a picture in the data the question can only be declined; - points (
points) — a click on the picture puts a point «this one», withShiftor the right button — «not this»; «Remove the last» and «Clear» edit what is put; «Answer» is available when there is a point «this one»; - brush (
mask) — the person paints over what is needed; the width of the brush is chosen with three buttons, the right button and «Erase» erase, «Clear» removes everything; «Answer» is available when anything is painted, and what is painted goes as a picture into the files of the run; - on the node an open question is shown as the data of the packet, as the node «Show» would show them, and under them the answer field of its kind with the signs «Answer» and «Decline»; the picture of a question about an area, points or a brush stands under the data, and the node is twice as wide as usual. The file of an answer goes into the files of the run;
- waiting for a signal — the field has no parameters of its own. The field on the node shows the branches of the run waiting on it — for a node with a key, by the key of each from the checkpoint, for a node without a key their number — a line of what to send, and «Send a signal»:
process.signal.sendwith thenode_idof the node, the chosen key and the typed text indata; an empty line sendsnull. With no waiting branches the field says that nobody waits for a signal; - a trial run of an event of any source. From the canvas an event is started also when it is not from the pulpit: a timer, a clock, switching on, a message, a call. The request
process.event.firecarriesby_hand: true; the packet is what is typed in the field, and without fields — what the source would give:{ "time": … }for a clock,{}for switching on. The pulpit starts only events of the pulpit.
16.7 A part started on its own
A node or a group is started on its own (process.run.start, The program: graph and runs, 12.1). An input of the part to which a link leads from outside gets:
- from a constant and a variable — their value, as in any run: these are cold links (The program: graph and runs, section 6);
- from an event with a field — what is typed in the field of this event, along the link and with the picking of the parts of the link (
parts); from an event without fields — what its source would give (16.6); - from any other node outside — nothing; the start is refused (
graph_no_entry,message_keygraph.part.input_cut) and names such an input innames: «node (input)». The words: «this input will get nothing from outside the part — give it a constant or start from an event».
The window passes what is typed in all the events of the graph (events: { <event id>: packet }, null for an event without fields), putting into the packet only the fields that read as their kind. Which of the events lead into the part the function of the graph knows, and only their typed values it checks against takes: a field that is missing or not of its kind is a refusal (graph_no_entry, message_key graph.part.event_unfit, in names — «event: field»). An event that does not lead into the part is asked nothing: a half-typed field in a neighbouring branch does not hinder the check.
A node of the part to which no hot link leads — neither from inside nor from an event outside — begins the run with an empty packet {} and reads its cold inputs: so a node with only a constant at its input is checked.
The window has no common input.
17 Sources
17.1 The showcase — ogas.catalog/1
A showcase is a JSON document an O.G.A.S. source gives at its address: by default https://ogas.space/catalog.json. It is read by the function of sources (The workshop, 5.6).
{
"format": "ogas.catalog/1",
"name": "O.G.A.S.",
"items": [
{
"id": "sobesednik",
"what": "program",
"title": "Sobesednik",
"description": "A conversation with a local network in the manner of a character",
"version": "1.0.0",
"author": "Viktor Ovchinnikov",
"license": "Apache-2.0",
"files": [
{ "path": "process.json", "url": "https://ogas.space/files/sobesednik/1.0.0/process.json", "size": 298115, "sha256": "…" }
]
}
]
}
Table 12 — A thing of a showcase
| Field | Type | Required | What it means |
|---|---|---|---|
id |
string | yes | the name of the thing in the showcase: small Latin letters, digits, _, - and .; under it the thing goes into downloads/ |
what |
string | yes | program — a program, an export folder of a process (10.1); module — a module folder; network — a neural network; piece — a piece of interface: exactly one .json file, a document ogas.piece/1 (7.4) |
title, description |
string | title — yes |
the name and description in the person's words |
kind |
string | for a neural network | the kind of the network — the subfolder of the folder of networks it will go into |
version, author, license |
string | no | the version, the author, the licence as they are called |
profile |
integer ≥ 1 | no | the number of the author's profile on ogas.space (21.5): by it the library shows the author and says whether a new version has the same author as the previous one |
category |
string | no | the section of the showcase the thing stands in, in the words of the showcase: by it the library shows what was found in groups |
gpu_mb |
integer ≥ 0 | no | how much video memory a program or a module needs, in MiB: by it the library says whether the thing will start on this computer |
files |
object[] | yes | the files of the thing: path — a relative path inside its folder, url — where to download it from (https; for a showcase file on this computer — file:), size — bytes, sha256 — the checksum; the optional role — what the file is to the thing (weights, part:<folder>, adapter, config, tokenizer, vae, docs, picture, other) and variant — how this variant differs from the others (fp16, Q4_K_M, pruned…); without them the role and the variant are read from the name of the file |
preview |
object | no | a picture of the thing for a tile: url, size, sha256, as for a file; PNG, JPEG, WebP or GIF no larger than 2 MiB |
A showcase of another format, a thing without a required field, a piece not of one .json file, a file path leading out of the folder of the thing, a file without size or sha256, gpu_mb not an integer, a role of a file that is not in the list are not read: the source refuses with source_answer_bad and names what is wrong.
The showcase of O.G.A.S. may name a new version of the platform too: the field platform — { "version": "1.0.1", "page": "https://ogas.space/…" }; the number is numbers with dots, the page only a page of ogas.space. Only the checked showcase is read for it (Methods of the platform services, section 4).
The showcase of ogas.space lies beside its signature catalog.json.sig (21.5); without a signature that holds it is not read (source_signature_bad). Programs, modules and pieces are on it, all their files lying on ogas.space itself; neural networks are not on it — the library takes them from Hugging Face and Civitai.
17.2 Downloads
The function of sources writes what is downloaded into the data folder, into downloads/:
downloads/<download>/— the folder of a download that is going; a file is downloaded into<name>.partbeside and takes its place by renaming when it is downloaded and checked;- a neural network after downloading goes into the folder of networks — the function of modules puts it there (
module.model.take, Methods of modules), and the folder of the download disappears; - a program stays in
downloads/<id>/, and a repeated download of the same program goes intodownloads/<id>-2/, not touching the former; a module — intodownloads/<download>/<id>/: a module is accepted from a folder named by its identifier; from there they are accepted like things brought in a folder.
A stopped or failed download removes its folder whole: nothing half-downloaded stays on disk. The list of downloads lives while the function works and is not written into a file.
18 The door for programs — ogas.gate/1
data/gate.json. The owner is the function gate (Methods of the platform services, section 5). A program of the person reads it to come in.
{ "format": "ogas.gate/1", "port": 50123, "key": "9f…e1" }
port— the port on127.0.0.1the door listens on;nullwhile the door is closed;key— the key of the door: 64 hexadecimal signs.
19 The assistant
The owner is the function assistant (Methods of the platform services, section 6).
data/assistant/network.json—ogas.assistant-network/1:{ format, module_id, params, environment }— the network of the assistant, its parameters and the program in whose environment it runs.data/assistant/own.json—ogas.assistant-own/1:{ format, programs, modules }— the ids of the drafts and modules the assistant made itself.data/assistant/before/<task_id>/<process_id>.json—ogas.assistant-before/1:{ format, process_id, graph, pulpit }— a program of the person as it was before the assistant with extended access first wrote over it in a task.data/assistant/tasks/<task_id>.json—ogas.assistant-task/1:{ format, task_id, title, created, state, access, messages, log, usage, budget_from, error }.messages— the conversation:{ role: "user" | "assistant" | "tool", text, calls?, call_id?, name? };usage—{ input_tokens, output_tokens, steps };budget_from— from what spending the current limit is counted.
20 The places of the parts — ogas.places/1
data/places.json is written by the kernel when a part names its folders outside the data folder (core.space.places, Exchange with the kernel, 5.19):
{ "format": "ogas.places/1", "parts": { "modules": [
{ "path": "/opt/ogas/modules", "backup": true },
{ "path": "/opt/ogas/models", "backup": false }
] } }
parts — for each part the list of its folders; backup: true — a backup takes the folder (Building, installing and maintenance, 5.6). The document is needed while the platform is stopped: by it the kernel knows what to take into a backup.
21 The profile, parcels and the files of the site
The owner is the function profile (Methods of the platform services, section 7); what guards against what — Protection, section 8. Base64 strings use the standard alphabet with =.
21.1 The recovery code and the key file — ogas.key/1
The code is 55 signs of the alphabet 0123456789ABCDEFGHJKMNPQRSTVWXYZ in groups of five joined by -: 34 bytes — the seed of the main key (32 bytes) and the first two bytes of its SHA-256 — with three zero bits at the end. When read, spaces, line breaks and - are skipped, small letters read as capitals, O as 0, I and L as 1.
The key file is a JSON document where the person saved it:
{ "format": "ogas.key/1", "code": "T2RBT-8P06Y-…-JMAWR" }
or, under a password:
{ "format": "ogas.key/1",
"kdf": { "name": "argon2id", "salt": "…", "m": 65536, "t": 3, "p": 1 },
"sealed": "…" }
sealed — a 24-byte nonce and the cipher of the code (XChaCha20-Poly1305) under a 32-byte key Argon2id derives from the password with salt (16 bytes) and the parameters m (KiB), t, p.
21.2 The profile on the computer
The folder data/profile/; its files are written by the function profile.
keys.json—ogas.profile-keys/1, readable by the user only:{ format, key, device, vouch, device_secret, letter_secret }— the public part of the main key, of the computer key, the vouching (a signature of the main key overogas.device/1\nand the stringdevice), the seed of the computer key and the secret of the letter key; all base64. The secret of the letter key is SHA-256 ofogas.box/1\nand the seed of the main key. No file — no profile.card.json—ogas.profile-card/1:{ format, name, about, links, picture, shown, number }— the card as the last parcelprofilesent it;number— the number of the profile on the site, once the site named it.sent.json—ogas.sent/1:{ format, sent: [{ id, what, made, title, thing?, request?, state?, number?, reason?, seen? }] }— one's sendings:id— SHA-256 of the parcel;state,number,reason— what the last look at the site said of it (21.5).letters.json—ogas.letters/1:{ format, letters: [{ id, kind, opened, … }] }— the opened letters:id— SHA-256 of the sealed one, the fields — those of the letter (21.4).outbox/<id>.json—ogas.outbox/1:{ format, id, what, title, made, bits, raw }— a parcel signed and not gone yet:raw— its text as it is,bits— how many zero bits the counting task asks. A parcel larger than the limit of a kernel document waits in the memory of the function until the platform stops.
21.3 The parcel — 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": "…" }
key,device— the public parts of the main key and the computer key, 32 bytes;vouch— the vouching (21.2), 64 bytes; a parcel the main key signs itself it signs as its own computer:deviceequalskey.body— the text of a JSON object: the signature is over its UTF-8 bytes as they are, with no new order of fields;sign— an Ed25519 signature by the keydevice, 64 bytes.- The body always has
what,lang(ruoren) andmade— a timeYYYY-MM-DDTHH:MM:SSZ; the other fields — by table 13. A field the kind does not name is refused.
Table 13 — Kinds of parcels
what |
Fields | Signed by |
|---|---|---|
profile |
name (up to 80 signs), about?, links? — up to five https:// addresses, picture? — { type: ".png" \| ".jpg" \| ".webp", base64 } up to 2 MiB, box — the public part of the letter key, device — the public part of the key of the computer the card came from: the site takes the signature only of computers named so, shown? — whether to show the page |
the main key |
review |
thing, version, works (boolean), platform?, gpu?, text?, incognito? |
the computer |
request |
title, wants, input?, output?, network?, gpu?, example?, incognito? |
the computer |
take |
request — the number of the request, about?, incognito? |
the computer |
offer |
request?, title, about?, note?, incognito?, things — up to 20 things { what: "program" \| "module" \| "piece", id, version, files: [{ path, text } \| { path, base64 }] } |
the computer |
bug |
where — platform or the id of a thing, version?, did?, expected?, happened, doctor?, journal?, box |
the computer |
comment |
bug — the number, text |
the computer |
solved |
bug, version, note? |
the computer |
reply |
review — the number of a review of one's own thing, text |
the computer |
withdraw |
parcel — SHA-256 of one's own parcel |
the computer |
revoke |
keep — the public part of the key of this computer: the other computers of the profile are revoked |
the main key |
delete |
— | the main key |
Limits: a parcel — up to 28 MiB; the files of things — up to 20 MiB and 500 of them, a path — up to 200 signs, relative, of plain names, without .., hidden ones and \, each path once regardless of case; base64 — only for pictures .png, .jpg, .jpeg, .webp, .gif, and the first bytes must be a picture of that kind; a piece — exactly one .json file as text. Texts: a name — up to 80 signs, a line — up to 500, a text — up to 20 000, doctor and journal — up to 100 000.
A parcel is sent by the request POST https://ogas.space/api/send with the header X-OGAS-Work: <day>:<number>: SHA-256 of the string <day>:<number>:<hex SHA-256 of the parcel> must begin with 20 zero bits, for the parcel profile — with 24; <day> — today or yesterday by UTC, YYYY-MM-DD. The answer is { "ok": true, "id": "<hex SHA-256 of the parcel>" } or { "ok": false, "error", "detail" }; the codes: bad_format, bad_kind, bad_path, not_a_picture, missing, too_large, main_key_only, no_work, blocked, too_often, full.
21.4 The letter — ogas.letter/1
A letter is a sealed box of libsodium (crypto_box_seal: X25519 and XSalsa20-Poly1305) for the public part of its reader's letter key; inside — a JSON object { "format": "ogas.letter/1", "kind", … }.
Table 14 — Letters
kind |
Fields | To whom |
|---|---|---|
answer |
parcel — SHA-256 of the bug report, text |
to the one who reported |
bug |
bug — the number, thing, version, did, expected, happened, doctor, journal |
to the author of the thing |
review |
review — the number of the review, thing |
to the author of the thing, when the review went up on the site |
21.5 The files of the site and their signature
Table 15 — What the platform reads from ogas.space
| File | Format | What is in it |
|---|---|---|
catalog.json |
ogas.catalog/1 |
the showcase (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 or done; by — the number of a profile or null |
reviews.json |
ogas.reviews/1 |
reviews — by the id of a thing a list { number, works, made, by, version, platform, gpu, text, reply? }, reply — the answer of the thing's author; bugs — by the id of a thing its known bugs { 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 — for each own thing its reviews and bugs |
states.json |
ogas.states/1 |
states — by SHA-256 of a parcel { state, number, reason?, profile? }; state — waiting, shown, accepted, done, rejected, withdrawn, answered, refused |
mail.json |
ogas.mail/1 |
letters — sealed letters in base64 (21.4) of the last 30 days |
Beside each lies <name>.sig: a base64 line of an Ed25519 signature, 64 bytes, over the bytes ogas.site/1\n<name>\n and the bytes of the file. The public parts of the site keys are in the common code of the platform.