Skip to content

fix: reject fill-in-the-blank/short-answer drafts with a placeholder … - #78

Merged
JoseEstevez520 merged 1 commit into
mainfrom
hotfix/fill-blank-placeholder-answer
Sep 14, 2026
Merged

JoseEstevez520 merged 1 commit into
mainfrom
hotfix/fill-blank-placeholder-answer

Conversation

@JoseEstevez520

Copy link
Copy Markdown
Collaborator

What and why

Users reported fill-in-the-blank (and other constructed-answer) exercises whose
correct answer was literally the word "respuesta". The authoring contract's example
ships a placeholder answer key (evaluation.expected: ["respuesta", "la respuesta", "respuestas"]) for didact.quiz.fill-in-the-blank, didact.quiz.short-answer and
didact.completion-problem. The runtime grounding gate that rejects echoed example
content explicitly skips evaluation/expected, by design, since for most
components that subtree holds structural ids, not content. A model that left the
placeholder there passed validation and shipped an unanswerable exercise.

This adds a second, narrower check (_reject_unsubstituted_expected) scoped to the
three components whose expected is free-text answer content, rejecting a draft
when any expected value is still the contract's placeholder — same decline-and-retry
path as the existing content-echo check.

Checks

  • uv run ruff check src tests and uv run pytest -m "not integration" (from apps/skillnet-api/) — 4339 passed, including two new tests that reproduce the reported bug.
  • pnpm lint, pnpm test and pnpm build (from apps/skillnet-web/) — not run; this change doesn't touch the frontend.
  • Touched a migration, the compose files or .env.example? — N/A, none of those changed.

Notes for the reviewer

This is a hypothesis grounded in the code and confirmed with a unit test that
reproduces the exact symptom (well-formed question, expected still the
placeholder) — I have not confirmed a live production row with this exact leak.
If you can check activity_definitions.private_definition -> evaluation -> expected for rows literally equal to "respuesta" / "la respuesta" / "respuestas"
before merging, that closes the loop.

…answer key

evaluation.expected was excluded from the grounding-echo check on purpose
(it usually holds structural ids), but for didact.quiz.fill-in-the-blank,
didact.quiz.short-answer and didact.completion-problem it holds the actual
graded answer text. A model that left the example placeholder there
("respuesta") passed validation and shipped an exercise whose correct
answer was literally the word "respuesta" — the bug users reported.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01SUqXYDVrx1DxZnk5B58Yxk
@JoseEstevez520
JoseEstevez520 merged commit edf6dd6 into main Sep 14, 2026
3 checks passed
@JoseEstevez520
JoseEstevez520 deleted the hotfix/fill-blank-placeholder-answer branch September 30, 2026 20:12
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