Record schemas and API contracts — dispatchable request model, calibrated absence bounds, payload versioning; record schemas deferred to M3
Context
The 2026-07-21 adversarial validity review (critic C1) found a structural blocker in the
shipped contracts: no public contract carries the destination binding or effect payload an
adapter needs to perform an effect (finding B1). The shipped intent contract is a closed
six-field object; the design documents nevertheless require the adapter to receive a
validated payload and to know which destination to call. Passing either through a side
channel would violate the trust boundary (master doc §6.3: model-generated content reaches
the deterministic core only via the validated intent contract). Two further findings bear on
the contracts: “confirmed absent” is uncalibrated without destination consistency bounds in
the capability declaration (C1 M3, companion to the AM-9 draft fields), and machine payloads
need a versioning convention (schema_version) enforced in the schemas themselves (C1 M13).
Separately, the developer-surface proposal drafted three record schemas (EffectRecord,
DispatchReceipt, ReconciliationFinding); C1 M13 showed those drafts do not enforce their own
contracts, and the ratified state-model correction (amendment AM-18 in the review queue:
DUPLICATE stays n>1; a CONTRADICTED classification is added) changes the classification enum
they would encode.
Decision
- Intent contract gains the dispatchable request model (fix for C1 B1), preserving the
identity rule unchanged — identity derives only from
stable_ids + effect_type + scope(ADR-001, RFC-001 §1); none of the new members is an identity input, and the no-model-output-in-derivation conformance test covers them:schema_version(required,"1").adapter_id(required): the configured adapter/destination binding for this effect.parameters(required, object; may be empty): the effect payload the adapter builds the destination request from. Validated against the adapter’s per-effect-type parameter schema before persistence (adapter-supplied, M4 artifact); the ledger stores it with a canonical digest as evidence, never as an identity input.branch_ref(optional): workflow branch lineage carrier — gives the commit gate’s branch check a carrier (absent ⇒ vacuous pass).event_time(optional, RFC 3339): upstream business time, evidence only.
- Capability declaration gains calibrated consistency bounds (fix for C1 M3): a
required
consistencyobject withstatus_settlement_lagandlisting_lag(ISO 8601 duration, or null when no finite documented/measured bound exists). The engine rule (docs/rfc-002-engine-design.md §6): a null bound means confirmed-absence cannot support automatic redispatch for that destination — human escalation only. Automatic redispatch-on-absence is opt-in per adapter/effect type, never default-on. schema_versionconvention: every machine-readable payload (schema instances, SDK responses, CLI--jsonoutput, exports) carriesschema_version; additive changes do not bump it; removals/renames/semantic changes bump it and require an ADR.- The three record schemas are DEFERRED to M3 (T-102), not admitted now. Reasoning:
(a) the proposal drafts fail their own contract rules (C1 M13 —
schema_versionnot required, no conditional subject/resolution requirements, receipts missing operation/execution identity); (b) the classification enum changed under them (AM-18 adds CONTRADICTED), so admitting them now would force an immediate second ADR; (c) the original deferral rationale in schemas/README.md (no producer/consumer until the ledger exists) still holds. Admission criteria, binding on the future ADR:schema_versionrequired; conditional (if/then) requirements tying resolution status toresolved_at/evidence;operation_idon receipts; orphan subjects keyed by(adapter, destination_ref); enums generated from the ratified state table (docs/rfc-002-engine-design.md §3), never hand-copied.
Alternatives
- Side-channel payload delivery (SDK sidecar argument) — rejected: violates §6.3; the trust boundary must be the schema.
- Admit the three record schemas now — rejected per item 4; deferral is recorded, not silent.
- Optional
adapter_id/parameters— rejected: an optional binding reproduces B1 (an effect the engine cannot dispatch is unrepresentable as a valid contract instance).
Consequences
The two shipped schemas change shape (this ADR is the required gate); their example suites are updated in the same change and must keep passing/failing as labeled. RFC-001 §1’s identity procedure is untouched; RFC-002 consumes the new members. The master-doc §7.3 record-field text now lags the contracts — recorded as proposed amendment AM-17 in the review queue (master-doc integration pending; contracts govern implementation meanwhile).
Risks
parameters reintroduces model-shaped content into a validated channel — mitigated by
per-adapter parameter schemas, digest-only evidence storage, and the M3 conformance test
that no identity/key derivation path reads it. Adapter parameter schemas do not exist until
M4; until then the stub destination’s parameter schema is the only consumer.
Reopen trigger
The M3 ledger implementation finds the request model insufficient (e.g. multi-step intents need per-step parameters); or the record-schema admission ADR (M3) discovers a conflict with the state table; or a second SDK needs a contract member this shape cannot carry.