Releases: homemade-software-inc/completion-kit
Release list
v0.28.42
Changed
- The four dashboard stat cards now line their numbers up with each other. Each card pushed its value into the middle of whatever space was left over, so the value landed at a different height in every card depending on how much content sat below it. The Checks percentage came out 63 pixels above the Activity count in the card beside it. The value now sits directly under the kicker in all four, which puts the kickers on one line, the values on a second, and the footnotes on a third along the bottom, so the row reads across instead of bobbing.
v0.28.41
Changed
- A dashboard card with nothing to plot no longer draws an empty chart. The Checks card and the Activity card both rendered all fourteen bars whatever the data, and a bar for a day with no data is held at a two-pixel minimum height, so a window with nothing in it came out as a row of dead dashes that reads as a broken chart rather than an absent one. Both cards now drop the sparkline entirely when the window is empty, leaving the headline and the footnote that says what to do about it. Days with no data inside a window that does have some are unaffected, because there the gap is real information.
v0.28.40
Changed
- The retry button on a run now says what it will actually retry, and it is no longer red. It read "Retry N failed cases" whatever had gone wrong, which implied regeneration even when the response was fine and only its judge had timed out. The label is now chosen from the failure state: "Retry scoring on 1 response" when only reviews failed, "Retry 1 failed response" when only generation failed, and the combined count when both did. The button also drops its bespoke red styling for the same secondary outline used by Edit and Compare in the page header. Red now belongs to the parts of the panel that report state, the failed count in the summary line and the row chips, rather than to the action that clears them.
v0.28.39
Fixed
-
"Retry failed cases" did nothing when the failure was a judge, and left the run stuck running. A response can generate perfectly well and still have its review blow up, which the run header counts as a failed case. The retry only ever looked at responses whose own status was
failed, so for a failed review it matched nothing, enqueued nothing, and still flipped the run torunning. Since the completion check is only ever enqueued by a finishing job, that run then had no way back tocompletedand sat running forever. Retry now collects failed reviews on succeeded responses too and re-queues each against its own metric, judge or check, followed by a completion check. When there is genuinely nothing to retry it returns without touching the run's status. -
A response whose judge failed claimed it was Done. The row chip treated any review in a terminal state as reviewed, and a failed review is terminal, so the row read Done while the header counted the same response among the failed. The two now agree: a response with a failed review shows a Failed chip once the run has finished. The gap it leaves in the metric bar is expected, because a review that never produced a score has no score to draw.
v0.28.38
Fixed
- The two buttons on the stale-metrics banner were touching. Each action column was capped at a fixed width chosen for its explanatory note, but a button never shrinks below its own text, so the wider "Re-grade with current metrics" overflowed its column by 26 pixels and closed the gap to the button beside it. Measured, the two buttons sat 3 pixels into each other. The column is now sized by the button rather than by the note, so the gap is the 1.25rem it was always meant to be and the note wraps underneath its own button. Checked at five widths from 1440 down to 520 pixels, where the pair wraps to a stack with the same spacing.
v0.28.37
Changed
-
Temperature is no longer something you configure. Runs send none by default. The parameter has aged out. Most current frontier models refuse it outright, several accept it and silently discard it, and the ones that still honour it are the previous generation and anything served locally, where sampling happens in your own process and no vendor API can say no. A knob that most models ignore is worse than no knob, because it invites you to believe you set something you did not.
The generation temperature slider and the judge temperature field are both gone from the run form, and the run's
temperaturecolumn now defaults to unset, so a new run sends no temperature at all and the model applies its own. This also settles a default that had drifted: the engine migration said 1.0 while installed copies said 0.7, and now both say nothing.Nothing is removed from the API.
temperatureandjudge_temperatureremain on the REST endpoints, the MCP tools and the run payload, so anything scripted against them keeps working, and anyone deliberately targeting a model that honours temperature can still set one. The drop-and-retry, the two ignored flags and the refusal warnings all remain, and they now do their real job: telling you a value you deliberately chose was refused.The run page mentions either temperature only when there is something to say. A run carrying a temperature still shows it, which keeps historical runs honest about what they sent, and the judge temperature row appears only when the scores are not reproducible.
Existing runs are untouched. A column default change does not rewrite rows, so a run that sent 0.7 still records 0.7. Host apps need
bin/rails completion_kit:install:migrations && bin/rails db:migrateto pick up the new default.
v0.28.36
Follow-ups to 0.28.35, all found by adversarially reviewing it after it shipped.
Fixed
-
A list of the parameters a model does support is no longer read as a refusal. OpenAI-compatible local servers answer with shapes like
unsupported parameter: logprobs. Supported: model, prompt, temperature, top_p, where the word temperature appears because it is allowed, not because it was refused. The 0.28.35 predicate matched that, so the client burned a second call re-sending the same rejected request and could flag a run as having had its temperature ignored when the model had been perfectly happy with it. The phrase-first branch now stops at a comma, which is what separates a list from a sentence. The temperature-first branch still allows commas, becausetemperature, top_p and top_k are not supportedis a real refusal. -
A provider that names the offending field in
paramrather than in the message is now recognised. A body reading{"message":"This parameter is not supported with this model.","param":"temperature"}matched nothing, so the row failed instead of retrying. -
The run page no longer renders an empty temperature for a run that deliberately sends none. It now reads "Not sent, provider default", matching how the Max tokens row two lines below already handles the same situation.
-
The judge-refusal chip appears without a reload. The run config block was not among the poll's targets, so a run could finish judging and never tell the watching user that its temperature had been refused, which is the one thing the new flag exists to say. The block is now a partial the status poll refreshes alongside the header and the panel.
Changed
- The MCP
temperaturedescription documents what null now means. An agent passing null to mean "use the default" would instead get no temperature sent at all, and nothing said so.
v0.28.35
Fixed
-
A run whose judge silently lost its temperature no longer claims the scores are reproducible.
JudgeServicesends the judge temperature and then nobody read whether the provider accepted it, so when a reasoning judge refused the parameter the request was quietly re-sent without one, the provider applied its own default of roughly 1.0, and the run went on reportingjudge_temperature: 0withnondeterministic_judge?returning false. The page was at its most confident exactly when the scores were least reproducible. Runs gain ajudge_temperature_ignoredcolumn,JudgeReviewJobrecords it, andnondeterministic_judge?folds it in. The run page and the MCP payload now distinguish a temperature you set high from one the model refused, because the fix for each is different.Host apps need
bin/rails completion_kit:install:migrations && bin/rails db:migrateto pick up the new column. -
Every provider client now recognises a temperature refusal it previously failed on. All five tested the error body for
"not supported","deprecated"or"Unsupported parameter", but OpenAI's current reasoning models answer withUnsupported value: 'temperature' does not support 0.7 with this model. Only the default (1) value is supported., which contains none of those three. The drop-and-retry never fired and the row failed outright. The predicate now covers the phrasings in use, in either word order, and it lives onLlmClientinstead of being copy-pasted into five subclasses, which is howAnthropicClientcame to be missing a clause the other four had.The match is deliberately bounded so it cannot cross a brace in the error body. A refusal aimed at some other parameter, in a response that echoes the request back, would otherwise have stripped a temperature the model was perfectly happy with and flagged the run as having had it ignored.
-
Both ignored flags now clear when the work they describe is redone. Neither was ever reset, so a run kept asserting that its temperature had been refused after a re-grade against a judge that accepts it.
regrade!clears the judge flag and starting a run clears both.
Added
- A run can now send no temperature at all, which is the only request many current models accept. Every client turned a nil into 0.7, so there was no way to express "leave it to the model" and a nil column silently became a value CompletionKit invented. Passing an explicit nil now omits the parameter from the request body, and the run form gains a "Send no temperature" option beside the slider. An absent key still gets the historical default, so no existing caller changes.
Changed
temperature_ignoredis now in the run payload. The MCP tool description told agents that "the run is flagged temperature_ignored" whileRun#as_jsonnever carried the field, so both REST and MCP pointed at something that did not exist. It andjudge_temperature_ignoredare now returned.
v0.28.34
This release also carries 0.28.33, which was versioned but never published. Its section is below in full; in short, a response scored only by deterministic checks no longer claims a judge reviewed it, a check that failed before its version was recorded is no longer blamed on the judge, and the gemspec's MCP tool count is corrected from 34 to the real 53. No migrations are needed for either version.
Changed
- The dashboard's Checks card no longer shows the same metric twice. It listed the two most recent failing checks, and because failures cluster by metric, both rows routinely named the same one, so two lines carried a single fact and could only be told apart by hovering. The rows now group by metric and carry a count, so two lines say two things: which checks are failing and how badly. The total moved to the footer, which reports it once instead of as a remainder.
Added
-
The seed demonstrates the deterministic check metric type, which it never did before. A workspace seeded from scratch had no check metric at all, so the Checks card had nothing to show and the check type was invisible to anyone evaluating CompletionKit. Two checks now run alongside the existing LLM judge on the triage runs:
Rationale Length, alength_boundscheck readingrationaleout of the JSON output, andTriage Schema, anot_containscheck for a key the prompt never asked for. Both are evaluated through the realChecks::RegistryandTargetResolverat seed time rather than hand-authored, so a seeded review is what the job would have written and a re-grade reproduces it.The result is the case the product exists for. On the triage rows the judge awards five stars and explicitly praises the extra
secondarykey, while the schema check fails the same response for emitting it, and on the bulk rows the judge scores a 2340-character "one-sentence rationale" at five stars while the length check fails it. The seeded data spreads across four days so the card's trend has shape, and the failures span two metrics and four runs so the card's two rows differ.
v0.28.32
This is the first release since 0.28.24, so it also carries everything in 0.28.25 through 0.28.31, which were versioned but never published. Those sections are below in full; in short:
- 0.28.31 Prompt serving is counted and surfaced, so you can tell which prompts are live in production. (#158)
- 0.28.30 Starting a run returns as soon as the run is claimed, ending false
runs_generatetimeouts over MCP. (#150) - 0.28.29 A run shows how often a human agreed with its judge, and says "Unverified" when nobody has checked. (#154)
- 0.28.28 A completed run whose scores cluster at the top now warns instead of presenting it as success. (#153)
- 0.28.27 The judge scores at temperature 0 by default, separately from the generation temperature. (#155)
- 0.28.26 Runs take a generation
max_tokens, andtemperatureis settable over MCP. (#159) - 0.28.25 Per-metric averages on
runs_get, plus field selection, score filters and paging onresponses_list. (#160)
Upgrading from 0.28.24 requires bin/rails completion_kit:install:migrations && bin/rails db:migrate. Three of the releases above add columns or tables: completion_kit_prompt_serves (0.28.31), judge_temperature (0.28.27) and max_tokens (0.28.26).
Changed
-
The dashboard's pulse cards say something on every workspace, or they don't show up at all. (#166) The failing-checks card sat at a permanent
0 / No failing checks this weekin any workspace with no check metrics, which is filler dressed as a signal, so it is now hidden entirely and the card row narrows to three. Where checks do exist it reads as an instrument instead of a lone weekly count: the headline is the pass rate across the trailing fortnight, a daily sparkline underneath shows the shape of it, and each bar takes the same three-tier colour as the headline so a 90% day is not painted the same red as a 25% day. A newDashboardStats.check_activitysupplies the series.The failures card named the error class on every row, which truncated to an identical
CompletionKi…and answered a question nobody was asking. Each row now names the run that failed, with the cause on hover, and thegenerationchip shortens togenso the name gets the width. The trend-card headers dropped· LAST 7 DAYS, which repeated on three of four cards and wrapped onto a second line on each; they now read· 7Dand· 14Dand fit on one line. The activity card leads with the run count and demotes its sparkline to supporting texture, so a fortnight where everything landed on one day no longer reads as a broken chart. -
The stale-metrics banner on a run now names the action it is actually recommending. (#166) Its closing line read "Re-run to refresh the scores with the current metrics", but re-scoring the existing responses against the current metrics is precisely what Re-grade does, at no generation cost, so the copy was steering people toward the expensive button. It now says Re-grade, and Re-grade leads. The difference between the two actions, and the cost gap, previously appeared only in
titletooltips and so were invisible at a glance; each button now carries its consequence on a line underneath it.