Skip to content

Releases: chussenot/judgment

judgment 0.14.0

Choose a tag to compare

@github-actions github-actions released this 15 Oct 19:52

Added

  • Images in a request, as Jev 1.13 and later take them
    (https://docs.typesafe.ai/images): Image holds a PNG or a JPEG and
    reads its format and size from the bytes, refusing what the hosted API
    refuses before anything is sent (not a PNG or a JPEG, animated, a side
    outside 256 to 1568 pixels, under 78,400 or over 2,458,624 pixels, over
    16 MiB) as the new Error::InvalidImage; Assets is the wire's
    assets map, each image under its own reference (img- and 32 hex
    digits of the bytes' SHA-256, Image::reference) or one the caller
    chooses, with the reference rules and the 32 MiB total checked
    (Error::InvalidAsset, Error::RequestTooLarge). Request::assets
    carries them (Request::new(..).with_assets(&assets)), left off the
    wire when empty, and SystemOne::answer_with_assets takes them through
    every backend. The client sends TypeSafe-Danger-Zone-Images: true on
    every request that has an image and on no other, refuses a reference
    that appears nowhere in the state or the questions and a body over
    32 MiB before sending, reports the images' count and bytes to the
    Observer (on_assets) and records the count on the
    typesafe.evaluate span as images. Error::is_request_too_large is
    also true of RequestTooLarge. Decision 0024 says why the images are on
    the request rather than a call option, why the reference is derived from
    the bytes and why the client sets the header.

  • canonical::request_fingerprint_with and eval::request_hash_with: the
    request fingerprint and hash with the images, each named by the SHA-256
    of its bytes under an assets key that is left out without any, so a
    request without images fingerprints as it always has and every committed
    recording still replays; Recorder and Replay key by them, so two
    requests that differ only by an image are two recordings.

  • Fake takes images, remembers each one's reference and digest in its
    Call, and refuses a reference the state does not carry as the hosted
    API does.

  • The Box primitive, Jev 1.14's fourth question type
    (https://docs.typesafe.ai/primitives/box): Questions::r#box(id, instructions) asks where what the instructions describe is in an image
    the request carries (no criteria; null instructions are refused, since
    they are all the question is), and the client sends the images header
    for it even without an image. The answer is Answer::Box { edges, confidence }, the wire's box as BoxEdges (top, bottom, left, right
    as fractions of the image) and a confidence the document lets be null;
    Response::verify refuses a box that is not a region (an edge outside
    0..=1, a left not below its right, a top not below its bottom) as
    Error::InvalidAnswer, and reads it as BoundingBox, with width,
    height, center, to_pixels, confidence_at_least and the geometry
    on BoxEdges (iou, padded, area, contains). A Box always answers
    with a box, so the typed view's documentation pairs it with a Noul gate.
    Fake::r#box scripts one. Judgment::located grades a Box against a
    labelled box by intersection over union at eval::DEFAULT_IOU_AT_LEAST
    (0.5) or the label's own bar, with the number on Judgment::iou and
    QuestionMetrics::mean_iou; a Box has no Brier score. In a rubric a Box
    is gated by confidence or bands (never threshold, fallback or
    level_at_least) into Verdict::Located or a deferral, and a case labels
    it {box: {top, bottom, left, right}, iou_at_least}.

  • The .jud format at minor 4 (jud::MINOR): a box question, the images
    a document names under spec.assets on a Rubric and assets on a case
    (jud::AssetSource: a path relative to the document, or format and
    data_base64 inline; decision 0025), loaded into a request's Assets by
    Rubric::load_assets and Case::load_assets, with a reference that
    appears nowhere in the state or the questions refused as the API refuses
    it; the Box label {box, iou_at_least} (jud::BoxLabel), graded by
    intersection over union at 0.5 unless the label says otherwise (decision
    0026); a Box in a gate's confidence or bands; Verdict::in_pixels,
    which adds the located box in an image's pixels beside the edges. The
    schemas, the format page and examples/jud/shapes.jud with its forty
    labelled synthetic images (examples/jud/images/) move together, and the
    format page carries a known fingerprint vector for a request with an
    image. A minor 3 reader refuses a minor 4 document by number; a minor 4
    reader reads every minor 3 document as it did.

  • jud: every subcommand that builds a request loads the documents' images
    and keys recordings by them; jud RUBRIC --asset REF=PATH (repeatable)
    adds an image from the command line and --pixels WxH names the size a
    located box is also printed in pixels of (the one image's size when there
    is exactly one); a located verdict prints as located with box, the
    confidence, the band and pixels; jud eval reports a Box question's
    mean_iou beside its accuracy, no Brier score, and a miss's iou; jud check counts a document's images.

  • jud: long_context: true in its configuration file, or --long-context
    on jud RUBRIC, jud record and jud eval, asks for long context on
    every call of the run (the switch of decision 0027, passed to
    ClientBuilder::long_context); the flag wins over the file, and a replay
    ignores both since it asks nothing. jud config reports long_context
    and long_context_from, jud record --dry-run prints a long context:
    line, and the line before a run's first call names it when it is on.

  • The multipart feature: CallOptions::multipart for one call and
    ClientBuilder::multipart for every call of a client send a request's
    images as the multipart/form-data body TypeSafe recommends, a JSON
    request part in which each asset is {type: image, part} and one part
    per image (part-0, part-1, … in reference order, under image/png or
    image/jpeg), instead of base64 in the JSON body; off by default, and
    nothing without an image in the request. The request's fingerprint and
    hash, the recordings, the checks before the wire, the images header and
    the observer's report are the same under either transport, and the
    typesafe.evaluate span records multipart. ImageFormat::content_type
    names the media type. Decision 0028 says why it is a feature and a switch
    and not the default; verified against the hosted API, which answers the
    form at the same tokens as the JSON body.

  • A second Box calibration study, on forty generated document pages with a
    round ink stamp a tenth of the page wide among a round logo, a signature
    and a barcode (examples/jud/stamps.jud, stamps-cases.jud and
    images/page-*.png, drawn by scripts/gen-document-pages.py from one
    seed), recorded on jev-1.14.0 under examples/recordings/stamps/ and
    set against the shapes baseline at two sizes
    (docs/project/verification/box-calibration-study-pages.md): the misses
    are near misses at an overlap of 0.45 to 0.49, twice the pixels turn
    every one into a hit at three times the tokens, and the Box's confidence
    does not say "nothing here" when a round logo is on the page, which the
    Noul beside it does. tests/jud.rs replays the recordings and pins the
    counts.

  • Get verdicts on images from the command line,
    a guide that walks a shell user from a rubric that names an image to a
    verdict with jud alone: --asset and --pixels, the verdicts a Noul
    and a Box print and why the Noul is read first, what is refused before
    any call, images a rubric always sends, the labelled loop over photos and
    what a real run needs and costs; every transcript is replayed from the
    stamps recordings and held to the binary by tests/docs_examples.rs.

  • Long context (https://docs.typesafe.ai/models#long-context): both
    context limits raised from 64k tokens per request and 32k per question
    to 262k through the TypeSafe-Danger-Zone-Long-Context: true header,
    on Jev 1.13 and 1.14. CallOptions::long_context(true) asks for it on
    one call and ClientBuilder::long_context(true) on every call of a
    client (a call's false turns it off again); the header is reserved
    (client::DANGER_ZONE_LONG_CONTEXT_HEADER) and recorded on the
    typesafe.evaluate span as long_context. Off by default, as TypeSafe
    says a long request is slower and less accurate, and never read off the
    request's size (decision 0027). Verified live: a 74,550-token state the
    default budget refuses as max_tokens_exceeded was answered under the
    header by jev-1.13.0 in 1.4 s.

  • The Claude Code plugin (now 0.4.0) knows Jev 1.14: the jud skill's
    rules and guidance for a Box question (what to locate, the Noul beside
    it, the reference in the state, the images a document declares, the box
    label in fractions and its bar), the jud-tune skill's reading of a
    Box's jud eval and jud tune numbers (a mean IoU where a Brier score
    would be, the labelled count, the empty images, the triage rows for a box
    that is loose, on the wrong thing or over nothing) and what re-encoding
    an image costs, and the jud-rust skill's third template,
    examples/jud/shapes.rs, a module whose decide takes the request's
    Assets and whose Located verdict carries a Box, exercised from the
    shapes recordings by examples/jud_typed.rs; the commands follow, and a
    seventh authoring eval asks for an image rubric over five parcel photos
    and their annotator's boxes (skills/jud/evals/files/images/), run once
    with the skill and once without through the new
    skills/jud/evals/run.py, and a ninth jud-rust scenario asks for the
    shapes module and replays the recordings with their images through the
    module it gets; the plugin guide records both. In a cloud session the
    start hook installs the plug...

Read more

judgment 0.13.0

Choose a tag to compare

@github-actions github-actions released this 10 Oct 18:48

Added

  • jud RUBRIC --options JSON and --options-file PATH supply the options
    of each Choice the rubric marks options_from: request: the tools an
    agent may call, the desks staffed now, whatever changes per request. They
    are asked in the order given, before the static options, and refused
    before any call when they cannot be asked. Such a rubric used to be
    refused by jud RUBRIC outright; jud eval and jud record already
    took a case's own options, and jud lower already took --options.

  • Jev through OpenRouter's System One API is a backend: base URL
    https://openrouter.ai/api, an OpenRouter key. Usage::cost holds the
    usage.cost it sends, in US dollars (None from a server that sends
    none, and left out of a recording then); its generation id (gen-dec-…)
    becomes Response::request_id when there is no x-typesafe-request-id;
    its 402 for a balance that has run out is the new
    Error::PaymentRequired, not retried. mise run live:openrouter runs the
    live tests against it with OPENROUTER_API_KEY, under a new openrouter
    profile that expects its GET /v1/models to be OpenRouter's own
    catalogue; an unprofiled run against openrouter.ai stops before it
    asks, as one against the hosted API does. Checked against a stand-in
    built from OpenRouter's documented shapes; no live run is recorded yet.

  • mise run live:pplx runs the ignored live tests against Perplexity's
    pplx-decider-v1.1-27b through the autojev-serve its checkpoint ships,
    which serves /v1/systemone (PPLX_URL, default
    http://127.0.0.1:8010; PPLX_API_KEY also runs the bearer test). The
    model itself needs a GPU with about 49 GiB free; the server's wire was
    checked with the checkpoint's own server.py and answer() over a
    stand-in network, where all the live tests pass, with and without a
    key. Its departures from the hosted API, and why to name the model
    autojev-qwen3.8-27b though it answers to jev-latest, are in
    docs/project/verification/autojev-serve.md.

  • The live tests check every body they read as sent, a success, a
    refusal or the model list, against the vendored OpenAPI document and
    print the verdict, down to the field of the answer kind that fails; a
    status the document does not list (the hosted API's 400, laya-serve's
    413) is named as such. A success body that does not conform fails the
    run against the hosted API and autojev-serve, and is reported for any
    other server. A new test, every_body_the_server_sends_holds_to_the_published_document,
    sends the request shapes the builders produce and fetches the model
    list for it.

  • JUDGMENT_LIVE_PROFILE (typesafe, laya, autojev, generic) names
    the server the live tests run against, and each mise run live:* task
    sets its own. Where servers differ (a refusal's status, the limits, the
    budget) a behaviour is asserted on the profile it was observed on and
    printed on the others; laya-serve 0.3.24's statuses, as its verification
    record has them, and autojev-serve's are now pinned too. Unset, the
    profile is generic, except against the hosted API, where it stops the
    run. docs/project/verification/autojev-serve.md records what the
    autojev profile pins and how it was observed.

  • jud names every TYPESAFE_* or JUD_* variable it does not read
    (JUD_BASE_URL, TYPESAFE_MODEL): one line per variable on stderr
    before it asks a server and in jud record --dry-run, saying what it reads instead and which model and server it is
    asking, and ignored_environment in jud config. An unset base URL is
    the hosted API, so a misspelt variable used to send billed calls there
    without a word. Names only, never values.

Changed

  • jud record and jud eval write one line to stderr before the first
    call to a server, naming the model, the server and where its base URL
    came from (asking jev-latest at https://api.typesafe.ai for up to 7 requests (base URL from default)). A server run of jud eval used to
    leave stderr empty on success. Nothing changes under --replay.
  • The live tests no longer decide from the model name whether the hosted
    API's behaviour is asserted: a model whose name starts with jev was
    taken for the hosted API, which autojev-serve, answering to
    jev-latest, is not. mise run live:typesafe sets the typesafe
    profile; a hand run against the hosted API sets
    JUDGMENT_LIVE_PROFILE=typesafe to keep its pins.
  • Breaking: Usage has a third field, cost: Option<f64>, and is no
    longer Eq (it stays PartialEq, Copy and Default). A Usage { .. }
    literal adds cost: None.

Fixed

  • A base URL with a path lost its last segment: the client joined
    v1/systemone onto it as a relative URL, so https://openrouter.ai/api
    reached https://openrouter.ai/v1/systemone, and any gateway served under
    a path got a 404. The path is now kept, with or without the trailing
    slash, as the official SDKs keep it. A base that only worked because its
    last segment was dropped (https://api.typesafe.ai/v1, which reached
    /v1/systemone) now reaches /v1/v1/systemone; drop that segment.

judgment 0.12.0

Choose a tag to compare

@github-actions github-actions released this 09 Oct 09:34

Added

  • jud eval reports, per question, its answers by outcome (how many labels
    name each, how often the model gave it, how often rightly), the majority
    label with its share, and five signals: no_better_than_majority,
    collapsed, never_answered, defers_most and defers_nearly_all, each a
    warning: line in the text and a code in the new outcomes, majority
    and signals keys of --json, none read from fewer than ten answers. The
    thresholds they were read with are the new signal_rules key, so a report
    says which it used (decision 0022). They are what the tuning skill
    computed by hand on the first real-world run (#46).
  • jud record --dry-run says what a run would do and does nothing: the
    requests, how many the directory answers, which are to ask or replace,
    the backend and model, whether a key is set, and the time at the median
    pace of the recordings already there. No key, no call, no file. It counts
    two cases that lower to one request once, and refuses what the run would
    refuse before its first call.
  • jud split CASES [--every N] [--out DIR] writes a tuning set and a
    held-out set, every Nth case held out, each case copied as read so the
    recordings over the whole set answer both. It writes over nothing and
    warns when a label one half has is missing from the other. A from_turn
    label counts as the turns it labels, and with --rubric RUBRIC a Score
    level written as its index and as its text is one level.

Changed

  • The Claude Code plugin (now 0.3.1) carries what a first real-world run
    taught it (#46): a rubric over Wikimedia's recentchange stream, 93 cases
    captured from it, recorded and tuned against tev1:0.8b on Ollama, and a
    Rust loop judging the live stream. jud-tune now reports each question
    against always giving its commonest answer, names a question that has
    collapsed onto one answer, flags a gate that defers nearly every case,
    states a local server's cost as time, and allows an announced subset
    experiment on a copy to measure a question change. The jud skill and
    /jud:rubric ask for the field each answer is read from and leave to code
    what machine-written fields decide; /jud:cases keeps captured states
    verbatim and labels from the best evidence, an outcome known later
    included. jud-rust gives the use path for a module mounted from
    lib.rs and says that every decide is one request a stream caller must
    bound. The mock System One server gains collapse and confidence
    profile keys, and a new jud-tune scenario uses them.

Fixed

  • /jud:rust no longer writes a Cargo.lock (or a target/) into the
    user's crate when that crate already mounts the module: it runs cargo test there only when a lock file exists, with a target directory outside
    the project.

Added

  • The Claude Code plugin (now 0.3.0) turns a rubric into a typed Rust module:
    the jud-rust skill and /jud:rust <rubric>. The module reads the rubric
    with include_str! and lowers the request with Rubric::lower, so it sends
    what jud lower sends and a retune needs no regeneration. It gives each
    Choice and Score an enum and the program one call, decide(backend, model, state), and its own test fails when the rubric's questions drift from it.
    examples/jud_typed.rs wires the two template modules
    (examples/jud/triage.rs, examples/jud/routing.rs) into a program and
    tests them; scripts/gen-plugin-rust.sh keeps the plugin's copies equal
    to them.

Added

  • The Claude Code plugin (plugins/jud/, now 0.2.0) measures and tunes
    rubrics as well as writing them: a jud-tune skill and three commands.
    /jud:record says how many calls a run spends, to which backend and model,
    before running jud record, and resumes what a directory already holds.
    /jud:eval grades the recordings and triages every miss into a wrong
    label, an ambiguous question, the bar's job, a coverage gap or the model,
    proposing each fix without applying it. /jud:tune decides gate by gate
    whether to take what jud tune proposes (never a bar of 0 on a handful of
    cases, never a bar that absorbs a wrong label), and with apply writes it
    into the rubric in place with its comments kept, then shows each gate
    before and after; with holdout it tunes on three quarters of the cases and
    reports the rest. The commands were battle-tested headless (claude -p --plugin-dir) against a mock System One server that knows the labels
    (plugins/jud/skills/jud-tune/evals/); no test calls a real API.

judgment 0.11.1

Choose a tag to compare

@github-actions github-actions released this 08 Oct 12:03

Fixed

  • jud completion zsh completes a subcommand's own arguments. The script
    clap generates declared the optional RUBRIC before the subcommand, so in
    jud eval <TAB> zsh read eval as the rubric and offered the subcommand
    names again; check, lower, record, eval and tune completed
    neither their files nor their flags. The first word now offers a
    subcommand or a file, and each subcommand completes its own arguments.
    Bash, fish, elvish and PowerShell were not affected. Regenerate the
    installed script (jud completion zsh > ..., or mise run install in a
    checkout) to pick it up.

judgment 0.11.0

Choose a tag to compare

@github-actions github-actions released this 08 Oct 11:46

Added

  • jud record, jud eval and jud tune run a rubric over its labelled
    cases from the shell (decision 0021; docs/reference/cli.md). jud record RUBRIC CASES --out DIR asks the configured backend once per case, or once
    per turn for a conversation labelled with from_turn, and writes each
    answer as a .jud recording. It keeps what DIR already answers, so an
    interrupted run resumes, and --refresh asks again. The server a
    recording names is the base URL (TYPESAFE_BASE_URL, or base_url in the
    configuration file) without its userinfo, query and fragment, so a
    credential kept in the URL is never written to a recording, and jud tune
    strips a recording's server the same way for its tuning block. jud eval RUBRIC CASES [--replay DIR] grades the answers against the labels and
    reports, per question, the model's accuracy with its 95 % interval, its
    Brier score and calibration error, how often the policy's gate acts and how
    often its verdict is right, and every miss, as text or as one JSON object
    (--json). --min-accuracy [QUESTION=]ACCURACY holds the model's
    accuracy per question and makes jud eval exit with the new status 3 when
    a bar is not met. jud tune RUBRIC CASES --replay DIR reads recordings
    only, prints each gate's sweep on stderr and proposes the bars as the
    policy and tuning blocks on stdout; --out PATH writes the whole
    rubric instead.

    Contract: exit status 3 (jud eval alone), the keys of jud eval --json
    (rubric, cases, requests, models, questions, min_accuracy) and
    the two places that write files, jud record --out and jud tune --out,
    join the command's contract (docs/reference/stability.md). Neither
    command writes over a rubric or a cases document it was given, and jud tune --out never writes among the recordings. Every other command stays
    read-only. stdout is the result and nothing else; progress, tables and
    failures go to stderr. Statuses 0, 1 and 2 keep their meaning.

Changed

  • The documentation is rebuilt in Diátaxis form under docs/: tutorials
    (start/), guides (guides/), reference (reference/), concepts
    (concepts/) and the project's own pages (project/, where the
    decision, verification and research records moved unchanged). The .jud
    specification is docs/reference/jud-format.md, in BCP 14 wording, and
    the plugin's references/format.md is generated from it; the command
    line's reference is generated from the binary's help; the README is a
    front door. Every Rust block, whole .jud document and marked transcript
    on a page is held to the code by a test, and every internal link is checked
    (mise run docs:links). The rebuild itself changed no behaviour, API or
    format rule.
  • Replay::open reads a directory in name order, so that when two files
    record one request the same one answers on every file system, and a
    .json recording that does not parse is Error::InvalidRecording, which
    names the file, instead of Error::Decode. Breaking for a caller that
    matched Error::Decode there.
  • jud RUBRIC, jud check, jud lower and jud config no longer panic
    (status 101) when stdout is closed (jud check FILE | head -0): a reader
    that has gone is not an error, and the status is the command's own, as it
    already was for jud completion and is for jud record, jud eval and
    jud tune.
  • Messages of the existing paths, each with its status unchanged:
    • A failure of jud RUBRIC names the backend as scheme://host/path,
      without the userinfo, query or fragment of its base URL, so a credential
      kept in the URL is not printed.
    • A misplaced --replay gets a hint. jud --replay DIR eval ... says the
      flag belongs after the subcommand, and jud --replay DIR alone says a
      rubric is required; both are status 2 as before.
    • A mistyped bare subcommand (jud evaluate) reads as a rubric path that is
      not there, and the message now adds (not a subcommand either: ...) with
      the subcommands' names.
    • Under jud RUBRIC --replay DIR, a recording that matches the state and
      the rubric but no longer fits the questions is reported as a recording under DIR matches this state and rubric but cannot answer it, where the
      message said that no recording answers; status 1 as before.
    • jud check points a document that is not jud/v1.3 at
      docs/reference/jud-format.md, where it named the page's old path,
      docs/jud.md.

judgment 0.10.4

Choose a tag to compare

@github-actions github-actions released this 07 Oct 15:39

Added

  • A container image, ghcr.io/chussenot/jud, for linux/amd64 and
    linux/arm64: cat event.json | docker run -i --rm -v "$PWD:/work" ghcr.io/chussenot/jud triage.jud. FROM scratch with the release
    tarball's binary, a CA bundle for the client's TLS and a non-root user,
    about 10 MB; tagged X.Y.Z, X.Y and latest, with a build-provenance
    attestation. The release workflow's new image job fills the build
    context from the tarballs it just built (scripts/image-context.sh),
    runs the image on the runner and pushes it after the publish
    (The jud command line, Releasing).

judgment 0.10.3

Choose a tag to compare

@github-actions github-actions released this 07 Oct 08:28

Added

  • cargo binstall judgment installs the release's jud tarball instead of
    compiling: [package.metadata.binstall] in Cargo.toml names the asset
    and the binary's path inside it, and the release workflow checks, on every
    platform it packages, that the templates name the tarball it just built
    (The jud command line).
  • A Homebrew formula for jud: brew install chussenot/tap/jud on Apple
    silicon and Linux, from chussenot/homebrew-tap.
    The formula installs the release tarballs by their checksums and generates
    the shell completions from the binary. It is rendered from each release's
    SHA256SUMS by scripts/homebrew-formula.sh and committed to the tap by
    the release workflow's new homebrew job, so the tap's version is the
    release's (The jud command line, Releasing).

judgment 0.10.2

Choose a tag to compare

@github-actions github-actions released this 07 Oct 06:55

Changed

  • A kind's reader (Rubric::parse, Cases::parse, jud::parse_recording)
    handed a document of another known kind refuses it with
    jud::Error::OtherKind { found, expected }, "a Cases document, not a
    Rubric; this reads kind: Rubric", instead of Error::Kind, which said
    the kind was not a document kind at all. Error::Kind still names a kind
    the crate does not know.

Fixed

  • jud lower and jud check name the file in every refusal and say what
    was expected of it: cannot read rubric PATH, PATH is not a valid Rubric: ..., --state is not JSON, and, for a file that is not a .jud
    document at all, the pointer to the envelope that jud RUBRIC already
    gave. jud lower examples/jud/triage-cases.jud used to print "kind: Cases is not a document kind" with no path.

judgment 0.10.1

Choose a tag to compare

@github-actions github-actions released this 07 Oct 06:41

Added

  • jud --replay DIR RUBRIC, or JUD_REPLAY=DIR, answers from the recordings
    under a directory through the crate's Replay backend instead of a server:
    no key, no network, a state nobody recorded is an error. The README's
    command-line transcript runs this way over examples/recordings/ and
    tests/jud_cli.rs holds it to what the binary prints.
  • docs/stability.md: what is promised across versions. jud/v1 is stable, a
    minor version only adds, readers accept every v1 document for at least
    twelve months after a later minor is published, fingerprints exclude the
    envelope and never change for a document's spec; the crate's 0.x rule and
    the command's contract.
  • Decision 0020, proposed and not applied: whether a v1 minor stays in the
    apiVersion string or moves to a minor field under apiVersion: jud/v1,
    each option priced.
  • scripts/record_demo.sh (mise run demo) records the command-line demo as
    an asciinema cast, docs/demo.cast, from the recordings, with no network;
    regenerated by the release bump so the version it shows is the release's.
  • mise run ci is an alias of mise run check, the gates in CI order.

Changed

  • The README opens with the command line for 0.10: a one-line pitch, the mise
    install, the cat event.json | jud triage.jud transcript with the verdicts
    the binary prints for examples/jud/triage.jud, then the Rust API; one
    comparison table of the four properties where the clients differ, the full
    grids linked; the live example's capture trimmed to the command and its
    output.

judgment 0.10.0

Choose a tag to compare

@github-actions github-actions released this 07 Oct 05:42

Added

  • jud completion <shell> prints a completion script for bash, zsh, fish,
    elvish or PowerShell, generated from the command tree the binary parses
    with, so it cannot drift from the binary; docs/cli.md says where each
    shell wants it, and mise run install refreshes the scripts a shell
    already has. The binary's arguments are now parsed by clap: jud --help
    and every subcommand's --help are derived from the same tree, a usage
    error names the argument and exits 2 as before, and jud lower refuses
    --state, --state-file and --cases together instead of taking the
    last.

Changed

  • The jud binary builds behind its own cli feature (jud, http,
    clap, clap_complete): cargo install judgment --features cli. The
    jud feature is the format alone again, so a library build with it
    compiles no command-line parser.