Making s1-model 'Judgements' a RubyLang primitive feature Developer innocentdiaz released s1_ruby, a Ruby gem that adds System One (S1) measurement and a "collapse" operation over meaning as a native Ruby primitive, with a companion Ruby on Rails implementation at s1_rails. The library lets code ask a typed question about data and receive a calibrated probability from an S1 model that does not generate or decide, exposing verbs such as choose, score, and judge plus a ψ operator for preparing state, lenses via given/against, and late-collapse operators &, |, and ~. The project's README states that where it and the bundled THEORY.md disagree, the theory is authoritative. AI built for interfacing with code useful — not with people too good to be true . The AI race has revealed the operation that computation was missing: collapse over meaning. System One S1 measurement — and the collapse that follows it — native to Ruby. An S1 model answers a typed question about data with a calibrated probability. It does not generate, and it does not decide. Code asks; code decides. - For the Ruby on Rails implementation, see: s1-rails https://github.com/innocentdiaz/s1 rails - For the terms, see THEORY.md https://github.com/innocentdiaz/s1 ruby/blob/master/THEORY.md . Where this README and the theory disagree, the theory is right. TABLE of CONTENTS - TL;DR tldr - The idea: collapse the-idea-collapse · Why why - Install install - Grammar: verbs, nouns, ? grammar-verbs-nouns- - The three kinds the-three-kinds — noul · choice · score · Level level · Scales scales-one-place-for-the-labels · Distribution distribution · Batch batch-many-questions-one-call · Structured state structured-state-and-structured-questions · Reading distributions reading-distributions - Experimental: making it native experimental-making-it-native — the core extension · ψ · pattern matching · === - Keeping the probability: collapse late keeping-the-probability-collapse-late — & | ~ · ranges · undecided? · collapse - Collections: judgments as predicates collections-judgments-as-predicates — select / group by / sort by / sum / grep · the lens given: - Dictionary and aliases dictionary-and-aliases - Errors errors · Testing testing · Observing calls observing-calls · Providers providers · Development development Illustrative code: Pull from a database: people = { name: "Michael", occupations: "owner @ large self-sustaining family homestead", "software engineer @ MedicalTech startup $2M/arr " }, { name: "Bob", occupations: "Exotic beast/animal hunter & trader pokemon hunter ", "Professional Sportsman office ping pong master ", "Front-Counter Point of Sale POS Operator MacDonalds in Hunstville, Alabama " } ψ people .choose "the most skilled individual", categories: people.map { 1 :name } = Michael — one call; .ranked lists everyone people.max by &ψ.score "How skilled is this person?", "novice", "competent", "expert", "exceptional" = the Michael hash; one call per person ψ people prepares the list: it is now a state , something questions can be asked about, none asked yet. Measuring it — choose the most skilled — is, by default, the model's own sense of "skilled". To make the judgement relative, hand the model something to judge against : a lens , with given or against : ψ people .given rubric: "skill = breadth of trades" .choose "the most skilled, per rubric ", categories: people.map { 1 :name } = Bob The same list, with the categories built from the data, is under choice the-three-kinds . Another example: python class EscalateToHuman < StandardError; end def handle chat chat triage = ψ chat .measure do |q| several measurements, one call q.judge :escalate, "Is the customer asking for a supervisor?" q.judge :new matter, "Is this a new matter?" q.score :severity, "How severe is the injury?", "None", "Minor", "Serious", "Catastrophic" end raise EscalateToHuman if triage.true? :escalate ? collapses; a bare distribution is always truthy create case triage :severity .level if triage.true? :new matter && triage :severity .level.position = 1 end chat = { messages: } inbox.each do |message| whatever feeds you messages: a queue, a webhook, a socket chat :messages << message handle chat chat one call per message; every question answered fresh rescue EscalateToHuman hand to person chat end Software is rows and associations. Its input is human: a form, a phone call transcript, a review, a chat, a résumé. Its output is what a person sees on the other side: a web UI, an API, an MCP. Between the two sits the one thing computers could never do — read the human input and judge it. For AI to be useful it has to tap that stream of human input — the data, one transcript or a list of calls, tickets, candidates — and categorize it, sort it, judge it. Not write about it: decide something about it that code can act on. That operation is the movement this gem is built around — four positions, three arrows: evidence ──prepare──▶ state ──measure──▶ distribution ──collapse──▶ category x ψ x by a question over a scale a point on it Two of the arrows have a symbol. ψ prepares : ψ chat is a state — the evidence rendered once, fixed, with calibrated answers to any question, none yet taken. Rendering happens at preparation and never again: mutating chat afterwards does not change what is judged. The verbs measure : judge , choose , score — three kinds of measurement, always one of the three — or several at once with measure { |q| q.judge …; q.choose …; q.score … } . Each returns a distribution over its scale, calibrated and kept. ? collapses : the distribution becomes a category. That is Ruby's own suffix with Ruby's own meaning empty? , any? : the decision, not the thing . Between the last two arrows there is nothing new — arithmetic, ranges, sum , case — because once a judgement is a number, Ruby already knows what to do with a number. Human stream + Lens ──ψ──▶ state ──judge / choose / score──▶ distribution ──?──▶ category │ & | ~ ranges sum case One point where the physics image is loose: S1 answers are deterministic and repeatable; the probability is calibrated credence, not a coin waiting to be flipped. "Collapse" names the code's choice to stop carrying the distribution — and it is a choice; the section Keeping the probability is about not making it too early. The human adjusts a judgement in exactly two places. The definition attaches to the question and changes what the concept means : a clarification of yes / no, a description per category, the ordered levels criteria: is its wire word, and the keyword in code . The lens attaches to the state and changes what the concept is applied to : a firm's acceptance criteria, a role's requirements, a return policy — given: , or a Rails form. If it changes the meaning, it is the definition; if it changes the evidence, it is the lens — a firm's "criteria" is a standard to judge against, so it is a lens. The judgement is semantic categorization, with a probability. A regex categorizes by characters; this categorizes by meaning — the same kind of tool a predicate you filter and match with , applied where characters run out. And the judgement is probabilistic : every distribution is kept whole, so "need more info / maybe / probably / sure" is as native as true / false, and a sum of nouls is an expected count. The thing that changes: name = "Andrew" male name = true if ??? there was never a way to write this line preference color = male name ? "blue" : "pink" male name = ψ name .is? "a man's name" now there is: ψ prepares, is measures, ? collapses ψ name .is "a man's name" = 0.97 — the distribution alone, when the number is what you want "Andrew".noul "Is this a man's name?" = 0.97 — the same distribution by its name, with the core extension on That is the whole foundation: make the movement native to the language, then give it the same surface everything else in Ruby has — filter, group, sort, sum, match, pattern-match, batch — so a stream can be judged with Enumerable the way it is counted with Enumerable . Everything in this README is one of those two moves. The model behind it jev, today is what makes it possible; the grammar is what makes it usable. An S1 model does one thing: measure judge, choose, score . Three kinds cover it: - Choice — group, classify, route choose - Score — a level on an ordered scale score - Yes / no, with a probability judge It is not a free-form assistant for people an LLM . It interfaces with code. Code-in-the-loop, not human-in-the-loop. The most basic usage: chat = { messages: "How may I help you?" ... } escalate to human if chat.judge? "is the customer asking for a human agent?" core extension on c.primitives = true escalate to human if ψ chat .is? "asking for a human agent" ψ on c.psi = true Under the hood, both are: state = S1::State.new "I have asked three times now. Can I just talk to a real person?" escalate to human if state.judge? "Is the customer asking for a human agent?" gem "s1" config/initializers/s1.rb or anywhere at boot S1.configure do |c| c.provider = :typesafe default; a name under Providers, or an instance c.timeout = 30 seconds per request c.threshold = 0.5 a noul at or above this reads as true c.logger = Rails.logger optional; debug lines per request, warns on retry c.primitives = false true extends String, Hash, Array; see "Experimental" c.psi = false true defines ψ x ; see "Experimental" c.typesafe.api key = ENV "TYPESAFE API KEY" default: read from the environment c.typesafe.model = "jev-latest" c.typesafe.base url = "https://api.typesafe.ai" c.typesafe.max retries = 2 transient failures before raising c.cua.checkpoint = "cua-s1-forms" only when c.provider = :cua c.laya.base url = "http://127.0.0.1:8765" only when c.provider = :laya self-hosted end Every value has a default; an initializer is only needed to change one. Each provider keeps its own settings under its name c.typesafe , c.cua , declared by the provider class. Ruby ≥ 3.2. No runtime dependencies. One rule names every method in this README: a verb measures and returns the distribution; a noun returns the thing it names; a ? returns a boolean. States carry verbs. A state is anything a question can be asked about: an S1::State ; a String, Hash or Array with the core extension on; a Rails record. A ψ. predicate carries the same verbs unapplied. | verb | asks | returns | |---|---|---| | judge is and same as fill the question in | "Is this true?" | Answer::Noul | | choose | "Which of these?" | Answer::Choice | | score | "Which level?" | Answer::Score | | measure ask , batch , ask about | several at once | Result | Distributions collapse. One contract: collapse threshold . The threshold only matters to a noul, and a noul carries the one it was measured under S1::State.new x, threshold: 0.9 ; the config's as of the measure otherwise — stamped then, not read at collapse; a noul built by hand carries the config's as of its construction ; the others accept and ignore it, so a Result collapses every distribution through one call, each noul at its own threshold, and to h , true? and case … in follow. Each kind names its collapse and exposes Ruby's own conversions. | collapsable | collapse returns | its own name | Ruby idioms | |---|---|---|---| | Answer::Noul | true / false | true? false? | so , to f , Comparable , & \| ~ | | Answer::Choice | a Symbol | choice | to sym , to s , loose == | | Answer::Score | an S1::Level | level | key the most likely level's rank , to f weighted position , levels | | Result | { id = collapsed value } | to h | deconstruct keys , so case … in | Nouns name; ? decides. On every state: x.noul q == x.judge q the dichotomous distribution, by its proper name — an Answer::Noul x.choice q, cats == x.choose q, cats .collapse the category picked — a Symbol x.level q, levels == x.score q, levels .collapse the point on the ordinal scale — an S1::Level x.judge? q == x.judge q .collapse threshold a boolean; noul?, ask? are the same; on an S1::State and a ψ. predicate is? and same as? fill the question in The asymmetry is deliberate. Only the dichotomous distribution has a proper name — noul — so its noun returns the distribution itself. The nominal and ordinal distributions have none, so their nouns can only name the category: choice is a Symbol, level is a point on the scale. And a ? method returns a boolean — Ruby's convention — so ? exists only for a noul: there is no choice? and no judge? on a Choice or a Score. Every question is one of three kinds — the first three of Stevens' scales: dichotomous, nominal, ordinal. Pick by what the answer is . Each kind has a verb that measures and a noun that names. The examples use state = S1::State.new text ; a ψ: line gives the same call with ψ on. A Noul prints as its probability, so = 0.98 below is a Noul at 0.98. noul — "Is this true?" The dichotomous distribution: a probability, 0 to 1, over { true, false } . The probability is the signal. judge measures it; noul is its name, and returns the same thing; judge? noul? is true at or above the threshold; is / is? take a phrase and ask "Is this …?". js state.judge "Is the customer asking for a human agent?" =