v0.1.0

nudgeDSL Specification

Status: Draft — Pre-implementation
Purpose: Agent context injection · Grammar source of truth · Contributor reference

1. What nudgeDSL is

nudgeDSL is a token-dense, human-readable Domain Specific Language for encoding executable intent from LLMs to multi-language backends (Go, Python, Dart).

An agent outputs a nudgeDSL string. A universal parser converts it to a JSON AST. Language-native executors read the AST and run the corresponding functions.

nudgeDSL does not: execute code directly, make network calls, or carry state between turns.

Key principle

Format follows consumer. AI-consumed outputs are telegraphic. Human-consumed outputs are scannable. nudgeDSL is both at the same time.

2. Core concepts

Atom

An Atom is a short-code (1–3 uppercase characters) registered by the developer and mapped to a backend function. Atoms are always uppercase. The atom registry is injected into the agent context at runtime.

REGISTRY — the special declaration atom

REGISTRY is a built-in atom that declares which domain registry a document expects. It must appear as the first expression if present. If the loaded registry does not match, the parser returns a RegistryError before evaluating any other atom.

Declarationmust be first expression in document
REGISTRY("nudge-framework", version="0.1.0")
  >> SHARD("A1", phase="A")

Operator

An Operator encodes the relationship between atoms. Operators are fixed — part of the grammar, not redefinable by developers.

Argument types

TypeSyntaxExampleNotes
String"value"MARK("task-1")No escaped quotes in v0.1 — use single-word identifiers or enums
Integerbare numberMOV(3, 7)May be negative
Floatdecimal numberHEAL("self", 0.5)May be negative
Booleantrue / falseLOCK(true)Lowercase only
NullnullRESET(null)Lowercase only

v0.1 constraint: Strings cannot contain escaped double quotes. Design atom arguments to avoid this — use single-word identifiers or enum values where possible.

3. Operator table

OperatorNameSemanticsFailure behavior
>>ChainExecute left, then right. Right does not run if left fails.Fail-fast (default)
|FallbackTry left. If left fails, try right.Best-effort per branch
//ParallelExecute left and right concurrently.Configurable (see §5)
**NAmplifyRepeat the preceding atom N times sequentially.Fail-fast

Precedence (high to low)

  1. ** — Amplify — binds tightest, applies to immediately preceding atom only
  2. // — Parallel
  3. >> — Chain
  4. | — Fallback — binds loosest

Use parentheses to override precedence. A() // B() ** 3 is parsed as A() // (B() ** 3) — amplify binds before parallel.

4. EBNF grammar

