Furth FortuneM9 reference

Mission foundation / System overview

Trident

One program in text and node views

Trident is a typed language for application rules and workflow. Its script view and node view edit the same program graph. The language includes bounded loops, complete branches, tasks, errors, and distributed locks.

System diagram

Track review as a node program

The node view and script view edit the same program. The branch, task budget, error path, and lock are visible before the workflow runs.

Event TrackUpdated
Guard typed trackId + source
Branch confidence ≥ 0.85?
yes
Task correlate • 50 ms
Lock track:{id} • 100 ms wait
Publish shared operating picture
no / invalid
Error hold + named reason

Inside the system

Architecture plates

Each plate preserves the internal layout, paths, boundaries, and highlighted decisions. Use the short label first, then follow the lines through the system.

Plate 01

Two views, one program, one parse

durable source · one parse · node view and script view

CANONICAL ARTIFACT durable .tri source the live-edit store row generations plus rollback ONE PARSE lex · p_stmt · resolve one flat statement list, hoisted static checks run before execution THE SHARED MODEL the AST node graph statement and expression nodes the editing model both views read node view t.code.toGraph(src) reads it t.code.fromGraph(graph) writes it t.code.palette lists verbs and constructs, filtered per editor script view trident --emit file.tri trident_emit(src), in C and in WASM 2-space indent, minimal parentheses literalText keeps the exact spelling THE PARSE AND EMIT FIXED POINT emit(parse(s)) == emit(parse(emit(parse(s)))) run_emit_golden.sh locks the format run_roundtrip.sh runs the regenerated source and diffs its whole transcript CANONICALIZATION DROPS //, /* */ and ordinary # comments original whitespace and text layout but #@node x/y/group/comment survive as structured graph annotations
Plate 02

One type vocabulary, and the grammar that refuses the rest

one table · two consumers · the refused spellings · the whole control-flow set

ONE TABLE, TWO CONSUMERS merbuf_type_mertek.h MERTEK_TYPES · 37 rows name · wire type · accessor ids are appended, never renumbered the Trident lexer is_type() asks the same table the schema column parser mertek_find() parses the spelling SO THE SET IS DERIVED 37 rows, less stream and enum (column-only, never a local) plus char, object and void one shared bound sizes both parsers REFUSED BY NAME, WITH THE REPLACEMENT inti32 shorti16 byteu8 longi64 floatf32 doublef64 stringtext CONTROL FLOW: THE WHOLE SET WHAT THE GRAMMAR HAS repeat (N) { } repeat (N; i32 i = 0) { } foreach (item in items) { } if · elseif · else, one keyword each when, exhaustive over an enum break and continue, in both loops lock, lock? and task blocks WHAT IT DOES NOT HAVE while, and the C-style for else if as two words the ternary ?: and the ?? operator string interpolation a slice, and a negative index let (write var) and print (return) .push (an array takes .add) WHY A BOUNDED repeat A repeat that stands in for a while must break when its guard goes false. Without that break the loop runs to its bound, does nothing on every remaining pass, and the interpreter pays for each one. Write the exit as you write the loop.
Plate 03

How a t. call resolves, and the five ways it refuses

the resolution cascade · one named refusal per step · why a composite lowers

ONE CALL t.<root>.<verb>(args) a bare call reaches a user function, never a platform verb 1 · reserved by prefix t is the one reserved top-level name; the whole t. subtree inherits the reservation 2 · the installed namespace closure one complete namespace per grant, checked before the call arguments evaluate 3 · the compiled C verb table 23 runtime-core namespaces, 1,226 registered verbs, enumerated from the C source by a generator 4 · the lazy Trident runtime library 399 trt_*.tri files under the configured lib root; raw bytes are SHA-256 pinned before the parse 5 · the host callback 17 host-callback namespaces reach the embedder's installed hook, so their surface varies per host THE NAMED REFUSAL AT THAT STEP ReservedIdentifier a write through t, or through a fused t.<root> receiver NamespaceNotGranted parent, child, wildcard and prefix inheritance do not exist UnknownFunction the dispatch is a hardcoded switch: no late binding, no lookup by string NamespaceSourceHashMismatch the pinned source bytes moved, so the runtime refuses before it parses them HostCallbackAuthorityMissing a closed runtime-core root does not authorize an undeclared callback verb WHY A HOT COMPOSITE LOWERS WHOLE INTO C many small C verbs one boundary crossing each: marshal, box, dispatch, per-call arena churn one lowered composite t.geom.diagramRenderBuild emits the whole placed diagram in one C pass The scenario values, the choices and the sequencing still arrive as parameters from Trident.
Plate 04

