First-class questions and Jev batches

Questions are ordinary SOS records. Construct them with pure std/jev operations, read them from JSON, pass them into actions or collect them in lists. Constructing questions never calls the provider.

10 lines
import "std/jev" as jevcall jev.noul with "Is this urgent?" called urgentcall jev.choice with "Which team?", {"platform": "Service reliability", "other": "Another team"} called teammake questions with:  urgent from urgent  team from teammake message "Checkout is unavailable"evaluate message by jev using questions called answersshow answers.urgent.p_yesshow answers.team.value

evaluate STATE by jev using QUESTIONS called NAME is fixed language syntax. It sends every named question against the same state in one HTTP request. Runtime judgment policy applies. A batch consumes one request admission, not one admission per question. Every attempt is counted, including failed responses; there are no automatic retries. Questions are limited to 1–128 per batch; this is not a monetary spending cap.

Question data

A question record has type, instructions, and optional criteria. Unknown fields are errors. Supported types are noul, choice, and score. Instructions are required; empty text is rejected. Choice needs at least two labels. Score needs at least two ordered levels. Explicit Noul criteria must contain true and false descriptions.

7 lines
{  "outage": {    "type": "noul",    "instructions": "Does this describe an active outage?",    "criteria": {"true": "Service is currently unavailable", "false": "No current outage is established"}  }}

Standard operations

OperationArgumentsResult
jev.noulinstructionsNoul question record
jev.choiceinstructions, criteria recordChoice question record
jev.scoreinstructions, levels listScore question record
jev.questionslist of {id, question} entriesNamed question record; duplicate/empty IDs fail
jev.answeranswers record, text IDNamed answer; missing IDs fail

These operations are pure and support native/WASM targets. The live evaluate operation is rejected on WASM, consistently with other live Jev operations.

jev.questions is useful inside loops that assemble rules dynamically. jev.answer retrieves an answer when the rule ID comes from data rather than a literal property name.

Results and validation

Each ID maps to the same normalized answer shape used by individual judgments: Noul p_yes; Choice value, confidence, probabilities; Score expected, confidence, probabilities. Missing, extra, wrong-kind or malformed answers fail the entire batch. There are no silently accepted partial results.

Trace records one request with the named answer map and reported input-token usage. Record/replay includes the entire batch in the source/state/question/model fingerprint. Changing questions invalidates replay; replayed nested answers are validated and consume no new provider requests.

SOS semlint milestone

examples/sos/semlint/main.sos implements sequential evaluation and threshold filtering over prepared units. Its JSON fixture includes two rules against one code unit. This is the first rewrite milestone, not a replacement for the Go semlint executable: it does not yet discover source files, extract functions, select rules from regexes, read Git diffs, trim context, run workers or preserve semlint's CI exit-code contract.

The source-scanning implementation now lives in examples/sos/semlint/scan.sos; see SOS semlint. It adds source/diff primitives, context handling, bounded concurrency and CLI reporting while keeping Go semlint as the reference. The prepared-unit example remains intentionally small.