Keyboard shortcuts

Press ← or → to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Osmiron / Developer documentation

Plan and optimize how operations change.

Osmiron is an operational model and optimization engine for software products. It uses a typed digital twin to find feasible plans, compare them by cost and other measures, and test how they respond to disruption.

State
Versioned and traceable
Plans
Feasible before optimal
Results
Inspectable by design

Target decision flow

From live state to a plan that can survive disruption.

The model defines the operation before the planner compares possible futures.

  1. 01Connect state

    Read the records that matter and preserve their identity and source.

  2. 02Build the twin

    Keep a durable and replayable model of the current operation.

  3. 03Define change

    Describe permitted mutations, requirements, and resource limits.

  4. 04Set the goal

    Declare the desired state and measures such as cost, time, or risk.

  5. 05Compare plans

    Find feasible sequences and make their trade-offs explicit.

  6. 06Stress-test

    Apply disruptions and expose the dependencies that can make a plan fail.

Current development scope

Build the operational model first.

The first release focuses on durable state ingestion, replay, local source-aware validation, and bounded exploration through Console, CLI, REST API, and agent tools.

The current checkout does not yet simulate operations, generate or select plans, run stress tests, or optimize decisions. Those capabilities come after the operational model is durable and reproducible.

Osmiron keeps confirmed state separate from proposals and predicted results. Selecting a plan does not make its predicted state true. An approved change or an observed result must update the digital twin.

Start here

Choose a developer surface.

Getting started

Osmiron does not yet have a published installation or hosted onboarding flow. With the current repository checkout, you can check Osmiron Schema Language (OSL) source and receive diagnostics tied to source spans.

Create model.osl at the repository root:

entity "vehicle-1" {
    description {
        name = "Service vehicle"
    }

    capacities {
        payload_mass = 800 kg
    }

    properties {
        payload_mass = 0 kg
    }

    traits [vehicle]
}

Check it from the repository root:

cargo run -p osmiron-dsl -- check model.osl

The command produces no output and exits successfully when parsing and the currently implemented change generation succeed. It writes a source diagnostic to standard error and exits with a failure status when either stage returns an error.

A successful check is not yet proof that every declaration became a semantic change or that the resulting changes satisfy the engine model. The command does not apply changes, store a model, or produce a plan. See Current limitations before relying on it in tooling.

Continue with the OSL overview, or read the CLI guide for standard input and diagnostic controls.

The developer surfaces have distinct roles:

SurfaceRoleCurrent status
OSLDeclarative source for operational model changesParsing, source diagnostics, and partial change generation exist in this repository.
Osmiron SDKPublic name for developer librariesNo supported public package is published from this repository yet.
Osmiron APIAuthenticated customer-facing data planeThe contract is under development.

Model boundaries

Osmiron models the part of an operation relevant to a bounded decision. It does not need an exhaustive representation of the world.

Confirmed state

The current digital twin contains operational facts accepted by the system. Stable identities remain distinct from changing state, and retained provenance records where information came from.

Desired state

Work describes what must become true, together with its constraints and objectives. It does not prescribe the sequence of changes used to reach that outcome.

Permitted change

A mutation declares a reusable change Osmiron may consider. It defines roles, requirements, temporary resource uses, and persistent transformations without binding concrete entities or granting execution approval.

Proposed plan

Planning binds resources, evaluates alternatives, and schedules mutations. A plan contains predicted state and remains separate from confirmed operational truth.

Observed result

An observation records what happened. It can update confirmed state through a new traceable change; selecting a plan does not silently make its predictions true.

Osmiron Schema Language (OSL)

OSL is the declarative source language for Osmiron. A source file describes changes to an operational model: condition vocabularies, entities, permitted mutations, tasks, and explicit removals.

OSL is intentionally small. It is not a general-purpose programming language or, in the current MVP, a general-purpose data query language.

The current pipeline has four stages:

  1. The lexer recognizes tokens and retains source spans.
  2. The parser builds a spanned abstract syntax tree.
  3. Change generation lowers supported syntax into sourced osmiron-engine changes.
  4. Dependency ordering arranges changes while retaining their source spans for diagnostics.

The osmiron-dsl check command runs these stages. It does not apply the changes to an engine, validate them against stored twin state, or persist a commit.

Declarations

The parser accepts four top-level declarations:

DeclarationPurposeIdentity form
conditionDefines a named set of condition variants.Identifier
entityDescribes an identity and its current components.Quoted string
mutationDescribes roles, requirements, resource uses, and transformations.Quoted string
taskDescribes predicates for a desired state.Quoted string