program ::= expression EOF expression ::= fallback fallback ::= parallel ( "|" parallel )* parallel ::= chain ( "//" chain )* chain ::= amplify ( ">>" amplify )* amplify ::= primary ( "**" INTEGER )? primary ::= atom_call | "(" expression ")" atom_call ::= ATOM "(" arg_list? ")" arg_list ::= arg ( "," arg )* arg ::= STRING | INTEGER | FLOAT | BOOLEAN | NULL ATOM ::= [A-Z][A-Z0-9]{0,2} STRING ::= '"' [^"]* '"' INTEGER ::= "-"? [0-9]+ FLOAT ::= "-"? [0-9]+ "." [0-9]+ BOOLEAN ::= "true" | "false" NULL ::= "null" EOF ::= end of input

5. Parallel failure modes

The // operator supports three configurable failure modes. Set at executor registration. Default is fail-fast.

fail-fast (default)

If any branch fails, all remaining branches are aborted immediately. No partial state is applied.

best-effort

All branches execute regardless of individual failures. Errors are collected and returned after all branches complete. Partial state is applied.

compensating

Each atom may declare a rollback atom in the registry. If a branch fails, the executor calls the rollback atom of each already-completed branch. The executor automatically passes the exact same arguments from the forward atom to its rollback atom.

Rollback signature rule

Rollback atoms must accept the same argument signature as their forward atom. This is enforced at registry load time, not execution time. A misconfigured rollback that surfaces during a compensating transaction is worse than a startup error.

6. JSON AST format

The parser always outputs this structure. Executors consume the AST — never the raw string.

AST — MARK("task-1", "done") >> NOTIFY("ops")
{
  "version": "0.1.0",
  "root": {
    "type": "chain",
    "nodes": [
      {
        "type": "call",
        "atom": "MARK",
        "fn": "UpdateStatus",
        "args": [
          { "type": "string", "value": "task-1" },
          { "type": "string", "value": "done" }
        ]
      },
      {
        "type": "call",
        "atom": "NOTIFY",
        "fn": "BroadcastEvent",
        "args": [
          { "type": "string", "value": "ops" }
        ]
      }
    ]
  }
}

Node types

typeFields
callatom, fn, args[]
chainnodes[]
parallelnodes[], failure_mode
fallbacknodes[]
amplifynode, count

7. Atom registry format

Developers register atoms before injecting context. The registry is the single source of truth for prompt generation and GBNF grammar compilation.

atoms.json — registration schema
{
  "domain": "my-project",
  "version": "0.1.0",
  "extends": [],
  "atoms": [
    {
      "atom": "MARK",
      "fn": "UpdateStatus",
      "description": "Transition an item to a new status.",
      "args": [
        { "name": "id", "type": "string" },
        { "name": "status", "type": "string",
          "enum": ["pending", "done", "skipped", "error"] }
      ],
      "rollback": null
    },
    {
      "atom": "HEAL",
      "fn": "HealUnit",
      "description": "Heal the target unit by a percentage of max HP.",
      "args": [
        { "name": "target", "type": "string",
          "enum": ["self", "ally1", "ally2"] },
        { "name": "amount", "type": "float",
          "min": 0.0, "max": 1.0 }
      ],
      "rollback": "UNHEAL"
    }
  ]
}

Arg constraint fields

FieldApplies toMeaning
min / maxinteger, floatInclusive range
enumstringAllowed values only
requiredallDefaults to true

Rollback signature validation

If an atom declares a rollback, these checks run at registry load time:

  • The rollback atom must exist in the same registry
  • The rollback atom must declare the same number of arguments as the forward atom
  • Each argument must have the same type at the same position

Fail at load time, not at execution time. A misconfigured rollback that surfaces during a compensating transaction is a silent correctness hole.

8. Validation pipeline

Parsing and validation are two separate steps. A string can be syntactically valid and semantically invalid.

two-stage pipeline
raw string
    │
    ▼
[ Parser ]  ──── syntax error ──▶  ParseError
    │
    ▼
  JSON AST
    │
    ▼
[ Semantic Validator ]  ──── constraint violation ──▶  ValidationError
    │
    ▼
[ Executor ]

nudgeDSL ships a DefaultValidator that enforces all registry-declared constraints. Developers may replace or extend it via the Validator interface.

9. Error taxonomy

All errors are structured. The parser and validator never panic.

ParseError codes

CodeMeaning
EMPTY_INPUTInput string is empty or whitespace only
TRUNCATED_INPUTInput ends mid-token — likely stream truncation
UNEXPECTED_TOKENToken does not fit the grammar at this position
UNTERMINATED_STRINGString opened with " but never closed
MISSING_CLOSE_PARENAtom call opened but ) never found
TRAILING_OPERATORExpression ends with an operator
UNKNOWN_ATOMAtom not found in registry or not uppercase

ValidationError codes

CodeMeaning
ARG_OUT_OF_RANGEInteger or float outside declared min/max
ARG_NOT_IN_ENUMString not in declared enum values
ARG_TYPE_MISMATCHArgument type doesn't match declaration
ARG_COUNT_MISMATCHWrong number of arguments for this atom
UNKNOWN_ATOMAtom in AST absent from registry at validation time

RegistryError codes

CodeMeaning
ROLLBACK_NOT_FOUNDRollback atom declared but not present in registry
ROLLBACK_SIGNATURE_MISMATCHArg count or type mismatch between forward and rollback
REGISTRY_MISMATCHDocument REGISTRY() declaration does not match loaded registry

10. Auto-generated agent prompt

nudgeDSL generates the system prompt injection from the atom registry. Agents receive the generated prompt — not this spec.

generated prompt — nudge-framework registry (excerpt)
You are operating with nudgeDSL v0.1.0.
Output ONLY valid nudgeDSL strings. No explanation, no preamble, no markdown.