The value model, the per-task arena, and why the budget exists

the declared budget · the four escapes · the two termination bounds

THE PER-RUNTIME DATA ARENA the declared data budget TRIDENT_ARENA_MB, default 64 MB per TridentRuntime, so per task and per request, never a machine knob a no-free bump allocator whose chunks grow by doubling over budget a catchable OutOfMemory trap the message carries used and cap, the chunk growth, malloc-backed bytes, and the task depth, plus the .tri function backtrace THE FORBIDDEN REPAIR A raise of TRIDENT_ARENA_MB that turns a red gate green hides the defect the cap exists to surface. Profile, remove the waste, then size the budget to the real data. A TASK REGION RECLAIMS ONLY WHEN NOTHING ESCAPES a clean task { } nothing the region allocates outlives it, so the outermost task rewinds its arena scratch an event handler obeys the same rule FOUR ESCAPES, AND EACH ONE KEEPS THE REGION 1 · the region stores a value in a container that outlives it 2 · the region assigns a value to a name bound above it 3 · an array, object or MerBuf that outlives the region GROWS inside it 4 · the region builds an object key text and stores it outside READ IT AS A COST, NOT AS A HAZARD The runtime never hands back reclaimed memory. The only question is whether the region reclaims. To keep a hot handler reclaiming, declare the products once outside the handler and refill them in place, so the handler writes into cells that already exist. the two termination bounds beside it TRIDENT_STACK_MB, default 64 MB, guards the native stack the call-depth bound is 1024, and it raises RecursionLimit Both exist for termination, never to cap what the hardware and the software can do.
Plate 05

From source text to execution: two engines, one result

lex · parse · resolve · static checks · tree-walker and VM · the bit-identity oracle

THE PIPELINE source text a file, or a live-edit store row lex and parse one flat statement list, grown on demand resolve storage class, global reads, reserved names static checks enum when coverage, use and on error order hoist and run functions and enums visible everywhere TWO ENGINES, ONE BIT-IDENTICAL RESULT the tree-walker the engine for cold code: under 8 calls never compiles the fallback for every shape the VM does not cover a block headed by on error always tree-walks, by design tier up on call 8 guard miss: deopt the register VM compiles a function body and its loops into a Chunk cache a cost model declines container and string dominated work every chunk is verified before the runtime publishes it THE ORACLE TRIDENT_BYTECODE=0 pure tree-walk: the frozen bit-identity reference TRIDENT_FORCE_BYTECODE=1 compile every function; the mode the differential gate uses WHAT THE THREE MODES MUST AGREE ON byte-identical output The corpus runs default, tier and force. A differing byte is a red gate, not a tolerance. The tree-walker is the truth. WHY NOT "CLOSE ENOUGH" An engine that rounds one f64 differently forks the language. An arithmetic constant fold moves a trap: 1 / 0 must trap at run time.
Plate 06

The frozen oracle, and the hostile half of it

the corpus · the adversarial cases · the emitter round trip

