AgentBlueprintProtocol.Reconcile (Agent Blueprint Protocol v0.1.1)

Copy Markdown View Source

The one call per import : the composed non-authorizing pass over a Blueprint + Deployment pair under host inputs. Stage order is PINNED — canonical → digest → negotiation → structure → portability → signatures → bind → bounds — each stage reject-or-annotate, never repair, the earliest defect reported.

Stage machinery (each denies typed, subject naming its side):

  1. canonical — re-encode both artifacts' values (RFC 8785). A struct has no bytes to compare against, so this stage catches only what ENCODE denies: the ceiling family ({:ceiling, :bytes} — the :canonical_bytes_exceeded name), :integer_magnitude (a hand-built above-I-JSON integer), and the encode-side Json reasons. :non_canonical_bytes is decode-time only (it needs the original bytes).
  2. digest — recompute each artifact's content digest over its covered members and compare against the declared member (:digest_mismatch).
  3. negotiation — both artifacts against Inputs.support. Extension facts land as checks: a quarantined optional namespace is %{surface: :extensions, verified: false} (the unscanned honesty), a retained one %{surface: :extensions, verified: true, detail: "retained"}. Notices stay in the Negotiation.Outcome for standalone callers — the frozen Evidence struct has no notices field.
  4. structureRegistry validation against each artifact's table (the closed world, cardinalities, member checks).
  5. portability — the DIRECT scans under the authored channel re-derived from THIS import's negotiated critical extensions (F8): non-authored extension bodies, eligibility expressions, every core string, and signature key_ids (:forbidden_portable_value). The registry half of the decode pipeline is NOT re-run here — it is stage 4's own catch, and re-running it would make that stage's guard unobservable.
  6. signatures — every signatures entry verifies against Inputs.keys AND its signed content_digest BINDS to the artifact's recomputed digest: an honestly-signed statement naming a different digest is evidence over THAT digest, not this artifact (:digest_mismatch). Attestations need no pass here — the registry table denies any non-empty attestation member today (the kind registry is empty; the fail-closed posture).
  7. bindDeployment.verify_binding/3 under Inputs.observations (host clock, attestation age, observed descriptor digests).
  8. boundsfrom_blueprint/from_deployment/host intersected under Inputs.protected_clamp. Every clamp lands as Evidence.clamps and as one surface: :bounds check whose detail is the %ClampEvidence{}; :clamp_applied remains the notice code for the notice machinery (a clamp notice cannot ride the negotiation Outcome — bounds runs after it).

The result is %Evidence{} — never a decision; not_verified names the seven host-owned surfaces by construction (Evidence.build/1).

Summary

Functions

Run the eight-stage composed pass. Denies typed at the earliest failing stage; every malformed input shape (either artifact, or any Inputs field) denies typed without raising.

Functions

reconcile(blueprint, deployment, inputs)

Run the eight-stage composed pass. Denies typed at the earliest failing stage; every malformed input shape (either artifact, or any Inputs field) denies typed without raising.