## Registered Atoms
SHARD(id: string, phase: string)  — Open a shard context.
ACCEPT(criterion: string)  — Add acceptance criterion.
MARK(id: string, status: string)  — Transition item status.
NOTE(text: string)  — Record decision note.

## Operators
>>   chain (sequential)
|    fallback (try left, then right)
//   parallel (concurrent)
**N  amplify (repeat N times)

## Constraints
MARK.status: one of [pending, done, skipped, error, blocked]

Output nudgeDSL only.

11. Worked examples

Example 1single call
MARK("task-42", "done")
Example 2chained sequence — right runs only if left succeeds
CREATE("report.pdf") >> NOTIFY("complete")
Example 3fallback — try primary, use replica if primary fails
FETCH("primary-db") | FETCH("replica-db")
Example 4parallel — concurrent execution, failure mode from executor config
WRITE("db") // CACHE("redis")
Example 5amplify — run health check 3 times sequentially
PING("health", 1) ** 3
Example 6compound — mark, parallel write/cache, then confirm
MARK("job-7", "running") >> (WRITE("db") // CACHE("redis")) >> MARK("job-7", "done")
Example 7fallback with chain — full sequence fallback
(MARK("gpu-0", "running") >> FETCH("inference")) | (MARK("gpu-1", "running") >> FETCH("inference"))
Example 8precedence — ** binds tighter than // (A() // (B() ** 3))
NOTIFY("a") // NOTIFY("b") ** 3 // parsed as: NOTIFY("a") // (NOTIFY("b") ** 3)
Example 9nudge framework — shard document
REGISTRY("nudge-framework", version="0.1.0") >> SHARD("A1", phase="A") >> ACCEPT("zero NotImplementedError") >> EXCLUDE("gif_writer.py")

12. Simulator / CLI

The nudgeDSL simulator takes existing agent output and produces the nudgeDSL equivalent, token comparison, inferred registry, and GBNF grammar.

CLI usage
nudge analyze ./output.json
nudge analyze ./output.py --format python
nudge analyze --stdin

# with custom registries (last-defined wins on conflicts)
nudge analyze ./output.json --registry core.json --registry nudge.json
nudge analyze ./output.json --registry ./atoms.json

Note: savings_percent is always net (output + amortized system prompt). Gross savings are not reported — they are misleading.

13. Versioning

This document is versioned. Breaking changes increment the minor version. The version field in every AST output references this spec version.

Agents and executors must agree on spec version. A mismatch is a runtime error, not a silent failure. Documents using REGISTRY() must declare the domain version — version mismatch returns REGISTRY_MISMATCH before any parsing occurs.

14. What is not in v0.1

These are explicitly out of scope. Do not implement them in v0.1 parsers.

  • Variables or state references between atoms ($result >> M($x, $y))
  • Conditional branching (IF(cond) >> A() | B())
  • Loops with dynamic counts (SHOOT() ** $n)
  • Typed return values from atoms
  • Multi-agent addressing (@agent1 >> M(3,7))
  • Streaming partial AST execution
  • Registry inheritance ("extends" field is reserved, must be empty array in v0.1)
  • Runtime registry merging beyond last-defined-wins

15. Registry system

nudgeDSL separates the grammar (this spec) from the vocabulary (atom registries). The grammar never changes within a major version. The vocabulary is fully customizable per project.

Three registry layers

LayerFilePurpose
Corenudgedsl-core.jsonGeneric atoms usable in any domain (MARK, CREATE, NOTIFY...)
Domainnudgedsl-{domain}.jsonAtoms for a specific methodology (SHARD, PHASE, ACCEPT...)
Projectatoms.jsonProject-specific atoms, lives next to shards

Composition rules

  • No inheritance — include both files explicitly, no extends logic in v0.1
  • Last-defined wins — on atom name conflicts, the last --registry flag wins silently
  • Load-time conflict check — signature mismatches (same atom name, different arg count) produce a RegistryError at load time
  • REGISTRY() is optional — if omitted, no domain/version check is performed

nudgeDSL-spec-v0.1.0 — pre-build artifact. Implementation does not yet exist at time of writing.