Repository navigation
Conversation
Why: every JevProvider call failed with HTTP 400. It sent operation, prompt, options and scale, while POST /v1/systemone requires model, state and questions, and it read answers from the wrong place in the response. The pinned systemone-2026-06-01 is also not a documented model. Mocks in the same invented shape kept the tests green, and the fail-open contract would have left the pr-triage pre-filter logging fell_through. Send one typed question per call with the prompt as state, read the typed answer under answers, and pin jev-1.14.0. score sends at most 10 numeric levels, the API's cap, and maps the returned position back onto the requested scale. The public contract does not change. Generated-by: Claude Code (Opus 5.5)
onlyarnav
left a comment
There was a problem hiding this comment.
LGTM! thanks for catching and fixing the mismatch with the live Typespace System One API.
I didnt cross-check the system against an actual JEV API, while finalizing, which is where I missed it. Really appreciate your help!
| { | ||
| "type": "choice", | ||
| "instructions": "Select the option that best fits the state.", | ||
| "criteria": {option: option for option in options}, |
There was a problem hiding this comment.
the docs example shows criteria for choice as a list of labels, but this sends a dict {option: option}. can you confirm the dict form is documented?
| - **Endpoint:** `https://api.typesafe.ai/v1/systemone` | ||
| - **Pinned Model:** The model version is pinned to an explicit constant (`systemone-2026-06-01`), **never "latest"**, ensuring behavioral stability and reproducible benchmark evaluations (RFC-AI-0004 § Principle 3). | ||
| - **Pinned Model:** The model version is pinned to an explicit constant (`jev-1.14.0`), **never "latest"**, ensuring behavioral stability and reproducible benchmark evaluations (RFC-AI-0004 § Principle 3). | ||
| - **Wire Format:** Each operation sends one question to the System One API, with the prompt as `state`. `score` sends numeric levels, at most 10 because the API caps them, and maps the returned level position back onto the requested scale. |
There was a problem hiding this comment.
i suggest adding one sentence here: score criteria are bare numbers, so callers must define what high and low mean in the prompt.
| @@ -652,17 +639,17 @@ def test_choice_empty_options_raises() -> None: | |||
| def test_choice_missing_label_in_response(approved_privacy_config: pathlib.Path) -> None: | |||
There was a problem hiding this comment.
minor suggestion: rename to test_choice_missing_choice_in_response(...) since the field is now choice
Summary
JevProvidercould never get an answer from the Jev API. Everychoice,scoreandnoulcall returned HTTP 400, because it sentoperation,prompt,optionsandscaletoPOST /v1/systemone, which requiresmodel,stateandquestions. It also readlabel,valueandprobabilityfrom the top level of the response, while the API returns them underanswers.systemone-2026-06-01is not a model the API documents. It is nowjev-1.14.0.pr-triageshadow pre-filter would only have loggedfell_through.The public
choice,scoreandnoulcontract does not change.Type of change
.claude/skills/<name>/) — eval fixtures updated belowtools/<system>/*.md)tools/*/withpyproject.toml)docs/,README.md,CONTRIBUTING.md)projects/_template/)prek, workflows, validators)Test plan
prek run --all-filespasses, through the pre-commit hook on this commituv run pytest/ruff check/mypypasses fortools/typed-decision, andtest_typed_decision_prefilter.pypassesapi.typesafe.ai, using made-up text onlyThe mocks now follow the published OpenAPI schema, so I also ran the provider against the real API.
enforce_privacy_gatewas patched out in a throwaway script for these calls, because I have no approvedprivacy-llm.mdentry. With the real gate left in place, the same call was still denied with no request sent.mainchoiceon a crash report, options bug/feature/questionbug, confidence 1.0noul"Is the sky usually blue on a clear day?"noul"Is the sun made of cheese?"scorefull production outage, scale (1, 5)scoretypo in a comment, scale 10typed_decision_prefilter.pyalso ran end to end on a synthetic PR, enabled throughMAGPIE_ENABLE_TYPED_DECISION_PREFILTER, with the gate patched the same way. It loggedoutcome: high_confidence,predicted_label: passing,confidence: 0.98.The updated tests fail against the old provider.
RFC-AI-0004 compliance
<PROJECT>,<tracker>,<upstream>,<security-list>) used in all skill / tool prose (thecheck-placeholdersprek hook is the mechanical gate)Linked issues
Follows #1402 and #1403.
Notes for reviewers (optional)
scoremapping: the API rates against ordered level descriptions, at most 10, and returns a position starting at zero. The contract takes a numeric scale, so the provider sends numeric levels and maps the position back. Scales wider than 9 steps, such as(0, 10), or with fractional bounds use 10 evenly spaced levels, so the labels are not all whole numbers.state, with short genericinstructions, so fenced contributor text stays data.resultanddecisionenvelope handling is gone, because the API does not return those envelopes.Not in this PR:
typed-decision-prefilter.mdcalls the script at<framework>/skills/pr-management-triage/scripts/. Theskills/symlink exists in a framework checkout, but the one marketplace<framework>copy I checked held onlytools/, and it predates fix(marketplace): ship every family's framework tools, not just security's #1937. Other skills use the same<framework>/skills/...form, so this looks like a separate fix.typed_decision_confidence_thresholddefaults to 0.85, which was never measured against real Jev answers. This fix makes that measurement possible.Generated-by: Claude Code (Opus 5.5), reviewed by
shahar1before submission