Authoring a workbook¶
This guide is for the person writing the assignment. It explains how to turn a Jupyter notebook into a Correxit workbook that can be distributed, completed by students, and graded, all without a backend.
Everything a student receives is contained in a single .ipynb file.
Everything the grader needs is too. There is no database, no server, no
external state.
Thinking in question–answer pairs¶
A well-authored workbook reads like a conversation: a markdown cell poses a question, the code cell immediately below is where the student answers.
┌──────────────────────────────────────────┐
│ ## Question 1 │ ← markdown (read-only for students)
│ Select the first 10 rows of `genres`. │
├──────────────────────────────────────────┤
│ select * from genres limit 10; │ ← code: the graded cell
├──────────────────────────────────────────┤
│ -----BEGIN PGP MESSAGE----- │ ← raw: encrypted reference (invisible)
│ ... │
└──────────────────────────────────────────┘
When a human grader reviews a student's work, the Reviewer shows the preceding markdown cell as context (the question) so the grader never has to scroll back to remember what was asked. This only works when the question cell is directly above the answer cell, so the order matters.
Cells that are not part of the rubric (markdown, setup code, boilerplate) become read-only after distribution. Students can only edit the cells you explicitly mark for grading.
Converting a notebook¶
Open any Jupyter notebook and click Convert to a workbook assignment… in the Correxit sidebar. You will be asked for a passphrase. This passphrase derives a symmetric encryption key that protects reference cells and the roster. Choose something memorable; you will need it every time you unlock the workbook.
The passphrase never leaves the browser. It is not stored in the notebook, in settings, or anywhere on disk.
After conversion the notebook is a workbook. The sidebar switches from a single button to the full authoring interface.
Cell types¶
Every code cell you add to the rubric becomes one of four types. Each type has a different grading strategy.
Answerable¶
The student's output is compared to a cryptographic digest (SHA-256) of the expected answer. You type the expected output when you configure the cell; Correxit hashes it immediately and discards the plaintext. The student cannot read the answer directly from the hash, but short or obvious answers can still be guessed offline.
Best for cells that produce deterministic textual output that is not drawn from a tiny answer space. Prefer comparable or correctable cells for small numbers, booleans, names, or other easy-to-guess answers.
To create one: select the code cell, click Answer in the sidebar, and type the expected output in the prompt.
Comparable¶
The student's output is compared structurally to the output of a reference cell, another code cell in the notebook that produces the correct answer. Both cells are executed during grading, and their last output messages are compared (data payloads for rich output, or stream content for text).
Best for cells that produce tables, charts, or structured data where a hash would be too brittle.
To create one: select the code cell, click Compare, then click on the reference cell in the notebook. The reference is linked and marked secret by default.
Correctable¶
Like comparable, but each reference cell is a test: an assertion or check that passes (no error) or fails (raises an error). A correctable cell can have multiple references, each worth a fraction of the total points.
Best for cells where correctness is better expressed as a suite of checks rather than a single expected output.
To create one: select the code cell, click Correct, then click on the test cell. Add more references with Add a reference cell… in the sidebar.
Reviewable¶
No automated grading. The cell is flagged for manual review by an author using the Reviewer interface. The grader sees the cell source and output, assigns a score, and optionally leaves a comment.
Best for open-ended responses, proofs, written analysis, or anything that requires human judgment.
To create one: select any cell and click Manual in the sidebar.
Reference cells¶
Comparable and correctable cells depend on reference cells. A reference is an ordinary code cell in the notebook that you link to a graded cell.
References have two modes, toggled via the Share button in the sidebar:
| Mode | During authoring | After distribution |
|---|---|---|
| Secret | Visible, editable | Encrypted, hidden, read-only |
| Shared | Visible, editable | Visible, read-only |
Secret is the default. Use it when the reference reveals the answer (e.g., the correct SQL query). Use shared when the reference is not sensitive (e.g., a unit test that the student should be able to read).
A reference cell cannot also be a graded cell. A cell is either in the rubric or it is a reference, never both.
Correctable references and partial credit¶
Each reference on a correctable cell carries its own point value. The cell's total possible score is the sum of its reference points. You can adjust individual reference weights in the sidebar.
For example, a correctable cell with three test references at 2, 1, and 1 points has a total of 4 possible points. If only the first two tests pass, the student earns 3.
Points¶
Every graded cell has a point value. The default is 1. Change it by editing the Points possible field in the sidebar.
For comparable cells, points are set directly on the cell. For correctable cells, points are derived from the sum of reference weights; you adjust them per-reference, not on the cell itself.
Notebook structure¶
Recommended layout¶
markdown Question or instructions
code Student answer (graded cell)
code/raw Reference cell, if needed (secret or shared)
markdown Next question
code Next answer
...
code Setup/boilerplate (not graded, read-only for students)
There are no hard structural requirements other than:
- Reference cells must exist in the notebook. They must be code cells (or raw cells, but only after encryption on lock).
- A cell is either graded or a reference, not both.
- Answerable cells need a payload. If you create one, you must provide the expected output.
But there are conventions that produce better results:
-
Place the question markdown cell directly above the answer cell. The Reviewer uses this position to show the grader what was asked. If there is no adjacent markdown cell, or the adjacent cell is itself graded or a reference, the grader sees no question context.
-
Place reference cells near their graded cell. During single-cell correction, the notebook is executed from the top down to whichever comes later: the graded cell or its furthest reference. If a reference is far below, every code cell in between executes too, including other students' answer cells, which may error or produce side effects that pollute kernel state.
Do not drag all reference cells to the bottom of the notebook. A reference at row 20 for a graded cell at row 3 means rows 4–19 all execute during single-cell correction of row 3. Keep each reference close to (ideally directly after) its graded cell.
- Use setup cells at the top for shared state. Database connections, imports, data loading. These are cells that every student needs but should not edit. These automatically become read-only for students.
Testing¶
Before distributing, test the workbook by clicking Correct workbook… in the sidebar. This executes the entire notebook against a kernel, scores every cells, and reports the total. Every graded cell should show a green checkmark.
You can also test individual cells with Correct cell… to iterate quickly while authoring.
If a cell scores incorrectly, the sidebar shows the error code and the cell is decorated with a red indicator. Common causes:
- The reference cell has a bug.
- The answerable cell's expected output does not match what the cell actually prints (whitespace, trailing newlines, encoding).
- A comparable cell's output structure changed (e.g., a library update changed the display format).
Assignment and distribution¶
Assigning¶
Open the workbook, enter a roster (list of student identifiers, one per line) and an assignment name in the sidebar. If a Registrar plugin is configured (e.g., Moodle), roster and assignment metadata are fetched automatically.
In manual mode, the sidebar deadline belongs to Correxit. You may choose an overdue policy: accept late work, dock the final score by a percentage of possible points, or reject submission after the deadline.
This policy is local to the workbook. Correxit applies it from the submission timestamp written into the document when the student clicks Submit. That is useful for backendless workflows such as exchanging notebooks over git, email, or shared storage, but it is not an authority-backed receipt.
If a Registrar plugin supplies the assignment metadata, Correxit treats that deadline as provider-owned registration data. It is displayed, but Correxit does not layer its own overdue policy on top of it.
If your submit path already has its own trusted clock and deadline rules (for example Moodle, a gradebook service, or a server-side git workflow), that external system should remain authoritative. Correxit's local overdue policy is for the cases where there is no backend to do that job.
If you use the local reject policy, the corresponding grading-side control
is in Correxit Corrector: enable Submitted to scan and grade only
workbooks that carry a local submission timestamp. That gives backendless
workflows a coherent intake rule without pretending the workbook has an
external authority behind it.
Propagating¶
Click Create N assigned workbooks… to distribute. Correxit creates one copy per roster entry:
- Secret references are encrypted.
- Non-graded cells are marked read-only.
- The rubric is locked and the passphrase is stripped.
- Each copy is issued to one assignee and carries a stable blank-slate
issuedigest plus authorissuersignature. - The roster is encrypted so students cannot see classmates.
Correxit always writes local copies. An optional Distributor plugin may also deliver each notebook elsewhere (Moodle, object storage, etc.).
Sidecar resources¶
If the assignment requires data files alongside the notebook (a database file, a CSV, an image), click Pick files... in the sidebar before propagating. Select one or more files in the current directory. Their names are stored in the rubric and loaded during propagation.
Correxit reads each file during propagation, copies it into the propagated directory, and passes its raw bytes to the Distributor plugin. The files are not embedded in the notebook. A Moodle distributor uploads them as feedback attachments alongside the notebook; a manual distributor leaves them in the local propagated directory.
To clear the resource list, click Clear next to the listed files in the sidebar.
Cell outputs and propagation¶
When Correxit creates assigned copies, it serializes the notebook as-is. Cell outputs are not cleared. Any output present in your workbook at propagation time ships to the student.
This means:
- If a graded cell still has your test output, the student sees it before writing a single line of code.
- If a secret reference cell has output (e.g., the correct query result), that output is not encrypted; only the source is. The student can read the output even though the code is hidden.
Treat outputs as intentional content. If an output is in the distributed notebook, it should be there because you want the student to see it (e.g., a sample result in a setup cell, or an expected-output preview in a shared reference). If you do not want students to see an output, clear it before propagating: Edit → Clear All Outputs, or clear individual cells manually.
What students receive¶
A locked notebook where:
- Markdown and setup cells are visible but not editable.
- Graded cells are editable: these are the blanks to fill in.
- Secret references appear as encrypted raw cells: PGP blocks with hidden source.
- Shared references are visible but not editable.
- The passphrase is absent. Students cannot unlock the workbook.
Double-clicking a read-only markdown cell will not switch it to edit mode (Correxit disables this per-notebook to avoid confusing students).
Locking and unlocking¶
- Lock: encrypts secret references, encrypts the roster, and erases the key.
- Unlock: prompts for the passphrase, decrypts references, and re-enables editing.
Lock before distributing. You can lock and unlock freely during authoring to preview what students will see.
Revert to draft¶
For submitted workbooks that were not sealed with a student passphrase, Revert to draft clears the submission state and makes answer cells editable again while keeping the rubric locked.
Revise submission¶
If the student chose Set passphrase when submitting, the workbook is sealed to both the author and student keys. In that case the student uses Revise submission and must enter the same submission passphrase.
Revision decrypts the sealed answers, clears the seal and submission metadata, clears the student key material, and makes answer cells editable again while keeping the rubric locked.
Lifecycle¶
A workbook moves through these stages:
┌───────────┐
convert ───────▸ │ Unlocked │ ◂── unlock
└─────┬─────┘
│ lock
┌─────▼─────┐
│ Locked │ ◂── draft / revise
└─────┬─────┘
│ submit
┌─────▼─────┐
│ Submitted │
└─────┬─────┘
│ certify
┌─────▼─────┐
│ Certified │
└─────┬─────┘
│ collect
┌─────▼─────┐
│ Collected │
└───────────┘
- Submitted: the student clicked submit. A timestamp is stored. If a Submitter plugin records the submission externally, its receipt is stored too. The local timestamp is useful workflow state, but only the external receipt comes from a separate authority.
- Certified: the grade has been computed and frozen. Certification is the grader's seal; it requires all cells to be scored.
- Collected: a Collector plugin acknowledged receipt of the grade and stored the external receipt.
Tips¶
- One passphrase per workbook. The passphrase is bound to the rubric ID. You cannot change it after conversion.
- Test early, test often. Run Correct after every change. A small drift in expected output can silently break answerable cell scoring.
- Answerable cells are fragile. A trailing newline, a different locale, a library update that changes formatting. Any of these will invalidate the digest. Prefer comparable or correctable cells when output is not perfectly deterministic.
- Correctable cells are the most robust. Tests that assert properties of the output are more resilient than exact-match comparisons.
- Reviewable cells are the escape hatch. When automated scoring is impractical, use reviewable. The grader can assign any score from 0 to the cell's possible points.
- Student code cannot break grading. The batch grader has a configurable per-workbook timeout. If a student's code hangs, runs an infinite loop, or crashes the kernel, that workbook times out and the grader moves on. The timeout, concurrency limit, and retry count are all configurable in the Corrector settings. You do not need to defensively design around pathological submissions.
- Keep the notebook self-contained. Everything the student needs (data files, imports, context) should be in the notebook or its working directory. There is no server-side setup step. If you use a Distributor plugin that can push files, declare sidecar data files via Set resources... so the distributor receives them alongside the notebook.
- Clear outputs before propagating. Unless you intentionally want students to see a cell's output, clear all outputs before distributing. Outputs are not encrypted, even on secret reference cells.
Converting from nbgrader¶
If your notebook was authored in nbgrader, Correxit can convert it
automatically. Open the notebook and click Convert to a workbook
assignment… in the sidebar. Correxit reads the per-cell nbgrader
metadata (grade, solution, task, points) and maps each cell to
the closest Correxit equivalent. The nbgrader metadata is stripped after
conversion.
How cells are mapped¶
| nbgrader cell type | nbgrader metadata | Correxit type |
|---|---|---|
| Autograded answer | solution=true, grade=false |
correctable |
| Autograder tests | grade=true, solution=false |
reference |
| Manual answer | grade=true, solution=true |
reviewable |
| Task | task=true |
reviewable |
| Read-only / locked | locked=true, no grade/solution |
(skipped) |
| Unmarked | no nbgrader key | (skipped) |
An autograded answer becomes correctable when test cells follow it in notebook order. If no test cells follow, it falls back to reviewable (the conversion report notes this with a warning).
Task cells are assigned to the next unmarked cell below them. If no unmarked cell follows, the task's points are discarded (also warned).
Solution and mark-scheme markers¶
### BEGIN SOLUTION / ### END SOLUTION marker lines are removed
from cell sources, but the solution code between them is kept.
=== BEGIN MARK SCHEME === / === END MARK SCHEME === regions are
removed entirely (markers and content).
Hidden tests¶
If a test cell contains ### BEGIN HIDDEN TESTS / ### END HIDDEN
TESTS markers, Correxit splits it into two cells: the visible portion
stays in place; the hidden portion becomes a new secret reference cell
inserted directly after. Both count toward the correctable cell's point
total. Correxit does not create zero-point references, so split hidden
tests can increase the converted total.
AUTOTEST directives¶
nbgrader's ### AUTOTEST and ### HASHED AUTOTEST directives are
expanded at conversion time. Correxit leases a kernel, executes the
answer cell to define its variables, then evaluates each autotest
expression and replaces the directive with generated Python test code.
This Python requirement applies only to AUTOTEST expansion; the rest of
nbgrader conversion remains kernel-agnostic.
When Correxit cannot safely reify an autotest, it leaves a commented
placeholder in the reference cell, inserts a failing
NotImplementedError, and reports the cell in the conversion summary so
you can rewrite that test manually.
If no kernel is available, the directives are left in place and a
warning is added to the report, but the rest of conversion still
continues.
Points and slippage¶
nbgrader stores point values in cell metadata as numbers. Correxit requires integer points. During conversion, two transformations can change the point totals:
- Recalibration. When nbgrader splits a cell's total across multiple test cells as fractions (e.g., two tests at 0.5 each), Correxit scales them to the smallest integers preserving their ratios (0.5 + 0.5 becomes 1 + 1). The ratio of partial credit is preserved, but the absolute total changes.
Hidden-test splits follow the same rule. A visible half and a hidden half remain nonzero references, so they may increase the converted total relative to the original nbgrader notebook.
- Rounding. Fractional points on reviewable and task cells are rounded to the nearest integer.
If the sum of the original nbgrader metadata points differs from the converted rubric total, the conversion report states both numbers so you can verify the result. This is informational: the converted values are what Correxit will use for grading. If the original notebook text mentions point values (e.g., "Part A (2 points)"), those strings are not updated automatically. You may want to edit them by hand after conversion so students see numbers that match the rubric.
After conversion¶
The conversion report appears in a dialog. Review it for warnings. Then use the sidebar to inspect each cell's configuration and run Correct workbook… to verify that every cell scores correctly before distributing.