- Status: Accepted (design). Execution phased Ф0–Ф7.
- Date: 2026-08-20
- Supersedes / relates to: builds on
@arno/origineVerifier (proof substrate); relates to ADR 0053 (token tiers), ADR 0059 (naming chord), the Studio-tools doc pattern (ADR 0058), and ADR 0022 (branch strategy). - Spec:
docs/component-model/model.md— the Arno Component Model with Part B — Binding Amendments (v2), which is normative.
Context
@arno/origine already ships a mature proof half of a component contract model: a fold-based Verifier (20/21 behaviours proven), hand-authored + DOM-sampled Witnesses, a framework-neutral observation adapter (DOM/React), an obligation store, and a human waiver. What it lacks is the authoring half: capabilities, dimensional states, a structured WHEN/THEN behaviour model, property semantics, temporal operators, and — above all — an Induction Engine that turns demonstrated behaviour into candidate obligations.
A new model document (model.md) formalises the whole: a component = Properties + States + Behaviours + Proof, plus Capabilities and derived Observables, with an Induction→Proof split and a human confirmation membrane. Review of that document surfaced seven under-specifications that, if left vague, would let an implementer invent semantics during development (the god-schema failure mode). Those are closed in Part B of the spec and are binding.
The user need this serves: create a component → make it interactive with a set of rules and interactions → verifiable at the Arno level, per every principle in the spec.
Decision
- Adopt the Component Model with its Part B binding amendments as the source of truth (
docs/component-model/model.md). - Do not rebuild origine's proof half. Treat origine's Verifier, Witness, obligation store and waiver as consumers. Build only the missing authoring half, as producer modules (each only emits; consumers already exist in the flow).
- Integrate via existing seams (Punta, WorkflowView, ObligationList, the token catalog, Component Builder), not new surfaces where an old one fits.
- Make
/buildmodel-aware (analyst classifies P/S/B/Capabilities and emits obligations; QA treats scenarios as Witnesses and writes safety-first, verify-beyond-example tests; reviewers enforce the 15 rules + the three-part contract + the trust-boundary law). This discipline is Arno-only scoped (role files are global; gate behind "building an Arno Foundation/Studio component"). - Execute design-first, in phases Ф0–Ф7, each a shippable
/buildrun.
Overarching law (root of every amendment)
No implicit derivation crosses the trust boundary. Everything the machine derives stays a candidate until a human confirms it. No proof → no truth. Enforced as a /build review gate.
The seven binding amendments (full text: Part B of the spec)
- Induction — Witness → candidate-gen → ranking (fixed prior) → human confirm → obligation. May rank, never create without confirmation.
- State ownership + Property/State discriminator — one membrane. Statehood granted by confirmed behavioural participation; non-sticky;
statehood {confirmedBy, sourceBehaviour}. - Timing —
TemporalConstraint {duration, bound, clock}; Core = finite bounds only; witness-time deterministic replay; witness-time ≠ temporal bound. - Enforcement layered — Authoring → Verifier → Projector.
- Observables declared, not guessed — Semantic map → observation contract → platform adapter; derivation proposes relationships as candidates.
- Multi-projector conformance — golden-case Conformance Harness before a second Core projector; the two projectors are Arno's DESIGN render and the customer's CODE render.
- Status system — non-mixing axes (below).
Status system (four non-mixing concerns)
- Obligation —
verdict {VERIFIED|VIOLATED|UNOBSERVABLE}×lifecycle {ACTIVE|INVALIDATED|ARCHIVED}(+PENDINGfor unresolved targets) ×waiver {none|active{waivedBy,reason,expiry}}. - Projector —
CONFORMANT | NON_CONFORMANT. - Contract completeness —
COMPLETE | INCOMPLETE{unresolved:[(node,slot,state)]}. - Component trust —
TRUSTED | DEGRADED | BROKEN. - Fold:
active obligations → verdict → severity → waiver overlay → trust, capped by conformance and completeness.UNOBSERVABLE(state unreached) ≠INVALIDATED(state gone) ≠NON_CONFORMANT(projector blind) ≠INCOMPLETE(contract hole).
Tokens ↔ state (the colour binding)
- Tokens are state-indexed under a role (
interactive.primary.hovered). Bind to the role, resolve the state-child (role[state] ?? role.default). - Token editor:
Role {Priority|Meaning|State}; a newTypedropdown appears only underRole=State, options = capability-licensed states (authoring enforcement at the token layer; kills free-text drift). appliedToken(node, slot)is a Core observable and a vector over the whole component tree — one state change moves background + icon + text at any depth; obligations are per(state, node, slot). State owned at root, consumed by presentational descendants.- Token-editor arrows = colour-relationship layer (no WHEN). WHEN is assigned at component assembly. They compose at verify time.
- Completeness + guided repair: a missing state-colour is
INCOMPLETE, not a silent fallback — the node is flagged red on canvas, and the token editor scaffolds a red placeholder card (relationship + settings pre-wired, colour value left to the human).
Producer modules (each only emits) and consumer seams
| # | Producer (working name → candidates) | Emits | Consumer seam (existing) |
|---|---|---|---|
| P1 | state dimensions (stato/dimensioni) | dimensional state model, authored dims; derived-state candidates via membrane | Punta States panel, WorkflowView, Verifier |
| P2 | capabilities (virtù/capacità/dote) | capability surface = authoring-enforcement gate | Punta section gate (mirror SurfaceCapabilities in ponte studio-bus), token Type dropdown |
| P3 | witness recorder (gesto/saggio) | demonstrated Witness with +t timing | ComponentPage preview ref; executable WorkflowView transitions |
| P4 | induction (induzione/congettura) | ranked candidate obligations (fixed prior) | ObligationList membrane (Accept/Reject), origine store |
| P5 | temporal grammar (tempo/durata) | bounded operators for predicates | verifier/evaluator.ts |
| P6 | colour-relationship (legame/nesso/arco) | palette relationship graph (Type-tagged edges, no triggers) | state→token resolver, Verifier; reuses @arno/rotta for drawing |
| — | completeness checker + repair scaffolder | completeness verdict + scaffold actions | canvas node + token card |
Create-entry bridge: Component Builder LayoutNode tree → ComponentContract (per-node colour bindings, not just root).
Module names require the user's pick (identity-consent) at Ф1; not needed for Ф0.
origine code deltas
- Split
Obligation.status = verified|violated|waived→ three orthogonal axes (verdict / lifecycle / waiver{waivedBy,reason,expiry}); addlocus. Coverage.uncovered→unobservable; verify the trust-fold does not count it as verified (honesty check, Ф0).Trust.verified→trusted; fold consumes projector conformance + completeness.- Witness
Observationframe gainst(elapsed ms);observe()/recordVerify()stamp it. - Verifier fold filters
lifecycle == activebefore computing verdicts. - Semantic dependency graph (behaviour → statehood → state → obligation) with cascade-invalidation; flat arrays don't capture it.
- Declarative Foundation
semantic → observablemap as data. - New projector-conformance level + Conformance Harness.
button.contract.ts: remove the Property/State collapse — in source onlyloadinganddisabledare both a State and a boolean Property (selected/pressedare Properties only, correctly, since no confirmed behaviour references them).
Phase plan (each = a /build run, shippable)
- Ф0 — unblockers (origine + punta, low risk):
locus; Property/State split + discriminator (statehood-by-participation); replace Rule 1;uncovered → unobservable+ verify fold honesty. - Ф1 — P1 authored dimensions + Punta consumer + Verifier guard-over-dimensions + migrate flat
ComponentState. - Ф2 — P2 capabilities + Punta gate + authoring enforcement + token
Typedropdown. - Ф3 — Witness
+t+ P3 demonstrator on preview + executableWorkflowViewtransitions. - Ф4 — P5 temporal + verdict set (incl. TIMEOUT) + Foundation semantic→observable map +
appliedTokenobservable (tree-aware). - Ф5 — P4 induction (fixed prior) + membrane (Accept/Reject, both candidate kinds) + derived-state candidates + 3-axis obligation model + cascade-invalidation graph + P6 colour-relationship + completeness checker/repair.
- Ф6 — Component Builder →
ComponentContractbridge (per-node colour bindings). - Ф7 — Conformance Harness (DESIGN vs CODE golden cases); may start React-only as self-test.
Cross-cutting: from Ф1, model-aware /build reviewer gates (trust-boundary law, no Property/State collapse, 15 rules, three-part contract), Arno-only.
Alternatives considered
- Rebuild the model as fresh code (ignore origine). Rejected — origine's proof half is mature and aligned; duplicating it wastes work and forks the source of truth.
- Bolt the model onto
/buildroles globally. Rejected — the model is Arno-specific; global role edits would pollute every project's workflow. Scoped Arno-only instead. - Leave the seven under-specifications as future work. Rejected by the maintainer — vague Induction / State-ownership / Property-State would force the implementer to invent semantics (
god-schema). Closed in Part B before any code. - Token vocabulary migration (rename tokens to a canonical enum). Rejected for an adapter map (§B.8) — non-breaking.
Consequences
- The whole "configure → demonstrate → confirm → verify" loop becomes buildable, with every arrow owned by a module.
- A component state change proves the coherence of the entire nested colour tree — the core value.
- Cost: a real new authoring surface (demonstration, membrane), a frame-schema change (timing), and a projector-conformance harness.
- Open: the five/six module names (Ф1), and whether production render hard-blocks on
INCOMPLETEor visually falls back to base (default: fall back + flag).