Core-N0 Linear Handler P1V3 Contract

Status: implemented and validated
Architecture decision: ADR-0015
Core profile: P1V3

1. Operation identity

OperationSignature =
    Operation<OperationId, (ParameterTypes...), ResultType>
  • OperationId is a canonical U32.
  • One ID has exactly one signature throughout an artifact.
  • Parameters and result contain neither Ref nor Closure.
  • Arguments match parameters exactly; there is no coercion or Any.

2. Handler representation

handle
    captures (operand0 as local0:type0, ...)
    clauses [
        operation(parameters...) => clause_term
    ]
in body
  • capture operands evaluate left-to-right once;
  • capture bindings are the only outer locals visible to clauses;
  • clause order is strictly increasing by operation ID;
  • every clause binds exactly its operation parameters;
  • a clause returns exactly the operation result type;
  • the handled body returns the surrounding term result type.

3. Affine implicit continuation

For:

let x = perform op(args) in continuation

under a matching handler:

  1. evaluate args left-to-right;
  2. execute the innermost matching clause;
  3. on Return(value), bind x = value and resume continuation exactly once;
  4. on typed error or unhandled operation, resume zero times and propagate.

The continuation is structural, lexical, and not a value. It cannot be named, returned, passed, stored, compared, cloned, or resumed more than once.

4. Deep body and clause forwarding

The resumed body retains the original handler stack. A clause executes outside its selected handler and every handler nested inside that boundary.

A same-operation perform in the clause therefore:

  • reaches the next outer exact handler; or
  • becomes an unhandled operation.

The innermost exact signature wins.

5. Effect subtraction

An active exact handler satisfies Effect::Operation(signature) for:

  • Perform;
  • direct-call effects;
  • closure-call effects.

Every other effect remains required in the enclosing function row. If no handler matches, Perform requires the exact operation effect in that row.

6. Unhandled outcome

An admitted unhandled operation terminates the current evaluation with:

UnhandledOperation {
    operation: OperationSignature,
    arguments: [CoreValue...]
}

The arguments have already been evaluated. No continuation object crosses the entry boundary.

7. Lifetime and logical store

  • handler captures are explicit and cannot escape the Handle term;
  • captured references must be active at handler entry;
  • handler environments containing references make dynamic calls borrow the same logical store;
  • clause mutation through a captured alias is visible after resumption;
  • closing a region removes its cells on return, typed error, unhandled operation, and budget failure;
  • a clause cannot reopen an active captured region.

8. Fail-closed boundary

P1V3 rejects:

  • handler or perform constructs in older profiles;
  • reference/closure operation parameters or results;
  • one operation ID with conflicting signatures;
  • empty, duplicate, or non-canonical clause sets;
  • capture arity/type mismatch or unbound capture;
  • inactive captured reference regions;
  • clause parameter arity or duplicate local IDs;
  • clause result mismatch;
  • perform arity/type mismatch;
  • missing unhandled operation effect;
  • unsupported first-class or multi-shot continuation behavior.

9. Budgets

  • entering a handler, performing an operation, and evaluating a clause consume the canonical global step budget;
  • calls made under handlers consume normal call depth;
  • recursive handled operations are bounded by both budgets;
  • no handler-specific hidden retry budget exists.

10. Canonical encoding

Semantic encoding v1 reserves append-only assignments:

profile P1V3 = 3
Effect Operation = 6
RValue Perform = 11
Term Handle = 6

Operation signatures, captures, bindings, clauses, and bodies are encoded in structural order. Existing P1V0/P1V1/P1V2 bytes and hashes remain unchanged.

The canonical capture-and-resume vector locked by the implementation has semantic hash:

20f4ae704987e1b61795085575c622111fb290dd72655899dcb770fa8a6723b4

11. Evidence required

  • handled substitution and exactly-once continuation;
  • typed error zero-resumption;
  • unhandled declared outcome and missing-effect rejection;
  • dynamic direct-call and closure-call propagation;
  • nested precedence and same-operation forwarding;
  • explicit capture ordering and alias-visible reference mutation;
  • signature, arity, type, clause-order, lifetime, and profile negatives;
  • call-depth and step-budget failures;
  • repeated semantic bytes/hash and tamper rejection;
  • unchanged older Core/T2 stability vectors;
  • full workspace, strict lint, formatting, governance, shell, and documentation-link gates.

12. Non-claims

P1V3 is not first-class continuation support, multi-shot effects, nondeterminism, async/generators, Surface handler admission, general escaping closures, handler specialization, partial evaluation, P1/P2, native lowering, or dependency closure.