# Contracts Contracts are the portable runtime boundary-checking layer for `tricu`. A contract is an ordinary `tricu` function that inspects a value and returns a standard `Result`. Contracts are not a type system. Tree Calculus is intensional: every value is a tree and can be inspected by any function. A contract can only observe a value and fail when it does not satisfy the advertised predicate. It cannot hide a value's representation or prove that an opaque function behaves correctly for all inputs. Static typing for Tree Calculus is an area of active research. This document describes the dynamic-contract layer that exists today and the guarantees it can honestly claim. ## 1. The contract type A contract is a function: ```tri contract : Tree -> Tree -> Result Tree Tree ``` The second argument is the conventional `rest` slot. It takes a value and a rest and returns one of the standard `Result` shapes from `lib/base.tri`: ```tri ok value rest = pair true (pair value rest) err msg rest = pair false (pair msg rest) ``` In contract contexts the `rest` slot is conventionally `t`. Two helpers make this explicit: ```tri contractOk = (value : (rest : ok value rest)) contractErr = (msg : (rest : err msg rest)) ``` - On success, a contract returns the checked value. This may be the original value or a transformed/normalized value. - On failure, it returns a reason. The reason is an arbitrary tree, often a string or a structured diagnostic. Because a contract is just a tree-valued function, any Tree Calculus implementation can apply it. No special contract object format is required. ## 2. Core boundary wrappers ### 2.1 Explicit check `checkContract` applies a contract with the conventional `t` rest slot and returns the raw `Result`: ```tri checkContract = (contract value : contract value t) ``` This is the most flexible form. The caller decides what to do with failure. ### 2.2 Direct boundary abort `withContract` applies a contract with the conventional `t` rest slot and continues on success, or calls a failure continuation on failure: ```tri withContract = (contract value onOk onFail : matchResult (msg _ : onFail msg) (checked _ : onOk checked) (contract value t)) ``` The failure continuation is supplied by the host or by the surrounding program. It may abort, log, return a default, or raise an effect. The core contract standard does not prescribe the failure behavior. ### 2.3 Example: a simple contract ```tri isZero? = n : equal? n 0 nat? = guardC "not a natural number" (n : gte? n 0) -- explicit check result = checkContract nat? 5 -- boundary abort five = withContract nat? 5 (x : x) (msg : 0) ``` Real contract predicates are usually more interesting than `isZero?`; this illustrates only the shape. ## 3. Contract combinators Contracts compose using ordinary `tricu` functions. A few common patterns: ```tri andC = (c1 c2 value rest : matchResult (msg _ : contractErr msg rest) (v _ : c2 v rest) (c1 value rest)) mapC = (f c value rest : matchResult (msg _ : contractErr msg rest) (v _ : contractOk (f v) rest) (c value rest)) listOf = (c xs rest : ...) -- checks spine and element contract pairOf = (c1 c2 p rest : ...) ``` These are library code, not core standard. A contract library can provide `listOf`, `pairOf`, `fnContract`, and similar helpers. ## 4. Higher-order contracts A contract for a function value returns a wrapped proxy. The proxy itself is a contract: it checks arguments on the way in and results on the way out. ```tri fnContract = (argC resC f rest : contractOk (x : (rest1 : withContract argC x (x' : withContract resC (f x') (y : contractOk y rest1) (msg : contractErr msg rest1)) (msg : contractErr msg rest1))) rest) ``` This does not prove that `f` is well-behaved internally; it only catches violations at observed calls. ## 5. Interaction-tree contract effects The core contract layer returns `Result`. For code that wants catchable, composable contract failures without threading `Result` through every function, contracts can be lifted into an interaction tree. ### 5.1 Interaction-tree constructors These reuse the same `pure`/`bind` tags already used for `tricu` IO: ```tri pureE value = pair 0 value bindE action k = pair 1 (pair action k) exceptE tag value k = pair 2 (pair tag (pair value k)) ``` `exceptE` is resumable: `k` is the continuation. A handler may resume with `k replacement` or abort by ignoring `k`. Contract failures usually abort; the resumable shape is provided for generality and for richer effect handlers. ### 5.2 Lifting a contract ```tri checkM contract value = matchResult (msg _ : exceptE "contract" msg (\_ : pureE t)) (checked _ : pureE checked) (contract value t) ``` `pureM` and `bindM` are aliases for `pureE` and `bindE`: ```tri pureM = pureE bindM = bindE ``` ### 5.3 Lifting pure functions ```tri liftM f = (x : pureE (f x)) ``` ### 5.4 Example ```tri halfM n = bindM (checkM even? n) (\n' : pureM (div n' 2)) use = handleM "contract" (\msg k : pureM 0) (halfM 5) ``` `handleM` is a pure tree-to-tree function that interprets `exceptE` nodes, either resuming with a replacement value or returning a failure tree. ### 5.5 Running a pure interaction tree ```tri runM tree = -- interprets pureE, bindE, and exceptE nodes -- returns a Result or a residual effect tree ... ``` If the tree contains no IO or other host effects, `runM` can be written entirely in `tricu`. ## 6. Source syntax Source annotations are frontend sugar for inserting contract boundaries. They do not change the runtime semantics of ordinary code; they tell the frontend where to emit contract checks. ### 6.1 Argument and result assertions ```tri idNat x@Nat =@Nat x ``` `x@Nat` inserts a `Nat` contract check on the argument. `=@Nat` inserts a check on the result. ### 6.2 Compound contracts ```tri sum xs@(List Nat) =@Nat ... useHandler f@(Fn [(NonEmptyList String)] String) =@String ... ``` Compound annotations must be parenthesized when they contain application. ### 6.3 Phantom arguments ```tri map @A @B =@(Fn [(Fn [A] B) (List A)] (List B)) ... ``` A phantom argument contributes a contract to the function boundary without introducing a term binder. ### 6.4 Missing annotations Unannotated binders in a contract-bearing head default to `Any`. A missing return annotation defaults to `Any`. ```tri foo x y@Bool = body -- foo : Fn [Any Bool] Any, y : Bool ``` ### 6.5 Export contracts A module export may advertise a contract: ```tri !export factorial : Fn [Nat] Nat ``` The advertised contract travels with the export in the module manifest. ## 7. Module and content-store integration Contracts attach to module exports as ordinary content-addressed tree terms. There is no special contract object kind. The manifest references the contract with the same object kind as any other tree term: ```text name: "factorial" object: kind: arboricx.tree-term.v1 hash: contract: kind: arboricx.tree-term.v1 hash: ``` The earlier `arboricx.view-contract.type.v1` object kind is removed. A contract is just a tree term. For locally built modules, advertised export contracts may be checked before the manifest is published. For imported modules, the advertised contract is a boundary assumption. The local checker may insert guard wrappers when a contracted import is used. See `docs/module-system-design.md` and `docs/content-store-and-module-format.md` for the full store, manifest, and bundle conventions. ## 8. Guarantees The contract layer honestly claims only: 1. A contract applied to a value returns a standard `Result` shape. 2. `withContract` and `checkM` invoke the contract at the represented boundary. 3. A failed contract invokes the supplied failure continuation or `exceptE` node. 4. Content-addressed references prevent an attached contract from silently drifting to a different stored object. 5. Provenance labels record where a contract assertion came from. Only the contract function itself observes the runtime value. The rest is metadata plumbing. ## 9. Limitations - Contracts do not establish parametricity or representation independence. - They do not prove that opaque recursive or primitive code satisfies its contract for every input. - They do not remove the need for tests, careful API design, or future static analysis. - Higher-order contract wrapping has the usual costs and proxy-like behavior of dynamic contract systems. ## 10. Summary - A contract is an ordinary `tricu` function: `Tree -> Result Tree Tree`. - `withContract` aborts at a boundary; `checkContract` returns the raw `Result`. - The interaction-tree layer (`checkM`, `bindM`, `handleM`) adds catchable, composable failures on top of the same core contracts. - Contracts attach to module exports as ordinary tree-term objects. - Provenance labels record source and blame, but do not prove truth.