Skip to content

Add feedback timing, attempt tracking, and answer review features - #22

Merged
backwerdrimshot merged 2 commits into
mainfrom
claude/challenge-mode-features-ui-7oomjh
Aug 8, 2026
Merged

Add feedback timing, attempt tracking, and answer review features#22
backwerdrimshot merged 2 commits into
mainfrom
claude/challenge-mode-features-ui-7oomjh

Conversation

@backwerdrimshot

Copy link
Copy Markdown
Owner

Summary

This release adds three interconnected features to support both teaching and assessment workflows:

  1. Feedback timing control (fb parameter): Teachers can now choose whether the correct answer appears after each question (each, the default) or only at the end (end). When feedback is held, the running score and guide highlighting are also hidden until the round completes, supporting graded assessments where the answer key cannot be shown mid-round.

  2. Per-student answer order variation (device variant + student ID): A stable per-browser identifier varies the position of answer choices so that one student's answers cannot be directly copied by classmates. A typed student name supersedes the device identifier, allowing teachers to reproduce a particular student's answer ordering. The variant is determined before questions are built so it affects choice order only, not the prompts or distractors.

  3. Attempt tracking and review: The app now tracks which run of a round a student is on (incremented by retry, reset by new rounds). Results display the attempt number, and a collapsible review section shows every question with what the student chose versus the correct answer. The review opens automatically for held-feedback rounds (where it is the only place answers are revealed) and stays folded for instant-feedback rounds.

Supporting changes:

  • Fixed assignmentLocks() to report only what the link actually pinned, not what an assignment implies (e.g., naming a round no longer falsely locks level/scope at defaults)
  • Added validation that measure rounds cannot exceed the pool's capacity (k rhythms make k⁴ unique measures)
  • Pass mark validation now checks against the round's actual length, not the maximum
  • Result cards now show which rhythms were missed and the sequence step (if assigned)
  • Device variant is stored in localStorage with graceful fallback for private mode

Validation

  • Added unit tests for feedback parameter parsing, measure-pool validation, pass-mark validation against actual round length, and answer-order variation
  • Existing tests pass; new tests cover the feedback setting, measure ceiling, and variant behavior
  • Smoke-tested the full workflow: practice mode, challenge with instant feedback, challenge with held feedback, retry, and result review

Documentation standard

  • README updated: build date changed to 2026-08-08.5, feedback timing documented in assignment link section, measure-pool bound explained
  • Build value in app code matches README (2026-08-08.5)
  • Capability manifest updated with fb parameter and new error codes
  • All required README sections present and accurate
  • Support and feedback destinations unchanged
  • Deployment and privacy/accessibility statements remain accurate

https://claude.ai/code/session_013jGA1JrHcFtpHu711uq5DN

claude added 2 commits August 8, 2026 20:14
An audit of challenge mode found four ways a student could reach a full
score without reading a notehead, and four defects where the app described
one round and ran another. This closes the ones that are fixes.

Refuse two link shapes that produced evidence for an assignment nobody set:

  * A full-measure round never repeats a measure, so a pool of k rhythms can
    fill at most k^4 questions. `?scope=measure&cells=quarter,eighths&n=20`
    passed validation and then threw while the round was being built — after
    the banner, level, scope and pass mark had applied. The student answered
    the default five-question beat round under the assignment's stated
    conditions, and the card reported its goal. Now refused at the link, and
    the round is built before any of it is applied, so the shape of that
    failure is gone rather than merely unreachable.
  * `pass` was checked against MAX_QUESTIONS rather than the round's real
    length, so `?a=Goal&pass=8` printed a goal of 8/5 that no student could
    clear.

Stop a posted answer key from transferring. A seed makes every student's
questions identical, which is what makes the scores comparable — and it also
fixed where the correct answer sat, so one student could post "4, 4, 2, 3, 4"
for the class. Questions still come from the seed alone; an optional variant
reshuffles the choices afterwards, from a typed name or a per-browser string
that never leaves the device. A round with no variant is byte-identical to
one generated before this existed.

Make a replayed round say so. Retry replays the same questions in the same
order after showing every answer, and the finish time was stamped once and
never re-stamped, so two attempts could carry one verification code. The
attempt is now counted, re-stamped, and reported on the card, in the copied
summary and in both the code and the attempt reference.

Add `fb=end`, which withholds the correct answer, the running score and the
guide's highlighting until the round is over — instant feedback teaches, and
a graded round cannot hand over an answer key while it is being answered.
Close Practice while an assigned round is unfinished, since it reveals the
counts for the same vocabulary.

Show the diagnosis the app already computed. Every completed round has built
an errorSummary since the result envelope was adopted and none of it reached
a human, so a card said "2 of 5" where it could name the rhythms that went
wrong. The card now lists them, the summary carries them as catalog ids for a
follow-up link, and every round ends with a review of each question beside
the count it wanted — open by default when feedback was held.

Lock only what the link pinned. `?a=Homework 1` froze the level and question
size at their defaults and told the student their teacher had chosen them;
the parser already reported exactly what was pinned and the UI recomputed it.

The attempt number is deliberately NOT added to the result envelope's own
fields: praxis.result.v0_1 is shared with two sibling apps, and adding a
field here would make this app emit a shape the others do not. It belongs in
the schema, which is a decision for the family rather than for this app.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_013jGA1JrHcFtpHu711uq5DN
The size note carried 2655 KiB / 995 KiB gzipped. The commit before this
release actually measures 1000.88 KiB, so the figure had drifted and nobody
would have known until a deploy failed with an unrelated-looking build error
— the exact failure mode the deployment section exists to prevent.

Records the measured numbers, the delta this release added, and the command
that produces them. Also flags that the note's own arithmetic implied a
ceiling near 1000 KiB while naming a 1 MiB limit; which is right decides
whether there is 20 KiB of headroom or none, and only the dashboard knows.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_013jGA1JrHcFtpHu711uq5DN
@cloudflare-workers-and-pages

Copy link
Copy Markdown

Deploying with  Cloudflare Workers  Cloudflare Workers

The latest updates on your project. Learn more about integrating Git with Workers.

Status Name Latest Commit Updated (UTC)
✅ Deployment successful!
View logs
count-it 930f321 Aug 08 2026, 08:17 PM

@backwerdrimshot
backwerdrimshot merged commit 850a553 into main Aug 8, 2026
3 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants