Repository navigation
Releases: ColePoppleton/Staffroom
Release list
v0.9.1
Nothing changes for teachers since 0.9.0. This version only fixes a check that stopped 0.9.0's release page from being published.
Update: quit Staffroom, run uv tool upgrade staffroom in Terminal, and open it again (Updating covers a copy installed from a release tag). New to Staffroom? Start with Install.
For contributors: the full list (1 change)
Fixed
- The changelog site test no longer expects an Unreleased fold right after a release, when that section is empty; this failure kept the 0.9.0 GitHub Release from being built.
v0.8.1
Staffroom is now public, so a colleague can install it from GitHub without asking for access. The documentation site has a part for teachers and a part for people who want to change the code.
Update: quit Staffroom, run uv tool upgrade staffroom in Terminal, and open it again (Updating covers a copy installed from a release tag). New to Staffroom? Start with Install.
For contributors: the full list (3 changes)
Changed
- The documentation site covers using Staffroom and contributing to it.
- The repository is public: the install docs no longer ask colleagues for access, and the wheel on each GitHub Release is the fallback when git is not available.
- Nothing in the repository names the owner's own folders, file counts or computer.
v0.8.0
Options forms only ask what matters: Worksheet shows Level only for truth tables, and Quiz asks for the taught log only in retrieval mode. The Library narrows its folder tree by tag and by type, and Bugs sheets mix programs that crash with programs that run but print the wrong thing. A full disk can no longer leave your settings half-written.
Update: quit Staffroom, run uv tool upgrade staffroom in Terminal, and open it again (Updating covers a copy installed from a release tag). New to Staffroom? Start with Install.
For contributors: the full list (15 changes)
Added
- Quiz shows the Taught log picker only while Retrieval mode is ticked, under the options it follows, and a hidden log is never handed to the run. Any panel can do the same:
PanelSpec.shown_whenhides a whole input while a field of an options form ("options.retrieval") or aChoicedoes not hold the given values; a hidden input passes its empty value and is not asked for, andcore.panelrefuses unknown keys, impossible values and loops when the spec is built. - The Library's column has a Tags ▾ filter beside All types. Its menu lists the tags on the files the Library shows, each with how many carry it; choosing one narrows the tree (opened all the way down) and the search results to files carrying it, and choosing more narrows further. It combines with the type filter and the query, follows tag edits in the preview at once, and the footer says how many files it leaves. Tags are still read from the sidecar (
.staffroom/tags.json); the resources folder is never written.LibraryService.tag_counts()and atags=argument onresources()andsearch()back it, over purecount_tags/paths_with_tagshelpers.
Changed
- The date in a sheet's header can be pinned with
STAFFROOM_DATE=YYYY-MM-DD, read in one place (core/export/dating.py); every sheet builder falls back to it instead of reading the clock.scripts/screenshots.shpins it, so the docs pages (docs/output-*.png,docs/worksheet-sample.png) stay byte-identical from day to day, andscripts/screenshots.sh outputsredoes just those pages. A teacher's own runs never set it and still print today's date.worksheet-sample.pngis re-rendered once: it still showed the old truth tables. - Options forms show only the fields that apply and say their choices in words.
OptionsFormgainsshown_when(a field shows only while another holds given values),choice_labelsandswitches(a segmented switch for a short choice). Worksheet shows Level only for truth tables and Boolean laws only for simplification, with topic names, Easy / Medium / Hard and Word + PDF / Word / PDF; the quiz shows Title only for Forms and do-now and As of only in retrieval mode; Fade shows Line ranges only for Only the lines I list; Parsons, Trace, Bugs and Pseudocode get readable output choices. A hidden field keeps what was set in it, but the tool is handed its default, so a value the teacher cannot see never changes or breaks a run. docs/classroom-dark.pngno longer changes every day: the launcher's screenshot mode takes--today YYYY-MM-DD, which pins only the day Classroom's run bar shows (Copies to …/sessions/<day>), andscripts/screenshots.shpasses itSTAFFROOM_DATE. It is a separate, display-only flag because the session folder decides where real lesson copies go: the launcher refuses it without--screenshot, it is never saved, and Open for class always copies into today's folder.
Fixed
- Bugs: a wrong variable name bug now swaps in a name a pupil might really type: one of the same apparent kind (number, string, list…) that is already assigned in the same scope, the most recently assigned first, instead of always the program's first name. In
examples/year9.pythat was the listscores, so seven of the eight wrong-name bugs were TypeErrors; now seven run with the wrong output (if count >= 50:), and onlyfor score in score:crashes. Still deterministic, so a seed gives the same sheet. - Bugs: the key shows an indentation slip. Its two lines used to read the same (
count = count + 1twice) because the key trimmed the indent; now each space of indentation shows as·when the indent is what changed, and the Bug cell says how far it moved (indentation slip (4 spaces to 0)), in the PDF, docx and text key and the panel's What each bug does table. The printed key adds a one-line legend for the dots. - Bugs aims for a mix of outcomes: at the defaults all four
year9.pyversions crashed, two of them with SyntaxErrors. With two or more versions the sheet now includes a runs, but the output is wrong bug when the program has one, and at most one SyntaxError unless nothing else can make up the count; still one bug per version, chosen in the seed's order, so the same seed gives the same sheet. A program that cannot offer the mix gets its sheet and a warning. - Saving settings can no longer leave
config.tomltruncated. The file is written to a hidden temporary file beside it and swapped in withos.replace, so a disk that fills or a folder that turns read-only mid-write leaves the old settings whole; the temporary file is removed and the teacher sees the same Settings could not be saved line as before. The file keeps its permissions, a symlinked config stays a symlink, and a config made read-only on purpose is still left alone.usage.tomland the Library's tags sidecar now use the same helper (core/atomic.py), so they cannot be truncated either. - In the Library, the type filter (All types) narrows the folder tree too, not only the search results: with no query, choosing python now leaves just the Python files, opened all the way down, as the Tags filter does. Type, tags and query always combine, and the footer says what is shown (
3 Python files tagged loops) above the library's own count, which the sidebar and the header keep.LibraryService.resources()takeskinds=, andcore/library/filters.py'sLibraryFilterwords the footer line. - A long failure in the result strip is shown whole, and the strip grows to fit it. A failure now wraps to as many lines as it needs (up to six; past that it is cut between words, with the full text in the tooltip and behind Details), so a message naming a file path keeps its last sentence: "… config.toml is read-only. You can use it until you quit." Outcomes still wrap to two lines. The strip lays itself out as soon as its text changes, so no frame shows the new lines squeezed into the old height, and a path that wraps inside itself no longer counts as cut (no needless tooltip).
just installupdates an installed Staffroom.app in place (overwriting its files, removing ones the build no longer has, then re-signing and re-registering it) instead of deleting and recopying it, so Spotlight keeps listing the app rather than dropping it until it re-indexes.just releasere-pins the documented install line (git+https://github.com/ColePoppleton/Staffroom@vX.Y.Z) and the wheel filename in README.md and docs/ to the new version in the release commit, so the docs no longer go on installing the previous release. The pins now point at v0.7.0, and a test holds them equal to the package version.- Bugs no longer fills a find-the-bug sheet with versions that run exactly like the original: at the defaults two of the four
year9.pyvariants did. Each candidate is run while choosing and a silent one is swapped for the next bug in the seed's order, so the same seed still gives the same sheet. Silent bugs allowed (--silent N, default 0) keeps up to N for a read-the-code lesson; the key says silent and the pupil sheet marks each one this version may run the same: read the code. When fewer visible bugs exist than asked for, a warning and the result strip say so. The seed is now in the sheet's header. - A config home that cannot be written no longer turns Settings changes or Save as preset in Marks into a bug traceback.
Config.save()never raisesOSError: it logs one warning per session and returns what went wrong, the change still applies until you quit, Settings says "Settings could not be saved: is read-only. Changes last until you quit." under its title, and Marks says the preset could not be saved in the result strip.
v0.7.0
Every tool is laid out as a workbench: what you give it on the left, and on the right the result, with the PDF you will print shown page by page. The Library hands a file straight to a tool, Marks fits its whole report on one screen, and the sidebar groups the tools by a teacher's week. Quiz no longer overwrites one kind of sheet with another.
Update: quit Staffroom, run uv tool upgrade staffroom in Terminal, and open it again (Updating covers a copy installed from a release tag). New to Staffroom? Start with Install.
For contributors: the full list (14 changes)
Changed
- Worksheet, Parsons, Trace, Bugs, Fade and the quiz do-now show the PDF the run wrote instead of an ASCII rendering of it: Sheet and Key tabs with their page counts, the current page large and whole, thumbnails of every page of both down the side (drawn off the GUI thread, and only once they scroll into view, so a 17-page bugs sheet opens as fast as one page), Open PDF and Print… (the system print dialog, then the pages as shown). A run told to write Word only says so over the text of the sheet, never an empty page. The quiz's Kahoot and Forms text moves to a Paste text tab shown only for those formats; Bugs' table is What each bug does and Trace's Completed table. The command line's
--previewtext is unchanged. The vocabulary gainsPagePreview,Pages/pages_from,RunResult.pagesandTextView.optional; screenshots take--taband--option field=value. - The five code tools (Parsons, Trace, Bugs, Fade, Pseudocode) take their program in one input: a chip naming the file (its Library path, Change ▾ for From library or Browse) over the program itself, read-only, highlighted and numbered the way the sheets number it, instead of a Python file picker and an empty Or paste code box. Paste instead empties the view for a paste; Use a file goes back. It is not an editor: a file saved again in Thonny is shown again and the run reads it afresh. Trace's table and the Bugs key point at the program: click a row and its line lights up, click a line and its rows are selected. Pseudocode shows the source beside the translation (numbered too), the could-not-translate notes under it; Language under the file follows the guess the moment a file is chosen or code pasted, and To moves off it. The vocabulary gains
CodeSource(valueCodeValue(path, text), read bycore.codeinput),ResultsTable.line_column,TextView.codeandPanelSpec.suggest. - The Library hands a file to a tool. It is one page: the tree and search in one column (search results replace the tree while there is a query), the file beside it with its tags as chips (+ tag inline, × to remove, the note behind one link) and a use bar: Open for class with the lesson label typed inline (Enter or ⌘O opens it), then one button per tool that takes this kind of file (
.py→ Parsons, Trace, Bugs, Fade, Pseudocode;.md→ Quiz;.csv/.xlsx→ Marks), each opening the tool with the file already picked. Opening a file for class from the Library is 3 actions instead of 8 and runs Classroom's ownrun, so the original is never touched. The buttons come from each tool's main file input (core.panel.main_file_input), so a new tool appears with no library change;filter_ext(ResourcePicker, CodeSource) may name several extensions. Office files keep Open externally as the main action. A long resources-folder path no longer widens the window past its minimum. - A run's result is one strip along the top of the output pane: a tick or a cross, a short outcome ("10 questions · seed 42", or the failure in plain words), one button per file written (PDF Sheet, PDF Key, DOCX Sheet …; click opens it in its app, right-click shows it in Finder) and a Folder button. Warnings (marks, quiz, bugs, pseudocode) show as "3 warnings ▸" that opens the list. The per-panel Log card is gone: the run log sits behind a one-line Details ▸ footer, closed by default and remembered per tool for the session. The foot of the inputs is the Run button and where it writes; the truncated status line and the second "Writes to" label are gone. Tools say what they made with
RunResult.outcome, may name a file's button withRunResult.labels, and raise warnings withctx.warn();staffroom --expandopens the warnings for a screenshot. - Every tool is now a workbench: the inputs in a 390 px column on the left with the run button pinned at its foot (⌘↵ runs it from anywhere in the window), the results filling the right, tabbed when a tool has more than one (Trace: Completed trace table · Preview). Lists to act on and notes sit under the main result; inputs are hairline-separated groups instead of a card each. Nothing scrolls on its own any more and the inputs stay beside the result, so the first result is in view after a run in 9 of 9 tools at 1240×780 (2 of 9 before). A panel can mark an output
place="main"or"below"(core.panel); the header loses the version chip. - The sidebar and the app's identity are redesigned. The brand row (mark, Staffroom in Fraunces, a settings gear), a library search field, then the places grouped by a teacher's week: Lessons (Library, Classroom), Sheets & quizzes (Worksheet, Quiz), From a program (Parsons, Trace, Bugs, Fade, Pseudocode), After a test (Marks). One line per tool with a monochrome glyph instead of a red letter badge and a truncated description (the description is the tooltip). The Library is a place in the sidebar, not a Tools/Resources mode switch, with its tree and search in their own column. The red accent marks only where you are, primary buttons, links and focus. The footer has the version with up to date or an update link, and Activity log. The theme switch moves to Settings only (plus ⇧⌘L). ⌘1–⌘9 follow the new order: Classroom, Worksheet, Quiz, Parsons, Trace, Bugs, Fade, Pseudocode, Marks (the Library is ⌘K). Group and glyph are optional plugin data (
group,glyph, read likeorder); a tool without them is listed under Other. The app now uses the brand type, bundled under the SIL OFL with their licences: Source Sans 3 for text, Fraunces for titles, IBM Plex Mono for code and logs. - The docs home page leads with what a teacher gets: a headline, the pinned two-line install, and a fan of real first pages (worksheet, trace table, Parsons) above the fold at 1240×780 in both colour schemes; a three-column privacy strip (stored / never stored / check it yourself) whose every claim is tested against the Privacy page; and a What comes out gallery with one real output per tool. The pages are rendered from the example files by
just screenshots. The site nav puts the teachers' pages first (Install, Tools, Privacy, Guides, as header tabs) and puts the contributor pages in one Contributing section at the end. - Marks is a one-screen report: after Analyse, four headline tiles (scripts, mean %, median grade with how many reached grade 4, the questions to reteach first), the grade chart with counts and percentages under the bars beside one question table sorted hardest first with an inline facility bar and the reteach rows tagged, and the per-script grades folded under "view only, never saved". 5.2 screens → 0.87 at 1240×780 (20 questions: 1.54). The separate distribution table (now Table on the chart) and "Worst questions" card are gone; the saved CSVs are unchanged and still aggregates only. Inputs: the file as a chip with what was found in it instead of an 11-row preview, and the boundaries as a 5 × 2 grid with the preset and a % / raw switch. New in the vocabulary and kit for any tool:
StatTiles,BarChart,ResultsTablebars, tags and folding,main_layout="row", compactEditableTableandTablePreview,Choice,FilePicker(chip=True). The CLI prints the same headline; the saved chart gains the percentages too. - CI and the release workflow run on macOS again: the repository is public, so macOS runners are free, and the layout and packaging tests are written for the platform Staffroom targets.
Fixed
-
staffroom --settingsno longer leaves the last tool highlighted beside the Settings page: every route to a page now sets the sidebar from what is shown. -
Classroom's Past sessions no longer lists the tools' shared output folder. A worksheet made with no input of its own goes to
<sessions folder>/outputs/worksheet/, and it showed up as a lesson on dayoutputswith Diff and Promote buttons. Only real sessions are listed now: a date-named day folder holding lesson folders with a.origin.json(classroom.logic.is_session_folder); stray files and hand-made folders are left out too. -
Quiz no longer overwrites one kind of sheet with another. A retrieval run is named for its date,
question_bank_retrieval_2026-10-09_donow_s1.pdf, and every export carries its seed,question_bank_donow_s1.pdf,question_bank_kahoot_s1.xlsx,question_bank_forms_s1.txt, so a do-now and the retrieval starter made after it both stay in the folder. A run that replaces a file of the same name still overwrites it, but the log and the summary now name it (replaced question_bank_donow_s1.pdf). -
Classroom's run bar now says where Open for class really puts the copy, Copies to ~/TeachingSessions//, following the label as it is typed, and its Open sessions folder link opens that folder (created on demand) instead of an output folder the copy never goes to. A tool can name its own destination with
PanelSpec.writes_to(core.panel.WritesTo); every other tool still shows Writes to its output folder. A row action such as Promote no longer moves the run bar's folder. -
The docs home page, the Install guide and the README now install from GitHub, pinned to the latest release: `uv tool install --python 3....
v0.6.0
Trace has a Year 9 preset that leaves out functions and their variables, and every trace sheet names its preset. Pseudocode works out which language it was given, Worksheet sets Boolean and truth-table questions that read like a textbook, and Marks analyses a whole year group in under a second. Staffroom keeps working when its settings folder cannot be written.
Update: quit Staffroom, run uv tool upgrade staffroom in Terminal, and open it again (Updating covers a copy installed from a release tag). New to Staffroom? Start with Install.
For contributors: the full list (12 changes)
Added
- Trace has a Preset dropdown with Full trace (the default, as before) and Year 9: the Year 9 preset turns on the new Top-level variables only option (
--top-level-onlyon the CLI), which leaves out the lines run inside functions and their locals, so the sheet has no Scope column and only the program's own variables. Every trace sheet now names its preset in the header (Full trace, Year 9 or Custom) so a teacher can tell which one they handed out. Presets for an options form are part of the shared panel vocabulary (OptionsForm.presets,core.panel.preset) and widget kit, so any tool can offer them. - The launcher shows the running version: the sidebar header reads
v0.5.0 · 9 tools, and Settings › Updates saysRunning Staffroom 0.5.0, adding the branch and short commit off a release tag (0.5.0 (dev, a1b2c3d)).packaging/make_launcher.pywrites the package version into the bundle'sCFBundleShortVersionStringandCFBundleVersion, so Finder's Get Info matches afterjust install.
Changed
classroompromote compares the copy with the original and with the latest promoted version before writing: an unchanged copy makes no new file and the message saysAlready promoted as year9_v2.py(or that it matches the original). The CLI exits 0 and prints no path when nothing was written.quiznames any taught-log column other thandateandtopicin the run log (ignored column 'room' — the log is date and topic only), by header only; the column's contents are never read or shown.
Fixed
quizreads the taught log throughcore.csvio.read_tablelike every other table, so an identifier column (name,class, …) is dropped before the tool sees it, with the usual dropped-column warning and a run-log line by header only. It used to parse the file as raw text, bypassing the privacy filter. A new boundary test fails if any tool reads a.csv/.xlsxwithoutcore.csvio(rawopen/read_textof a table path,csv.reader,openpyxl.load_workbook, or csvio's unfilteredread_csv/read_xlsx).- The launcher opens when the config home cannot be written. It used to die in
LibraryDBwithsqlite3.OperationalError: unable to open database file. The library now opens the last index read-only, or an empty in-memory database when there is none, and says Resource Library unavailable: cannot write once in the log, in the Resources sidebar and header, and instaff library status(exit 0). Re-index is disabled,staff library indexandsearchexit 1 with that line, and every tool still runs. The window's own settings (last tool, sidebar mode, theme) last for the session with one warning instead of a traceback per click. staffno longer dies with aPermissionErrortraceback when the config home (~/.config/staffroom/orSTAFFROOM_HOME) cannot be written.setup_loggingused to createlogs/and open the log file with no fallback, before any command ran; it now carries on with stderr alone and prints one warning line naming the file it could not open. The launcher takes the same path, so its startup gets the same fallback.worksheetrefuses a count outside 1–60 with one sentence ("Questions must be between 1 and 60 (you asked for 0).") instead of writing an empty sheet and key; the CLI and the panel share the limits. Boolean simplification questions are now built from textbook forms only (absorption, the distributive pair, the redundancy formA AND (NOT A OR B), De Morgan over two literals) within a size budget per difficulty, so a hard three-step question reads(A OR (A AND C)) AND NOT (A AND NOT B)rather than a form nested three deep; each key practises more than one law and a sheet never repeats a question. GCSE truth tables get one shape per difficulty (one gate, two gates, three gates or aNOTover a bracket), so medium and hard sheets no longer look the same. Keys stay reproducible from the printed seed.staff usagenow counts CLI runs as well as launcher runs: everystaff <tool> <command>that finishes without aToolErroris recorded by the one wrapper incli.py, so no tool needs its own call. The total stays one number per tool, with the launcher's and the CLI's shares shown beside it; older files (launcher-only) need no migration. Nothing is recorded when the config isread_onlyor the home folder cannot be written, and a failed write never fails the command.- Pseudocode works out the input language from the code itself when
--fromis not given, instead of calling every non-.pyfile OCR ERL:defand:blocks mean Python,endif/next/thenmean OCR,←/OUTPUT/USERINPUTmean AQA, with the file name as the tie-breaker. The log and summary say what was decided ("Treated input as AQA pseudocode (guessed from the code)"); code with nothing to go on, or that already looks like the target, stops with a message naming the--fromto pass. The panel's single Direction is now From (defaultguess) and To. marksgrades a whole cohort in well under a second:discrimination()computed every script's total once per comparison, which took a minute for 3,000 rows. Fixed quietly in 0.4.0; now measured and guarded by tests (3,000 × 30 marks analysed in 0.15 s).- The library's file counts agree everywhere. The sidebar said "563 files" and the Resources header "587 files indexed" because one left out hidden cruft and the other did not; a pending exclusion widened the gap. Both now show the one line
LibraryService.counts()produces,563 files (24 hidden) · 3 name only, with the hidden shown as a subset instead of silently dropped, andstaff library statusand the index summary print the same tally in long form (587 indexed: 563 shown, 24 hidden, 2 cloud-only, 3 name only). The definition is in the launcher guide.
v0.5.0
Fade no longer makes duplicate versions, and Quiz's Kahoot export says exactly which questions it wrote and why it skipped any. The launcher no longer crashes while the Library is being indexed.
Update: quit Staffroom, run uv tool upgrade staffroom in Terminal, and open it again (Updating covers a copy installed from a release tag). New to Staffroom? Start with Install.
For contributors: the full list (6 changes)
Fixed
- Checked every
QListWidgetItemthe shell reaches for the stale-wrapper hazard behind the launcher crash below: the tool list, the string-list editor and the library result lists are safe as they stand, because PySide invalidates row wrappers onQListWidget.clear()and with the list, anditem(i)wrappers never outlive the call that made them. Each site now says why, andtests/shell/test_lifetime.pypins the wrapper counts for all three. - Fade no longer makes duplicate or blank-free versions when asked for more versions than there are fadeable lines: versions are capped at the fadeable-line count with a log note, so every version has at least one blank and strictly more than the one before. A file that is not valid Python is refused with the same "That is not valid Python: … (line n)" message as the other tools. Range mistakes say what is wrong: lines past the end of the file or below 1, ranges typed without choosing the
rangesorder, and listed lines that are headers, comments or blank (skipped with a log note, or an explanation when nothing is left to fade). staff updateand Settings › Updates compare the checkout with the released branch (origin/main, orrelease_branchin config) whatever branch it is on, and name the newest release tag when one is ahead. A checkout on another branch ("on dev; releases are on main"), with no upstream, or detached gets one plain line instead of git's "ambiguous argument" error; the release is reported but never pulled from there, and the update never switches branch.- Quiz's Kahoot export reports what it actually wrote: the summary and the chosen-questions table describe the rows in the file ("3 of 5 written; 2 short answers skipped: Q5, Q7"), every skipped question has its reason in the log, and an export that would be empty stops with a message instead of writing a file. Short-answer distractors are now borrowed from the whole bank rather than only the chosen questions, nearest first (same topic tag, then the same spec section, then anywhere), and the log names the source question and topic whenever one had to come from outside the topic.
- The launcher no longer crashes or aborts around a running library index. The Resources tree is built through model indexes instead of
QStandardItemobjects, whose Python wrappers outlived the items and made the next Qt object at that address come back as the wrong type (the flaky'QStandardItem' object has no attribute 'selectionChanged'on CI). Closing the window, a--screenshotrun and the test fixtures now stop a running index at its next file and wait for every worker thread (MainWindow.wait_for_workers), so Qt never destroys a runningQThread; an index stopped early keeps what it has done and finishes on the next launch.ActionTableignores a refresh that arrives after its view is gone.
Changed
- Docs screenshots redone after the sidebar reorder and the first-run card: every image the docs reference shows the workflow-ordered sidebar without
hello;just screenshotsnow runsscripts/screenshots.sh, which renders the whole set offscreen from a throwawaySTAFFROOM_HOMEand the invented fixture resources inscripts/screenshots/resources/. Ten unreferenced PNGs are gone; the first-run card and the Marks warnings run are now shown in the guide.
v0.4.0
The first time Staffroom opens it asks for your resources folder, and you can keep folders out of the Library or have files that look like pupil details indexed by name only. Parsons and Bugs sheets print on half as many pages, and a mistake in an input file is one plain sentence instead of an error dump. Worksheet's truth tables never set a question with a trivial answer, and Marks warns about marks it cannot trust.
Update: quit Staffroom, run uv tool upgrade staffroom in Terminal, and open it again (Updating covers a copy installed from a release tag). New to Staffroom? Start with Install.
For contributors: the full list (14 changes)
Added
- First run asks for the resources folder. With no folder set, the launcher opens on one card, "Choose your resources folder": Choose… opens a folder dialog (at the home folder; the app never suggests a folder, cloud or otherwise), the sessions-folder default is shown as text, and a sentence points at Settings and the privacy guide's "What the Resource Library stores". Choosing a folder saves it, runs the first index with progress on the card and lands on Classroom; "Not now" lands there too and leaves the "No folder chosen: set it in Settings" hint in the Resources sidebar.
FirstRunCardjoins the widget kit;staffroom --first-runshows the card for screenshots.staff library index/searchwith no folder set now say where to set it (the Settings page and theresources_rootkey) instead of "resources root not found: ". - Library privacy: an exclusion list for the resources folder (Settings,
staff library exclude, or<root>/.staffroom/ignore) whose paths are neither indexed nor listed and whose changes re-index; files whose text looks like pupil details (candidate number, surname, UPN, date of birth next to a value) are indexed by name only, counted in the index summary, the sidebar status andstaff library status, and flagged in the preview; Settings anddocs/guide/privacy.mdstate what is indexed, where the database lives, that the folder is only read, and how to delete the index.StringListEditorjoins the widget kit;staffroom --settingsopens Settings for screenshots. examples/marks_messy.csv: a fake marks file on which everymarkswarning fires, for trying the tool and for the tests.
Changed
- Parsons and bugs sheets print on fewer pages: Parsons blocks are numbered cut-out boxes, two across, with dashed cut lines and the answer grid on the same page (
year9.py, 15 blocks: 2 pages → 1); the bugs sheet puts two versions on a page (4 versions: 4 pages → 2).core.exportgainsBoxedBlocksandAnswerGridfor every tool, rendered to docx, PDF and text;examples/year9.pyis the program the page-count tests measure. marks: the saved distribution chart is always print-friendly: white background and the light palette's ink, whatevergeneral.themeis. The panel shows the same file.- The sidebar lists tools in workflow order (classroom, marks, worksheet, parsons, quiz, trace, bugs, fade, pseudocode) instead of A–Z, and ⌘1–⌘9 follow it, so a fresh install opens on Classroom and ⌘1 is Classroom.
hello, the developer reference tool, is hidden from the launcher: it keeps its CLI, its tests and its place as thestaff newmodel, andstaff listshows it marked[hidden]. Plugins may declare optionalorderandhiddenattributes (docs/adding-a-tool.md); tools without them need no change.just screenshotsnow renders the marks tool. - Input mistakes are one-line messages for the teacher, never tracebacks.
read_tableraisesToolErrorfor the wrong kind of file, a missing file, a CSV that is really a binary file or a damaged workbook, naming the file and what is accepted, so every tool, the CLI and the launcher show the sentence;code_from_inputsdoes the same for code files; every tool CLI command turns aToolErrorinto a red line and exit 1 without per-commandtryblocks.fade --ranges abc,marks --max 4,6,xand the quiz "as of" date say what was expected instead ofinvalid literal for int(). - Outputs never land in the code checkout or the shell's current directory. With no output folder set and no input file, tools write to
<sessions folder>/outputs/<tool>/(created on first write); the run bar names the folder before Run and "Open output folder" works at any time; Settings explains the default. Screenshot runs (just screenshots) write to a throwaway folder, sogit statusstays clean. - A docs page, Running pupil code, that says what a trace / bugs run is limited to and what it does not stop (
os.system, file writes, computed import names); the Trace, Bugs and Fade panels point to it. - Docs for a teacher who is not the owner: the Privacy page lists the identifier filter's header words and what passes through (per-pupil flag columns such as SEN/PP/EAL reach the preview and are never saved), what the run log and the app log file hold and where the file is, the full table of what is stored where (including
.origin.json), and how to delete everything; a new Outputs page gives the output-folder rule and every tool's file names; a new Glossary covers facility, discrimination, seed, ERL, Parsons problem, faded example, do-now, retrieval windows and the rest; the launcher page shows the workflow-order shortcuts and the tool pages name their files and link across.
Fixed
- Worksheet truth tables never set a degenerate question: every input the table lists is used, no gate is fed the same input twice, and Q is neither constant nor just one input. Gates follow the exam board (OCR J277: AND, OR, NOT; AQA 8525 adds XOR); a new Level option,
a_level, adds XOR and, at hard only, NAND and NOR. Boolean simplification wraps one letter at a time so questions read like a textbook, no longer setsX AND X,NOT NOT Xor0/1unless the new Boolean laws option isidentities, and every key step is written in the question's own letters (absorption: B AND (B OR NOT C) = B, leaving A AND B). The header states the gate set or the law family so a sheet is self-describing, and an A-level sheet carriesalevelin its file name. trace: a program that callsinput()with the Inputs box empty (or short) stops with "<file>.pyasked for input but the Inputs box is empty: add one line per input() call" and writes nothing, instead of a green status and a one-row sheet. The tracer records theEOFErrorthatinput()itself raised, so a program that catches the EOF, or raises its own, is not mistaken for it. Any other runtime error still produces the sheet, and the status line now says "ended with " as the log did.marksfinds theMAXrow of a markbook export even when the flag sits in the name column:core.csvio.read_table(path, flag=...)decides which rows carry the word on the raw file and passes only the row indices on (Table.flagged_rows); the identifier filter itself is unchanged and still unconditional. The tool now warns, in the CLI and the panel log, on a mark above its max (question, count, highest), a max of 0, blank or non-numeric cells (ab), and grade boundaries above the paper total (a percent preset applied as raw marks). Blank cells count as 0 in a script's total but are left out of facility and discrimination instead of dragging them down, and the distribution gains an "Incomplete scripts" row saying how many scripts had one. The run still succeeds; the summary says how many warnings to read.- The runner caps captured stdout and stderr at 1 MB each and drains the rest, so a
while True: print(i)no longer captures hundreds of megabytes before the timeout kills it; capped output ends with[output truncated at 1024 KB]and the trace and bugs keys say so. The tracer caps the program's output inside the run too. The import check now also catches__import__("socket")andimportlib.import_module("socket")with a literal name.
v0.3.0
Teaching Tools is now called Staffroom, with a new look and icon; your settings and tags come across the first time it opens. The launcher app now opens properly from Finder on Apple silicon Macs.
Update: quit Staffroom, run uv tool upgrade staffroom in Terminal, and open it again (Updating covers a copy installed from a release tag). New to Staffroom? Start with Install.
For contributors: the full list (5 changes)
Changed
- Renamed to Staffroom. The package is
staffroom; the commands arestaff(CLI) andstaffroom(launcher), withttandtt-guikept as aliases for one release. Config moves to~/.config/staffroom/and is copied from~/.config/teaching-tools/on first run (the old folder is left alone); resource tags live in<root>/.staffroom/tags.jsonand an old.teaching-toolssidecar is still read. Environment variables areSTAFFROOM_HOMEandSTAFFROOM_BOOKLET_DIR. - New brand: the door-ajar mark, a manila / navy ink / red-pen colour scheme in both the dark and the light theme, and an icon, icns and favicon rendered from the SVG with QtSvg (
scripts/make_icon.py). The docs site uses the mark, the scheme and Fraunces / Source Sans 3. - The thin launcher is
Staffroom.app(uk.staffroom.launcher, executablestaffroom). The repository and docs URLs are unchanged until the GitHub repo is renamed. - The repository is now github.com/ColePoppleton/Staffroom and the docs site is colepoppleton.github.io/Staffroom/ (the old URLs redirect).
Fixed
- The thin launcher no longer runs under Rosetta when opened from Finder (
LSRequiresNativeExecution,arch -arm64), which made the arm64 wheels fail to load, left only three tools discovered and took a minute to start. The bundle is ad-hoc signed (Spotlight ignores an unsigned one), the build indist/is unregistered and the installed copy registered with Launch Services and Spotlight, and the app icon keeps the macOS inset instead of drawing oversized.
v0.2.0
The app gets a documentation website with a page for every tool, and numbered releases that install with one command. Nothing is set up for one particular teacher any more: the resources folder stays empty until you choose it in Settings.
Update: quit Staffroom, run uv tool upgrade staffroom in Terminal, and open it again (Updating covers a copy installed from a release tag). New to Staffroom? Start with Install.
For contributors: the full list (5 changes)
Added
- Documentation site (MkDocs Material on GitHub Pages): install, launcher, privacy, updating, one page per tool, file formats.
Changed
- Personal references generalised; the resources folder is empty until set in Settings; the booklet round-trip test reads
TT_BOOKLET_DIR. - Thin launcher app (
just install) and self-update from the git remote. - Semantic versioning, Keep-a-Changelog, tag-driven GitHub Releases with a wheel and sdist (
.github/workflows/release.yml,scripts/release.py,just release).uv tool installis the canonical install. - MIT licence.