<nil>NILScript

Core Concepts

The NILScript DSL

If NIL is the syscall interface, the NILScript DSL is the program. A declarative, event-driven language describing multi-step intent over business systems — a JSON DAG of typed nodes that is deliberately not Turing-complete, so unsafe steps are unrepresentable.

The program envelope

Every program carries a fixed set of top-level fields.

FieldMeaning
wosoolLanguage version (“0.1”)
workspaceTenant / isolation unit
localeBCP 47 tag for previews (e.g. “ar”)
entryNode id where execution starts
pipelineThe array of nodes (the DAG)
on_errorhalt · continue · compensate
program.nil.json
{
  "wosool": "0.1",
  "workspace": "ws_acme",
  "locale": "ar",
  "entry": "step_1",
  "on_error": "compensate",
  "pipeline": [ /* nodes */ ]
}
The version field is load-bearing
A runtime that doesn’t recognize the wosool version refuses the program rather than guessing. There is no “best effort” interpretation of an unknown dialect.

Node types — a closed set

Eight node types. The validator rejects any node whose type is not one of them — no escape hatch, no custom, no eval.

TypeSide effectsNIL mappingPurpose
actionYes (gated)PROPOSE → COMMITInvoke a verb
queryNoQUERYRead state
conditionNoBoolean guard, routes only
parallelVia branchesFan out branches
foreachVia bodyLoop over a bounded array
await_approvalNowaits for DECIDEBlock for owner decision
notifyNoUser-facing message
waitNoDurable pause until a time

action & compensation

One node, one verb. args are hints; the system resolves the authoritative facts. An action may carry compensate_with — a compensating verb the runtime runs to undo the step if a later step fails.

action node
{
  "id": "step_3",
  "type": "action",
  "verb": "commerce.create_purchase_order",
  "args": { "supplier_hint": "default", "sku": "SKU-1042", "quantity": 50 },
  "retry_policy": { "max_attempts": 3, "backoff": "exponential" },
  "on_error": "compensate",
  "compensate_with": {
    "verb": "commerce.cancel_purchase_order",
    "args": { "po_id": "$.step_3.output.po_id" }
  }
}
The DSL is a saga
On terminal failure, the durable runtime unwinds completed steps in reverse order via governed compensation — each reversal previewed and committed like any other action.

query & condition

A query is read-only and produces output later nodes can reference. A condition is a side-effect-free, total boolean guard — it routes, it never acts. Both branches are explicit; a branch may be null to stop.

condition node
{
  "id": "step_2",
  "type": "condition",
  "expr": "$.step_1.output.stock < 5",
  "on_true": "step_3",
  "on_false": null
}

parallel, foreach, await

parallel fans out independent branches with a join policy of all or any. foreach loops over a bounded array — no unbounded iteration. await_approval blocks until the owner decides on a parked proposal and routes on the outcome.

foreach node
{
  "id": "step_4",
  "type": "foreach",
  "items": "$.step_1.output.line_items",
  "item_var": "line",
  "do": ["step_4a"]
}

Data references

Nodes pass data through backward-only references of the form $.step_N.output.field. A node may only reference earlier nodes, which guarantees the graph is acyclic — a DAG with no cycles, provable before execution.

Validation

Before any side effect, the validator proves: the schema is valid (additionalProperties: false); every reference resolves backward; the graph is acyclic; every verb is within the grant’s scope; and arg types match the verb’s profile. A rejected program comes back with structured diagnostics the generator reads to self-heal.

Least power, by design

The DSL is the least expressive language that does the job: no unbounded loops, no arbitrary code, no file or network access beyond declared verbs. Expressiveness is intentionally capped so that the set of representable programs is exactly the set of safe ones.

NILScript is an open standard, stewarded by the Wosool project. The spec is extracted from running code.

Draft standard v0.3.0 · 0.x stage · NIL wire 0.1 · DSL 0.1