Make starter arithmetic verifiable by default - #3161
Conversation
The starter's natural calculation suggestion allowed the model to answer without its calculator, while the bundled eval only tested an explicit tool instruction. Require calculator use for arithmetic, evaluate the real suggestion, and provide a reusable LLM rubric judge for semantic quality. Constraint: Keep deterministic tool and numeric gates alongside LLM judging Rejected: Rewrite the suggestion to explicitly demand the tool | hides routing reliability instead of testing it Confidence: high Scope-risk: moderate Directive: Keep starter eval inputs aligned with the prompts users actually see Tested: full unit suite (2716 tests/22087 steps), fmt, lint, typecheck, guide validation, repeated live tool-routing eval (5/5), live rubric judge pass/fail Not-tested: consumer typecheck (storybook toolchain missing); full docs validation blocked by pre-existing release-assets docs gap
There was a problem hiding this comment.
Pull request overview
This PR strengthens Veryfront’s eval tooling and starter template by adding a reusable built-in LLM rubric judge, then using it to make the AI Agent starter’s arithmetic behavior verifiable by default (calculator tool use, deterministic answer checks, and judge-based quality gating). It also updates public docs and bumps the release version.
Changes:
- Added
judges.llm.rubric()as a built-in general-purpose semantic grader formetrics.judge.rubric. - Updated the AI Agent CLI template to instruct calculator usage for arithmetic and to ship a stricter smoke eval (tool-use, tool-failure, numeric contains, and rubric judge gates).
- Updated eval documentation/API reference exports and bumped version to
0.1.1173.
Verification noted in PR description:
deno task fmt:check,deno task lint,deno task typecheckdeno task test:unit(2716 tests, 0 failures)- Guide/public-doc validation passing;
typecheck:consumerand fulldocs:validatehave known external blockers (as described)
Reviewed changes
Copilot reviewed 11 out of 11 changed files in this pull request and generated no comments.
Show a summary per file
| File | Description |
|---|---|
| src/utils/version-constant.ts | Bumps shared VERSION constant to 0.1.1173. |
| deno.json | Bumps package version to 0.1.1173. |
| src/eval/judges.ts | Adds EvalLlmRubricJudgeOptions, rubric prompt builder, and judges.llm.rubric() factory. |
| src/eval/judges.test.ts | Adds unit coverage ensuring rubric judge prompt construction and JSON parsing behavior. |
| src/eval/index.ts | Exports EvalLlmRubricJudgeOptions from the public eval entrypoint. |
| docs/guides/evals.md | Documents rubric judges using the new built-in judges.llm.rubric() helper. |
| docs/api-reference/veryfront/eval.md | Adds API reference entries/links for EvalLlmRubricJudgeOptions and updates source anchors. |
| cli/templates/manifest.json | Updates AI Agent template strings: system prompt requires calculator for arithmetic; eval uses rubric judge + stricter gates. |
| cli/templates/index.test.ts | Updates template tests to assert new system prompt text and rubric-judge eval wiring. |
| cli/templates/files/ai-agent/evals/assistant.eval.ts | Updates shipped template eval to use the tip/split prompt and judges.llm.rubric() gate. |
| cli/templates/files/ai-agent/agents/assistant.ts | Updates shipped template agent system prompt to require calculator tool for arithmetic. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
The semantic judge is useful for answer quality, but provider failures must not abort the eval and arithmetic correctness must not depend on a probabilistic grader. Fail the judge metric cleanly, isolate evaluator instructions from untrusted data, and gate every expected monetary result. Constraint: Valid calculator behavior may require multiple binary tool calls, so call count is not fixed Rejected: Require an exact calculator call count | couples the eval to one valid reasoning path Confidence: high Scope-risk: narrow Directive: Keep deterministic correctness gates alongside semantic judges Tested: focused judge/template tests (24 steps), fmt, lint, typecheck, manifest check
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 11 out of 11 changed files in this pull request and generated no new comments.
Comments suppressed due to low confidence (2)
docs/api-reference/veryfront/eval.md:188
- The API reference "Source" link for
judgespoints at the wrong line insrc/eval/judges.ts(currently the export starts at line 358). This makes the generated documentation link land in the middle ofcreateLlmGroundednessJudgeinstead of the constant definition.
| `judges` | Built-in judge factories for semantic eval metrics. | [source](https://github.com/veryfront/veryfront-code/blob/main/src/eval/judges.ts#L345) |
src/eval/judges.ts:336
createLlmRubricJudgefails closed on provider/runtime errors, butcreateLlmGroundednessJudgestill allowsgenerateText()errors to throw. BecauserunRecord()does not catch metric evaluation errors, a judge outage can abort the entire eval run instead of producing a failed metric result. Consider adding the same try/catch fail-closed behavior to the groundedness judge.
function createLlmGroundednessJudge(
options: EvalLlmGroundednessJudgeOptions = {},
): GroundednessJudge {
Rubric judging already converted provider failures into failed metrics. Apply the same contract to groundedness and correct the API reference anchor after the shared judge changes shifted its export. Constraint: Judge-provider availability must not abort an eval run Rejected: Leave groundedness behavior unchanged | creates surprising outage semantics between sibling built-in judges Confidence: high Scope-risk: narrow Tested: focused judge/template tests (25 steps), fmt, lint, typecheck, public docs validation Not-tested: full API-doc validation remains blocked by the pre-existing release-assets JSDoc/reference gap
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 11 out of 11 changed files in this pull request and generated no new comments.
Comments suppressed due to low confidence (1)
src/eval/judges.ts:276
parseJudgeResponse()currently makes the finalpassdepend on the model-providedpassboolean (modelPass && score >= threshold). Because metric gating already applies score thresholds, a judge response with a high score butpass: falsewill be forced to fail (false negative) even though it meets the threshold. Consider treating the numeric score as authoritative and derivingpassfromscore >= thresholdso eval outcomes are stable even if the judge model returns an inconsistentpassfield.
const details = [
typeof parsed.explanation === "string" && parsed.explanation.trim()
? parsed.explanation.trim()
: "LLM judge returned a structured score.",
...(unsupportedClaims.length > 0
Summary
judges.llm.rubric()as a reusable built-in semantic grader0.1.1173Evidence
deno task fmt:checkdeno task lintdeno task typecheckdeno task test:unit(2716 tests, 22089 steps, 0 failures)Known validation gaps
typecheck:consumerrequires the Storybook-local TypeScript toolchain, which is not installed in this worktreedocs:validateis blocked on currentmainby the unrelated missingrelease-assetsAPI reference/JSDoc entry; guide and public-doc validation pass