Prefix any top-level declaration kind with drop to request its removal.

Every currently supported condition, entity, mutation, and task entry lowers to a semantic change. Those changes are not yet validated against a stored digital twin or applied. See Current limitations for the exact boundary.

Read Language structure for lexical rules and block syntax. The complete example is the representative parser fixture checked by the documentation recipe.

Language structure

OSL source is a sequence of top-level declarations and removals. Whitespace separates entries. Blocks do not use semicolons, and lists do not use commas. Function arguments are the exception: commas separate arguments inside parentheses.

condition readiness [not_ready ready]

entity "van-110" {
    traits [vehicle van]
}

drop entity "retired-van"

The current lexer does not support comments. A marker such as # or // produces an unknown-token diagnostic.

Identifiers and identities

An identifier starts with an ASCII letter or underscore. Later characters can also be digits.

vehicle
payload_mass
ready_2

Conditions and mutation roles use identifiers. Entities, mutations, and tasks use quoted string identities.

condition readiness [ready]
entity "van-110" {}
mutation "transport-payload" {}
task "deliver-cargo-42" {}

The lexer accepts backslash escapes inside quoted strings. Decoding and validation of those escapes during change generation are incomplete, so avoid escaped identities and description values for now.

Numbers and quantities

Numbers contain digits and can have a decimal fraction. A leading sign is a unary operator rather than part of the number token.

0
59.3293
-18.0686

A quantity is a number, whitespace, and a unit. A compound unit can contain slash-separated identifier segments without spaces around the slash.

800 kg
0.08 l/km
70 km/h

Change generation stores the numeric value, decimal scale, and unit label. It does not convert units or check dimensional compatibility. Unary quantities are parsed but are not safe to lower yet.

Blocks and lists

Curly braces contain named sections or expressions. Square brackets contain identifiers or reference paths, depending on the section.

entity "cargo-42" {
    properties {
        mass = 120 kg
    }

    traits [cargo]
}

Inside supported sections, prefix an entry with drop to request removal of that entry. Whitespace is sufficient between entries. OSL does not yet have a formatter or canonical formatting rule.

Source order and context

The parser preserves source order. Current change generation does not resolve declarations against one another, collect forward declarations, or accept a separate base source. References remain symbolic for later engine validation.

Conditions

A condition declaration defines a named vocabulary of operational states. The condition name and each variant are identifiers.

condition readiness [
    not_ready
    ready
    drop retired
]

An entity records condition state in its conditions section:

entity "van-110" {
    conditions {
        readiness = ready
        drop former_state
    }
}

A condition value can be referenced through a concrete entity or mutation role:

@"van-110".conditions.readiness
@vehicle.conditions.readiness

The parser and change generator emit condition declarations, variant edits, entity assignments, removals, and condition references. Applying the generated changes rejects duplicate definitions, missing definitions, variants from the wrong vocabulary, and deletion of definitions that current entity state or stored expressions still use.

An entity may hold at most one current variant from each condition. Assigning a new variant replaces the previous value. A missing assignment remains missing; condition declarations do not create default operational state. Condition values support equality and inequality, but they are not ordered or numeric.

Entities and state

An entity has a stable quoted identity and explicit components. OSL accepts description, capacities, properties, traits, and conditions sections.

entity "van-110" {
    description {
        name = "White VW van"
        plate = "ABC-123"
    }

    capacities {
        payload_mass = 800 kg
    }

    properties {
        payload_mass = 0 kg
        speed = 70 km/h
    }

    traits [vehicle van diesel]

    conditions {
        readiness = ready
    }
}

Description

description contains named string values for human-readable metadata.

description {
    name = "White VW van"
    drop former_name
}

Properties and capacities

properties contains current state values. capacities contains named limits or available resource amounts. Their expressions use the same syntax.

capacities {
    payload_mass = 800 kg
}

properties {
    payload_mass = 120 kg
    depot = @"hq".properties.located_at
}

The parser accepts condition symbols, quantities, component references, location(...), parentheses, unary operators, and binary arithmetic or comparison operators. Current change generation handles condition symbols, quantities, references, groups, and binary expressions. Unary lowering is not implemented safely. Location lowering also has known coordinate order, scale, and range defects, so do not use location values as an operational contract yet.

Current change generation does not check that a capacity has a matching property, compare value kinds or units, resolve referenced entities, or reject duplicate component names. Those checks belong to later engine validation and are not wired into the CLI today.

Traits

Traits are identifier labels for capabilities or classifications.

traits [vehicle van diesel]

A trait path names one trait on an entity or mutation role:

@"van-110".traits.vehicle
@vehicle.traits.vehicle

Conditions

conditions contains named condition values. See Conditions for declaration and validation limits.

Entry removal

Every entity section accepts drop entries. A top-level removal deletes the whole entity.

entity "van-110" {
    properties {
        drop legacy_speed
    }
}

drop entity "retired-van"

References and expressions

Expressions appear in entity values, mutation requirements and transformations, and task predicates. The parser preserves their source spans, structure, and precedence.

References

A concrete entity reference starts with @ and a quoted identity:

@"cargo-42".properties.mass

A mutation role reference starts with @ and a role identifier:

@payload.properties.mass

A component reference identifies one named value:

@"van-110".description.plate
@"van-110".capacities.payload_mass
@"van-110".conditions.readiness
@"van-110".properties.fuel_volume
@"van-110".traits.vehicle

References cannot stop at a component or continue past the value name. Mutation definitions are reusable templates, so their references must be role-rooted. The observe, share, and reserve mutation sections also accept a whole role such as @vehicle; concrete entity references are rejected in every mutation section.

Current change generation preserves component references symbolically. It does not check that an entity, role, component, or value name exists.

Evaluation values

An evaluation value belongs to a mutation role:

@vehicle.$distance
@vehicle.$duration

Only distance and duration are accepted. A concrete entity cannot be the root of an evaluation value. OSL does not compute these values; they remain symbolic inputs for future evaluation and planning systems.

Values and calls

The expression parser accepts:

  • condition symbols such as ready;
  • quantities such as 12 kg;
  • component references and role evaluation values;
  • the location(...) call;
  • parenthesized groups;
  • unary + and -; and
  • binary arithmetic and comparison operators.
@van.properties.fuel_volume > 0 l
@van.$distance * @van.properties.fuel_per_distance
(1 kg + 2 kg) * 3 kg

Quoted strings and plain unitless numbers are not general expression values. Calls are not generic: location(...) is the only recognized call name. Location arguments are captured as source text and checked during change generation. Their operational lowering has known defects described in Current limitations.

Condition symbols are resolved in the namespace supplied by a condition reference in the same expression. For example, ready in @vehicle.conditions.readiness = ready resolves to the ready variant of the readiness condition. A condition symbol without that context cannot be materialized into the digital twin.

Operators and precedence

Operators bind in this order, from strongest to weakest:

PrecedenceOperators
1unary +, unary -
2*, /
3+, -
4=, !=, <, <=, >, >=

Operators with the same precedence associate from left to right. Parentheses override precedence.

The parser supports all operators in the table. Change generation supports binary and grouped values but does not safely lower unary values yet. It does not type-check expressions, compare units, or require task and requirement expressions to produce Boolean values.

Mutations

A mutation describes a reusable permitted change. It defines abstract roles, requirements for binding those roles, temporary resource uses, and persistent transformations. Declaring a mutation does not bind entities or approve an execution. Every mutation reference must begin at one of its abstract roles; concrete entity references are rejected so definitions remain reusable.

mutation "transport-payload" {
    roles [van payload destination]

    requires {
        @van.traits.vehicle
        @payload.traits.cargo
        @destination.traits.location
        @van.properties.located_at = @payload.properties.located_at
    }

    uses {
        reserve [@van @payload]
        observe [@destination.properties.located_at]

        occupy {
            @van.capacities.payload_mass += @payload.properties.mass
        }
    }

    transforms {
        @van.properties.located_at -> @destination.properties.located_at
        @payload.properties.located_at -> @destination.properties.located_at
    }
}

Roles and requirements

roles lists the abstract entities a mutation needs. requires contains expressions that describe acceptable bindings and required values.

roles [van payload destination]

requires {
    @van.traits.vehicle
    @van.conditions.readiness = ready
    @van.properties.fuel_volume > 0 l
}

The parser accepts role references but does not check that a role was declared, that roles are unique, or that resource and transformation references also appear in requires.

Resource uses

uses describes temporary access while a mutation is active.

SectionIntended meaning
observeRead an entity or component value.
shareShare an entity or component value.
reserveReserve an entity or component value.
occupyApply a temporary change to a component value.

The first three sections contain reference lists. occupy contains change expressions.

uses {
    observe [@destination.properties.located_at]
    reserve [@van @payload]

    occupy {
        @van.capacities.payload_mass += @payload.properties.mass
    }
}

Transformations

transforms describes persistent component changes.

