Facts about how you work that a session must not re-derive, each dated from when it was settled. If one of these has gone stale, it is worth saying so — every session reads them before it reads anything else.
Keyboard
A non-Romanian layout with Option dead keys. This produces ǎ U+01CE, ş U+015F, ţ U+0163 and ś U+015B — visually equivalent look-alikes for ă ș ț. Normalize silently, score as fully correct, never flag or tally. A knowing choice, not a language fact; the hard rule is in ../../CLAUDE.md. A missing diacritic is a different thing and remains a real error: adresa for adresă is a different word. The list is open, not closed — ś U+015B (s-acute, for ș) turned up on 2026-08-09 in faceśti and numeśti, four codepoints in, and š U+0161 (s-caron, also for ș) on 2026-08-10 in ši, five in. Judge by the principle, not by the enumeration: a character that is a dead-key neighbour of the Romanian letter is the input method; a character that is simply absent is an error. Two sessions running have found a new one simply by looking, which is the strongest available evidence that the enumeration will never be complete and must not be treated as the rule.
The learner declares typos, and the declaration settles it
2026-08-09
Told that uncrainean and stundent carried an inserted n, the learner said: "both times just typos, I didn't mean to add that." That ends the question — drop them from the marking, the tally and the ledger notes, and do not re-derive them from the text later. This is the same principle as the keyboard rule above, one level up: the learner is the authority on what their hands did, and a session cannot tell a motor slip from a memory failure by looking at the output. Ask when a pattern repeats and looks mechanical; accept the answer.
Ask one typo question per message, or number them
2026-08-12
The declaration rule above is load-bearing — a declared slip leaves the marking, the tally and the ledger — so the question that invokes it must be impossible to answer ambiguously. A session asked about two items in one message (piciore, objecte); the reply was two lines, both labelled piciore, and the intended mapping was recoverable only from the order plus a same-word contradiction. It happened to be read correctly and the marking would have changed if it had not. Numbering costs nothing.
Flags their own uncertainty inline, and volunteers a second form beside a correct one
2026-08-19
Two shapes in one drill: "Ai cane? (maybe au, not sure)", and "o oglindă, ună" — where the first answer was right and ună is not a form at all. Both are output and both get read under the grade-everything rule, but they are not the same thing. An inline "not sure" is a confidence report: record it beside the mark, because a right answer the learner distrusts and a right answer they own are different states and only one of them is finished. A volunteered second form is an answer: say briefly that it is wrong, and do not let it change the mark on the item they actually answered. Neither is a request to be re-asked.
Vowel-pair order is mixed — ask, never assume
2026-08-12
Four sightings are on record with the right vowels in the wrong order: saere for seara, dimeniața for dimineața, ucarini for ucrainean, frumaos for frumoas(ă). Asked whether these are finger slips or the real thing, the learner answered "mixed, depends on the word". So this class gets no blanket treatment in either direction: a session asks about the item in front of it, drops a declared slip entirely, and codes a declared-real one as ORTH-VOW (../mechanics/error_taxonomy.md). Before this answer the whole class was uncodable and therefore absent from the tally.
Many parallel sessions, always returning cold
Placement statements, session tab names, and the Next pointer are one requirement wearing three hats. Assume nothing carries over from a previous conversation.
Two study sessions in one day is a thing that happens
2026-08-12
SES-014
SES-014 cleared the whole backlog in ~90 minutes, and SES-015 opened a few hours later on the same date. Nothing in the scheduling design expects this: tier 1 has a zero-day interval, so queue.mjs reported 47 items "due" that had all been answered that morning, and the previous session's Next pointer carried a date-based embargo ("nothing before 2026-08-13") that the queue cannot see. A session must check the last column, not just the due count, before treating the queue as work. One occurrence, recorded because the second session had to derive the whole policy from scratch mid-flow — which is exactly what this file exists to prevent.
Seventy-seven answers in one sitting was fine, and they said so unprompted
2026-08-19
A five-block queue drill was budgeted as "roughly fifty items"; multi-part questions made that 77 answers, and the session reported the gap at close-out as an overrun. The learner's reply: "to my opinion the volume was fine, actually." Take that as the calibration, not the number that was agreed. This is the only capacity reading on record for a five-block sitting, and it matters in one direction specifically: with a backlog over a hundred items, a session that quietly shrinks the block out of caution is costing real progress. What needs fixing is the unit a budget is agreed in — items against answers — not the size.
Preservation beats economy
No size limit on generated artifacts — audio embedded in every visual, nothing stripped to save bytes. Stated 2026-07-31.
Test items name the form. No personas
2026-08-09
"I don't like all those personas, this is simply distracting — phrasing the form or simply stating it in Romanian is much better." Write a avea · dumneavoastră or Ce mai ___ ? · tu, not "asked of your landlord". Invent a situation only when the situation is itself the thing being tested.
Being asked again is how the learner remembers
2026-08-09
Re-asking something whose answer was published earlier in the session is wanted, not a flaw: "it makes me remember stuff when I am being asked about it." The answer-leak rule is therefore scoped to a single message. What a re-ask may never do is carry a score or move a tier — ../mechanics/session_format.md → Re-exposure.
Marking goes in a table first, prose after
2026-08-17
"Your assessments of my answers should always come in tables first, paragraphs with details after that are welcome." One row per item — what was asked, what they wrote, the target, a short label — including withdrawn and unanswered items, so the row count matches what was asked. The diagnosis, the pattern and the teaching go below the table. The learner reads a marked set to answer "how did I do" before anything else; prose-first marking makes them hunt for their own items inside the explanation. Applies to unscored practice rounds and re-exposure, not only to graded sets.
Plain language at the moments that matter
now a mechanic, not a fact about this learner: ../mechanics/narration.md owns it (§ 3, and § 2 for the commands and paths that were never worth showing at all). It sat here as a profile bullet until 2026-08-17, which put a rule every session obeys in the one file no machinery change could reach. What is genuinely specific to this learner stays here: they audit the narration — see the next bullet — so a number said plainly is also a number they will check.
Audits the workspace mid-exercise
The learner has caught untaught material being scored, a coverage label that was false, and a script that had never run. Treat a "have we actually studied this?" question as reliable evidence that something upstream is wrong, not as a learner doubt to reassure.
Their bug reports are diagnostic, and the detail they volunteer is the useful one
2026-08-12
Told a page's audio was silent, the session's first hypothesis was that the learner was looking at the wrong copy — the chat preview rather than the real page. The learner's reply closed that off in one line and supplied the deciding fact: "none work, hosted or local … I click on sound button and it doesn't even change state." A button that does not change state is not an audio fault at all, and that single observation localised a duplicated click handler that the audio-wiring test could not see. So: take the reported symptom at face value and follow it, rather than first explaining why the learner might be looking in the wrong place. This is the same rule as the line above, one domain over — it applies to the tooling, not only to the teaching.
Prefers the two-layer reveal for practice surfaces
2026-08-10
"This page has an awesome mechanism to practice material with batch reveal filter + per element reveal … I want to have it when it is meaningful for drilling/repeating/refining material." Said of the U01 deck. The shape: a page-wide mode filter that conceals one whole side (RO→EN / EN→RO), plus a per-item reveal inside it. Reference implementation: scripts/deck.mjs → work/visuals/deck.html, which also fixes the old deck's leak (grammar rows and notes conceal with the answer). Any drill or repair sheet that quizzes material should use this shape; teach pages keep their inline guided attempts.
Prefers loops to single passes
SES-007
Given the choice, the learner asks for test → analysis → correction → retest rather than one pass and a score. The preference is real; the claim that it outperformed single-pass shapes is retracted (audited 2026-08-09) — SES-007's 43% → 86% re-asked its own questions after publishing the key. What the loop demonstrably delivers is its diagnosis step; see ../mechanics/session_format.md → the repair loop.
Audits the exercise, not just the material
On 2026-08-09 the learner read a 16-item drill and said "almost all of the answers were obvious from the other questions in the same exercise" — which was true of 14 of them, and had been true of earlier sessions nobody checked. Sessions here get inspected as designs, not only as content.
Audits the plan, not only the material and the exercise
2026-08-15
Told at close-out that the next lesson was the present tense, the learner asked: "do you mean that next lesson will be this topic? I thought that it will be Articolul hotărât part 2, where we will discuss cases when it is used." They were right, and the cause was structural: U05's curriculum bullet named article usage and topics.md carried no row for it, so the aspect was invisible to routing — every Placement beat and every Next pointer is derived from that map. The session had promised the topic on its own teaching page and then pointed elsewhere. This is the third domain the learner audits, after the material and the exercise design, and it is the one the workspace has the least defence against: a missing row produces silence, not a wrong answer. Treat "I thought the next session was X" as a routing bug report, the same way a "have we actually studied this?" is treated as a coverage bug report.
Asks for forward orientation, not just current position
2026-08-15
Immediately after, the learner asked to be oriented across "the next several sessions". The placement statement answers where am I; it does not answer what is the sequence and why. Worth having the next few blocks and their dependencies ready at close-out, not only the single Next pointer.