Pipelines across domains and roles · each journey lists its cast: learner / staff / two browsers · app under test: https://app.sprinklejelly.com
Before you run these
A journey is a pipeline: it starts in one place, crosses features — and usually roles — and ends somewhere else, with the product's promises checked at each hand-off. Page-level behaviour (a button's states, a list's paging, a form's validation) is covered in docs 01–05; a journey references those case IDs where a step is already covered page-deep, and only asserts what the hand-off must deliver.
Anatomy
Cast — who must be signed in where · Steps — the pipeline, with the expected hand-off inside each step · Expected — at every step — the invariants that hold throughout · Also try — edge legs worth taking while staged
Tags on the cast line
🖥🖥 two browsers needs two signed-in people (or learner + staff) at once — use different accounts in different browsers or a normal + private window. Super Admin needs sprinklejelly/yashmini. destructive — coordinate changes shared state other testers see; announce it in the team channel first.
The one-account trap
One web session per person — newest wins. Every 🖥🖥 journey uses different accounts, except TC-JRN-42, which deliberately signs the same account in twice. Sign back in between legs if the older browser was displaced.
Timing
The product day rolls at 09:00 IST. Journeys marked "timing" wait for real clocks — run them when you can keep a browser open or across two sittings, and mark N/A with a note rather than faking a wait you did not do.
Generated assistance
GENERATED_ASSISTANCE=false on this deployment: Credits and AI help legs are absence checks — verifying nothing appears is the test (TC-JRN-33).
Reporting
Report by journey ID (e.g. TC-JRN-19) and name the leg that failed ("step 5: learner never received the notice").
The rules that judge every leg
Unavailable is not empty · unknown is not zero · nothing claims it saved when it didn't · platform failures never look like the learner's failure · hidden material stays hidden · not-found is privacy-safe · once means once · pending is named, not faked · people-facing text says "Wizly Learning", never "Labs". The full table is in index.html §8 — any journey fails on them even when its own steps pass.
A · First-day learner
What a brand-new account experiences, in order: the main-site handoff, the one-time orientation, the first solve and all it produces, the first Daily, the first lesson — and coming back the next day. These are the journeys every other journey quietly assumes.
TC-JRN-01First sign-in: main site → handoff → orientation → HomeP1
Cast
A learner account that has never signed in to Labs (the orientation runs once per account — if every tester account has already been in, re-run the sign-in/orientation legs anyway and mark the "only once" expectations from your first run's notes).
Steps
Fully signed out (clear cookies or a private window), open https://app.sprinklejelly.com → you land on /handoff saying Signing you in and are sent to the WordPress main site — once, in that tab.
Sign in on the main site as the learner → you are returned to the app with a session and land on Home (/). No sign-in or sign-up form exists anywhere inside the app.
On the first arrival, WizBit's orientation dialog opens on Home: an introduction, then exactly four landmarks lit one at a time with the rest of the page dimmed — the Continue card, the primary navigation, where help is, and Settings — then a theme question.
Pick Halo at the theme question → it previews live → answer the closing presentation question → the orientation closes and Home is fully usable.
Home greets by the main-site display name (a time-of-day greeting in India time when there is none), with the page's regions: Continue, today's Daily, the suggestion or Tests to take, your record, Notes and news.
Reload Home, open a second tab, sign in again → the orientation never opens again on its own.
Expected — at every step
The handoff goes to the main site once per tab; a tab that comes back still unsigned is offered Try again, not sent round in a loop.
Skip is available from the orientation's first frame, before the introduction.
The theme pick is previewed live and saved to the account as the starting theme; a device with no saved appearance starts from it. Skipping records no choice and keeps Prism.
A skipped or finished orientation is remembered on the account — it never reopens on another tab, after another sign-in or on another device. Replay lives at Settings → Companion (/profile/settings/companion).
Nothing in the flow asks for a password inside Labs, and no demo panel or feature flag appears.
Also try
Interrupt the handoff (close the tab mid-trip, or block the main site briefly) → return → We could not finish signing you in with Try again — it says this is not a membership problem.
Add ?dev-role=admin to the address → nothing happens; dev-role parameters are inert in this deployment.
Replay the orientation from Settings → Companion → it runs on Home and leaves your saved preferences unchanged unless you answer its closing question.
Orientation page-deep checks: doc 03 (WizBit section) and TC-PLT-… platform cases in doc 03.
TC-JRN-02First accepted solve, and everything one acceptance producesP1
Cast
A learner with at least one unsolved easy challenge (showcase: "Running Total of Marks", "Balanced Brackets", "Climbing the Stairs").
Steps
/challenges → open an easy challenge → note its standing Not started and the XP shown beside it (30 XP for easy).
Choose a language, write a deliberately wrong program → Run → the visible examples fail, with output, errors and case results clearly separated. Run costs nothing and creates no submission.
Submit → the same wrong code is checked against every case including hidden ones → verdict is not accepted → standing becomes Tried on the page and on the catalogue card.
Fix the program → Run passes the examples → Submit → Accepted.
Check the wake the acceptance leaves: the challenge reads Solved; /solutions holds a new entry under Challenges; the accepted result offers Read the editorial (where authored), Next challenge and Open it in My Solutions; the editorial tab is now unlocked.
/xp-history → newest entry is the award with its source and amount (30 XP); the shell's level pill re-reads to the new total.
/inbox → if the award crossed a level boundary (250 XP to Level 2, 1,000 to Level 3) there is exactly one Level Ups notice; an ordinary solve sends no inbox message of its own.
Expected — at every step
Acceptance, standing, saved source and XP are one fact — the page, the catalogue, Solutions and XP history never disagree about whether the solve happened.
Hidden test cases stay pass/fail counts only — never inputs, expected outputs or your output.
Reopening the solved challenge says it is solved before you press a control and that re-solving is free practice — no second award.
A wrong or failed submission is the learner's result; a refused execution or grading outage is named as the platform's and changes nothing.
Also try
Double-click Submit — one submission, one result.
Close the tab the instant Submit is pressed → reopen: the recorded outcome stands; work that never actually ran is not invented.
Solve the same challenge in a second offered language → a second Solutions entry, no second XP, standing still one Solved.
TC-JRN-03First Daily, and the product day that follows itP1
Cast
A learner; today's Daily is published (the showcase seeds one per date). Two sittings, one product day apart, or a staged equivalent.
Steps
Home → the Daily card → today's Daily opens (/daily-challenges), showing difficulty, base reward and bonus where present, languages, Solve rate and when it closes: Open until 09:00 IST tomorrow (after 09:00) or …this morning (before 09:00).
Solve it before the product day ends → accepted → the streak reads 1; today's calendar cell reads Solved; XP history shows the difficulty award plus the Daily's authored bonus (40 XP where the default applies).
Come back after the next 09:00 IST → the streak still reads 1 and today's unsolved date shows At risk today.
Solve that day's Daily → streak reads 2; the "At risk" warning clears.
Expected — at every step
The product day runs 09:00 → 09:00 IST on the platform's clock; the device clock never decides the date.
On-time is decided by the platform's confirmed receipt of a valid submission on the scheduled date — a solve received in time but graded later still counts.
The strict on-time rule and the 09:00 boundary are explained in place before the learner can lose a first streak.
A pending grade is named as awaiting its result — never a false break, a zero or a fake pass.
Also try
/daily-challenges/past → solve an old date → the full award pays (catch-up), but no streak repair for any missed date — TC-JRN-24 covers the missed-day leg.
Open a future date's address → no title, difficulty or content is disclosed ahead of its 09:00.
TC-JRN-04A course lesson → Home Continue → the next-day returnP1
Cast
A learner; a showcase written subject ("Python Fundamentals" / "Data Structures in Python" / "SQL Basics"). Two sittings or a staged equivalent.
Steps
/courses → open a subject → Start now → the first lesson opens in the lesson player.
Read it → Complete and continue (Complete lesson on the last) → the next lesson; the lesson is marked done in the outline.
Leave the subject and open Home → the Continue card names the subject at the lesson last opened — its kind, title, course, chapter and place, with the course's progress.
Continue → you land on that saved position, not the subject's start and not the next lesson.
Sign back the next day (same account, same browser) → Continue still resumes the same place.
Expected — at every step
Opening a lesson of a subject being taken saves it as the resume point; a completed lesson never comes back as unfinished work.
Continue picks the most recently active eligible item and never invents a different task when the exact position is gone (it opens the section's start instead).
Lessons and quizzes pay no XP; only finishing the whole subject does (250 XP — JRN-11).
An area that cannot answer leaves Continue saying it could not check, with Try again — never a wrong guess.
Also try
Start an unfinished challenge submission as well → Continue offers whichever was touched most recently.
Staff walking the same subject are never held back by prerequisites and their reading earns nothing.
TC-JRN-05The grand tour — every space opens honestly on day oneP2
Cast
A learner, fresh after TC-JRN-01.
Steps
Walk each navigation destination in turn: Home, Courses, Video courses, Challenges, Tracks, Daily Challenges, Debug Detective, Code Lab, Typing Quest, Mock Tests, Company Tests, Test results (/test-results), the Assessments dashboard (/tests-dashboard), My Projects (/projects), Tools (/tools), My Solutions (/solutions), Achievements (/achievements), XP history (/xp-history), Skills (/skills), Recap (/recap), Inbox (/inbox), Quick Notes, Topic Requests (/requests), Profile, Settings.
Open /aptitude and /bounties directly.
Try /credits and /credits/history directly.
Try a nonsense address and any /admin/… address.
Click every Quick-launch tile on Home (Challenges, Daily Challenges, Debug Detective, Code Lab).
Expected — at every step
Every built page renders inside the shell with real content or an honest first-run empty state — nothing blank, nothing that reads as an error.
/aptitude shows This page is coming soon. inside the shell; /bounties shows the deliberate programme text page. These are the only unbuilt destinations.
No Credit surface exists anywhere: no header balance, no You link, and both credit addresses answer as unknown pages.
A nonsense address and /admin/… give the same plain not-found — which one it is (missing, hidden, someone else's) is never hinted.
Every Quick-launch tile leads somewhere working; nothing on Home is a dead control.
Also try
Signed out, open a deep link like /daily-challenges → the handoff runs and returns you to it.
Repeat the tour at 390 px → the bottom dock with popover menus replaces the sidebar.
Empty-state honesty is covered page-deep per area in docs 01–03.
The lifecycle every piece of authored content lives: draft → submitted → published → archived. These journeys prove the pipeline end to end — that a studio draft becomes catalogue content a learner can solve, that the learner's records survive the content's retirement, and that the publishing switch and the submissions queue gate exactly what they should. Studio mechanics are covered page-deep in doc 04; here we care about the hand-offs.
Coordinate the publishing switch
Allow Admins to publish (/admin/settings/publishing) is global — it changes what every Admin's studio offers. Note its state before touching it and put it back; the queue journeys need it off, TC-JRN-08 needs it on.
🖥🖥 two browsersSuper Admin Admin (tester-staff-1) in one browser, Super Admin in another, a learner for the last leg. Prerequisite: Allow Admins to publish is off.
Steps
SA confirms the publishing switch is off (/admin/settings/publishing). Note its previous state for cleanup.
Admin: /admin/challenges → new challenge → title it "QA-<initials> <date> — …" → write the statement, pick languages, starters, at least one visible and one hidden test case, a reference solution that passes every case, difficulty easy, a topic → save the draft.
Run the studio's checks → all green → Submit for approval (Publish is not offered while the switch is off). The item now waits in /admin/submissions.
SA: open /admin/submissions → the item appears in the queue → open it → the review pane loads ("Loading the submission…" first) with the learner preview, the submitted changes, validation results and impact.
SA: Approve & publish → one action; the item leaves the queue and is published at the exact revision reviewed.
Admin: the inbox receives a System notice — "Your submission was approved", naming who approved what (title and kind) and that it is live; it opens the item's studio page.
Learner: /challenges → the QA challenge is findable → open it → solve → standing Solved, XP paid, Solutions entry — exactly as TC-JRN-02.
Expected — at every step
An incomplete draft saves; nothing publishes before its checks pass; approval is publication — no second Publish step.
The review shows the item, the submitter, the submitted changes, validation and impact; missing validation or impact blocks the decision.
Approval applies to exactly the revision reviewed — later draft edits cannot ride along (JRN-09).
The catalogue shows it to learners at once; its Solve rate reads Not enough data until the population is real — never a fake 0%.
Also try
Admin opens /admin/submissions/:id → they read the queue, never the SA review pane.
A note for the reviewer, where the studio takes one, shows above the submitted content.
Studio-level mechanics: doc 04 (challenge studio and submissions cases).
TC-JRN-07Sent back with a reason → fixed → resubmitted → approvedP2
Cast
🖥🖥 two browsersSuper Admin Admin + Super Admin + the same QA draft as JRN-06 or a new one. Publishing switch off.
Steps
Admin submits a QA draft for approval.
SA opens its review → Send back with a reason ("the third example contradicts the statement").
Admin's inbox: "Your submission was sent back" naming who sent it back, with their note, telling them to make the changes and submit it again; it opens the studio page.
The draft is editable again → Admin fixes → Submit for approval → a fresh queue entry.
SA approves → published; the submitter's approval notice arrives as in JRN-06.
Expected — at every step
Sending back returns the draft with its reason; inaction never approves anything.
Each notice goes out once, on the decision's own transaction — a decision never hinges on whether its notice delivered.
The staff side keeps the full decision history; the learner side sees none of the internal back-and-forth.
Also try
Send back with no reason where the form requires one → nothing happens.
Both staff members act on the same queue item in quick succession → one outcome, no double apply.
🖥🖥 two browsersSuper Admindestructive — coordinate SA + Admin + a learner. The switch is global — announce before flipping.
Steps
SA turns Allow Admins to publish on at /admin/settings/publishing (recent main-site check; the change and its old/new value land in the audit history).
Admin's open studio is refused the moment its next save meets the new policy — or on a fresh save now offers Publish rather than Submit. Admin publishes the QA item directly through the checklist.
Learner sees it in the catalogue at once; no queue entry ever existed.
SA turns the switch back off → an Admin studio left open gets its next Publish refused, says so, re-reads the item without a reload and offers Submit for approval with the draft kept.
Audit history holds both switch changes with who and the old/new value.
Expected — at every step
The switch never grants approvals, unpublish, archive, protected settings or people actions — only direct publish of authored content.
Direct publication by either staff role asks for the ≤15-minute main-site check at confirm.
A press of Publish is never carried out as a submission, nor Submit as a publication, when the policy moves mid-edit.
Also try
SA publishes the same item — a Super Admin always publishes directly, switch or not.
The switch survives an app restart; check it is still as left after your round.
TC-JRN-09A submission the draft moved past is refused, never approved blindP2
Cast
🖥🖥 two browsersSuper Admin Admin + Super Admin. Publishing switch off.
Steps
Admin submits a QA draft → it waits in the queue.
Admin edits the same item further (a studio that takes a waiting item back warns once first — editing takes it out of the queue).
SA opens the submission's review: where the kind keeps only the draft, the review says nothing is shown as submitted and it needs submitting again; where the item left the queue, it is simply not there to approve.
Admin resubmits the current draft → SA approves → what goes live is the revision reviewed, never the earlier one.
Expected — at every step
Approval never applies to content other than the exact submitted revision; further edits need renewed review.
A stale or withdrawn submission cannot be approved into a state nobody looked at.
Also try
Two staff members with the same item open → the second save is refused, never merged; Keep mine / load theirs is offered where the studio saves by itself.
TC-JRN-10Unpublish: the catalogue loses it, the learner keeps the recordsP1
Cast
Super Admindestructive — coordinate SA + the learner who solved the QA challenge in JRN-06.
Steps
Learner first: note the standing Solved, the Solutions entry and the XP history line.
SA: open the QA challenge's studio → Unpublish (recent main-site check) → the catalogue stops listing it for learners.
Learner: the challenge is gone from /challenges; a saved direct link opens read-only or the area's honest not-found — never a broken editor, never a fake "Not started".
The learner's records are untouched: standing, Solutions entry, XP line and any achievement all remain.
SA republishes (or leaves it down): if it returns, the learner is not paid again — the first-solve fact is permanent.
Expected — at every step
Unpublish/Archive changes availability, never history: solves, XP, Solutions and streak facts survive.
No dangling live links: anywhere that pointed at it (catalogue, tracks, suggestion slot) drops it or explains honestly.
A repeated solve after republication pays nothing again — once means once.
Also try
Delete names the item and needs its title typed; where it cannot preserve required history it refuses and offers Archive.
An archived item stays read-only for learners whose records refer to it, and is not offered as new solving.
TC-JRN-11Subject completed → certificate → public verifyP2
Cast
Super Admin Learner + SA + any signed-out browser for the public check. Longest staging in this doc: completing a subject means finishing every required lesson — either finish a showcase subject over sessions, or author a tiny QA subject (one chapter, one reading lesson, one quiz) through the JRN-06 pipeline and have SA enable its Certificate switch in the subject studio.
Steps
Confirm the subject awards a certificate: its catalogue card and subject page carry the Certificate mark (a video subject, or a written subject whose certificate switch is on).
Learner completes every required lesson → the completion page (/courses/:subject/completion) leads with the certificate in its state — Awaiting name if none is set — then what the completion earned, then where next.
The written-subject award lands once: completion page names it ("Finishing a written subject earned you 250 XP, once."), /xp-history shows it, the subject's achievement unlocks in /achievements.
Home shows Set certificate name while the certificate waits → Settings → Certificates → type a name (2–100 chars, English letters and ordinary punctuation) → preview of the exact printed name → confirm → the name locks.
The document generates in the background → "Your certificate is ready" System notice → state Issued → Download works and Copy verification link gives the public address.
Signed-out browser: open /certificates/verify/:identifier → it shows the identifier, display name, awarding item, issue date and current status, the time checked and the assurance statement — and nothing else.
Expected — at every step
The certificate carries name, item, completion and issue dates (IST), identifier and QR — no score, readiness or skill judgment.
Opening the completion page never awards completion; issuing is automatic and free; repeated delivery returns the same certificate.
Public verify discloses only the approved fields: hidden, unknown, pending or erased all read "No certificate can be verified for this code" — which case applies is never revealed.
One System notice on issue; name-setting and hide/show send none.
Also try
Hide the certificate → the public check goes non-disclosing → show it again → valid again; a revoked certificate answers not valid either way.
Type the code lowercased and dashless at /certificates/verify → still found; hammer past 60 lookups in a minute → the throttle explains itself.
Correct a locked name → the proposal waits for a staff decision; reissue keeps identifier and dates.
TC-JRN-12A published course change reaches learners even with System notices offP2
Cast
🖥🖥 two browsers Staff + a learner enrolled in (or who completed) the subject being changed. Learner pre-step: turn System notifications off at /profile/settings/notifications.
Steps
Learner switches the System category off and saves it alone.
Staff publish a real change to the subject (edit a lesson's text and publish — a draft autosave does not count).
Learner: a System notice still arrives — the mandatory course-change exception; it explains the meaningful change, not merely "something changed".
The subject's change page (/courses/:subject/changes) groups what was added/updated/moved/removed and stays authoritative whether the notice is read, deleted or delayed.
A completed learner's completion and any issued certificate are untouched.
Expected — at every step
Course-change notices are delivered even with System off — the preference explains this exception beside the switch.
Contrast: a general broadcast with System off does not arrive (JRN-53) — the exception is course changes only.
Publication never reverses if its notice cannot be delivered.
Also try
Eligible learners who already completed the subject are notified too.
The full recorded-test life: a paper authored and published, the learner's systems check and conditions, the timed room, grading, the result, what comes after (review, practice, a relief grant, invalidation) and the cross-feature restrictions while a test is live. The test room's own behaviour is covered page-deep in doc 02 (TC-TST-…); these journeys prove the pipeline around it.
Staging papers
Use the showcase papers where they fit ("Programming Fundamentals", "Python Foundations", "Data Structures Essentials", "SQL Queries"; companies Northvale, Corvane, Kestrelworks, Tamarind Grove). Where a journey needs a specific setting — Strict limit 3, a short duration — author a QA paper through JRN-13 rather than changing showcase content.
TC-JRN-13The whole recorded test: paper authored → published → taken → graded → resultP1
Cast
🖥🖥 two browsersSuper Admin Staff (Admin with the switch on, or SA for direct publish / submit-and-approve) + a learner on a computer at ≥1024 px.
Steps
Staff: /admin/mock-tests → New → title "QA-<initials> — …" → Details (category, difficulty, pass %) → two sections → questions across kinds (single-choice, multiple-choice, numerical, one coding with cases + reference) → Settings (duration, strictness, the six navigation features) → Checks view lists every failure together → fix them → publish.
Learner: /mock-tests → the paper card → Start → /papers/:paper → the systems check runs by itself on arrival, each item Passed / Warning / Could not check.
Read the conditions → tick to accept (required when the check warned; nothing that could not be checked is accepted) → Accept the conditions and start → the test room opens in the focus frame.
Answer across sections; mark one for review; on the coding question Run the examples (the section's run allowance shows, if set). Each answer shows its own save state: Saving → Saved.
Submit test → the confirm shows time left, answered/not answered/marked counts and links to the first unanswered/marked → confirm → the test ends once.
/tests/:test/result reads Grading until it is done (it says so after thirty seconds, calmly after five) → Final: the score against the pass mark, counts, time used, each section, what it earned, the permitted review.
First completion pays 200 XP; a first pass pays 300 XP — a first completed Mock that is also the first pass earns both, once each.
Expected — at every step
No test exists until Start succeeds — opening the paper or running the check creates nothing.
Could not check blocks Start until checked again; warnings are accepted explicitly; a check older than ten minutes is refused at Start with Check again offered.
One press of Start makes one test however often pressed; repeated Submit produces one result; the clock is the platform's and answers stop at the deadline.
The paper is frozen for the test: later staff edits reach future starts only — questions, keys, marking, timing and reveal settings are as the test began.
Pending is named: Grading is never converted to a provisional score; a coding answer is graded on every case, hidden ones counted only.
A phone or tablet sign-in is refused at Start, honestly; the test is computer-only.
Also try
Leave (it asks first — the clock keeps running) → the paper's page offers Resume → same place, confirmed answers kept.
Refresh the test page → it is recorded for staff, never counted, and never ends the test.
Studio/checklist and room mechanics: doc 04 (paper studio) and doc 02 (TC-TST-…).
TC-JRN-15Strict: the counted-event limit ends the test itselfP2
Cast
Learner + a paper set to Strict, event limit 3 (default; studio allows 1–10).
Steps
Start → produce counted events one at a time (leave the tab and return) → the header reads 1 of 3, then 2 of 3, each with its note.
At the third counted event the test submits itself → the result and history say the event limit ended it — phrased as the recorded fact, not an accusation.
The confirmed answers are scored as for any ended test.
Expected — at every step
The limit applies to counted events; a refresh is recorded for staff and never counts.
The event stream caps at 500 — the Strict limit ends the test long before.
The ending reason is honest in every place the test is named: result, history, staff events page.
Also try
Leaving the test for another Labs page (Code Lab included) counts as leaving the test page.
Events the browser cannot send (offline at that moment) are simply not recorded — nothing is queued to send later.
TC-JRN-16Deadline passes while away → Overdue → the worker completes itP3
Cast
Learner + a paper short enough to stage (staff can set a QA paper's duration toward its 5-minute minimum; grace default 60 s).
Steps
Start the paper → answer some questions → close the laptop or walk away past the deadline plus grace.
Come back after the deadline → the test no longer accepts answers; its row in /test-results reads Overdue until the worker completes it.
The worker ends a test nobody came back to within about a minute of its deadline + grace; the overdue label clears to a graded result shortly after.
The result scores confirmed answers; questions are distinguished Not reached / Skipped / Not answered — never described as wrong.
Checkpoint
Honest label
Test still open past deadline+grace, nobody returned
Overdue — visibly unfinished, never lost
Worker completes it
Result graded on confirmed answers; "time ended" as the ending reason
Late answer or late Submit
Reported as late or completes the ending from confirmed answers — never mislabelled Saved
Expected — at every step
Time keeps running through leaving, refresh and disconnection; a lost connection alone never ends a test.
The grace finishes submission only — it is not extra answering time.
If the automatic Submit cannot go through, the time-up dialog says the saved answers are safe and submitted for the learner, retries on reconnection or after fifteen seconds, and See your result says honestly whether the test has ended.
Also try
Time runs out mid-typing → what was being typed is kept and carried with the automatic submission; nothing after the deadline counts.
Mark N/A if you cannot stage a real deadline — record that and move on.
TC-JRN-17Review honors reveal settings; open practice unlocks only after finalP1
Cast
Learner + staff; a finished test from JRN-13.
Steps
On the final result, the answer tiles (All, Correct, Partly correct, Wrong, Not answered) filter the review; each section's questions are listed; rows open to the answers, the explanation and the code.
What the review shows follows the paper's reveal settings captured at Start: correct answers, explanations, reference solutions each only where allowed — a withheld element explains the policy, it does not look broken.
From the current result, Practice opens /papers/:paper/practice: no clock, no recorded events, each question checked on its own; a coding one on every test case with hidden cases counted.
Practise the N you missed limits practice to the questions not answered correctly where the paper shows its questions; Show all brings the rest.
Check: nothing from practice reaches history, Skills, Economy or a notice; the score so far lives on the page.
Expected — at every step
Practice is unavailable before the recorded test finalizes and closes while the newest test is in progress or being graded — or when the paper is archived.
The result applies the reveal settings the test began with — a later settings change reaches tests started after it, never this result.
A paper that keeps its right answers back still says right or wrong in practice and says it keeps them back.
The result page offers practice only from the learner's current result, never an archived one.
Also try
A withheld review explains rather than erroring; detail aged past retention explains it kept answers for 90 days or the 20 most recent of the type — no dead review button.
Another learner's result address is the same privacy-safe not-found.
TC-JRN-18A relief grant: settings change → told → second test → old result archivedP2
Cast
🖥🖥 two browsersSuper Admin SA + a learner with a finalized result on the paper.
Steps
SA edits the live paper's settings → the publish dialog shows each setting old → new → choose to tell the learners who have its result and, only with that, give each a relief grant → confirm lists the changes, the number told, and that a notice cannot be recalled.
Learner: the notice names what changed (in a sentence of what they will see after their next test where it applies) and the next action reads Use your relief grant.
Learner starts the second test → finishes → once the new result is final it becomes the measured result; the earlier result stays in history marked Archived and no longer counts toward readiness.
The grant's notice is protected — it survives Delete and Clear, saying beside it why it stays.
Expected — at every step
Only a Super Admin publishing directly can tell learners and grant; an Admin's submitted change approved later tells nobody.
At most one unused grant per learner and paper — grants never stack; a grant waits while the paper cannot be started, and archiving the paper ends unused grants (the confirm says how many first).
The old result is replaced only once the new one finalizes — not when the grant is issued or the test starts.
The audit history keeps the settings change as old → new values and the grants as their own entry ("Gave relief grants", with how many).
Also try
Invalidating the grant's test gives the grant back and the replaced result stands again.
A learner whose account is being erased gets no grant and no notice — everyone else whose result stood still does.
TC-JRN-19Invalidation: the learner sees the true reason and the XP reversesP2
Cast
🖥🖥 two browsersSuper Admindestructive — coordinate SA + a learner with a final Mock result on the paper (ideally one where another valid Mock test also stands, to see the re-pay leg).
Steps
SA: the paper's /admin/papers/:paper/tests view lists its tests (learner, when started, where it stands, how it ended, counted events — never a score) → open the test → Invalidate → choose a reason (a fault on our side / faulty content / account security / a staff decision), write a private note → recent main-site check → confirm.
Learner: the history row stays, marked Invalidated with the reason's sentence — never the staff note; the paper offers a fresh test where availability allows; open practice closes until it finalizes.
Learner gets the invalidation notice — a fresh test restored — and /xp-history shows the reversal of exactly what that test paid.
If another valid Mock test stands, the first-completion/first-pass XP is paid onto it instead — that test's result then shows the reward as earned, and the notice says whether the XP now counts for another Mock Test or is taken back.
Skills sets the invalidated test's evidence aside; readiness no longer counts it.
Expected — at every step
Invalidation is one action with no duplicate effects however repeated; only ended tests (being graded or final) can be invalidated — one in progress cannot.
Only XP is reversed; the first-completion and first-pass achievements stay earned; the private note never reaches the learner or an Admin's audit view.
Staff have no score editor, re-grade button or choice of outcome — invalidation is the only tool, and a proven calculation defect follows the bounded correction instead.
A reversed first-completion/first-pass award becomes eligible again — paid once to the learner's valid qualifying test, never twice.
Also try
Invalidating an already-replaced result leaves the newer current result and gives no new test.
A test still grading an hour after it ended is marked on the staff list with its reason, not a technical detail.
TC-JRN-20Company readiness: two tests and half the coverage before a ring appearsP2
Cast
Learner on a computer + a company with at least two published papers (showcase: Northvale Systems and Corvane Software have two each). Multi-session by nature — each paper gives one recorded test.
Steps
/company-tests → the company card → its page (/company-tests/:company) → note the readiness figure's starting state (untouched: visibly untested).
Take and finish a test on one of its papers → the readiness shows Not enough evidence with the relevant count — one finalized test of the two needed, coverage short of half — never a 0% ring.
Finish a test on a second paper of the same company → once coverage reaches at least half of currently published papers and two tests are final, the ring computes: 40% coverage + 60% performance, shown to one decimal, rounded down.
The band reads Not ready (below 50), Developing (50 to below 75) or Well prepared (75 to 100), decided on the shown figure (74.96 → 74.9, Developing).
The Assessments dashboard (/tests-dashboard) shows the same company's ring among its readiness rings; the Company result leads with accuracy and readiness rings of its own — no pass/fail, no XP.
Expected — at every step
Untaken papers affect coverage, never performance — no fictional zero scores enter the figure.
Readiness recalculates after a finalized, invalidated or repaired result and when paper availability changes; while recalculating it says unavailable rather than pairing a fresh result with a stale figure.
Company Tests pay no XP, Credits or achievements and have no pass mark — ever.
Also try
An archived result stops counting toward readiness; invalidate one and watch the figure react (JRN-19 leg).
Accuracy = correct ÷ answered, not ÷ all — with nothing answered there is no accuracy figure at all.
TC-JRN-21The live-test cap: a second start points to Resume, never replacesP2
Cast
Learner on a computer + two startable papers (any mix of Mock and Company).
Steps
Start a test on paper one → it is live.
In another tab of the same session, open paper two's page and try Start → refused, pointing to Resume the running test — the running test is never displaced or discarded.
Resume → the first test is intact: clock, answers, position.
End the first test → the second paper's Start now works.
Expected — at every step
The cap (one by default, at most three — SA-configurable on the paper lists) counts across Mock and Company together and across all tabs of the session.
A blocked start states one clear reason and the remedy — here, Resume.
Opening details or finishing the systems check never uses up the test — only Start does.
Also try
One timed Debug window may coexist with the live test (JRN-26) — the cap is about recorded tests, not everything timed.
The dashboard's Coming up shows nothing while the limit is reached.
The product day is 09:00 → 09:00 IST and only the two dailies turn on it. These journeys prove the boundary, the streak's on-time honesty, the scheduled-to-live pipeline, catch-up, voiding, and how timed activities coexist. Several legs wait for a real clock — stage them across sittings, and mark N/A where the wait is not practical.
TC-JRN-22A scheduled Daily goes live at 09:00 IST — and not a minute earlierP3
Cast
🖥🖥 two browsers Staff + a learner who keeps /daily-challenges open across the boundary.
Steps
Staff: /admin/daily-challenges → author a QA Daily (statement, language, cases, reference, bonus if wanted) → validate → /admin/daily-challenges/schedule → schedule it onto a free future date (scheduling is publishing — the Admin-publishing switch rules apply; with it off it waits in Submissions for a Super Admin).
Before 09:00 IST on the date: learner's Daily page discloses nothing of it — no title, difficulty or hidden content.
Across 09:00: the open page refreshes at the boundary; the date is now live and its facts (difficulty, bonus, languages) lock.
Learner solves it on its date → ordinary on-time rules (JRN-03): streak, calendar, award.
Expected — at every step
A date that begins with no Daily stays neutral — honestly empty, never fabricated; a date whose 09:00 passes before approval stays neutral too.
A scheduling conflict names the occupying challenge and date and changes nothing; a begun date cannot be bypassed by normal editing.
A failed refresh at the boundary keeps the previous view under an explicit stale-view notice with Retry — it never claims yesterday is still today.
Schedule health (/admin/daily-challenges/schedule-health) shows future scheduled, empty and blocked dates; the Operations hub flags the nearest empty date in the next seven.
Also try
Move an untouched scheduled Daily to another free date / unschedule it to draft — the confirmations name both dates or that the date is freed.
Tomorrow with no Daily → the hub's Needs attention row names it.
TC-JRN-23Solving between midnight and 09:00 counts for the date still openP3
Cast
Learner willing to test after midnight IST (or stage with staff's own account). N/A-friendly if nobody can.
Steps
Between 00:00 and 09:00 IST, open /daily-challenges → the page reads Open until 09:00 IST this morning — the Daily that began the previous 09:00 is still today's.
Solve it → the receipt stamps it to the product date that opened yesterday morning → the streak counts that date, not the calendar date.
Keep the page open through 09:00 → it refreshes to the new product date and its own challenge.
Expected — at every step
The product clock decides the date — never the device clock; every other platform date stays midnight-to-midnight.
The countdown never goes negative; the boundary refresh is honest.
A submission received on time but graded after 09:00 still counts for its date.
Also try
Submit seconds before 09:00 → still on time; at 09:00:01 it belongs to the new date.
Typing Daily shares the same boundary — a round finishing verified at ≥90% accuracy before 09:00 counts for the open date.
TC-JRN-24A missed day breaks the streak — catch-up pays in full but never repairs itP2
Cast
A learner with at least one missed eligible date behind them (leave a Daily unsolved for a product day, or use an account whose calendar already shows a Missed cell).
Steps
After a missed eligible date: the streak ends when the day changes; the lapse is acknowledged once — previous length named, a fresh-start message, no repeated blame, nothing to buy.
Open /daily-challenges/past → the missed date is listed → solve it → the full award pays: difficulty XP plus the authored bonus, as catch-up.
The calendar cell now reads solved with a Catch-up mark — not a streak repair: the current streak stays broken, the run does not reconnect.
The longest streak is a lifetime record and does not shrink.
Expected — at every step
Catch-up has no deadline and no reduced reward; a re-solve pays nothing again.
The current streak is consecutive eligible dates completed on their scheduled dates — never a count of all solved cells.
Dates before the learner's membership read as Before you joined — they neither count nor break.
Your own incorrect code, slow connection or missed visit never makes a date neutral.
Also try
A pending grade on a submitted-in-time solve is named awaiting its result — the late-resolving success reconciles the streak with no false break.
While the Daily is turned off, a missed date draws Off, never Missed (JRN-28).
TC-JRN-25Void a Daily: neutral for everyone, solves preserved, irreversibleP2
Cast
Super Admindestructive — coordinate SA + a learner. Voiding makes the date neutral for every learner — safest staging: schedule a QA Daily onto a near date (JRN-22), let it begin, void that. Voiding today's showcase Daily is allowed but affects everyone — announce it.
Steps
With the date begun, a learner solves it (or just has it open) — note their streak and reward.
SA: on the Daily's staff page → Void Daily → confirm the affected date and a reason → recent main-site check → confirm.
New submissions stop; the date reads neutral for everyone — the calendar marks it Voided/Neutral and it still opens for Runs and hints (not falsely described as missing).
Existing valid solves and rewards survive; the date neither adds nor breaks anyone's streak — no At risk warning on a neutral day.
The Operations hub and audit history keep the void with its reason; there is no un-void.
Expected — at every step
Void is a date outcome, not a lifecycle state and not a delete — only a Super Admin, with a recent main-site verification.
Archiving is not a way to grant neutrality — void is the explicit operation.
An already-delivered evening reminder is not recalled; it opens that date's explanatory page.
Also try
A learner mid-solve when the void lands → their submission is stopped honestly; nothing is invented as a completion.
Repeat the void press → one outcome, no duplicates.
TC-JRN-26A timed Debug window beside a live test — neither clock pausesP2
Cast
Learner on a computer + a startable test + a "Timed then practice" Debug case.
Steps
Start a recorded test → it is live.
In another tab open the Debug case → Start timed window in one language → its clock and Finish now sit under the title — allowed: one timed Debug window may coexist with one recorded test.
While the test is live, its account-wide restrictions hold in the Debug tab too: hints, editorials, Quick Notes, WizBit help and problem-reporting are closed — asking for them anywhere does not bypass.
Finish the timed window (accepted or time out → the acknowledged checkpoint is validated) → the Debug deadline ran its own course; the test keeps its own clock untouched.
End the test → the help restrictions release; Debug's own rules and deadline were never paused by either side.
Expected — at every step
Only one timed window across Debug Detective; a second start names the current case and remaining time with Resume or an explicit finish.
Neither clock pauses for the other; the test's restrictions are account-wide and release only when the test ends.
A failed validation inside the window does not spend another window or end it; an accepted fix ends it; exhausted allowance leaves unlimited practice.
Code kept for the deadline — on Save, Run, Validate Fix or a 30-second pause — is what a closing validation grades, never unseen typing.
Also try
Let the window outlive its minutes → a sweep ends it within about a minute and grades the checkpoint.
A content correction or unpublish mid-window ends it and restores the allowance.
TC-JRN-27Typing Daily: same-day completion, its own streak, 20 XP once per dateP1
Cast
Learner on a computer (Typing Quest is computer-only).
Steps
/typing-quest/daily → today's English passage, or the day's snippet in the learner's chosen code language → type it whole and finish at ≥90% accuracy → the date completes.
/xp-history gains "Typing Daily completed" — 20 XP, once per date, catch-up included.
The Typing streak — separate from the Daily Challenges streak — increments; its calendar shows the date Done; milestones and At risk today read as the Daily's do.
Open a past date (?date=) → its text types as catch-up → 20 XP pays, the streak never counts it.
Next product day: the streak holds; today's round undone shows At risk today.
Expected — at every step
Each date offers its passage/snippet from the published pool — the same for everyone; a date offering nothing is neutral.
The round sets no personal best (bests compare tests alike); a Custom-text round never counts toward the Daily, bests or achievements.
Staff keep their streak and are refused the switch.
Also try
Finish below 90% accuracy → the date is not completed — the figures say why, honestly.
TC-JRN-28Daily off → on: each turn-off is a cut no run crossesP2
Cast
A learner with an active Daily streak.
Steps
On the Daily page's streak panel or Settings → Dailies (/profile/settings/dailies) → turn the Daily off → with a streak to lose it asks first → the streak is cancelled at once — no "your streak ended" message, ever.
While off: the Daily stays open as ordinary practice — solve it → XP pays as usual, but no streak day, no At risk, no evening reminder; Home and Profile read Daily turned off, never a zero.
Missed dates while off draw Off on the calendar, never Missed.
Turn it back on → applies at once → a fresh streak starts with the next on-time solve — including a solve the same day made after turning on (a solve earlier that day while off does not count).
Off → on → off on the same day → each turn-off is a cut; the earlier run is not repaired.
Expected — at every step
The longest streak, milestones already reached, achievements, XP and past solves are all kept; only the current streak restarts.
An unseen lapse from before is never announced while the switch is off.
Staff keep their streak and see no switch — the server refuses one.
Also try
The Typing Daily's switch follows the same rules independently — check it on /typing-quest/daily.
A progress reset's Daily scope restarts the current streak but leaves the switch as it is (doc 05's reset cases).
XP, levels, achievements and their staff-side repair — where the learning fact becomes economy and where an economy mistake gets fixed without touching the learning fact. The award table for reference: easy 30 · medium 60 · hard 100 · extreme 150 · Daily bonus 40 default · written subject 250 · first Mock completion 200 · first Mock pass 300 · Typing Daily 20. Level L begins at 250 × (L − 1)² XP (Level 2 at 250, Level 3 at 1,000, Level 4 at 2,250).
TC-JRN-29Solve → XP history → level pill → a level crossing told onceP1
Cast
A learner — ideally one a single award short of a level boundary (e.g. 100–240 XP from Level 2 at 250).
Steps
Complete any XP-paying activity (solve, Daily, subject completion) → the award applies with the acceptance/completion itself — it cannot "arrive later".
/xp-history → the entry appears newest-first under its month: its source and amount, twenty per page.
The shell's level pill re-reads after the change and when a stale view returns — total XP, current level, next threshold and XP remaining agree everywhere they appear.
Crossing a boundary (250 / 1,000 / 2,250 …) → the pill shows the new level and the inbox gets exactly one Level Ups notice.
No crossing → no notice; a plain solve creates no inbox item of its own.
Expected — at every step
Total XP and its recorded entries never disagree; a mismatch is a platform problem, never silently clamped or invented.
Repeated delivery produces no duplicate entry; an unavailable figure is shown as such, never a fabricated zero.
A missing animation or a failed notice never reverses an applied award.
Also try
An award whose badge bonus also crosses a level can produce both notices — they describe different facts.
Staff earn none of it: staff solves and tests never pay XP or unlock achievements.
TC-JRN-30An achievement unlocks — exact progress before and afterP1
Cast
A learner who can still earn something cheap: a first Typing Quest round ("First round"), a first completed project, or the Mock first-completion from JRN-13.
Steps
/achievements → find the target card among Not earned yet → read its exact progress in the requirement's own units ("0 of 1 Mock Test completed", "3 of 8 lessons", "12 of 100 days").
Note "Closest to unlocking" — up to three unearned badges already begun, by share completed.
Earn it → the card shows Earned with its date; the Achievements-category notice arrives once (a streak badge is named inside the daily's milestone notice instead of a duplicate item).
Home's achievements card counts up and names it among the newest three.
Re-do the earning activity → nothing unlocks twice.
Expected — at every step
No Claim action exists; each unlock happens at most once, on the transaction that earned it.
Where the qualifying activity does not exist yet, the card says so in words ("No Mock Test completed yet", "No 60-second English test completed at 95% accuracy yet") — never "0% of 90%" or "0 of 40 WPM", and it does not count toward Closest.
An owner that cannot be read leaves only its own cards saying progress could not be read — not Unavailable everywhere, not fake progress.
Completion badges read "Completed:" plus the item's published name; bonuses or Recognition only are shown on the card.
Also try
Ninety percent / Perfect score / Perfect section show the best Mock score to a tenth, rounded down — as its result prints it ("81.5% of 90%").
Achievements survive progress resets and content changes; only an invalidated awarding fact leaves a visible correction.
TC-JRN-31A failed reward notice surfaces to staff — and a retry pays it onceP2
Cast
Super Admin SA + whatever is listed on /admin/economy/failed-rewards. N/A-friendly: a reward's notice is what fails (the XP already committed), and you cannot force one — if the list is genuinely empty, verify the honest empty state and mark the retry legs N/A.
Steps
Staff open /admin/economy/failed-rewards: each paused notice with its reward and category, the learner by name ("A learner with no name on record" otherwise), what is owed, when it paused, its tries and why — in words; and how many are still being tried.
An Admin reads the page but has no retry — that is a Super Admin's.
SA retries one → recent main-site check → the notice delivers to the learner once → it leaves the list; a retry that fails keeps it visible.
Retry all → retries page after page on one transaction each, answers which went and which were left, and stops at the first refusal.
Learner side: the notice exists exactly once — the XP it described was already in the history; nothing double-pays.
Expected — at every step
No paused awards is a genuine good state — an unreadable list is not an empty list.
The retry uses the reward's original identity — it cannot pay twice, and there is no write-off or replace-with-correction control.
The retry is recorded in the audit history.
Also try
Failures waiting for recovery also surface on the Operations hub's Needs attention and Waiting for recovery lists.
TC-JRN-32An economy correction: previewed, typed, audited — and readable by the learnerP2
Cast
Super Admindestructive — coordinate SA + a tester learner's account (announce the figure you will move, e.g. +50 XP, and pick an account that can hold it).
Steps
SA: from the person's support view → Correct XP or Credits (or /admin/economy/correction?person=…) → choose XP, add, 50.
The preview shows the current total, the signed change, the resulting total and any level change — a non-whole or out-of-range amount shows no preview.
Enter the reason and a nonempty incident reference, type the change in words ("add 50 XP") → main-site check → Apply → it commits with its audit entry; repeated confirms apply once.
Learner: /xp-history gains a correction entry showing the reason and the reference — never who made it; the level follows the new total with no level-up notice or celebration.
Expected — at every step
Bounds: up to 100,000 XP either direction per correction; a deduction that would take the total below zero is refused with the amount actually permitted — never trimmed to fit.
A correction appends an explanatory entry — it never edits or deletes the original record; nobody corrects their own account or someone being erased.
It cannot reward new behavior, manufacture achievements or change a test outcome — it repairs a verified platform fault only.
Also try
Correction based on a total that cannot be read → no guessed preview, no confirmation.
A deduction into a total a reversal left below zero: an add applies whatever it leaves; the below-zero total is shown as it is (Level 1, no way along).
TC-JRN-33Generated assistance is off — the Credit legs are absence checksP2
Cast
Learner + SA. GENERATED_ASSISTANCE=false platform-wide on this deployment — the expected result of every leg is absence, honestly.
Steps
As the learner: the header and You menu carry no Credits balance or /credits link; /credits and /credits/history answer as unknown addresses (not-found back to Home).
On a challenge, editorial, lesson and in Workspace: no "Analyse my code", no "Explain" paid action, no generated help or agent panel.
As SA: /admin/economy/configuration still opens — it says prices are not charged and the allowance is still granted, and the "where generated assistance answers" section says it is off or not yet configured; the eight saved settings show honestly.
A staff-side Credit correction or extra (/admin/economy/correction, /admin/economy/extra) still works where permitted — and stays hidden from the learner's history like the rest of the Credit experience.
Expected — at every step
Absence is clean: no dead links, no half-rendered Credit UI, no "0 Credits" pretending to be a balance.
Not-found stays privacy-safe; nothing inside the app errors or apologises for the disabled feature.
Any genuine Credit-history entries the learner had remain hidden — never surfaced as zeros.
Also try
Covered page-deep in doc 03 (TC-PLT-…) — this journey is the pipeline-shaped sweep across areas.
TC-JRN-34First Mock completed and passed: both awards, once each, never againP2
Cast
A learner who has never taken a Mock test + any published Mock paper they can pass.
Steps
Take the first Mock test and pass it → the result finalizes.
/xp-history shows two entries: 200 XP first completion and 300 XP first pass — the occasions are distinct, each once per learner, never to staff.
The two first-Mock achievements unlock (First completion, First pass) — each card earns its date; recognition-only high-score/perfect badges follow their own thresholds.
Any later Mock — a relief-grant test or another paper — pays neither award again.
Expected — at every step
The amounts are fixed catalogue values, not settings — what is stamped is what was in force at the grade.
A first completed Mock that fails still pays the 200 completion; the 300 pass stays available for the first passing test.
Reversed by invalidation, each reward becomes eligible again once (JRN-19) — repeated processing never pays twice.
Also try
A grading outage delays only the result — it never invents a partial award; a reward-delivery fault never changes a valid result.
The pipelines that protect people: learner content reports reaching the staff queue, topic requests reaching implementation, and restrictions reaching a real session. Moderation actions are Super Admin's, behind the ≤15-minute main-site check, and each one lands in the audit history. Page-deep moderation controls are in doc 05; here we prove what they do to the other side.
Destructive — coordinate every suspension and ban
Suspending or banning a tester account ends its sessions immediately — including any live test (scored on saved answers) and any running programs. Announce the account and the window in the team channel, use a dedicated tester learner (e.g. tester-learner-5), and lift/unban when done.
TC-JRN-35Content report: learner flags it → staff investigate → resolved with an outcomeP1
Cast
🖥🖥 two browsers Learner + staff (Admin or SA).
Steps
Learner on an eligible detail page (a challenge, Daily, Debug case) → Report → choose Spam, Incorrect, Inappropriate (note optional) or Other (note required) → send.
Staff: /admin/reports → the queue lists reports oldest first, with Open / Investigating / Resolved / Dismissed states, domain filters and real status counts.
Open the report → mark Investigating → the link opens the content's current editor — with an explanation when it differs from what was reported.
Correct through the owning domain's normal validated update (no report-specific publication bypass) → Resolve with an outcome: Corrected, No action, Escalated or Duplicate — optionally referencing the correcting change.
The report's history keeps the whole arc; domain filters and the cross-status breakdown reflect the real totals.
Expected — at every step
Dismiss requires a reason; a Resolved or Dismissed report must reopen with a reason before another outcome; repeated moves never create duplicate actions.
The report note is intentionally readable by staff — it grants access to nothing else of the reporter's.
Report controls are not offered inside a live test or Workspace — no back door through another tab.
Also try
Only eligible detail pages offer Report; an unknown or removed target is never fabricated.
Super Admindestructive — coordinate Learner + staff + a QA item staff will delete.
Steps
Learner reports a QA-authored item (JRN-06's challenge, say).
SA deletes that item (typed title where required, recent check).
Staff open the report: it is still in the queue; its link explains the content's current editor is gone or differs — it never pretends the historical screen is openable.
Resolve the report with an outcome → the history is intact and correctly attributed.
Expected — at every step
Removed content does not remove the report; no dangling editor link is presented as working.
The queue's totals and zero counts stay real through the deletion.
Also try
Report → item edited (not deleted) → the link explains the editor differs from the reported reference.
🖥🖥 two browsers Learner + staff (either role; only SA replaces links after implementation).
Steps
Learner: on a mapped page's foot callout (e.g. beneath the Challenges catalogue — "Request a topic", or beside a challenge — "Request a topic like this") → the form takes title (≤120) and description (≤2,000) with a read-only context summary → Send → the acknowledgement says it arrived and points to Your Requests — not that anyone read it or promised work.
/requests shows it Pending, newest first.
Staff: /admin/topic-requests → find it (search across titles and descriptions; newest first) → its words and context open beside the list — never who sent it → Approve (optionally a private team note).
Learner: a System notice — "Your topic request was approved" — unless their System switch is off; the status is visible on /requests either way.
Staff: on the request, find real published content by title and link it (up to five items) → Mark implemented becomes available once at least one linked item can actually be opened → confirm.
Learner: "Your topic request was implemented" names the linked content → the request reads Implemented → Open content opens it.
Expected — at every step
The context summary carries exactly what the page supplied — area, item, topic/difficulty/search — never raw addresses or private work; an unworkable context does not block sending.
Submitted wording is never editable by learner or staff; reviewer identity and the team note never reach the learner.
Status moves follow the graph; each accepted move queues one System notice on the same transaction; the five-requests-a-minute and twenty-a-day limits say Try again shortly / tomorrow.
A linked item that later cannot be opened says so without silently moving the request out of Implemented.
Also try
Same normalized title + same context while one is open → the existing request returns with an explanation and a link — not a duplicate.
Demand shows on Content gaps (/admin/content-gaps): totals, distinct learners, still-open and status breakdown over 30/90/365 days or all time.
TC-JRN-38Retract vs decide: one outcome, never bothP2
Cast
🖥🖥 two browsers Learner + staff with the request open.
Steps
Learner sends a request, then on /requests chooses Retract while it is Pending → confirm → it reads Archived — final, no restoration.
Staff had it open mid-decision → their pending move is refused with the current state shown; archived requests are read-only to staff and absent from the working queue.
Race leg: the learner retracts at the same moment staff approves → exactly one outcome stands — both is impossible.
Learner files the same title again (the earlier one is Archived, not open) → a fresh request is allowed.
Expected — at every step
A failed retraction leaves the request unchanged; the learner's own retraction sends no notice.
A move back (Approved→Pending, Rejected→Pending, Implemented→Approved) needs a staff reason and is refused while a newer same-title request is still open.
Also try
Re-selecting the status it already has changes nothing and sends no notice.
TC-JRN-39Suspend → the session dies into /restricted → lift early → access returnsP1
Cast
🖥🖥 two browsersSuper Admindestructive — coordinate SA + a dedicated tester learner signed in and using the app.
Steps
SA: /admin/people → find the learner → Suspend → reason, optional private note, duration (presets 1 / 7 / 30 / 90 days or custom 1–365) → the dialog says when they could come back in, ticking with the clock → recent main-site check → confirm.
At once: the learner's sign-ins end on web and app; any live test ends as access ended and scores its saved answers; running programs stop.
Learner's browser: its next request shows the notice — "Your access changed, so you are signed out." — and any page leads to /restricted: "Your access to Wizly Learning is suspended", with its end, a Try again, and the main-site contact route. No staff reasons, notes or the moderator's name appear.
SA: Lift early → the dialog names the active suspension → capture a reason → confirm → the person's standing returns.
Learner: Try again on /restricted (or a fresh sign-in) → asks afresh → access returns; the restriction history records suspend and lift with who and when.
Expected — at every step
A restriction wins over everything else at the gate; it affects Labs access, never the main-site purchase.
No notice is sent — the restricted page is what tells them; a suspension reaching its end is recorded as a platform transition ("A suspension reached its end"), not an admin act.
Each action and its audit record commit together; the operator is told what was confirmed and nothing more.
Self-suspension is blocked on page and api alike — "nobody can do it to their own account" with no form.
Also try
Suspend during a live test → it is scored on its saved answers and the learner is told as for any test that ended without them.
An Admin reads standing and reason on the support view but is offered no action.
TC-JRN-40Ban with the name typed → unban — the harshest confirmationP2
Cast
Super Admindestructive — coordinate SA + a spare tester learner.
Steps
SA: the person's support view → Ban → reason + type the person's name exactly as shown (or the start of their address where the main site gave no name) → recent check → confirm.
Learner: sessions end; the restricted page reads "Your access to Wizly Learning is banned" with the main-site contact route — and nothing to try again.
SA: Unban → typed name again + attribution, no reason required (the explicit exception) → confirm → access returns.
The standing history shows the ban, its reason, who placed it, and the unban — newest first.
Expected — at every step
A mistyped name performs nothing; a ban replaces a suspension in force at once with no moment between them — the history reads "Replaced by a ban".
Only Super Admin changes restrictions; an Admin reads them.
Staff can be suspended or banned like anyone — never by themselves.
Also try
Opening /admin/people/:identity/ban on someone not bannable says why ("They are not suspended, so there is nothing to lift." style) with no form.
TC-JRN-41The main-site check goes stale mid-action: the round-trip holds everything typedP2
Cast
Any staff role on a protected write (suspend dialog, publish confirm, correction apply — wherever the check bites).
Steps
Sign in as staff, then let more than 15 minutes pass without a fresh main-site verification (or open the console well after signing in).
Open a protected action and fill it — a reason, a note, a typed name.
The confirming button itself reads "Confirm on the main site" → it takes you to the main site and back to the same address.
Back in the console: everything typed is held in the tab and restored — the reason, the note, the broadcast, the change's own id. A typed person-name confirmation is typed again.
Confirm once → it applies; the api refuses a stale write regardless of what the page showed.
Expected — at every step
The check is asked at confirm, not at page open — a long-open page is not a loophole.
The round-trip is expected behaviour, not a bug; nothing typed is lost, nothing is submitted twice.
In a practice studio the lit save-bar button becomes the confirming button; a refused archive/delete is said in the api's words, never as "Not saved".
Also try
Let the session's freshHandoffUntil pass while a dialog sits open → the confirm flips to the trip in place.
One account, one active place per kind — newest sign-in wins — and the gate outcomes that decide who gets in at all. Session mechanics and notices are covered page-deep in doc 03 (TC-SES-…/TC-PLT-…); these journeys cross the browser boundary and the account's whole life.
TC-JRN-42Newest wins: the same account in two browsersP1
Cast
🖥🖥 two browsers The same learner account in browser A and browser B — the one journey where sharing an account is the point.
Steps
Browser A: sign in, open a page with work on it (a draft answer, an open challenge).
Browser B: sign in with the same account → B gets the session.
Browser A's next request → the top-of-page notice: "Your account was opened on another browser or device, so it is signed out here." — the page and what is typed on it stay visible; it offers Sign in here and never signs itself back in (that would end B).
A live-test leg: if A had a test running, it is not displaced — the test keeps running and resumes on B (or the next computer sign-in) with its confirmed answers; unsent answers stay on A's device.
A clicks Sign in here → through the main site → A's session opens and B is now the one told it was opened elsewhere.
Expected — at every step
Several tabs in one signed-in browser share the session — only a new sign-in displaces.
The replaced session explains why, preserves safe local work, stops protected actions and never looks like a random logout.
The explanation also says to change the main-site password if it was not them; an ended session is kept 30 days so the returning browser is told why it ended.
A sign-in moving to another computer during a test is recorded, never counted.
Also try
Duplicate a tab mid-test → tabs share the session and never displace each other.
The newer session is never bothered — no prompt, no approval.
TC-JRN-43A main-site password change ends the session politelyP2
Cast
A learner + access to change the password on the main site (coordinate — change it back).
Steps
Learner signed in and working → on the WordPress main site, change the account's password.
The app's next request → the notice: "Your password was changed, so you are signed out here." — page and typed work stay visible; protected actions stop.
Sign back in with the new password → a fresh session opens; the old one cannot resume.
Both kinds of session end — web and app alike.
Expected — at every step
The delivered change ends sign-ins on arrival; the wording is the recorded reason's own, never a generic error.
Local work follows its recovery rules — nothing is silently erased before the applicable rule.
Main-site sign-out ends only the web session; a password change ends both.
Also try
Main-site sign-out (not password) → the web session ends with "You are signed out."; the app session would stay (JRN-48).
TC-JRN-44Idle two hours, alive twelve — the documented waitsP3
Cast
A learner; mostly a documentation-and-spot-check journey — real waits are impractical for most testers.
Steps
Document the expectations before testing: web session life 12 hours from the latest handoff; inactivity allowance 2 hours; the worker's sweep ends sessions idle past their allowance.
If practical: leave a signed-in page untouched for over two hours → its next request → "You were away for a while, so you are signed out." (idle).
Longer still (past 12 h of life): "Your sign-in reached the end of its time, so you are signed out." (past-its-life).
An ended session is kept 30 days, so a returning browser is told the real reason — then it reads as an ordinary signed-out visit.
Expected — at every step
Background activity does not extend total life indefinitely; refreshing through the main-site flow renews only the handoff-based life.
A recorded test uses its admitted clock rather than ordinary idle expiration — Start verifies the session can cover test + grace + 5 minutes.
Mark long-wait legs N/A with a note rather than simulating them dishonestly.
Also try
The app's own figures differ (90-day life / 30-day idle) — document them; verify only if you have the app.
TC-JRN-45The denied account: the gate refuses, honestlyP1
Cast
The denied account — verified on the main site, holding no membership.
Steps
Sign in on the main site as denied → return to the app → the handoff resolves and the gate refuses.
/restricted explains that access is required and points to the main site — factual wording, no invented "your membership ended", no misconduct hint, no partial entry to learner pages.
Every app page and deep link answers the same way — there is nothing to reach by guessing addresses.
The refusal is kept in that browser for the handoff's ten minutes; after that the visit reads as ordinary signed-out and asks the main site afresh.
Expected — at every step
Membership admits; a role never does — a WordPress administrator without membership is refused identically.
"Access cannot currently be checked" is a different, honest page — verification unavailability, not missing membership.
A sign-in the gate refuses opens no session: the browser keeps the refusal instead.
Also try
/restricted while admitted → it sends a person in good standing to Home — the page reads the session's gate, never the address's claims.
TC-JRN-46Lapsed member: privacy-only sign-in → erasure request → cancel in the windowP1
Cast
The lapsed account — membership ended 2026-09-23, previously admitted to Labs.
Steps
Sign in as lapsed → the page says the membership is past its end, offers Renew on the main site, and beneath it "Erasing your learning records" → the privacy-only sign-in opens.
That session reaches only the person's own erasure: every other page and route answers as for someone not signed in — try /, /daily-challenges, /admin/….
Request erasure: type the confirmation (email or name as shown) → recent main-site check ("Confirm on the main site" if stale — the privacy-only session takes the same trip) → the request starts its seven-day window and shows its status.
Cancel the request inside the window → the status shows it cancelled; learning access is not restored (the membership is still past its end).
Request again later — allowed; the window restarts.
Expected — at every step
Privacy-only means privacy-only: no learning content, no reading or downloading records — only ask, cancel within seven days and read where it stands.
The sign-in ends when the main site's answer changes — a renewed member signs in ordinarily — and while the main site cannot be asked it ends rather than working from the last answer.
No staff approval is part of a learner's own request — the window and the processing are automatic.
Also try
A membership that ended before the person ever reached Labs → the lapse page alone — there is no account to erase.
Try every ordinary route under the privacy session → all answer as signed-out.
TC-JRN-47Staff-initiated erasure: /admin/lifecycle stages to a privacy-safe endP2
Cast
Super Admindestructive — coordinate SA + a disposable account — this permanently erases it. Use a spare tester learner created for the purpose; do not run on an account other testers need.
Steps
SA: the person's support view → Erase this account → a mandatory reason + the person's name typed + recent main-site check → confirm. It begins at once — no seven-day window.
/admin/lifecycle lists it: source, stage, relevant dates, due date (thirty days out), whether overdue, per-step progress and any failure — never "Erased" until the last required step succeeds.
Effect: the person's sign-ins end at once and they are answered as being erased; their browser shows the erasure gate outcome, not a generic logout.
Each owner removes what it holds as background steps; a step that fails retries, and a spent-failure shows as Failed on the lifecycle page for an SA retry — Held and Failed are distinct states.
Completion: the person's certificates answer public verify as an unknown code; audit entries keep but name nobody; Access keeps only the pseudonym marked erased — the account cannot return through a later sign-in or a restore.
Expected — at every step
While an account is being erased, the server refuses every action on it except a legal hold — suspend, ban, reset, correction, reversal, extra time, invalidation, certificate actions all refuse with the honest reason.
A legal hold pauses the erasure (it reads Held) and releasing the last one resumes it from the first unfinished step — a hold never restores what is already gone.
Erase pressed twice returns the erasure already under way — never a parallel run.
Protected administrative history (moderation, resets, reversals) survives, naming the person only by pseudonym.
Also try
A learner's own request still inside its window is begun at once by the SA's action — without the window.
The Operations hub's Needs attention counts erasures overdue or stopped — it links here narrowed to them.
How the platform behaves when its own parts hurt — and the rule under everything else in this doc: unavailable is not empty, unknown is not zero, platform failure is never learner failure. You cannot safely break a shared deployment to test these, so most legs are "catch it live or verify the honest path exists" — catch degradation during the maintenance window (TC-JRN-52), watch the health signals, and mark unstageable legs N/A with what you checked.
TC-JRN-49Readiness and the Operations hub: health reads as it isP1
Cast
Any tester (the endpoint) + staff (the hub).
Steps
Open https://app.sprinklejelly.com/api/v1/readiness → 200 serving / 503 not — check it before a session and whenever something looks down.
Staff: /admin → four regions: Needs attention, Signals, Background work, Waiting for recovery — each says when it was read and stands on its own.
Signals read Healthy / Degraded / Down / Unknown — a record older than three measurements reads Unknown, never Healthy; the console's health light shares the state and reads Unknown when the hub cannot be read.
Needs attention rows each count what their link shows and link to the owning page — account erasure, main-site changes, legal hold review, grading waits, failed rewards, certificate documents, submissions, content reports, topic requests, the Daily schedule — folding into one "Also clear" line when nothing waits.
Owner alert conditions list on the hub: thirteen checked from what Labs keeps, five reading Cannot be checked yet with why (outside uptime, backup/restore, disk, video processing, WizBit silence) — and it says delivery is not set up.
Expected — at every step
A failed panel leaves other panels usable; an unreadable figure says so — never a fabricated zero.
The hub reads again each minute while open, backing off after a failed read; interactive down beside healthy standard execution is a degraded capability, not "everything is down".
The Operations hub is the administrative landing page — both staff roles read it; protected recovery is a Super Admin's.
TC-JRN-50Degraded services on learner surfaces: unavailable, never zeroP2
Cast
A learner during a genuine degradation (maintenance window, real outage) or verifying expectations. N/A-friendly.
Steps
Inbox count unreadable → a hollow badge mark, never a missing badge and never "0".
Daily streak unreadable → Unavailable, never 0; Home regions fail independently — a good region stays, a failed one keeps last-known data with freshness and retry.
A dependency staff cannot be asked → surfaces say so in learner words ("can't be asked"/unavailable) — never an empty list or a false success.
A grading outage leaves a test result Grading — after thirty seconds it says it is taking longer; after five minutes it calmly says grading is busy, answers are safe, you need not wait — never a provisional score.
A submission refused by a full grading service waits for room — the try uncounted — and a platform failure changes no solve, reward, evidence or streak.
Expected — at every step
"Pending is named, not faked": Grading / Being marked / Could not check / Not enough evidence are shown as themselves.
A genuinely empty state and a failed read are different messages everywhere.
A platform/content conflict during grading is rejected as such — never blamed on the learner.
Also try
Kill the connection mid-page → reload an answer save → Saved locally with Retry or Not saved with Retry — never claimed Saved.
Continue says it could not check rather than choosing from partial answers.
TC-JRN-51Where code runs: this device, the cloud, the runner's own origin — labelledP2
Cast
A learner in Code Lab and dev tools open.
Steps
/code-lab → run a Python program → the run bar names the place with an icon: on this device (the browser's worker) or in the cloud — and each run names where it ran with that place's exact Python version.
A run that cannot finish on the device offers Run in the cloud — an explicit choice, not a silent switch.
Open a browser-preview language (a page/HTML) → dev tools: requests go to the runner's own origin, run.sprinklejelly.com — by design, and it is normal to see them; learner code there never receives the Labs session cookie.
The environment view names real values (language/version, limits) — an unknown value says Unavailable rather than inventing a number; learner text calls the service "the cloud".
Expected — at every step
Labs decides where a run goes — never the learner; on a phone or tablet, or a connection saving data, it is the cloud, saying why.
A device run is held to the same time and output limits as in the cloud and names its own bounds — never dressed as a server terminal.
If the runner origin cannot be reached, the feature says it is unavailable — there is no silent fallback pretending a run happened. (Staging the block on a shared deploy is impractical — verify the honest labels and the offered Run in the cloud.)
Also try
A cloud run's errors name the learner's file (main.py), never the service's folder.
SQL runs on a database in the browser, never the server — the page says so.
🖥🖥 two browsersSuper Admindestructive — coordinate SA + a learner. A declared window shows on every learner page — announce it.
Steps
SA: /admin/maintenance-windows → declare: start now (or minutes ahead), expected end within seven days, affected capability grading, and a learner-safe explanation up to 300 characters → recent check → recorded in the audit history. The page previews the learners' banner as it will look.
Learner: every learner page shows the window at its top — from a day before a scheduled start, at once for one in progress — with what it affects, its times and the explanation. Staff pages carry no banner.
Learner tries to Start a Mock/Company paper with coding questions whose window would fall inside its time → refused honestly — an existing test continues while saving stays available; Quick Notes turns read-only while the window is under way.
Past the expected end the window reads Ending (waiting for the first health measurement after it) → if anything it affects measures unhealthy it reads Overrunning and learners are told it is taking longer than expected → the first measurement where everything affected is healthy ends it as the platform's own act.
The banner clears within about a minute of ending; the hub's Maintenance signal reads Degraded while it is in progress or overrunning.
Expected — at every step
There is no Force healthy or manual End that bypasses measured health; passing the expected end never hides an outage.
States: Scheduled, In progress, Ending, Overrunning, Ended, Cancelled — a window can be cancelled only before it starts, and a cancellation leaves the banner within a minute.
Declarations carry their own id — a double press or the trip back is one window.
Also try
A window affecting interactive programs or file storage → the same banner mechanics; each affected page keeps its own safe behaviour.
TC-JRN-53Broadcast: send → delivers where System is on → stop mid-flightP2
Cast
🖥🖥 two browsersSuper Admindestructive — coordinate SA + learner A (System notices on) + learner B (System off) + a staff account. Everyone eligible sees the send — announce it and keep the words QA-appropriate.
Steps
SA: /admin/broadcasts → title ≤120, message ≤4,000 → the preview shows the row the bell and Inbox draw, plus the announcement whole → it states the audience as an upper-bound estimate and that delivery carries on after the page closes.
Confirm Send — naming the audience, that delivered notices stay, and that it goes in the sender's name; at 5,000 estimated recipients or an unworkable estimate it asks once more. A double Send returns the same broadcast — never a second.
The worker delivers in steps of 200: learner A's bell badge counts up and the Inbox gains the System notice, readable in full; learner B gets nothing; no staff account gets one.
SA stops remaining delivery mid-flight with a reason → work already being settled finishes → the final status reads Stopped with settled counts (delivered + System-off skips) — items already delivered remain.
/admin/broadcasts/history lists it newest-first: sender, time, title, state, estimate, delivered and System-off counts, and the stop's actor, time and reason.
Expected — at every step
The audience is learners whose last main-site answer admitted them, with no restriction and no erasure begun — staff are always excluded; the System preference is honoured (a general broadcast, unlike a mandatory course-change notice).
The estimate is an upper bound, never a promised delivered count; no figure reads as zero when it could not be calculated.
A stop is repeat-safe; stopping a finished broadcast reports that it finished; stopped delivery cannot resume — a correction is a new message.
Nothing ever shows who received, read, deleted or muted a notice.
Also try
Send while a learner's session is live → the badge arrives over the live channel as its delivery step lands.
A failed step marks the broadcast Failed with the counts it reached — learners already reached keep their copy.
TC-JRN-54Handoff and /unavailable: the failure pages tell the truthP2
Cast
A signed-out or interrupted learner.
Steps
Open the app signed out → /handoff says Signing you in and goes to the main site once per tab.
Make the sign-in unfinishable (close mid-trip, or return without a session) → the handoff says We could not finish signing you in, that it is not a membership problem, and offers Try again for the same page.
Refusals land on /restricted and /unavailable: /unavailable shows a genuine platform failure — Wizly Learning is not available right now — with a safe retry and no invented account or content state.
/restricted asks the session read and shows only the confirmed gate outcome — a person in good standing goes to Home; the address's own claims are never trusted.
Expected — at every step
A request with no session is refused with one message everywhere: Sign in to continue.
Not-found stays privacy-safe; a refused sign-in never ends an existing session.
Failure pages use the product's words — no stack traces, no "Labs", no speculation about membership.
Also try
Return to a deep link through the handoff → you land on the page you asked for, never an external destination.
Wizly Learning Testing Handbook · 06 · End-to-End Journeys · generated from the product specification (docs/) and source of Sprinkle-Jelly-V1 · November 2026