@@ -10,6 +10,32 @@ GitHub Releases.
1010
1111Use this section for changes that are merged but not released yet.
1212
13+ ### Added
14+ - Continuous integration. Quoto was the only bot in the family with no
15+ ` .github/ ` at all: the suite in ` tests/ ` ran only when somebody remembered,
16+ and nothing checked that a migration could be applied or undone before it
17+ reached the host. ` ci.yml ` runs the tests, compiles every source file, checks
18+ that each package in ` requirements.in ` is pinned in ` requirements.txt ` ,
19+ applies the migrations against a real PostgreSQL 17 and steps one back down
20+ again, refuses a branched alembic history, and builds the image.
21+ - ` release.yml ` publishes the image to GHCR and creates the GitHub Release from
22+ the matching ` CHANGELOG.md ` section on a ` v* ` tag, refusing a tag that is not
23+ an ancestor of ` main ` or that has no changelog section. That is steps 6-8 of
24+ ` docs/releases.md ` , which were done by hand.
25+ - ` deploy/ws04/compose.yaml ` , the production stack, pulling the released image
26+ from GHCR. The stack on the host built its own image from a working copy, so
27+ what served users was not a published artifact and nothing on the host could
28+ say which commit it came from. ` QUOTO_IMAGE ` has no default: an unset one
29+ stops the stack rather than quietly starting something else.
30+
31+ ### Fixed
32+ - The Dockerfile no longer defaults ` QUOTO_VERSION ` to ` 0.10.2 ` . It stayed at
33+ that value through the whole of v0.10.3, so an image built without the
34+ argument labelled itself as a release it was not.
35+ - A second ` ## Unreleased ` section, left behind by the v0.10.2 release, sat
36+ between v0.10.2 and v0.10.1. Release preparation renames ` ## Unreleased ` to
37+ the new version, and with two of them the wrong one could be renamed.
38+
1339### Changed
1440- Media description prompts now cast the model as the eyes and ears of someone
1541 who can't see or hear the file: on-screen text and speech must be quoted
@@ -96,55 +122,6 @@ Use this section for changes that are merged but not released yet.
96122- AI audit retention is intentionally unchanged and remains available for debug
97123 and quality verification.
98124
99- ## Unreleased
100-
101- Use this section for changes that are merged but not released yet.
102-
103- ### Removed
104- - Legacy ` OPENROUTER_MODEL ` setting. The quote evaluation model is now read only
105- from ` OPENROUTER_EVAL_MODEL ` , whose default is ` poolside/laguna-s-2.1:free ` ;
106- a blank value falls back to that default. Previously the two settings aliased
107- each other at startup and whatever was written into ` OPENROUTER_MODEL ` was
108- silently overwritten.
109-
110- ### Added
111- - ` scripts/bench_web.py ` + ` scripts/bench_web_ui.html ` : a local web hub for
112- picking an eval model. Lists the days recorded in ` logs/ai_audit.jsonl ` , shows
113- the day's messages and what production picked, runs any set of models against
114- that day with a chosen reasoning effort, streams each model's reasoning and
115- answer live, then compares the picked quotes with tokens, cost and timing.
116- Runs are archived under ` logs/bench_runs/ ` . Read-only, and it sends nothing
117- until Run is pressed. Sampling temperature is never set, matching production.
118- Each selected model can carry its own reasoning effort (or follow the global
119- one), and the catalog sorts by release date, alphabetically or by price, with
120- filters for structured-output support and free models.
121- A second, fully separate tab benchmarks media description: upload an image,
122- video or audio file, watch it go through the bot's own normalization pipeline
123- (resize, re-encode), and compare how each model describes it and at what cost.
124- Each tab keeps its own model selection, efforts, settings and results, since
125- the two jobs need different models. The media tab narrows the catalog to the
126- input modality the uploaded file needs; image-generating models (anything
127- that answers with pictures) and ` :batch ` tier ids (refused by
128- ` /chat/completions ` ) are dropped from the catalog entirely. The effort picker
129- offers only the efforts a model actually accepts, read from the catalog's
130- ` reasoning ` block, and flags models where reasoning is mandatory or where the
131- effort is ignored. When a model asks for context, the card shows the whole
132- context block in the exact order production would publish it, reusing
133- ` scoring._valid_context_messages ` so the two can't drift apart. The summary
134- table sorts by price ascending out of the box, and every column header is a
135- sort toggle; rows without a value (failures) always sink to the bottom.
136- - ` scripts/compare_eval_models.py ` : replays days saved in ` logs/ai_audit.jsonl `
137- against several eval models in parallel and prints, per model, the quote it
138- picked, the day verdict, token usage and the dollar cost. Read-only — nothing
139- is written to the database.
140- - Token usage and cost of the winning eval call are now requested from
141- OpenRouter (` usage.include ` ) and stored on ` ai_evaluation_runs `
142- (` prompt_tokens ` , ` completion_tokens ` , ` reasoning_tokens ` , ` total_tokens ` ,
143- ` cost_usd ` ); migration ` 20260907_01 ` .
144- - Startup warning for renamed env keys (` OPENROUTER_MODEL ` ,
145- ` OPENROUTER_REASONING_EFFORT ` ). ` extra="ignore" ` used to swallow them, so a
146- stale ` .env ` kept settings that had stopped applying.
147-
148125## v0.10.1 - 2026-07-21
149126
150127### Changed
0 commit comments