Skip to content

Architecture decision records

Start here to find a decision without loading the whole archive. This is a reading index, not another specification. Each record owns its rationale, status and amendment history.

Reading protocol

  1. Read the relevant specification chapter and check open questions. Repository invariants are in CLAUDE.md; an unresolved conflict is not permission to change a product rule.
  2. Pick a topic below. Read the record's Status before its Decision, then follow its named amendments. A later record overrides only the scope it explicitly changes; a higher number alone establishes no precedence.
  3. Consolidated records put the current rule first and link to historical snapshots only for rationale or old section references. Do not load history/ by default. In other records, follow the Reading map when present. Cite the full file and section when handing work to another agent.
  4. Accepted is a decision state, not a deployment state. Check the code, tests and merge progress for implementation. Imported records describe heig-classroom until their Quiz status/addendum adapts them; its GR-, GH-, AU- and NFR- IDs are not Quiz requirement IDs.

Topics

Each record appears once below. Cross-topic dependencies live in the records, so this index does not duplicate their status or maintain a second dependency graph.

Platform and operations

Identity, access and exam confinement

Question authoring and types

Evaluations, grading and practice

Question analytics

LLM services

Classroom merge, projects and journal

Maintaining a record

Use the template for new decisions. Keep one decision per record; put requirements in the spec, operational commands in the runbook and delivery progress in the merge task cards. Link to those sources instead of copying them.

Keep existing IDs, paths and heading anchors stable, except to resolve a duplicate number, noted in the record's Status (2026-10-09: an anchor list into history/ may be reduced to a correspondence table of the cited sections plus bare compatibility anchors). Select an unused ID after checking both the repository and concurrent branches/PRs; rebase before merging, and renumber yours if that ID landed meanwhile. For a changed decision, name the affected section in the new record and add a reciprocal link in the old record's Status. Use superseded only for a whole decision that no longer applies; otherwise say amended, with its scope. A record folded into its successor keeps its number and path as a short stub whose Status names the successor and where each living rule went; the successor carries a correspondence table for the sections code and documents cite, and this index marks the stub "(superseded, folded into ADR-NNN)". Keep the old rationale, and mark obsolete instructions where they occur if a reader could retrieve them alone. Do not append another implementation diary to an already long record.

Amended 2026-10-09 (rules carried from the archived 2026-10-02 audit):

  • A record never restates another record's decision: it links to the record that owns it and names the affected points, so the copy cannot drift.
  • Records on one topic that settle different trade-offs stay separate (project CI runners, ADR-007, and the question runner, ADR-016; the freeze, ADR-012, and its application to projects, ADR-064); a repeated reference to an access invariant is local rationale, not duplication. Fold only a record whose living rules have all moved.
  • Consolidating keeps every stated limit explicit — an at-most-once loss window, a privacy exception, what a preview does not exercise, a change a notification can miss — and never replaces it with a stronger promise.

Add a link under one topic here. The site's Decisions entry points to this index; there is no separate per-ADR navigation list to update. Build the documentation and check links before opening the PR. The 2026-10-02 audit, archived, records the reasons for this organization.