🧪 Lightcodelab

📝 Canvas quizzes

The desk for the module checks: read what Canvas holds, lint a spec, write it back. Private HQ tool — the engine loads only in the lab, and the gate never carries it to pedia.

The specs live beside their module, in a dundered folder — module_05/__quiz/canvas.md. __ is the travel rule: the courses gate mirrors with --exclude '__*', so an answer key cannot reach the vault that every enrolled learner can read. The course audit checks both halves of that on each push: the key is dundered, and the gate still excludes dunders.

05 · Basement

Canvas quiz desk

Set course= to the Canvas course id before pushing (Canvas → the course → the number in its URL).

410 · 02 · Data Quest 2

Canvas quiz desk

Three matching questions — the first check written in that kind.

410 · 03 · Build the Shop

Canvas quiz desk

⚙️ Quiz 3b, three matching questions; the survey 📍 Assignment 3a sits beside it in the same folder and rides the module gate.

Matching questions

Michel, 2026-09-04: “NOT multiple choices BUT a classic quiz with Matching questions”. A matching question is a table under its stem — the sentences on the left, the answer to each on the right — and its why sits under the table, because Canvas shows no per-pair comment:

### Say it in SQL

Match each sentence with the SQL that answers it.

| English | SQL |
|---|---|
| Select all customers | SELECT * FROM Customers; |
| Select London customers | SELECT * FROM Customers WHERE City = 'London'; |
| Select names and cities | SELECT ContactName, City FROM Customers; |
|  | SELECT ContactName AND City FROM Customers; |

> A comma lists columns; AND joins conditions, never columns.

{: .quiz kind="matching" points="5" }

A row with an empty left cell is a distractor: a right side that matches nothing, Canvas’s own “incorrect matches” box. Opened as a page, the table is the key. The linter reads matching in its own terms: at least three pairs, no right side shared by two lefts (letter for letter — 'London' and London are two answers), no two identical lefts, an anchor somewhere in the question, and a why under the table.

What the linter refuses

A quiz leaks when the key looks different from the distractors — the longest option, the only bold one, the only one without an “always”. A learner who never opened the material can score on that pattern alone, which is the exact hole these quizzes exist to close. So the tells are a gate, not a warning:

One more rule runs on the command line only, because it needs the course tree: a key the course already marks [x]. Enrolled learners hold read on the vault (the session team is granted the vault, so that nobody can read a classmate’s bench), which means a learner with their own key can clone the whole course and grep for the answers. Fine for the in-page quizzes — they are formative, and the answer sits four lines below the question. Not fine for the graded check, where the same wording would mark whoever greps instead of whoever learns.

The same six rules run in tools/canvas_quiz.py, so the command line and this page agree about what a fair quiz is.

If the browser cannot reach Canvas

Canvas answers a browser only where its own cross-origin policy allows it. When the call never lands, the desk says so rather than blaming your key — and the command line is the way through:

export CANVAS_TOKEN=...
python3 tools/canvas_quiz.py push courses/micro_build_ai/module_05/__quiz/canvas.md --course <id>
Edit page Modes
📋 · 0/0

Edit

⚙️ engine 30259e4