TEAL feedback: step through a trace without redrawing the page; drop the stale trace-sat fallback - #178
Merged
Merged
Conversation
The fallback fired on the half of trace-satisfaction yes/no questions whose
trace genuinely satisfies the formula (TRACESAT_YES_PROBABILITY = 0.5), where
there is no misconception formula to contrast against. It has been stale since
per-state feedback landed in 2.1.6: it rendered *below* a paragraph that
already explains the verdict ("This trace does satisfy the formula... a trace
satisfies the formula exactly when it holds from the very first state"), and
its step-through recommendation duplicated the "Want to see it step by step?"
stepper button below it.
Those questions now carry no predetermined feedback; both templates and the
model view already guarded on truthiness. The "No" case keeps its contrastive
feedback, which names the formula the trace does satisfy -- something the
per-state marks don't say.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Each trace state was rendered as its own copy of the formula tree and a step cross-faded between two of them. For 250ms both copies were display:block inside a flex-wrap container, so the stepper took two rows and everything below it jumped down and back; the entering copy rebuilt its trace diagram from scratch even though the diagram is the same at every step but for the highlight; and a 1s flash animation ran over the tree. A step read as a page reload. Only the sat/unsat classes and the highlighted state actually differ between steps, so only those change now. getStepperViewData sends the tree once plus a truth vector per state, addressed by a new data-node-index emitted in the pre-order getAllSubformulae walks. TraceRenderer.setHighlight moves the highlight by toggling attributes on the existing SVG -- every state gets a hidden CURRENT badge at render time -- so nothing is created, measured or resized. Dropping the transition also drops the guard that ignored input while it ran, so holding an arrow key no longer loses most of the presses. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Two changes prompted by the TEAL demo and the feedback that came out of it.
1. Stepping through a trace no longer redraws the page
The complaint from the demo was that clicking through the stepper felt like a reload. It isn't one — no request fires — but three things happened on every click:
showContainercross-faded between two of them. For the 250ms transition both copies weredisplay: blockinside#statecontainer, which isdisplay: flex; flex-wrap: wrapwith.containerchildren — so the stepper occupied two rows and the rule, the "different trace" button and the footer were shoved down and snapped back.renderTraceForContainercalledTraceRenderer.render, which ends incontainer.innerHTML = ''. The diagram is identical at every step; onlyhighlightIndexdiffers. The whole thing blanked and repainted to move one box.flashHighlightanimation fired over the tree, every step.Only two things actually differ between steps: which nodes of the tree are satisfied, and which state is current. So only those change now.
TraceSatisfactionResult.getStepperViewDatareturns the formula tree once plus one truth vector per state. Nodes are addressed by a newdata-node-index, emitted in the same pre-ordergetAllSubformulaewalks, so vector position i is the node with index i. A step togglestree-sat/tree-unsat.TraceRenderer.setHighlight(container, index)moves the highlight by setting attributes on the SVG that is already there. Every state gets aCURRENTbadge at render time, hidden but for the current one, so moving the highlight creates, measures and resizes nothing.renderis unchanged for callers that pass nohighlightIndex(the feedback panel, the misconception explainers).Verified in the running app, stepping forward through all 4 states and back:
<svg>elementDropping the transition also drops the
isTransitioningguard, which discarded clicks and keypresses that arrived inside the 250ms window — so holding an arrow key lost most of them. Stepping now keeps up with the keyboard.Smaller things in the same file: the empty stepper tab says "No formula loaded" like the Table and Matrix tabs instead of rendering blank; the arrow buttons carry
aria-labels rather than relying ontitleover an<i>; the resize re-render is debounced and deferred while the tab is hidden; and the keydown handler no longer throws on an event whose target has notagName.Not in this PR. The tree colours each subformula by its truth at the current instant, so a satisfied
p U qsits directly above an unsatisfiedqwith nothing on screen explaining thatqholds three states later — same forX.2. The stale "no further feedback" message on trace-satisfaction y/n
On a wrong answer to a trace-satisfaction yes/no question, students could see:
It is the fallback for the half of those questions whose trace genuinely satisfies the formula (
TRACESAT_YES_PROBABILITY = 0.5), where there is no misconception formula to contrast against. It has been stale since per-state feedback landed in 2.1.6, on both halves:build_tracesat_yn_questionnow leavesfeedbackasNonefor that case. The "No" case is untouched and keeps its contrastive feedback, which names the formula the trace does satisfy — something the per-state marks don't say.exercise.htmlandstudentexercises.htmlboth wrap the block in{% if q.feedback %}, andmodelroutes.pyreads it asstr(question.get('feedback') or ''), so nothing else needed changing.Tradeoff:
displayTraceSatFeedbackhas several silent early returns (SPOT evaluation raises,TraceRendererabsent, unparseabledata-trace, state count not matching the drawn trace). Those rare cases previously fell back to this sentence and now show the verdict line plus the stepper button alone. The better fix is a verdict-aware fallback on the client, where it can fire exactly when the per-state block is missing; that is not in this PR.Testing
336 passed(full suite). Five new tests intest/test_stepper.pycovergetStepperViewData: one vector per trace state,data-node-indexvalues contiguous and in pre-order, vector length matching the node count, values binary and agreeing with per-state satisfaction, the tree shape identical at every step (the invariant the class-swapping relies on), and the empty-result case.Version bumped to 2.1.8 with CHANGELOG entries.