with one click
deterministic-llm-panel
Stable id-based voting for multi-model review panels
Install with Codex or Claude Copy this prompt, paste it into Codex, Claude, or another assistant, and let it review the skill page and install it for you.
Menu
Stable id-based voting for multi-model review panels
Install with Codex or Claude Copy this prompt, paste it into Codex, Claude, or another assistant, and let it review the skill page and install it for you.
Based on SOC occupation classification
How to write comprehensive architectural proposals that drive alignment before code is written
How the eval engine works: generate → grade → review → report
Record final outcomes to history.md, not intermediate requests or reversed decisions
Tone enforcement patterns for external-facing community responses
Team initialization flow (Phase 1 proposal + Phase 2 creation)
Core conventions and patterns for this codebase
| name | Deterministic LLM Panel |
| description | Stable id-based voting for multi-model review panels |
| created | "2026-04-27T00:00:00.000Z" |
| updated | "2026-05-01T00:00:00.000Z" |
| status | shipped |
| confidence | high |
Multi-model review panels produce non-deterministic results when each reviewer LLM paraphrases the same check text differently. Vote aggregation keyed by exact string match on c.Name causes paraphrases to split into separate criteria → inconsistent point counts across runs.
Stable check IDs assigned once at criteria-bundling time flow through the entire pipeline:
check_1: File hello.md exists...{"id": "check_1", "passed": true, "reasoning": "..."}bucket::check_1 (not by paraphrased name)hyoka/internal/criteria/buckets.go:326 (FormatUnifiedPromptEntries emits ReviewCheck with check_<n> IDs)hyoka/internal/review/prompt.go:87 (BuildReviewPrompt renders check_1: text format)hyoka/internal/review/reviewer.go:278 (parseReviewResponseV2 validates id-set match)hyoka/internal/review/reviewer.go:694 (averageReview keys by bucket::id, not Name)check_<n> where n is 1-based index within the rendered bucket. Deterministic, short, easy for LLMs to echo back.
{
"criteria": [
{"id": "check_1", "passed": true, "reasoning": "..."}
],
"summary": "...",
"issues": ["..."],
"strengths": ["..."]
}
Dropped from contract: criterion text field (LLM no longer trusted to echo label).
On validation error, re-prompt with precise feedback:
Your response is missing ids: [check_2]. Extra ids: [check_99].
Please return exactly: [check_1, check_2, check_3].
After 3 retries, synthesize a failing CriterionResult for each missing ID:
for _, check := range checks {
if !returnedIDs[check.ID] {
result.Scores.Criteria = append(result.Scores.Criteria, CriterionResult{
ID: check.ID,
Name: check.Text,
Passed: false,
Reason: "reviewer failed to return a vote after 3 attempts",
})
}
}
Critically: The reviewer is not dropped. MaxScore = len(expected) always. This ensures:
<bucket-name>::<check_id> for non-combined buckets, plain <check_id> for combinedExample:
// Bucket "security" has check_1: "No hardcoded secrets"
voteKey := "security::check_1"
displayLabel := "[security] No hardcoded secrets"
parseReviewResponseV2 sets CriterionResult.Name from expected[i].Text (YAML source of truth), never from LLM echo. This ensures identical labels across runs.
Ran test-dp-test-hello-markdown twice with test/baseline config (2 models, panel review). Grader breakdowns identical:
Any code touching the reviewer-pipeline MUST preserve:
Violating these rules will re-introduce non-determinism.