A · THE CORPUS AND ITS FROZEN FIXTURES 2,740 .tri programs plus 27 adversarial cases the C runtime built -static on Windows one top-level return printed to stdout string-equal vs frozen 2,767 .expected fixtures B · THE ADVERSARIAL HALF: THE BOUNDARY, PROVED BY REFUSAL a hostile .tri on error (err e) { return e.code; } then the malicious operation the trap fires IndexOutOfRange, CapabilityDenied, RecursionLimit, StackOverflow, UnknownFunction, OutOfMemory the code IS the expected value A SILENT SUCCESS CANNOT PASS If the operation goes through, control falls past the handler to the sentinel return "NO_TRAP"; and the diff fails. A case cannot pass by doing nothing. C · THE EMITTER ROUND TRIP, OVER THE SAME CORPUS run_emit_golden.sh 7 per-construct fixtures 7 committed .gen goldens the format lock, plus idempotence run_roundtrip.sh over tests plus the whole corpus 1 · a re-emit is byte-identical 2 · the regen runs the same transcript WHY THE PAIR MATTERS The corpus runs the ORIGINAL text. The round trip runs the REGENERATED text. One gate proves the runtime, the other proves the emitter.
Plate 07

A fault is data, not an exit

bootloader and supervisor · the unwind path · the two declared dispositions

WHO OWNS WHAT the C bootloader (one host) owns main(), the OS handles, the window and the GPU wires the backing vtables: the MerDB engine, the gfx backend, the clock and entropy sources, the transport declares the runtime policy, then hands control over the Trident program (the application) outer layer · the supervisor owns the run loop and dispatches the work catches the faults that inner code raises inner layers · handlers, scenes, jobs any of which may fault an Application adds no compiled C of its own A FAULT IS DATA the trap is raised it sets the runtime error and a code; eval and exec bail out the stack unwinds back to the nearest handler, reclaiming the C stack and the arena on error (err e) { ... } e.code · e.message · e.origin · e.task · e.fatal · e.retryCount it must be the FIRST statement of its scope (after top-level use); a later declaration is a parse error, never a silent no-op the four dispositions: retry · resume · fail · panic THE TRAP DISPOSITION IS THE BOOTLOADER'S DECLARED POLICY application profile · catchable The image must stay up. One bad task is not a whole-system crash, so the supervisor recovers it. An application bootloader clears the fatal flag. CLI AND CONFORMANCE · FATAL A fault is a program defect. Halt deterministically and never mask it. The fatal flag defaults to on, so a bare run fails closed.
Plate 08

The boundary test: a scenario value, or a generic kernel

the question · the two answers · gravity, declared and consumed

THE BOUNDARY TEST, ASKED ONCE PER PIECE OF WORK Is it generic parameterized computation, or a scenario value, choice, or composition? generic compute goes to C a kernel, a codec, a primitive a scenario goes to Trident a value, a choice, a sequence THE DEFECT A hardcoded algorithm constant baked into C. The repair is to PARAMETERIZE the kernel, never to move the compute out of C. GRAVITY: THE WORKED EXAMPLE the scenario declares the value biomechSceneDeclare reads the gravity field of its spec and refuses a missing or non-finite three-component value Moon, zero-g and a dynamic field are the same mechanism with a different declared value, so C needs no new case the kernel takes it as an argument keel_anim_springbone_chain.h steps a chain from the parent transform, the per-bone parameters, gravity and dt keel_physics_fields.h carries gravity on its parameter struct, so the kernel stays generic and stays fast in C THE SAME RULE, THREE MORE PLACES Math is a pure C library of primitives only. The Trident scenario composes them. The C core holds physics DATA as inert hooks. The core does not simulate anything. Glint consumes transforms. No physics and no scenario ever enter a shader.
Plate 09

What "done" means for a Trident change

the reachability claim, recorded per leaf · the three docs and the census gate

