Repository navigation
Conversation
…tep 2) The answerer stored top_k and never sent it, so retrieval asked the doc source for its default max_results. It now sends max_results=top_k, the same request DocTreatment makes on Stack A. With the default top_k of 3 the reranker sees 3 raw docs, not 5, so with-docs answers and their judge scores move. Flips the PINNED rows D1 retrieval.passed and D1 retrieval.max_results. Test fakes that take the doc-source call now accept max_results. Signed-off-by: Nikolay Petrov <nikolay.a.petrov@intel.com>
…ntel#228 step 2) benchmark run had no judge temperature flag, so its judge always ran at the provider default while evaluate and arms run took one. The flag is added (default unset, so runs without it are unchanged) and reaches the EvaluationPipeline judge. Flips the PINNED row D6 cli.judge_temperature_flag. benchmark batch does not get the flag yet. Signed-off-by: Nikolay Petrov <nikolay.a.petrov@intel.com>
…#228) EvaluationPipeline took the library id from --context7-id or the client's own resolver, so a product whose products.yaml declares context7_id was still looked up by its registry key. Resolve it with the shared resolve_library_id_for_product helper, the same order the arms stack uses: explicit id, then the registry's context7_id, then the client. Question generation and answer generation both go through the helper. The registry is injectable (registry=) and defaults to the bundled products.yaml. Parity row D8 flips from client/resolved to registry/lib. Signed-off-by: Nikolay Petrov <nikolay.a.petrov@intel.com>
…el#228) When no document reached the prompt (no hit, or the reranker raised), the answerer records "[FALLBACK: No relevant documentation found]" as the with-docs answer, and the judge scored that text like a model answer. It inflated the with-docs side of the paired delta on questions the docs did not answer. The judge now leaves a context answer whose doc_source is a no-retrieval source (NO_RETRIEVAL_SOURCES) unjudged, so its with-docs score and delta are None and the question drops out of the paired statistics. The record and its retrieval_hit stay. Opt back in with judge_placeholder=True, or --judge-placeholder on benchmark run, orchestrate evaluate and eval score. The trust gate's retrieval_hit_rate read only the both-arms-scored evaluations. Unjudged misses would then vanish from it and an all-miss run would read as "not measured". It now counts every evaluation's retrieval_hit. The thresholds are unchanged. Signed-off-by: Nikolay Petrov <nikolay.a.petrov@intel.com>
Answerer built a self.llm client in __init__ that nothing read: the answer call goes through llm_call_with_usage, which picks the provider's client itself. Only the unsupported-provider ValueError is kept; the client construction and its imports are gone. _generate_with_docs had an "if not docs" branch that could not run, because _generate_answer_pair calls it only when retrieval returned documents. The branch is deleted with its unreachable "[No documentation retrieved]" record. No parity row changes: nothing observable on either stack moved. Signed-off-by: Nikolay Petrov <nikolay.a.petrov@intel.com>
…intel#228) The Stack P answers artifact and the judge's evaluation output now carry method_version, from defaults.ANSWERING_METHOD_VERSION (2). The steps before this one are version 1 and have no stamp, so a later compare can refuse to put runs of different versions side by side. compare does not read the stamp yet. answers.v1 and eval.v1 document the field. The arms artifact is not stamped in this change; the new parity row records that. Signed-off-by: Nikolay Petrov <nikolay.a.petrov@intel.com>
ruff F821 flagged the annotation on _paired_deltas. The module uses `from __future__ import annotations`, so the missing name did not fail at import time and the parity tests passed without it. Signed-off-by: Nikolay Petrov <nikolay.a.petrov@intel.com>
…set-then-read tests (intel#228) With the llm construction removed from Answerer.__init__, test_init_openai and test_init_anthropic only set attributes and read them back, which the test quality audit flags (set_then_read). The new parametrized test checks what init does now: each supported provider is accepted. It is marked as a must-not-raise smoke test. Signed-off-by: Nikolay Petrov <nikolay.a.petrov@intel.com>
) test_calls_mcp_client builds the Answerer with the default top_k, so a literal max_results=5 would pass it. The new test builds it with top_k=3 and asserts the doc source is asked for 3. On intel/main the same probe sends no max_results at all, so the test fails there. Signed-off-by: Nikolay Petrov <nikolay.a.petrov@intel.com>
…ons (intel#228) The methodology list and the method_version comment described the trust gate and the stamp more broadly than the code does. The score checks run over the both-arm-scored questions, so a question with no document leaves them. Nothing reads method_version yet; the comment now says so. Signed-off-by: Nikolay Petrov <nikolay.a.petrov@intel.com>
…fraction (intel#228) A question whose retrieval missed is no longer judged with docs, so it has no context score. The zero-score check counted only scored questions, so a run where most questions miss passed it: 4 misses of 14 gave 0.0 PASS, where intel/main gave 0.286 FAIL (the misses were judged at zero there). The check now counts a miss (no context score, a baseline score, and retrieval_hit False) as unusable, in the numerator and the denominator. The message says such rows had no document. Thresholds, min_questions and the early return are unchanged. The new fail-severity retrieval check is not added here. Regression test: tests/test_trust_gate_unjudged_misses.py. It fails on the parent commit (4 of 14 passes at 0.0) and passes with this change. Signed-off-by: Nikolay Petrov <nikolay.a.petrov@intel.com>
…ons once (intel#228) The methodology bullet still said the zero-score fraction leaves out questions with no document. It counts them now (c517c72). Update it. Also parse the evaluations once in evaluate_trust. The input may be a one-shot iterable, and the old code parsed it again for the retrieval check. Signed-off-by: Nikolay Petrov <nikolay.a.petrov@intel.com>
|
Codecov Report✅ All modified and coverable lines are covered by tests. Additional details and impacted files@@ Coverage Diff @@
## main #274 +/- ##
==========================================
+ Coverage 93.48% 93.52% +0.03%
==========================================
Files 272 272
Lines 35363 35376 +13
Branches 6001 6000 -1
==========================================
+ Hits 33060 33085 +25
+ Misses 1489 1479 -10
+ Partials 814 812 -2
🚀 New features to boost your workflow:
|
CLI interface change detectedThis PR changes dokimi's user-facing CLI surface (commands and/or options): ~ `dokimi benchmark run` parameters changed:
+ added option `--judge-placeholder`
+ added option `--judge-temperature`
~ `dokimi eval score` parameters changed:
+ added option `--judge-placeholder`
~ `dokimi evaluate` parameters changed:
+ added option `--judge-placeholder`Updated on every push; the |
vlad-perevezentsev
left a comment
There was a problem hiding this comment.
Review at 6bec891. The five Stack P fixes do what step 2 of #228 asks, and the zero-score check keeps failing the same runs as main. Not judging the placeholder has side effects outside the gate's score checks (the retrieval coverage, the diagnosis and the pipeline summary), and the registry lookup misses a custom --registry. These are in the line comments.
What I ran, at 6bec891:
make ci-local --offline: 0 failed, 17 passed, 13 skipped (network and Docker jobs).- Trust gate with 15 judged rows and 5 judge-error rows, on the base and on the head: the retrieval check goes from 100% (15/15) to "not measured".
summarise_diagnoseson 10 hits and 4 misses judged through_evaluate_answer_pair, on the base and on the head:empty_retrieval4 becomes 0 andinsufficient_data0 becomes 4.resolve_library_id_for_product("my_lib", <Context7 client>)returnsmy_libunchanged.
Checked, no issues
top_k:Answerersendsmax_results=top_k, asDocTreatmentdoes.evaluateandanswers generatepass their--top-k, and the new test pins the value at the call site.- Zero-score check: unjudged misses count in both the numerator and the denominator, so 4 of 14 misses still fail at 0.286, as on main. The new test fails on the parent commit.
- Judge temperature:
benchmark run --judge-temperaturereaches theJudgein single and multi-run mode. - Dead code:
Answerer.llmwas never read, and_generate_with_docsis only called with docs. The provider allow-list keeps the same set. - Schemas:
method_versionis an optional new property inanswers.v1andeval.v1. That widens the schemas, and old files still validate.
antonwolfy
left a comment
There was a problem hiding this comment.
Review at 6bec891. The five Stack P fixes do what step 2 of #228 asks, and the zero-score check keeps failing the same runs as the base. Three things are worth fixing before merge, all test gaps on the new code (inline). The open problems from @vlad-perevezentsev's review still hold at this head and block the merge.
I agree with @vlad-perevezentsev on the judge-error rows losing the retrieval rate, the insufficient_data diagnosis of misses, the registry lookup in benchmark run --registry, the summary averages over different questions, the unstamped --judge-placeholder runs, the 0-hit gate test and the changelog flag names. New evidence: 10 hits and 4 misses move min_delta from -17.1 (fail) to +0.0 (pass).
What I ran, on a Linux review host at 6bec891:
make ci-local: 27 passed, 1 failed, 7 skipped. The failure ispip-audit, which lists advisories onfilelockin the lock files. This PR does not touch them.- 9,705 tests passed, 4 skipped; the changed-line coverage step passes.
- Reproductions for the code findings, with the LLM transport mocked.
- A mutation run on the new code (33 mutants, 13 of which pass the related tests):
_library_id, theunjudged_missesfilter and the flag wiring inbenchmark run,evaluateandeval scoreeach have mutants that pass every test.
Checked, no issues
- Schemas:
method_versionis an optional property on an open object inanswers.v1.jsonandeval.v1.json.schema_compatagainst the base passes, and no version bump is needed. top_k: every doc-source client'sget_library_docsacceptsmax_results, so the new argument raises nowhere.- Dead code: no caller of
Answerer.llmor of_generate_with_docswith empty docs remains. - Zero-score check: 10 hits and 4 misses give 4/14 = 0.286 and fail, as on the base. Judge-error rows are excluded from the new term.
- Commits: all 12 carry
Signed-off-by; the changelog fragment is present.
|
🔍 OpenCodeReview found 4 issue(s) in this PR. By severity: 4 low
Review details
|
…rs-stack-p-step2 Signed-off-by: Nikolay Petrov <nikolay.a.petrov@intel.com> # Conflicts: # dokimi/dokimi/orchestrator/pipeline.py
The retrieval coverage floor counted every judge-error row as an unrecorded outcome, so a run with more than 20% judge errors lost the retrieval check. Thread: PRRT_kwDOVBg7g86xgwoY Signed-off-by: Nikolay Petrov <nikolay.a.petrov@intel.com>
With the no-retrieval placeholder left unjudged its delta is None, and diagnose() returned insufficient_data before it looked at the doc source. Thread: PRRT_kwDOVBg7g86xgwog Signed-off-by: Nikolay Petrov <nikolay.a.petrov@intel.com>
The summary averages the questions scored in both arms (paired_summary, intel#250), so an unjudged retrieval miss is in none of the three numbers. The run result now carries paired and unpaired, and the printed line names them. Thread: PRRT_kwDOVBg7g86xgwon Signed-off-by: Nikolay Petrov <nikolay.a.petrov@intel.com>
…s loaded benchmark run and batch loaded the registry for the entry, but the pipeline looked the key up in the bundled products.yaml. A custom entry without a context7_id then reached Context7 as a bare key and retrieved nothing, and a custom key that the bundled registry also has took the bundled id. Thread: PRRT_kwDOVBg7g86xgwou Signed-off-by: Nikolay Petrov <nikolay.a.petrov@intel.com>
…ibrary_id Both mutants named in the review (explicit_id=None, product instead of product_key) now fail a test. Thread: PRRT_kwDOVBg7g86xiJYO Signed-off-by: Nikolay Petrov <nikolay.a.petrov@intel.com>
--judge-placeholder gives different numbers on the same answers under the same method_version. The eval output now carries judge_placeholder (declared in eval.v1), so two files of one version that are not comparable can be told apart. Thread: PRRT_kwDOVBg7g86xgwoz Signed-off-by: Nikolay Petrov <nikolay.a.petrov@intel.com>
… arms With every question an unjudged miss the gate returned after min_questions with "0 questions evaluated", pointing away from the cause. The retrieval check is now a helper and also runs on that path. The 0-hit case has its test again, and the 2-hit test is named for what it checks. Thread: PRRT_kwDOVBg7g86xgwo7 Signed-off-by: Nikolay Petrov <nikolay.a.petrov@intel.com>
A legacy row, a hit that was not scored and a miss without a baseline must leave zero_score_fraction unchanged; each mutant of the filter named in the reviews now fails. The judge stub branch that only a judged miss reached is gone: the default leaves misses unjudged. Thread: PRRT_kwDOVBg7g86xiJYM Thread: PRRT_kwDOVBg7g86xlsnp Signed-off-by: Nikolay Petrov <nikolay.a.petrov@intel.com>
…e-placeholder benchmark run (single and multi-run) is driven through cmd_benchmark_run with a faked pipeline; evaluate and eval score run end to end against a mocked judge transport. Each removed call-site kwarg named in the reviews now fails a test. The old test named for the handler called _run_single_library directly. Thread: PRRT_kwDOVBg7g86xiJYT Thread: PRRT_kwDOVBg7g86xlsUD Thread: PRRT_kwDOVBg7g86xlsb0 Signed-off-by: Nikolay Petrov <nikolay.a.petrov@intel.com>
…es differ benchmark run has no --top-k and there is no orchestrate evaluate: the command is dokimi evaluate. The fragment now says what each command asks for, that answers generate changes too, that old scores are not comparable, and covers the fixes of this round. Thread: PRRT_kwDOVBg7g86xgwo3 Thread: PRRT_kwDOVBg7g86xlsKV Thread: PRR_kwDOVBg7g88AAAABU4c24A Thread: PRR_kwDOVBg7g88AAAABU5LNng Signed-off-by: Nikolay Petrov <nikolay.a.petrov@intel.com>
dokimi.eval.answerer neither imports nor uses ChatOpenAI; the patch with create=True and its mock did nothing and suggested the init builds a client. Thread: IC_kwDOVBg7g88AAAABg14M_w Signed-off-by: Nikolay Petrov <nikolay.a.petrov@intel.com>
…ft unused main's paired_summary (intel#250) replaced the BASELINE/CONTEXT/records reads in run(); the merge kept this branch's import line, which ruff F401 rejects. Signed-off-by: Nikolay Petrov <nikolay.a.petrov@intel.com>
…extractor Codecov flagged the one patch line in _generate_questions that no test reached. The test asserts the extractor gets the registry's declared id; reverting the line to the client's name lookup fails it. Thread: IC_kwDOVBg7g88AAAABgqSv4w Signed-off-by: Nikolay Petrov <nikolay.a.petrov@intel.com>
|
Its findings are the threads above (judge-error row, diagnoser, summary count, registry, |
|
The three test gaps are the threads on the unjudged-miss term, |
|
Fixed in 284b240: the one patch line codecov flagged is the library id in |
|
This is the CLI-surface notice listing the added options ( |
|
Fixed in 87a1a0a: the patch of |
| `top_k` docs the command was given: `benchmark run` asks for 3 (`DEFAULT_RETRIEVAL_TOP_K`; it | ||
| has no `--top-k`), `dokimi evaluate` and `answers generate` for their `--top-k` (default 3). | ||
| Before, they left `max_results` at the client default of 5. `benchmark run --judge-temperature` | ||
| now reaches the judge (it used to be dropped), and the doc library id resolves through the |
There was a problem hiding this comment.
| assert result["label"] == EMPTY_RETRIEVAL | ||
|
|
||
|
|
||
| def test_unjudged_retrieval_miss_is_an_empty_retrieval_not_insufficient_data(): |
There was a problem hiding this comment.
Nit: this covers only the fallback_none happy path. Deleting not context_answer.error from the new diagnoser branch would still pass. An errored placeholder answer must stay insufficient_data, and the docstring says so. The second NO_RETRIEVAL_SOURCES member ("none") and context_answer=None are not exercised on the delta is None path either. Add a case with error set and one with doc_source="none".
| assert client.asked == [] | ||
|
|
||
|
|
||
| def test_the_registry_key_not_the_display_name_finds_the_declared_id(tmp_path, registry): |
There was a problem hiding this comment.
Nit: _RecordingClient.asked exists to record the fallback, but no test reaches it. A product that is not in the registry should resolve through client.resolve_library_id(product_key). A mutation that skips the fallback, or passes self.product instead of self.product_key, would pass these tests. Add a test with an unregistered product that asserts client.asked == [<key>].
| assert (step["paired"], step["unpaired"]) == (7, 3) | ||
| printed = capsys.readouterr().out | ||
| assert "Evaluated 10 answers: context=80.0, baseline=60.0, delta=+20.0" in printed | ||
| assert "over the 7 scored in both arms; 3 left out" in printed |
There was a problem hiding this comment.
Summary
Step 2 of #228, "Fix Stack P in place". Stack P (
EvaluationPipeline+Answerer) gets five fixes and one stamp, one commit each. Each fix flips the rows it owns in the step-1 characterization table (tests/test_answering_stack_parity.py, PINNED), so the diff of this PR shows the change in numbers. No step 3 work is in this PR.eval/arms_run.py,commands/arms.pyandcommands/subjects.pyare not touched (PR #270 owns them).Which scores move, and why
These are the parity-table values, measured on the six-question fixture. No live benchmark was run for this PR; the size and direction of the live shift are not measured here.
top_kdocs (was the default 5). Retrieved context is smaller, so with-docs answers and their judge inputs change.retrieval.max_results5 to 3;retrieval.passed("max_tokens",)to("max_results", "max_tokens")"[FALLBACK: No relevant documentation found]". It is recorded, not scored.judge.calls12 to 10;judge.contexts.q-emptyandq-reranklose the placeholder with-docs context;delta.per_questionq-empty and q-rerank 0.0 to NoneMIN_PAIRS_FOR_TEST(6). P gets no significance test.stats.delta_mean13.33 to 20.0 (4 pairs, was 6);significance.n6 to None;significance.significantFalse to Nonecontext7_id, the pipeline resolves the id through the registry before the client.library_idclient/resolvedtoregistry/libbenchmark rungains--judge-temperature. The default is still the provider default, so no default score moves.cli.judge_temperature_flagFalse to Truemethod_version: 2in the answers artifact and in the eval artifact of the singleJudge. No score moves.artifact.method_version2 (P), None (A)Direction of the live shift, from the D2/D3 change: the placeholder answer is scored near zero by a judge, so dropping those rows raises the with-docs average and the delta on any live run with retrieval misses. Old and new runs of the same product are therefore not comparable on those numbers.
comparedoes not readmethod_versionyet, so it will not refuse the mix (out of scope, below).Default behaviour that changes live runs:
benchmark run,orchestrate evaluateandeval scoreno longer judge a placeholder with-docs answer. Pass--judge-placeholderto restore the old judging.An eval artifact made by
eval scoreon answers from before this PR is stampedmethod_version: 2. The stamp records the judging method; the answers artifact keeps its own stamp (absent, so version 1). Read the two together; a single eval stamp does not say which answers it judged.Trust gate: numbers, thresholds not changed
Thresholds are unchanged:
min_retrieval_hit_rate0.60,min_retrieval_coverage0.80,min_questions10,max_zero_fraction0.20, and the rest ofDEFAULTS.What changes is the input of the checks:
min_questionscounts the both-arm-scored questions. Placeholder questions (no document, not judged by default) drop out of that count. Fewer counted questions makes the minimum harder to reach, so this is a stricter number change, not a weakening. On the 4-of-14 fixture the count goes from 14 to 10, which still passes at min 10.zero_score_fraction(fail) counts a question whose retrieval missed as unusable, in the numerator and the denominator. On main a miss was judged at 0 and counted as a zero, so this keeps the fail-severity check failing on the same run. The message says "scored 0 or had no document". Commitc517c727. Regression test:tests/test_trust_gate_unjudged_misses.pyfails on the parent commit (4 of 14 passes at 0.0) and passes here.min_with_docs_avg,min_deltaandscore_cv(warn) run over the both-arm-scored subset only. The placeholder zeros that main counted are gone from that subset, so these three checks are more lenient than on main. Not changed here; see the decision below.Thresholds are not changed, and no retrieval check was added with fail severity.
Probe (
probes/gate_probe.pyin the review scratch; 14 both-arm questions, mock judge scores aFALLBACKanswer 0, otherwise 60; re-run on the head after the fix):min_questions(fail, min 10)zero_score_fraction(fail, max 0.20)retrieval_hit_rate(warn, min 0.60)min_questions(fail, min 10)Net effect: the fail-severity zero-score check gives the same answer on the same run as main (FAIL at 0.286). A run where 29% of questions get no document still fails the gate. The retrieval miss shows as a warn-severity rate that passes at 71%, as before. A run where every question misses still fails, through
min_questions, and has no retrieval line.Adding a fail-severity retrieval check, or changing its threshold, is a separate design decision. It is not in this PR.
Changes
fix(answers): the doc source is asked fortop_kdocs (was the default). Dead code deleted in the context arm.fix(benchmark):benchmark run --judge-temperatureis parsed and passed to the judge. Batch is not changed.fix(pipeline): the library id goes throughresolve_library_id_for_product(explicit id, then registrycontext7_id, then client).fix(judge): the no-retrieval placeholder is not judged by default;--judge-placeholderonbenchmark run,orchestrate evaluateandeval scorerestores it. Trust gate counts all records for retrieval (see above).fix(gate):zero_score_fractioncounts retrieval misses as unusable, so the fail-severity check matches main on the 4-of-14 fixture (commitc517c727, regression testtests/test_trust_gate_unjudged_misses.py). Commit6bec8910updates the methodology bullet and parses the evaluations once.refactor(answerer): removed the unusedself.llmclient, the unreachableif not docs:branch, and their imports.feat(artifacts):method_version(defaults.ANSWERING_METHOD_VERSION = 2) on the answers artifact and the eval artifact of the singleJudge; documented inanswers.v1.jsonandeval.v1.json. Artifacts without it read as version 1. Nothing reads it yet.test(parity),test(answerer),test(answerer): lint fix (missingListimport); the init tests that only read back attributes replaced by a provider allow-list smoke test (flagged by the test-quality audit); a direct test thattop_kreaches the doc source.docs: methodology trust-gate list says which checks run on both-arm-scored questions; themethod_versioncomment says nothing reads it yet.changelog.d/20261028_120000_napetrov_stack-p-step2.md.The flag registry (
dokimi/cli_flags.py) does not exist on main, so the new flags were added to the parsers directly.Evidence
top_ktest: fails on intel/main (the probe sends nomax_results), passes on the head.6bec8910; the full run was on3685c29f, and the last commit only changes one comment line, with the targeted gate and docs tests re-run):9703 passed, 6 skipped.tests/test_trust_gate_unjudged_misses.py: fails on the parent commit0fe7452d(value 0.0, expected0.286), passes on the head.ruff check .: clean.ruff format --checkreports 482 files that would be reformatted; the project does not gate onruff format, so this is pre-existing and not changed here.review.mdof the review scratch.Merge Danger
Checked by trial merge against
intel/main(no rebase needed for this branch: it containsintel/main).fix/report-eval-generate-agree, OPEN, BLOCKED): textual conflict indokimi/dokimi/orchestrator/pipeline.py, the import block at intel/main lines 12 to 14. fix(report): report eval, generate and pipeline use one paired arm summary (#229 P1-3) #250 removes thecreate_doc_source_clientimport line; this PR addsresolve_library_id_for_productto it. Resolve by keeping both names. fix(report): report eval, generate and pipeline use one paired arm summary (#229 P1-3) #250 also editspipeline.pyat intel/main lines 383 to 391, near the_generate_*call sites this PR changes; no conflict there, but re-run the parity test after the merge.feat/claude-cli-backend, OPEN, DIRTY): textual conflicts indokimi/dokimi/eval/answerer.py(theChatModelimport at lines 18 to 19, and theAnswerer.__init__llm block at lines 98 to 110, which this PR removes). Resolve by taking this PR's removal and feat(llm): claude-cli provider: run the Q&A track on a logged-in Claude Code CLI #255's provider change.commands/benchmark.py,commands/evaluate.py,commands/orchestrate.py,defaults.py,eval/judge.py. Those are semantic overlaps, not textual ones: the--judge-placeholderand--judge-temperaturewiring, andANSWERING_METHOD_VERSION, sit next to feat(llm): claude-cli provider: run the Q&A track on a logged-in Claude Code CLI #255's backend changes. Re-run the suite after either merge.scripts/growth_baseline.jsonandtests/test_import_architecture.pyagainst this branch. Those are not this PR's lines: feat(llm): claude-cli provider: run the Q&A track on a logged-in Claude Code CLI #255's base predates50250218on main (the import contract test). Rebasing feat(llm): claude-cli provider: run the Q&A track on a logged-in Claude Code CLI #255 ontointel/mainclears them.Both #250 and #255 are ours and the coordinator owns those conflicts; this PR does not resolve them.
Out of scope (listed, not changed here)
benchmark batchhas no--judge-temperature.comparedoes not readmethod_versionyet, so it does not refuse mixed versions.eval panel-score(JudgePanel) still judges the placeholder answer and writes its artifact withoutmethod_version. The panel's trust numbers therefore differ from the single judge's on the same answers.context7_idnow raisesValueErrorfor clients that require a declared id, in question generation and answer generation (the registry-first lookup). Intended, but a hard stop where the client used to be asked.min_with_docs_avg,min_delta,score_cv) run over the both-arm subset, so they are more lenient than on main; (b) a fail-severity retrieval check is not added (retrieval_hit_ratestays warn). Neither is changed here.Refs #228
🤖 Generated with Claude Code