OperatorMeaning
=Assign
+=Add and assign
-=Subtract and assign
*=Multiply and assign
/=Divide and assign
->Become
transforms {
    @van.properties.fuel_volume -=
        @van.$distance * @van.properties.fuel_per_distance

    @payload.properties.located_at ->
        @destination.properties.located_at
}

Every mutation section accepts drop edits, and drop mutation "identity" requests removal of a whole mutation.

Mutation declarations emit ordered create and update changes that the digital twin stores as definitions. Resource scheduling, role binding, requirement evaluation, and transformation execution remain outside the current OSL pipeline.

Tasks and desired state

A task states what should become true. It does not prescribe a mutation or a sequence of steps.

task "deliver-cargo-42" {
    desired {
        @"cargo-42".properties.located_at =
            @"workshop".properties.located_at
    }
}

A task identity is a quoted string. Its desired section contains expressions. Prefix an expression with drop to remove that desired predicate, or use drop task "identity" to remove the whole task.

The parser preserves desired expressions and their source spans. Task declarations currently emit no create or desired-state changes. Top-level task removal does emit a delete change.

OSL does not yet type-check desired expressions, evaluate them, select mutations, or produce plans. The task above describes a target state only. Planning is a later stage built on the durable model foundation.

CLI source workflow

The osmiron-dsl binary checks or development-applies one OSL source file. Run the check command through Cargo from the repository root:

cargo run -p osmiron-dsl -- check path/to/model.osl

A file that passes the parser and currently implemented change generation produces no output and exits successfully. A returned lexer, parser, or change generation error produces a source diagnostic on standard error and exits with a failure status.

The command does not accept a base source, inspect stored twin state, apply changes to the engine, or persist a commit.

Development commit

The commit command requires both an input and an explicit target model, then runs the same parsing, change-generation, and ordering checks before applying the ordered changes to a fresh in-memory digital twin:

cargo run -p osmiron-dsl -- commit model.osl development \
  -m "Add warehouse capacity"

The model argument and message establish the future CLI contract. They do not select remote state yet because the Osmiron API is not implemented. The in-memory twin is discarded when the command exits, so a successful development commit is not durable and must not be treated as an accepted state revision.

The development application path currently supports entity creation, deletion, and description changes. Other checked changes return an unsupported-change error instead of being persisted or silently ignored.

Standard input

Pass - to read OSL from standard input:

printf 'entity "vehicle-1" {}' | cargo run -p osmiron-dsl -- check -

Color

Use the global --color option with auto, always, or never:

cargo run -p osmiron-dsl -- --color never check model.osl

Debug output

Use --debug changes to print compact semantic changes in their original source order:

cargo run -p osmiron-dsl -- check --debug changes model.osl

Use --debug order to print dependency generations followed by a dependency tree. Change indexes in both modes refer to the original source order:

cargo run -p osmiron-dsl -- check --debug order model.osl

Repeat the option to print both views. Changes are always printed before the ordered dependency tree:

cargo run -p osmiron-dsl -- check \
  --debug changes --debug order model.osl

Debug output is developer-facing and follows the Rust semantic and dependency type names. Nested values and long generation lists use indented lines to avoid terminal wrapping. The output is not a stable machine-readable format. A dependency absent from the tree may be satisfied by stored twin state rather than another change in the current batch.

Diagnostic families

Diagnostic codes identify the stage that rejected the source:

PrefixStage
OSL-LLexing
OSL-PParsing
OSL-CChange generation
OSL-OChange ordering

Diagnostics include the source path and labeled source spans. Some also include help text.

What success means today

The check command is a development tool, not a complete model validator. It lexes, parses, lowers, and dependency-orders the current source, but it does not validate references or generated changes against stored twin state.

Use the command to catch supported source, lowering, and batch-ordering errors. Do not use a zero exit status as proof that the full source has valid operational meaning.

Complete example

This fixture exercises the current OSL parser with condition vocabularies, entities, a transport mutation, removals, and a delivery task. The documentation test runs the same file through osmiron-dsl check.

condition readiness [
    not_ready
    ready
]

condition cleanliness [
    clean
    dirty
    contaminated
    drop old
]

drop entity "van-111"

entity "van-110" {
    description {
        drop type
        name = "White VW van"
        plate = "ABC-123"
    }

    capacities {
        drop legacy_payload_mass
        payload_mass = 800 kg
        fuel_volume = 60 l
    }

    properties {
        drop legacy_fuel_volume
        payload_mass = 0 kg
        curb_mass = 1800 kg
        fuel_volume = 50 l
        fuel_per_distance = 0.08 l/km
        speed = 70 km/h
        located_at = @"hq".properties.located_at
    }

    traits [
        drop petrol
        vehicle
        van
        diesel
    ]

    conditions {
        drop legacy_readiness
        readiness = ready
        cleanliness = clean
    }

}