A · A CAPABILITY IS NOT SHIPPED UNTIL TRIDENT CAN REACH IT a C kernel lands plus a C harness plus one green gate and no verb reaches it UNFINISHED WORK, NOT A LAYER A C harness verifies numerics. It cannot verify reachability, so the green gate is a false completion signal. THE HALF-SURFACE FORM a debugView nothing can enable an activate with no rollback a subscribe with no retention HOW EACH GATE LEAF RECORDS THE CLAIM trident · 1,116 drives the capability through the real authoring edge evidence: tracked .tri paths c-kernel · 522 a generic parameterized kernel or codec with no author-facing surface host-edge · 49 the narrow trusted per- deployment boundary that correctly owns the operation c-only-hold · 106 an attributed exception: author-facing, no Trident path yet. The burn-down. B · THE THREE REFERENCE DOCS MOVE IN THE SAME CHANGE LANGUAGE.md hand-written syntax and semantics every example verified against the built runtime; no em dash LIBRARY.md hand-written namespace tables 59 built-in namespace rows, plus one generated file-index block PURE-LIBRARY-CATALOG.md fully GENERATED, never hand-edited 346 library files, 6,770 functions regenerated by the metadata script the docs-surface gate The pure-library census is a git enumeration, and it FAILS CLOSED: the enumeration runs once in the main shell, git's exit status is checked at every step, and the population must clear a measured plausibility floor. A negative control drives the gate against failing and under-enumerating git shims, and demands RED from each.

Key parts

What the system does

These are the main boundaries, inputs, outputs, and failure rules. The examples show a specific use of each part.

Two useful views

A workflow can appear as text for precise review or as connected nodes for visual understanding. Both views represent the same program.

Specific example

A planner can review a sensor-to-alert flow as a diagram while an integrator checks the exact rules in text.

Clear system boundaries

Mission choices stay in the application layer. Fast, reusable platform functions stay in the shared foundation.

Specific example

A team can change a flight rule or approval path without rebuilding the platform beneath it.

Failures as useful information

When work cannot continue, the system reports a structured reason instead of only stopping. Applications can respond in a planned way.

Specific example

If a data source is missing, the workflow can record the cause, notify an operator, and move to an approved fallback.

Language examples

A program can read the mission behavior

These short examples show how Trident makes control, data checks, failure, task limits, and shared work visible in the source.

Typed mission values

Types carry exact width, time, and physical meaning into the data model.

i32 readyAssets = 12;
duration responseWindow = 90s;
measure safeDistance = 5<km>;
text status = "ready";

Bounded control flow

Repeat and foreach make the work limit visible instead of hiding an open-ended loop.

i32 available = 0;
repeat (assets.count(); i32 i = 0) {
    if (assets[i]["ready"]) {
        available += 1;
    }
}

foreach (text unit in assignedUnits) {
    t.log.info("checking " + unit);
}

Closed branching

An enum branch must handle every declared state. A new state forces a review.

enum TrackState { New, Confirmed, Rejected }
TrackState state = TrackState.New;

when (state) {
    is TrackState.New { action = "review"; }
    is TrackState.Confirmed { action = "publish"; }
    is TrackState.Rejected { action = "hold"; }
}

Guarded data intake

Dynamic input becomes usable only after required fields pass a typed check.

var { i32 quantity, text source } = report else {
    t.log.warn("report refused");
    return 0;
}
accepted += quantity;

Structured error response

Errors expose a code and message so the application can choose a planned response.

on error (err fault) {
    if (fault.retryCount < 2) {
        retry;
    }
    fail;
}

t.debug.raiseError("SourceUnavailable", "feed offline");

Isolated task with a budget

A task contains a failure and applies a clear time budget to the work.

text result = "pending";
task(50ms) {
    result = evaluateReport(report);
} else (err fault) {
    result = "held: " + fault.code;
}

Lock with a safe busy path

The lock declares its mode, wait, lease, and renewal policy. Busy work takes an explicit alternate path.

object policy = t.sync.exclusive(100ms, 60s, true);

lock? ("asset:" + assetId, policy) {
    readiness += delta;
} else {
    queued = true;
}

Mission event handling

A host event enters through typed accessors and keeps missing data behavior explicit.

on event("TrackUpdated", evt) {
    text trackId = evt.getText("trackId");
    bool trusted = evt.getBool("trusted", false);

    if (trusted) {
        t.log.info("accepted " + trackId);
    }
}

Uses

Example uses

Pilot questions

What the team must decide

Which mission rules should be easy to change

Who must review the visual and text views

How the application should respond to missing or disputed data

Request a technical briefing