Repository navigation
Conversation
sgardoll
marked this pull request as ready for review
September 28, 2026 08:16
…ing-chrome Both sides replaced the racy synchronous read of generatorModels with a polled expectation; keep the landed version's poll-with-timeout. Co-Authored-By: Stuart Gardoll <sgardoll@gmail.com>
…ing-chrome reopenWalkthrough keeps the modal-function reopen (STU-445 removed the header entry) but drops the ccc_usage wait: the base's updateUsageDisplay now defers the paywall while a dialog is open, so a passive exhausted resolution no longer closes an open tour. Co-Authored-By: Stuart Gardoll <sgardoll@gmail.com>
A mid-demo click/keypress canceled the typing timer but left the frozen prefix in the field, so a Generate click or Enter could submit a half-typed example. Takeover now lands the demo's own end state — the complete shipped prompt with the caret retired — via finishHeroDemo. Two takeover shapes skip the restore instead: an interaction arriving with text already selected (select-all, assistive insert) is an edit in flight — overwriting the field would destroy the selection the incoming replacement needs — and a takeover during the hold period has nothing typed to complete. Both freeze the demo on the prefix and mark it demo-owned: send stays disabled and Enter stays inert until a real input event hands the text to the user. Also fixes the reduced-motion listener lifecycle: a pagehide dispose made bfcache restores lose the listener, so a demo replayed after back-forward navigation ignored a later flip. The listener now lives for the document's lifetime (dispose reserved for genuine teardown), and a repeat initComposer on the same DOM replaces the dead registration via a WeakMap instead of stacking a second listener. Adds an e2e covering a mid-demo click followed by an immediate submit, and demo-completion waits in smoke/stu376 where prompts were being polled mid-type. Co-Authored-By: Stuart Gardoll <sgardoll@gmail.com>
Takeover restore landed the full shippedPrompt in the field, but a keystroke, Backspace, paste, drop or IME commit that followed then joined the example — the browser inserts into whatever the field holds, and the input handler treated the combination as user text. Text the demo supplied while interrupted is now tracked as demo-owned (heroDemoOwned) through the frozen and restored states. A beforeinput listener — the single funnel every real edit passes through — clears it before the native mutation lands, so typing mid-demo produces a prompt of the user's own and Backspace removes demo text rather than deleting inside the example. A demo that finishes untouched hands the shipped text back as the field's own content, so ordinary editing resumes. New e2e coverage: mid-demo typing yields only the typed text, and Backspace during the demo leaves an empty field. Co-Authored-By: Stuart Gardoll <sgardoll@gmail.com>
…ui-ux' into pr105 Co-Authored-By: Stuart Gardoll <sgardoll@gmail.com> # Conflicts: # e2e/stu385-composer-settings.spec.js # e2e/stu391-tutorial-onboarding.spec.js # src/composerAdapter.js
- cancelTyping() lands each running demo's end state instead of abandoning a submittable prefix (view switches, tab hides). - A pointerdown takeover releases demo ownership after the restore, so the first Backspace trims the complete prompt; focus/keydown restores stay demo-owned so typing mid-demo still writes a fresh prompt. - e2e: click+Backspace trims one char; switchView during typing and during the hold both settle the shipped prompt and Generate submits it whole. Co-Authored-By: Stuart Gardoll <sgardoll@gmail.com>
sgardoll
merged commit Sep 28, 2026
34d1c0f
into
milestone/stu-implement-updated-ui-ux
1 of 2 checks passed
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.
STU-445 items addressed (owner's wording quoted)
#wt-reopen). The walkthrough still auto-opens for fresh users; there is no user-facing reopen entry for now (the returning-user spec now reopens through the app's ownopenWalkthroughModal()).--fg(the mock'sbrand-logomarkgeometry); the rounded-rect box and the FlutterFlow / Custom Code Connect wordmark are gone..topnavnav is gone. Account stays reachable via#topbar-avatar, Home via the logo, Plans via its/#plansdeep link and the account surface's "Change plan" action..topbarno longer paints--bgor the mobileborder-bottom; it keepsposition: fixedso every existing--topbar-hlayout offset is unchanged..brandstill links#home; new coverage proves Account → logo → Home, and avatar → Account.is-demo-typing; the.ghost .typed::aftercaret was already in the stylesheet). Starts on Home load, cancels on any real interaction, skipped under reduced motion and on non-home deep links.textarea:focus { box-shadow: 0 0 0 4px rgba(59,130,246,.1), … }rule painted a blue ring on#pipeline-input..composer .fieldoverrode its outline but never its box-shadow. The field now setsbox-shadow: none, leaving the composer's own orange border +:focus-withinring.stu385 CI race — diagnosis and fix (the red
cion PR #100)Symptom on CI:
e2e/stu385-composer-settings.spec.js:175received[]forgeneratorModelsin the initial run and both retries (Ubuntu, node 22.15.1,CI=1, 1 worker), while passing on macOS.Root cause: a test-harness race, not an app race. The test waits for
#generation-stageto be visible and then reads the captured array synchronously.runThinkingPipeline()reveals the stage inshowPipelineProgress()before the architect request is issued; the generator request only leaves after the architect round-trip completes. On a fast local machine the whole mocked pipeline finishes before Playwright's visibility poll resolves (probe timings: click at 687 ms, architect 718 ms, generator 734 ms, stage observed visible at 748 ms). On slower CI the poll resolves while the architect step is still in flight, so the read sees[]. The app's selection path is not at fault: the dialog'schangehandler forwards to the canonical#code-generator-modelsynchronously, and the request carries exactly what the selector holds.Reproduction (the break): adding a 250 ms delay to the architect route in the real spec made it fail 9/9 locally with
Received: Array [], exactly matching CI:CI=1 CCC_TEST_PORT=3105 npx playwright test e2e/stu385-composer-settings.spec.js --grep "a model chosen in the dialog" --repeat-each=3→ 9 failed.Fix: observe the request itself with
expect.poll(() => generatorModels).toEqual(["anthropic/claude-opus-5"]). No timeout increase, no weakened assertion.CI=1 CCC_TEST_PORT=3105 npx playwright test e2e/stu385-composer-settings.spec.js --repeat-each=10→ 80 passed (10 consecutive runs of all 8 specs).Fail → pass evidence per acceptance criterion
Each new assertion was run against the pre-change app (temporarily restored
index.html+src/composerAdapter.js), watched to FAIL, then restored and watched to PASS.npx playwright test e2e/stu375-hero-navigation.spec.js --grep "header shows only"→ 3 failed--grep "mobile topbar keeps"→ 3 failednpx playwright test e2e/stu376-composer.spec.js --grep "hero demo types"→ 3 failed--grep "clicking the prompt input shows only"→ 3 failed[]The typing test samples
.ghost .typedfrom navigation commit and asserts every sample is a strictly longer prefix of the shipped prompt (text CHANGES over time), ending on the full prompt with the caret class retired.Full CI sequence on the pushed head
CI=1 npm testCI=1 npm run buildCI=1 CCC_TEST_PORT=3105 npm run test:uiCI=1 npm run test:accessibilityCI=1 npm run test:deploy-guardCI=1 npm run test:proxiesCI=1 python3 scripts/scan_bundle_for_leaks.pyJudgement calls (flagging explicitly)
a.nav-link[…]clicks to update, but removing the nav links also brokee2e/stu375-hero-navigation.spec.js(its mobile/navigation/focus tests clicked.topnav a[data-view=…]),e2e/stu389-hero-mark-field.spec.js:153,173(a[data-view=…]), ande2e/stu391-tutorial-onboarding.spec.js(#wt-reopen). They were updated to the surviving controls; the rest of their assertions are untouched. Without this, the full suite cannot be green.stu375; typing demo + computed focus styles instu376) because the acceptance criteria require fail→pass evidence and no existing test covered those behaviours.src/composerAdapter.jswas edited: the brief named "hero typing demo" under app.js ownership, but the composer's state machine (and therefore send gating for a mid-demo submit) lives in this module. The edit is confined to the composer's own typing/suggestion logic.switchView()cleanup: removed the now-orphaned.nav-link[data-view]aria-currentloop.updateUsageDisplay→showPaywallExhaustedcloses the open modal). The old click helper raced it too (the baseline CI log shows one of these tests failing its first attempt at 30.2 s). The helper now waits for the app's own usage signal (ccc_usagewritten) before opening.Not implemented / not verified
position: fixed(the mock uses absolute); only the background/border was removed, so the--topbar-hoffsets are unchanged.