Repository navigation
Added
-
Images in a request, as Jev 1.13 and later take them
(https://docs.typesafe.ai/images):Imageholds 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 newError::InvalidImage;Assetsis the wire's
assetsmap, 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, andSystemOne::answer_with_assetstakes them through
every backend. The client sendsTypeSafe-Danger-Zone-Images: trueon
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.evaluatespan asimages.Error::is_request_too_largeis
also true ofRequestTooLarge. 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_withandeval::request_hash_with: the
request fingerprint and hash with the images, each named by the SHA-256
of its bytes under anassetskey that is left out without any, so a
request without images fingerprints as it always has and every committed
recording still replays;RecorderandReplaykey by them, so two
requests that differ only by an image are two recordings. -
Faketakes 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 isAnswer::Box { edges, confidence }, the wire'sboxasBoxEdges(top, bottom, left, right
as fractions of the image) and a confidence the document lets be null;
Response::verifyrefuses 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 asBoundingBox, withwidth,
height,center,to_pixels,confidence_at_leastand the geometry
onBoxEdges(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#boxscripts one.Judgment::locatedgrades a Box against a
labelled box by intersection over union ateval::DEFAULT_IOU_AT_LEAST
(0.5) or the label's own bar, with the number onJudgment::iouand
QuestionMetrics::mean_iou; a Box has no Brier score. In a rubric a Box
is gated byconfidenceorbands(neverthreshold,fallbackor
level_at_least) intoVerdict::Locatedor a deferral, and a case labels
it{box: {top, bottom, left, right}, iou_at_least}. -
The
.judformat at minor 4 (jud::MINOR): aboxquestion, the images
a document names underspec.assetson a Rubric andassetson a case
(jud::AssetSource: apathrelative to the document, orformatand
data_base64inline; decision 0025), loaded into a request'sAssetsby
Rubric::load_assetsandCase::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'sconfidenceorbands;Verdict::in_pixels,
which adds the located box in an image's pixels beside the edges. The
schemas, the format page andexamples/jud/shapes.judwith 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 WxHnames 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 aslocatedwithbox, the
confidence, the band andpixels;jud evalreports a Box question's
mean_ioubeside its accuracy, no Brier score, and a miss'siou;jud checkcounts a document's images. -
jud:long_context: truein its configuration file, or--long-context
onjud RUBRIC,jud recordandjud 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 configreportslong_context
andlong_context_from,jud record --dry-runprints along context:
line, and the line before a run's first call names it when it is on. -
The
multipartfeature:CallOptions::multipartfor one call and
ClientBuilder::multipartfor every call of a client send a request's
images as themultipart/form-databody TypeSafe recommends, a JSON
requestpart in which each asset is{type: image, part}and one part
per image (part-0,part-1, … in reference order, underimage/pngor
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.evaluatespan recordsmultipart.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.judand
images/page-*.png, drawn byscripts/gen-document-pages.pyfrom one
seed), recorded onjev-1.14.0underexamples/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.rsreplays 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 withjudalone:--assetand--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 bytests/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 theTypeSafe-Danger-Zone-Long-Context: trueheader,
on Jev 1.13 and 1.14.CallOptions::long_context(true)asks for it on
one call andClientBuilder::long_context(true)on every call of a
client (a call'sfalseturns it off again); the header is reserved
(client::DANGER_ZONE_LONG_CONTEXT_HEADER) and recorded on the
typesafe.evaluatespan aslong_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 asmax_tokens_exceededwas answered under the
header byjev-1.13.0in 1.4 s. -
The Claude Code plugin (now 0.4.0) knows Jev 1.14: the
judskill'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), thejud-tuneskill's reading of a
Box'sjud evalandjud tunenumbers (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 thejud-rustskill's third template,
examples/jud/shapes.rs, a module whosedecidetakes the request's
Assetsand whoseLocatedverdict carries a Box, exercised from the
shapes recordings byexamples/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 ninthjud-rustscenario 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 plugin from the checkout, with TypeSafe's
typesafeplugin, throughscripts/claude-plugins.sh(mise run plugins:install,mise run plugins:update).
Changed
-
Breaking: the
.judformat spells its minor asmetadata.minor
underapiVersion: jud/v1(decision 0020, accepted):jud::API_VERSION
isjud/v1,jud::MINORthe minor the crate reads up to and writes (4,
with this release's additions below), andjud::EARLIER_SPELLINGSnames
jud/v1.3, the spelling minor 3 was published under, which the reader
keeps reading as minor 3, without ametadata.minor, for at least twelve
months from this release. Ametadata.minorabove the crate's is
jud::Error::Minor, refused by number before anything else is read.
Every document the crate writes now carriesapiVersion: jud/v1and
metadata.minor; every committed example and recording was rewritten to
minor: 3, the lowest that reads it, and the documents that use minor 4
carryminor: 4;jud checkprintsjud/v1 minor N. No fingerprint
moves: the envelope is outside every one. -
Breaking:
client::Requesthas a fourth field,assets: &Assets;
a struct literal names it (&Assets::new()for none) or becomes
Request::new(state, model, questions).backend::Callhas an
assetsfield.assetsis a reserved extra field and
typesafe-danger-zone-imagesa reserved header: a caller that sent
either throughCallOptionspasses the images throughRequestinstead. -
Breaking:
Question,Answer,jud::Verdictandjud::Expecthave
a Box variant, so amatchoutside the crate that named every variant
adds an arm; an answer of kindboxno longer decodes as
Answer::Unknown.eval::Judgmenthas anioufield and
eval::QuestionMetricsamean_ioufield.Question::instructionsand
instructions_mutread the instructions of any primitive.jud::Rubric
andjud::Casehave anassetsfield,jud::Verdict::Locateda
pixelsfield, andjud eval --jsonamean_ioukey on every question. -
examples/jud/agent-mail.jud, a rubric asked about one message between
coding agents sharing a repository (needs an action, warns that something
broke, reports status only), with 33 labelled cases taken verbatim from
one repository's coordination store andjev-1.13.0's live answers under
examples/recordings/agent_mail/. Three Nouls rather than one Choice,
because the messages are multi-label. The recordings rank well (area under
the ROC curve 0.90, 0.89, 0.97) and threshold badly at 0.5, so the gates
are the onesjud tuneread off the 33 cases, marked as a starting point;
tests/jud.rsreplays every case under them.
Fixed
jud RUBRIC --asset REF=PATHwith a reference the state does not carry is
refused before any backend is opened, with status 2 and a message naming
the flag, under--replayas against a server; it was the client's
refusal reported as a backend failure (status 1) against a server, and a
request nobody recorded under a replay.