Skip to content

feat(quiz): confidence rating — pre-reveal prompt, calibration, and agent visibility - #31

Merged
jonasbrami merged 2 commits into
mainfrom
feat/confidence-rating
May 29, 2026
Merged

feat(quiz): confidence rating — pre-reveal prompt, calibration, and agent visibility#31
jonasbrami merged 2 commits into
mainfrom
feat/confidence-rating

Conversation

@jonasbrami

@jonasbrami jonasbrami commented May 29, 2026

Copy link
Copy Markdown
Owner

What

Roadmap #3 — the confidence slice of the feedback loop, end to end.

In the browser (practice mode): committing a deterministic question (mcq/tf/mermaid) asks "How sure are you? 1–5" before revealing. The revealed card surfaces calibration:

  • confident (≥4) but wrong → "Confident but wrong — worth a closer look." (red)
  • right but unsure (≤2) → "Right — but you weren't sure. Lock in why." (orange)

Exposed to the host agent (so it can follow up — re-probe confident-but-wrong, drill weak concepts):

  • POST /confidence {question_id, value:1-5} — fired on pick (validated; rejects out-of-range / non-int).
  • QuizState.confidences: dict[str,int] — persisted in the snapshot beside answers; reset on set_quiz, dropped per-question on replace_question.
  • QuestionResult.confidence: int | Nonegrade_state attaches each rating to the grade tool result.
  • get_answers tool returns confidences too (agent can inspect before grading), with a docstring nudge.

Scope / invariants

  • Confidence is collected only in practice mode; exam/batch flow untouched.
  • Backward compatible: optional throughout — old snapshots load with an empty map, results with confidence=None.
  • Honor-system (the answer already ships in /state); the server copy just mirrors the local rating for the agent.

Teach-back (#6) is the remaining feedback-loop slice, as its own PR.

Testing

  • Unit: state persistence/reset/drop; QuestionResult.confidence validation (1–5); /confidence record + 422 paths; get_answers + grade carry confidence. Full mcp/engine suite green; ruff + ruff format + mypy --strict clean.
  • Real browser (Chrome DevTools): picker gates the reveal; under/over-confidence flags render; and end-to-end rating → POST /confidence/state.confidences → grade result carries confidence. Screenshots shared.

🤖 Generated with Claude Code

jonasbrami and others added 2 commits May 29, 2026 20:08
In practice mode, committing a deterministic question (mcq/tf/mermaid) now asks
"How sure are you? 1–5" before revealing. After the rating, the answer reveals as
before and the card surfaces calibration:

- confident (≥4) but wrong → "Confident but wrong — worth a closer look." (red)
- right but unsure (≤2)    → "Right — but you weren't sure. Lock in why." (orange)
- otherwise just shows the rating.

Honor-system and client-side only (the answer already ships in /state); confidence
is collected only in practice mode (exam mode keeps the batch flow untouched).
Surfacing high-confidence-wrong is the calibration payoff.

Frontend only. Verified in a real browser: the picker gates the reveal; rating 2 on
a correct answer flags under-confidence; rating 5 on a wrong answer flags
over-confidence; exam mode shows no picker.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Confidence (the 1–5 self-rating from #31's pre-reveal prompt) was browser-only;
now it's persisted server-side and surfaced to the host agent, so it can act on
confidence-vs-correctness — re-probe confident-but-wrong questions, drill weak
concepts.

- POST /confidence {question_id, value:1-5} — browser fires it on pick (validated;
  rejects out-of-range and non-int, incl. bool).
- QuizState.confidences: dict[str,int] — persisted in the snapshot beside answers;
  reset on set_quiz, dropped per-question on replace_question.
- QuestionResult.confidence: int | None — grade_state attaches each reader's rating
  to the result the `grade` tool returns.
- get_answers tool now returns `confidences` too (agent can inspect before grading),
  with a docstring nudge to follow up on confident-but-wrong / unsure answers.
- JS pick(n) mirrors the local rating to the server (fire-and-forget).

Backward compatible: confidence is optional throughout; old snapshots load with
an empty map and results with confidence=None.

Tested: state persistence/reset/drop; QuestionResult.confidence validation;
/confidence record + 422s; get_answers + grade carry confidence. Verified in a
real browser: rating → POST /confidence → /state.confidences → grade result
carries confidence end-to-end. Full suite green; ruff + mypy --strict clean.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@jonasbrami jonasbrami changed the title feat(quiz): confidence rating before reveal + calibration feedback feat(quiz): confidence rating — pre-reveal prompt, calibration, and agent visibility May 29, 2026
@jonasbrami

Copy link
Copy Markdown
Owner Author

Quiz results

Total: 60%

Question 1 — ❌ 0%

Prompt: Which diagram correctly shows what renderQuestion does with a deterministic, answered question in practice mode — from answer committed to result card visible?

Your answer: C

Question 2 — ✅ 100%

Prompt: Before this PR, shouldReveal(q) returned true for any answered deterministic question in practice mode. After this PR, what is the earliest moment it can return true?

Your answer: After the user clicks one of the 1–5 confidence buttons

Question 3 — ✅ 100%

Prompt: A user rates confidence 4 ('Fairly sure') and their answer is correct. What does calibration(q) return?

Your answer: null

Question 4 — ✅ 100%

Prompt: In exam mode, a user who answers a question will see the confidence prompt before the result is revealed.

Your answer: false

Question 5 — ❌ 0%

Prompt: The comment on line 415 says confidence is an 'honor system (the answer's already in the page)'. What does this mean for the integrity of the calibration feedback, and why did the author still consider it worth shipping?

Your answer: testing

The answer ("testing") does not address any rubric item — it makes no claim about the answer being accessible in the page before the confidence prompt, about calibration data relying on honest self-reporting, or about why the feature is still worth shipping despite that limitation.


Results state (used by the CLI)
{
  "version": "1",
  "pr_number": 31,
  "total_score": 60,
  "per_question": [
    {
      "question_id": "q1",
      "correct": false,
      "score": 0,
      "feedback": "",
      "confidence": 4
    },
    {
      "question_id": "q2",
      "correct": true,
      "score": 100,
      "feedback": "",
      "confidence": 2
    },
    {
      "question_id": "q3",
      "correct": true,
      "score": 100,
      "feedback": "",
      "confidence": 3
    },
    {
      "question_id": "q4",
      "correct": true,
      "score": 100,
      "feedback": "",
      "confidence": 2
    },
    {
      "question_id": "q5",
      "correct": false,
      "score": 0,
      "feedback": "The answer (\"testing\") does not address any rubric item — it makes no claim about the answer being accessible in the page before the confidence prompt, about calibration data relying on honest self-reporting, or about why the feature is still worth shipping despite that limitation.",
      "confidence": null
    }
  ]
}

@jonasbrami
jonasbrami merged commit 8ee6496 into main May 29, 2026
2 checks passed
@jonasbrami
jonasbrami deleted the feat/confidence-rating branch May 29, 2026 18:15
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant