agentic examples

The Projection Agreement Prover

The Projection Agreement Prover: relation rules now render twice - the validator enforces them in Ruby, and to_json_schema projects them into draft-07 keywords (dependencies, not-required). Two renderings of one law can drift, so this prover evaluates BOTH against every presence combination and demands they agree. It also walks to the exact frontier where they don't: JSON's null.

Testing & Verification Round 10 Xavier Noria exit 0

source on github

bundle exec ruby examples/projection_agreement.rb

a real captured run

PROJECTION AGREEMENT PROVER (4 fields -> 16 presence combinations)

  {express                                 } validator: reject schema: reject agree
  {express, api_key                        } validator: reject schema: reject agree
  {express, oauth_token                    } validator: reject schema: reject agree
  {api_key, oauth_token                    } validator: reject schema: reject agree
  {express, api_key, oauth_token           } validator: reject schema: reject agree
  {customs_code, api_key, oauth_token      } validator: reject schema: reject agree
  {express, customs_code, api_key, oauth_token} validator: reject schema: reject agree

  16 combinations, 0 disagreement(s) - the dependencies and
  not-required clauses say exactly what the validator enforces,
  proven point by point rather than asserted.

  the frontier: {express: nil}
    typed field:   validator rejects (per-key: nil isn't a boolean)
                   schema    rejects (the property EXISTS - dependencies fire)
    untyped field: validator allows  (nil is ABSENT - rule not triggered)
                   schema    allows  (projection declined - the keyword was never emitted)

  on the nil-free plane the projection is faithful, point by point.
  and at the frontier the projection now knows its own limits: a
  relation over untyped fields is not rendered into keywords it
  cannot render truthfully - it rides x-agentic-rules instead.
  a projection that declines is honest; one that guesses is a trap.

source

# frozen_string_literal: true

# The Projection Agreement Prover: relation rules now render twice -
# the validator enforces them in Ruby, and to_json_schema projects
# them into draft-07 keywords (dependencies, not-required). Two
# renderings of one law can drift, so this prover evaluates BOTH
# against every presence combination and demands they agree. It also
# walks to the exact frontier where they don't: JSON's null.
#
#   bundle exec ruby examples/projection_agreement.rb
#
# Runs offline; exits 1 if the projections disagree on the nil-free plane.

require class="s">"bundler/setup"
require class="s">"agentic"

SPEC = Agentic:class="y">:CapabilitySpecification.new(
  name: class="s">"connect", description: class="s">"Connect an integration", version: class="s">"1.0.0",
  inputs: {
    express: {type: class="s">"boolean"},
    customs_code: {type: class="s">"string"},
    api_key: {type: class="s">"string"},
    oauth_token: {type: class="s">"string"}
  },
  rules: {
    customs: {relation: class="y">:requires, fields: [class="y">:express, class="y">:customs_code]},
    one_auth: {relation: class="y">:mutually_exclusive, fields: [class="y">:api_key, class="y">:oauth_token]}
  }
)

VALUES = {express: true, customs_code: class="s">"HS-1", api_key: class="s">"k", oauth_token: class="s">"t"}.freeze

# A four-line draft-07 evaluator for exactly the projected keywords
def schema_allows?(schema, payload)
  keys = payload.keys.map(&class="y">:to_s)
  (schema[class="s">"dependencies"] || {}).each do |trigger, needed|
    return false if keys.include?(trigger) && !(needed - keys).empty?
  end
  (schema[class="s">"allOf"] || []).each do |clause|
    required = clause.dig(class="s">"not", class="s">"required")
    return false if required && (required - keys).empty?
  end
  true
end

def validator_allows?(validator, payload)
  validator.validate_inputs!(payload)
  true
rescue Agentic:class="y">:Errors:class="y">:ValidationError
  false
end

schema = SPEC.to_json_schema
validator = Agentic:class="y">:CapabilityValidator.new(SPEC)
fields = VALUES.keys

puts class="s">"PROJECTION AGREEMENT PROVER (#{fields.size} fields -> #{2**fields.size} presence combinations)"
puts

disagreements = 0
(0...2**fields.size).each do |mask|
  payload = fields.each_with_index.select { |_, i| mask[i] == 1 }.to_h { |f, _| [f, VALUES[f]] }
  ruby = validator_allows?(validator, payload)
  json = schema_allows?(schema, payload)
  disagreements += 1 if ruby != json

  next unless ruby != json || !ruby # print the interesting rows only

  puts format(class="s">"  {%-40s} validator: %-6s schema: %-6s %s",
    payload.keys.join(class="s">", "), ruby ? class="s">"allow" : class="s">"reject", json ? class="s">"allow" : class="s">"reject",
    (ruby == json) ? class="s">"agree" : class="s">"DISAGREE")
end

puts
puts class="s">"  #{2**fields.size} combinations, #{disagreements} disagreement(s) - the dependencies and"
puts class="s">"  not-required clauses say exactly what the validator enforces,"
puts class="s">"  proven point by point rather than asserted."
puts

# --- the frontier: explicit nulls ---------------------------------------------
# Ruby's relation presence is "given and non-nil"; JSON Schema's
# dependencies trigger on the PROPERTY existing, null or not. Two
# metaphysics of absence - walk to the exact spot where they part.
#
# First discovery: for TYPED fields the frontier is guarded. An
# explicit nil never reaches the relation check, because per-key
# typing rejects it first ("must be boolean"), and the schema rejects
# it too (dependencies fire) - agreement, but for different reasons.
frontier = {express: nil}
puts class="s">"  the frontier: {express: nil}"
puts format(class="s">"    typed field:   validator %-7s (per-key: nil isn't a boolean)", validator_allows?(validator, frontier) ? class="s">"allows" : class="s">"rejects")
puts format(class="s">"                   schema    %-7s (the property EXISTS - dependencies fire)", schema_allows?(schema, frontier) ? class="s">"allows" : class="s">"rejects")

# In round 10 an untyped field exposed the true divergence: nil
# sailed past per-key checks, the validator's relation read it as
# absent, and the schema's dependencies read null as present. The
# round-11 release closes it from the projection side: a relation
# over any UNTYPED field stays out of the draft-07 keywords entirely
# (it still travels in x-agentic-rules), so the schema never claims
# a law it can't render faithfully.
untyped = Agentic:class="y">:CapabilitySpecification.new(
  name: class="s">"connect", description: class="s">"x", version: class="s">"1.0.0",
  inputs: {express: {}, customs_code: {type: class="s">"string"}},
  rules: {customs: {relation: class="y">:requires, fields: [class="y">:express, class="y">:customs_code]}}
)
ruby = validator_allows?(Agentic:class="y">:CapabilityValidator.new(untyped), frontier)
json = schema_allows?(untyped.to_json_schema, frontier)
projected = untyped.to_json_schema.key?(class="s">"dependencies")
puts format(class="s">"    untyped field: validator %-7s (nil is ABSENT - rule not triggered)", ruby ? class="s">"allows" : class="s">"rejects")
puts format(class="s">"                   schema    %-7s (projection %s)", json ? class="s">"allows" : class="s">"rejects",
  projected ? class="s">"STILL EMITTED - divergence is back!" : class="s">"declined - the keyword was never emitted")
puts
puts class="s">"  on the nil-free plane the projection is faithful, point by point."
puts class="s">"  and at the frontier the projection now knows its own limits: a"
puts class="s">"  relation over untyped fields is not rendered into keywords it"
puts class="s">"  cannot render truthfully - it rides x-agentic-rules instead."
puts class="s">"  a projection that declines is honest; one that guesses is a trap."
exit(1) if projected

exit(disagreements.zero? ? 0 : 1)