Repository navigation
Conversation
A criteria case kept its criteria in referenceAnswer, so a reference answer and the criteria a judge checks were the same field. The nynorsk test set, for example, held "Svaret er skrive på nynorsk ..." there. ADR 0003 as amended by ADR 0040 moves them to expected.criteria, named fields such as criteria or supporting_quotes (part of #94). - A case reads its criteria from expected.criteria, and referenceAnswer holds only a reference answer. A new criteria case from the portal, an import or an accepted candidate writes expected.criteria. - Test sets are upgraded on read: a type: criteria case with its criteria in referenceAnswer is read with them in expected.criteria. Both test set stores parse what they read, so stored versions keep their numbers. The nynorsk test set is rewritten in the new shape. - The criteria judge reads expected.criteria.criteria, and the reference answer when a case has none, so the golden sets are judged as before. - An evaluator plug-in receives the case's criteria beside its reference answer. - The portal's test set list, import and case editor show and keep the criteria.
This was referenced Oct 29, 2026
There was a problem hiding this comment.
🟡 Changes recommended
Saving or importing cases can silently discard reference answers and supporting quotes, while imports with only supporting quotes are incorrectly rejected.
2 open issues
What changed in this PR
This PR separates evaluation criteria from reference answers by introducing expected.criteria, advancing the test-case migration in #94 on top of #191.
Changes:
- Adds named criteria fields and upgrades legacy criteria cases when test sets are read.
- Updates case creation, judging, and HTTP evaluator payloads to use the separate criteria.
- Updates portal handling, the Nynorsk test set, tests, and documentation.
| File | Description |
|---|---|
packages/providers-postgres/src/eval.ts |
Parses stored test sets to migrate legacy criteria on read. |
packages/eval/testsets/nynorsk-sporsmal.yaml |
Moves Nynorsk criteria into the new structure. |
packages/eval/src/testsets.test.ts |
Checks the migrated Nynorsk expectations. |
packages/eval/src/store.ts |
Applies read-time migration in the memory store. |
packages/eval/src/schema.ts |
Defines named criteria, legacy migration, and expectation creation. |
packages/eval/src/feedback.ts |
Writes accepted candidates’ criteria separately. |
packages/eval/src/cases.ts |
Updates case creation, display, and grading. |
packages/eval/src/cases.test.ts |
Tests criteria storage, migration, validation, and judging. |
docs/bring-your-own-logic.md |
Documents criteria in evaluator requests. |
docs/architecture/system-atlas.html |
Updates the generated expectation schema. |
apps/portal/src/types.ts |
Adds criteria to portal test-case types. |
apps/portal/src/screens/quality/TestSetsTab.tsx |
Displays criteria from the new field. |
apps/portal/src/screens/quality/import-cases.ts |
Reads criteria text during imports. |
apps/portal/src/screens/config/TestSetEditor.tsx |
Adds criteria handling to editor drafts and saves. |
apps/api/src/stores.contract.test.ts |
Tests legacy migration across both stores. |
apps/api/src/plugin-contracts.ts |
Sends named criteria to HTTP evaluators. |
Review effort: Balanced
- The case editor sends back the stored case with only the fields it
edits changed, since a save replaces the whole case: a reference
answer beside the criteria, other criteria fields, the type, tags and
sources stay.
- POST .../test-sets/{setId}/cases takes expected as a text, as before,
or as a reference answer and named criteria, kept as they are. An
import keeps every named criterion and the reference answer beside
them, and a case whose criteria have no criteria field is no longer
refused.
- Given as fields, a criteria case needs criteria and an exact case a reference answer, and an expected that names neither is refused, so no case is stored that its type cannot be judged on. - The case editor picks its field by the case's type, labels it Kriterier for a criteria case, asks for criteria rather than saving a criteria case without them, and saves an unchanged case as stored. - An import refuses a row whose criteria name judges do not read, instead of importing half the file. - The mock lists a new case as the API's caseView does, and OpenAPI states the criteria name pattern. - Tests now state the rules that had none: criteria sent to an HTTP judge, the Test sets tab, the editor's first value, caseFrom's own output and the refused shapes.
Contributor
Author
|
Ready for review. Copilot and a claim-checking review are done (no blind review) and CI passes. Open: test sets are upgraded on read rather than migrated, so stored versions keep their numbers; the mock's flattening of a structured |
This branch has not been deployed
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.

Stacked on #191.
What and why
A criteria case kept its criteria in
referenceAnswer, so a reference answer and the criteria a judge checks were the same field. The nynorsk test set, for example, held "Svaret er skrive på nynorsk ..." there. ADR 0003 as amended by ADR 0040 moves them toexpected.criteria, named fields such ascriteriaorsupporting_quotes. Part of #94.expected.criteria, andreferenceAnswerholds only a reference answer. A new criteria case from the quality page, an import or an accepted candidate writesexpected.criteria.type: criteriacase with its criteria inreferenceAnsweris read with them inexpected.criteria. Both test set stores parse what they read, so stored versions keep their numbers.packages/eval/testsets/nynorsk-sporsmal.yamlis rewritten in the new shape.POST /tenants/{tenant}/test-sets/{setId}/casestakesexpectedas a text, as before, or as{ referenceAnswer, criteria }, kept as they are. Given as fields, a criteria case needscriteriaand an exact casereferenceAnswer, and anexpectedthat names neither is refused.expected.criteria.criteria, and the reference answer when a case has none, so the golden sets are judged as before.docs/bring-your-own-logic.md).docs/api/work.md, OpenAPI. i18n:apps/api/src/i18n/{en,nb}/errors.ts, portaldata-configandoperate-quality.How it was tested
CI on this head:
checkand the three test shards pass. The top of the stack (Delete what genki sent to an agency's Langfuse when it purges the case #197) with main merged passesnpm run check: 470 files, 5092 tests.New tests: "keeps the criteria of a new criteria case in expected.criteria, and an exact text as the reference", "keeps a reference answer and named criteria given together, as an import brings them", "reads a criteria case written before expected.criteria with its criteria moved there", "judges a criteria case on its criteria, and on its reference answer when it has none", "names criteria fields as judges read them", for both stores "reads a test set stored before expected.criteria with its criteria moved there", "adds a case with a reference answer and named criteria as they are, and refuses a shape its type cannot be judged on", "keeps every named criterion and a reference answer beside them, so none is dropped on import", "refuses a row whose criteria name is not one judges read, rather than importing half the file", "keeps what the form does not edit when it saves a case: the reference answer beside the criteria, its type and tags", "saves an unchanged case as it is stored, and asks for criteria rather than saving a criteria case without them", "shows a criteria case by its criteria, and by its reference answer when it has none", "sends a case's reference answer and named criteria to the judge, and leaves out what the case lacks".
Rules broken on purpose: the review broke 21; the five that no test stated now have the tests above. Two are equivalent mutants, since every parse upgrades a case.
npm run checkpassesChecklist
packages/providers-*docs/architecture/modulesare updated if a contract, boundary or module changed