You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
There is no storage for a written response and no rubric field. Answer (now_lms/db/__init__.py:1067) persists only selected_option_ids, a JSON array of option UUIDs. Question carries text and explanation; both are instructor-facing and neither is a grading criterion.
So the platform can assess recognition and cannot assess explanation. A question can ask a learner to pick the correct answer from a list. It cannot ask a learner to predict what a command will do before running it, justify an architectural choice, or say what they expect to break — and then hold that written answer against stated criteria.
That ceiling binds any practice-based curriculum on this platform. It is also a general limitation rather than an Intent Solutions one: every comparable LMS ships a short-answer or essay question type.
Why it is smaller than it looks
The whole grading path is four functions in one file (now_lms/vistas/evaluations.py:134, 150, 161, 180).
Question.type is String(20) with no enumeration constraint (now_lms/db/__init__.py:1022), so a new type value needs no schema change.
EvaluationAttempt.passed is already nullable=True (now_lms/db/__init__.py:1056), so a pending-grade state is representable in the schema as it stands. It is simply never produced, because take_evaluation scores every attempt synchronously on submit.
Estimated: one additive migration (all columns nullable, no backfill), roughly 150 lines of application code, and three templates — question editor, learner view, instructor grading queue.
This estimate comes from reading the code, not from building it. Treat it as an estimate until the migration exists.
Proposed decision
ADR-6, filed as 000-docs/012-AT-ADEC-short-answer-evaluations.md in the linked PR, status Proposed. It applies ADR-1 rather than excepting it: the capability is generic, so it is authored upstream to bmosoluciones/now-lms rather than carried as a fork patch.
Automated grading of written answers is explicitly out of scope of that ADR. It carries an external model provider, a cost model, and a revision loop the current one-shot attempt model does not support, and it should not ride along on a question-type decision. The proposed interface admits a grader of any kind later without a second migration.
Open questions for the reviewer
Upstream first, or fork first? ADR-1 says upstream. Upstream PR fix(db): bootstrap a fresh PostgreSQL database correctly on first boot bmosoluciones/now-lms#179 has been open and waiting on the maintainer for a while, so upstream-first carries real schedule risk. The alternative is carrying the change on deploy/now-lms-fixed while the upstream PR is open and dropping it on acceptance — a temporary divergence rather than a permanent one, which ADR-1 does not currently describe.
Multiple short answers per evaluation, or capped at one to bound grading load?
Partial credit as a free score, or fixed bands?
Three-way circle — incomplete, needs closing
Per CLAUDE.md every tracked unit exists as bead ↔ GitHub issue ↔ Plane issue, each carrying the other two IDs. This issue was filed from a machine with no bd binary and no .beads/ database (it is local-only and gitignored), and no Plane access. The bead and the Plane issue still need to be created and linked back here. Flagging it in the open rather than leaving the circle silently broken.
Beads: not yet created —
bdis not installed on the filing machine, see "Three-way circle" belowPlane: not yet created — see below
The gap
NOW-LMS evaluations support exactly two question types.
now_lms/forms/__init__.py:129is the complete set:There is no storage for a written response and no rubric field.
Answer(now_lms/db/__init__.py:1067) persists onlyselected_option_ids, a JSON array of option UUIDs.Questioncarriestextandexplanation; both are instructor-facing and neither is a grading criterion.So the platform can assess recognition and cannot assess explanation. A question can ask a learner to pick the correct answer from a list. It cannot ask a learner to predict what a command will do before running it, justify an architectural choice, or say what they expect to break — and then hold that written answer against stated criteria.
That ceiling binds any practice-based curriculum on this platform. It is also a general limitation rather than an Intent Solutions one: every comparable LMS ships a short-answer or essay question type.
Why it is smaller than it looks
now_lms/vistas/evaluations.py:134, 150, 161, 180).Question.typeisString(20)with no enumeration constraint (now_lms/db/__init__.py:1022), so a new type value needs no schema change.EvaluationAttempt.passedis alreadynullable=True(now_lms/db/__init__.py:1056), so a pending-grade state is representable in the schema as it stands. It is simply never produced, becausetake_evaluationscores every attempt synchronously on submit.Estimated: one additive migration (all columns nullable, no backfill), roughly 150 lines of application code, and three templates — question editor, learner view, instructor grading queue.
This estimate comes from reading the code, not from building it. Treat it as an estimate until the migration exists.
Proposed decision
ADR-6, filed as
000-docs/012-AT-ADEC-short-answer-evaluations.mdin the linked PR, status Proposed. It applies ADR-1 rather than excepting it: the capability is generic, so it is authored upstream tobmosoluciones/now-lmsrather than carried as a fork patch.Automated grading of written answers is explicitly out of scope of that ADR. It carries an external model provider, a cost model, and a revision loop the current one-shot attempt model does not support, and it should not ride along on a question-type decision. The proposed interface admits a grader of any kind later without a second migration.
Open questions for the reviewer
deploy/now-lms-fixedwhile the upstream PR is open and dropping it on acceptance — a temporary divergence rather than a permanent one, which ADR-1 does not currently describe.Three-way circle — incomplete, needs closing
Per
CLAUDE.mdevery tracked unit exists as bead ↔ GitHub issue ↔ Plane issue, each carrying the other two IDs. This issue was filed from a machine with nobdbinary and no.beads/database (it is local-only and gitignored), and no Plane access. The bead and the Plane issue still need to be created and linked back here. Flagging it in the open rather than leaving the circle silently broken.