Warrior API
A warrior is an external binary that owns execution, proving, verification and deployment on one battlefield. Trident compiles; warriors fight.
Two contracts hold between them:
| contract | direction | where |
|---|---|---|
| process | trident build/run/prove/verify → <warrior> on PATH |
targets.md §Warriors |
| library | warrior links trident-lang as a Rust crate |
this document |
This document is the library contract: what a warrior may depend on, what the core promises not to break, and where the line between them runs.
The line
A thing belongs to the core if it produces trident's own
representation or every warrior consumes it: the front end (lexer,
parser, AST), the type checker, TIR and its optimizer, nox lowering
(nox is the semantics every other target is checked against), the cost
framework, audit, the LSP, the package system, and the MIR import.
A thing belongs to a warrior if it knows one machine: the lowering from TIR to that ISA, its cost model and verifier, its runtime, its prover, its deployment path, and its hand-written baselines.
The 2026-09-11 ownership review records the migration rationale and its historical checkpoints. The implemented resource contract is compiler API3 below. Current ownership evidence records the final removal of machine-window legalization from the core.
Surface
Everything below is pub in trident-lang and covered by the stability
promise. Paths are as a warrior writes them.
Compilation
compile_to_bundle
The nox entry point returns assembly, entry point, function hashes, costs,
source hash and reads_state. Stack warriors obtain per-module TIR through
build_tir_modules, lower/link it, then call:
bundle_with_assembly
The core derives source metadata once through this shared contract. The warrior supplies its own assembly and measured or explicitly unavailable costs.
build_tir
For a warrior that owns its own lowering: typed, optimized TIR — a flat
op list, already monomorphized, with control flow structured. The
warrior turns it into its ISA. build_tir_project resolves imports;
build_tir is the single-file form.
CompileOptions::default() selects the canonical nox ABI. For an external
target, resolve trident::target::TargetPackage::discover(target) and pass the
validated owner package to CompileOptions::with_package(package). An owning
warrior may supply its own validated package directly. This selects the ABI,
module sources and intrinsic capabilities together. TerrainConfig::triton()
is a compiler test helper; external target implementations come from their
owners, not a compiler-local machine manifest.
source_options(input, options) resolves a project directory or a source file,
applies the project's named profile and dependency paths, and preserves the
caller's chosen terrain. module_sources carries version-matched warrior
modules by dotted name. Resolution prefers an explicit editor overlay, supplied
package sources, explicit dependency sources, then the compiler's embedded
portable libraries. Reserved std/vm/os names missing from those sources
fail rather than loading an ambient checkout. The compiler embeds portable
libraries and owner discovery metadata; warriors embed their target resources.
CLI target precedence is explicit register/target selection, then project target, then nox. Selecting nox explicitly overrides a Triton project. Missing warriors, unknown terrain, and failed child processes produce nonzero exit.
Runtime
ProgramBundle is the pipeline boundary. The five traits are the shapes
a warrior implements; nothing in the core calls them — the CLI delegates
by process, not by trait object. Implement the ones your battlefield
supports.
Utilities
content_hash_bytes // cyber-hemera
ContentHash // hex, parse
// proof sizing
Feature contract
A warrior takes trident-lang without default features:
trident-lang = { version = "0.3.0", default-features = false }
The default feature set is empty. Opt-in neural enables the shared model,
training and inference framework; warriors provide an ISA vocabulary, grammar,
equivalence oracle and costs. Ordinary build/run/prove installations require
no neural backend. The compilation and runtime surface is available without it.
Stability
- The paths above follow semver on
trident-lang. Breaking them is a major bump with a CHANGELOG entry naming the warrior-visible change. TIROpis an in-process contract: a Rust type, not a wire format. A warrior links the sametrident-langbuild it compiles against. Serialization is deliberately absent — the day a non-Rust warrior exists, it gets a defined encoding and a version tag; until then a schema would be a promise with no reader.ProgramBundledoes have a wire form (JSON) because it crosses the process boundary intrident run/prove/verify. Fields are additive andfrom_jsonignores unknown keys. Function metadata, named cost values, assembly and state declarations survive transport. Malformed JSON, duplicate identity keys and invalid field types are rejected. Named cost tables are maps; their textual order carries no semantics.- Everything else in
trident-langis internal. Depending on it is allowed and unsupported: it moves without notice.
Warriors today
| warrior | battlefield | uses |
|---|---|---|
| joy | nox · cyber | runtime::*, target, field::proof — takes the bundle, executes on cyber-nox, proves with zheng |
| trisha | Triton VM · Neptune | per-module TIR, owned lowering/linker and runtime, source metadata via bundle_with_assembly |
Neptune runtime modules and Triton baselines live in Trisha. The core discovery catalog records owners; implemented target declarations come from their runtime packages. The release audit records current proof-support limits; this API contract does not certify the cryptography of a linked warrior.
Target packages (compiler API 3)
The owner-approved target resource contract uses target::TargetPackage.
Warriors implement describe --target <terrain-or-union> and emit one JSON
object without executing user programs. schema_version and compiler_api
are 1 and 3 respectively. API 3 is the incompatible coordinated compiler/warrior
contract for Trident 0.3, Trisha 0.3 and Joy 0.5; API 1 and 2 packages are rejected.
API 3 adds resolved primitive EntryParameters metadata to shared TIR. The owner
must marshal executable entry parameters using its documented calling convention;
Trisha consumes a typed public-input prefix and preserves explicit public output
(entry ABI). Ordinary function
calls retain their calling conventions. The nox source-entry adapter validates
exact arity and typed leaves and reconstructs internal noun aggregates
(nox entry contract); raw nox programs retain their own ABI. The JSON
schema remains 1. The package carries owner/version, terrain ABI, optional union,
state presets, module sources and their Hemera content hashes, intrinsic and
assembly-instruction names, and separate runtime capabilities. Missing or
incompatible packages fail explicitly. The compiler retains the nox reference
ABI; external target definitions come from their warrior.
TargetPackage::seal computes module identities; validate checks the schema,
bounds, matching module declarations/content hashes, reserved generated module
keys and selected-network membership. CompileOptions::with_package validates the
package and selects its terrain, module sources and capabilities together.
Public IO, secret execution, public proofs and deployment are independently
specified by runtime restrictions and proof format identifiers.
Core resource names are dotted language namespaces, independent of physical
lib/ paths. Explicit locked/project module sources precede embedded sources;
ambient working-directory library trees never replace packaged modules.
std.target is generated from the selected ABI. Intrinsic declarations must
match the selected ABI. Transitive requirements of reachable functions must be
provided by the package; unused unsupported helpers may remain in libraries.
Instruction batching and addressable stack depths belong to warrior lowering.
TargetPackage::discover reads an explicit lock directory when
TRIDENT_TARGET_PACKAGES is set, otherwise the installed owner's descriptor.
Descriptor lookup and command dispatch choose the same executable: registered
trident-<target>, trident-<owner>, then <owner> on PATH. Descriptor output
is bounded to 32 MiB and 15 seconds. Before a locked package is used for runtime
or foreign compilation, its compilation identity must equal the actual
executable's describe output. Both packages must support the requested command.
Unknown owners and incompatible versions fail before executing user programs.
Compilation identity binds the selected ABI, package version, compile-time
network, cfg and the actual resolved module bytes. Deployment state presets
are excluded. Package manifests name program<output_extension> and bind its
bytes; foreign cost estimates are absent when the owner supplies none.
package --state and registry deploy --state are unsupported and fail
explicitly before compiling or writing an artifact, for both source and packaged
inputs. Network transaction preparation/submission belongs to the installed
warrior's separate deploy interface. Reading declared state presets does not
imply live state execution.
Production resources contain modules only. Entry programs and unfinished recursive verifier experiments live in Trisha examples and are never exported through the Neptune SDK package.
The production Triton package exports vm.triton.proof.verify(Digest) -> ()
through its registered triton_stark_verify_v1 operation. Its input commits to
the expected native claim: program digest, version, complete public input/output
and lengths. The owner links the pinned, corrected official Triton verifier and
loads its bounded private witness. A caller must bind the expected commitment to
its own policy or public inputs. This VM operation is independent of Neptune's
transaction policy; os.neptune.proof remains an excluded prototype. The complete
transport and memory contract is owned by
Trisha.
Owner-defined typed operations
A target package may provide intrinsic_abis, a map from an opaque operation
name to IntrinsicAbi { params, results }. The default is an empty map for
existing packages. Each type is Field, Bool, U32, Digest or XField;
digest/extension widths come from the selected machine contract. No results
means unit; multiple results form a tuple. The operation must also appear in
the package's available intrinsics list. ABI declarations are included in
the package compilation hash, so signature changes invalidate its identity.
The compiler checks every imported #[intrinsic(name)] declaration against
this owner-supplied signature and still checks reachable capability requirements.
Packages cannot redefine a language intrinsic, invent an ABI for the reference
nox lowering, or exceed 64 parameters/results and 4096 input/output words.
Zero-width primitive ABI values are refused. Custom operations are available
through typed SDK declarations; a name alone is not a signature.
Both ordinary calls and pass-through functions emit
TIROp::TargetCall { name, inputs, outputs }. The core performs no ISA rendering
or target-specific implementation for this operation. The warrior must validate
its registered name and exact word effect before lowering, and reject unsupported
calls without producing an artifact. This extends the typed compiler/warrior
boundary; it does not authorize arbitrary inline assembly or let a source file
change the selected package ABI.
trident run and trident prove forward --input-file PATH to the selected
warrior, which owns the file schema and bounds. The compiler does not load or
log witness contents. This option conflicts with --input-values, --secret
and --digests; explicit digest queues are forwarded unchanged. Trisha accepts
its version1 public/secret/digest JSON format for recursive witnesses that exceed
OS command-line limits. Other warriors reject unsupported input transports.