entity "cargo-42" {
    properties {
        mass = 120 kg
        located_at = @"hq".properties.located_at
    }

    traits [
        cargo
    ]

}

entity "hq" {
    traits [
        location
    ]

    properties {
        located_at = location(59.3293, 18.0686)
    }
}

drop entity "hq"

entity "workshop" {
    traits [
        location
    ]

    properties {
        located_at = location(59.3498, 18.0707)
    }
}


drop mutation "transport-payload"

mutation "transport-payload" {
    roles [
        drop driver
        van
        payload
        destination
    ]

    requires {
        drop @van.traits.petrol
        @van.traits.vehicle
        @van.conditions.readiness = ready
        @payload.traits.cargo
        @destination.traits.location
        @van.properties.located_at = @payload.properties.located_at
        @destination.properties.located_at
        @van.capacities.payload_mass
        @payload.properties.mass
        @van.properties.fuel_volume
        @van.properties.fuel_per_distance
    }

    uses {
        observe [
            drop @destination.properties.legacy_location
            @destination.properties.located_at
        ]

        share [
            drop @van.properties.legacy_location
        ]

        reserve [
            drop @driver
            @van
            @payload
        ]

        occupy {
            drop @van.capacities.payload_mass = @payload.properties.mass
            @van.capacities.payload_mass = @payload.properties.mass
        }
    }

    transforms {
        drop @van.properties.legacy_fuel_volume = 0 l
        @van.properties.fuel_volume = @van.properties.fuel_volume
            - @van.$distance * @van.properties.fuel_per_distance

        @van.properties.located_at = @destination.properties.located_at
        @payload.properties.located_at = @destination.properties.located_at
    }
}

task "deliver-cargo-42" {
    desired {
        drop @"cargo-42".properties.located_at = @"hq".properties.located_at
        @"cargo-42".properties.located_at = @"workshop".properties.located_at
    }
}

The fixture demonstrates accepted syntax, not end-to-end model semantics. Current change generation emits partial entity changes and top-level delete changes. It does not emit condition, mutation, or task declaration changes, and the command does not apply a model or produce a plan.

Current limitations

OSL is under active development. The parser recognizes more of the planned language than change generation and engine validation currently support.

Available now

  • Lexing and parsing retain source spans and produce OSL-L and OSL-P diagnostics.
  • The parser accepts condition, entity, mutation, task, and drop declarations.
  • Condition, entity, mutation, and task declarations generate sourced semantic changes for their supported entries.
  • Top-level drop declarations generate delete changes.
  • Supported string escapes are decoded into semantic values.
  • Unary expressions and location(latitude, longitude) values lower with checked coordinate bounds and precision.
  • Generated changes are dependency-ordered within the current batch.
  • Supported change-generation failures produce OSL-C diagnostics.
  • Dependency cycles produce OSL-O diagnostics.
  • The repository includes a CLI for checking one file or standard input.

Not complete yet

  • Generated changes are not applied to the engine, validated against stored twin state, or persisted.
  • References remain symbolic. OSL does not resolve local or forward declarations, validate paths or roles, or accept a separate base source.
  • Unit labels are stored but not converted or checked for dimensional compatibility.
  • General expressions are not type-checked, and condition values are not checked against declared variants.
  • Resource access, mutation binding, requirements, transformations, and tasks are not evaluated.
  • OSL does not materialize source into a durable twin, replay history, simulate operations, select plans, or optimize decisions.
  • Comments, a formatter, canonical formatting, a public package, and a standalone installer are not available.

A successful osmiron-dsl check only means that parsing and the change generation paths reached by that file completed. It is not proof that every declaration produced changes or that the model is valid.

Osmiron SDK

Osmiron SDK is the public umbrella name for developer libraries that interact with Osmiron. Individual packages will keep concrete, role-based names.

No supported public SDK package is published from this repository yet. Package installation, language-specific examples, and compatibility guarantees will be added only after those artifacts exist.

Osmiron API

The Osmiron API is the future authenticated product API. Console is a first-party client of this API, which also serves customer integrations. It is separate from Osmiron’s unauthenticated local development server.

The endpoint and authentication contracts are still under development. This section will document them from the generated Osmiron OpenAPI schema once that contract exists.

Only use a generated schema from the active Osmiron API boundary here.

API reference

The reference below is generated from a Osmiron OpenAPI document when one is provided to the documentation build.

The generated Osmiron API contract is not available in this build. The API remains under development.