Repository navigation
Add regression tests for keyboard handling, expanders, and distortion updates - #53
Merged
Merged
Conversation
…lt-sense intensity cues
Three problems reported from the phone.
1. Tapping a text box left it hidden; you had to scroll to find it.
On Android, interactive-widget=resizes-content shrinks innerHeight
along with the visual viewport, so kbHeight() (innerHeight minus
vv.height) read ~0. .kb-open never switched on, the bottom nav and the
capture step's sticky Back / Continue bar stayed parked above the
keyboard, and the visibility check ignored both, so a field behind
them counted as visible. Reproduced on a 390px viewport: the Body
textarea sat 143px under the footer while being typed into.
Keyboard height is now measured against the tallest height seen at
the current width while a text field has focus. revealInView()
measures the visible band minus the bottom nav, the sticky footer and
the top banners, clips it to a scrolling dialog, and scrolls the
dialog then the page. It only acts on focus the user caused (a tap on
the field or its label, Tab, or focusForUser() for "Add another
thought" and the starter chips), so code that restores focus with
preventScroll still never moves the page, and hand scrolling still
switches auto-scroll off. A <details> expander, a journal entry, and
a new mood row opened near the bottom now unfold into view instead of
under the footer or nav.
2. The suggested Socratic question didn't fit the distortion.
All-or-Nothing, Mental Filter and Minimization were all handed the
responsibility pie ("how big would my slice actually be?"). The type
used to be "Perspective broadening" (zoom out to the week); PR 6
swapped its question for the pie and left the mapping pointing at it.
Added Shades of gray (0 to 100 continuum) and Full picture, renamed
the pie to Responsibility pie and gave it Personalization and
internal control fallacy. Added three reframe styles so every default
fits its distortion: Balanced thought, Flexible preference (shoulds,
fairness, change) and Behavior, not identity (labeling). Compassionate
reattribution's starter now works for blame in either direction.
Stored "Zoom out (pie chart)" and "Perspective broadening" migrate.
3. Intensity cues described how someone sounds, not how it feels.
"Raised voice", "vocal frustration" and "yelling" were an observer's
checklist on a self-report scale. The cues now describe felt
experience, and "Inferred from speech, not directly felt" on the body
field reads "Pieced together later, not felt at the time". The
Socratic box is three lines so its starter question isn't cut off.
Regression blocks 28-30 cover the keyboard reveal, the expander reveal,
and the pairings / migration / cue wording; each fails against the
previous code. Full suite green: lint, check, crypto, smoke, flows,
robustness, sync, regressions.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01N8j1Ct5L5H38YPLcFi7bfn
…and scales against sources A source-by-source review of every piece of clinical content, checked against Burns (Feeling Good 1980, Handbook 1989, 2016 checklist), J. Beck (2020, Beck Institute worksheets), Greenberger & Padesky (Mind Over Mood, 2nd ed.), Padesky (1993, 1994, 2019), Salkovskis (1999), McKay, Davis & Fanning (1981), Wolpe's SUDS, Borkovec et al. (1983) with Dippel et al.'s 2023 meta-analysis, Beck et al. (1979), Furukawa et al. (2018), NICE NG116 and CG178, and each crisis service's own site (checked Sep 2026). Crisis resources: the US 988 Lifeline and Canada's separate 9-8-8 Suicide Crisis Helpline were merged under one "US / Canada" label with a US-only chat link; they're now listed apart. The text-line keywords were wrong outside the US (UK is SHOUT to 85258, Canada's 686868 is Kids Help Phone with CONNECT, Ireland is Text About It on 50808). The IASP directory link now redirects to their homepage; Find A Helpline replaces it. Emergency numbers cover Canada and Ireland. Distortions: plain definitions faithful to Burns and Beck. always/never moved to Overgeneralization; Catastrophizing is the worst-case prediction; "Minimization" is restored to Burns's two-way Magnification and Minimization (stored tags migrate); Personalization covers assuming others' moods are about you; Should Statements cover shoulds aimed at others. "Common pairs" had no published support and are now labelled as examples with a reason each. The first Blame example told users "responsibility is usually shared", which can blame victims; it now makes room for having had no part. Questions and reframes: Evidence examination weighs both lists; Decata- strophizing asks worst, best and most likely before coping; the responsibility pie fills in your own slice last, as Salkovskis does, and is now Blame's default too; "Historical test" (a schema life-review in the literature) is "Track record"; Behavioral experiment is an actual test; the Socratic explainer no longer claims Socrates never lectured. Structure: picking a distortion no longer writes a stock reframe into the entry. Tapping through saved sentences with a literal "[X]" as the user's balanced thought, the "unsupported thought replacement" the Reference warns against; the starter is now the placeholder only. Step 4 gains a field to answer the Socratic question, carried through review, detail view, Markdown export, search and draft autosave. Wording and attributions: the step-order comment credited Padesky with an order the code doesn't use (the order matches Burns and J. Beck); README no longer calls the flow "the full Mind Over Mood walk"; "Padesky asks for both" is Beck's outcome column. Hot thought is the most emotionally charged one; belief is rated "at the time". The accuracy tile no longer tests thoughts by how true they feel. The Outcome screen referred to a prediction that is never collected. The intensity scale gets a 0 (None) anchor and personal endpoints, and Severe starts at 80 where the grounding note appears. The mood list drops non-emotions (hypervigilant, blameworthy, threatened, excluded), de-duplicates "contemptuous", and adds each family's plain word; retired words on old entries stay selectable. Worry, activity, scope: "It's worry time" shows only inside the window; "Most worries dissolve" and the fixed "Most worries didn't need the work" overclaimed; Settings path fixed; a see-a-doctor line for symptom worries. Mastery is a sense of accomplishment relative to today; the predicted-vs- actual "gap" claim is softened per Furukawa 2018; the Patterns card no longer claims a category is "most worth the time". The pivot chip no longer prompts an apology. "CBT alone tends to fall short" for trauma, psychosis and severe depression contradicted NICE; it now says a self-help journal isn't enough on its own and names what does help. Regression blocks 30-31 extend coverage: no stock reframe written on seeding, Blame's default, the Track record / Magnification migrations, the 0 anchor and Severe edge, and per-country crisis lines with no dead links. Full suite green: lint, check, crypto, smoke, flows, robustness, sync, regressions. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01N8j1Ct5L5H38YPLcFi7bfn
…eelings, pivot prediction, worry loop
Decisions on the open questions from the content audit.
- Accuracy is judged after the evidence. The "facts back this thought up"
choice from Step 3 comes back on Step 4 once both evidence lists are
written, since distorted thoughts feel true too. No "partly accurate"
state: the true-fact, distorted-conclusion case is the normal reframe
path, and Step 5 now says so ("keep the true part, rewrite the
conclusion").
- New feelings after the reframe. Mind Over Mood's last column re-rates
the original moods "as well as any new moods". Added as words (relief,
calm, hope), not rated rows: every mood statistic reads a falling
number as progress, which a rising "relief" is not.
- A prediction before the pivot. Optional "What do you expect will
happen?" on Step 6, shown again on the Outcome screen and entry, and in
the reflection prompt, so the action becomes a small behavioral
experiment with something to check against.
- Worry loop. Postponements are counted; after two, the worry says
worry time is for dealing with it. "Open as thought record" becomes
"Work it through or make a plan", since the thought record ends in one
concrete step. No new resolution value, so stats and sync are unchanged.
- Activity types add "Work or study" and "Meaning", the behavioral
activation life areas that had nowhere to go, with matching icons.
- "Jealousy" becomes "Jealousy & envy" (Parrott & Smith, 1993); stored
moods migrate. Family names are now escaped wherever they render.
- Kept as is: saving an untouched belief slider's shown value. It is a
deliberate choice (the number is on screen when you move on), and
dropping it would silently remove belief-change data from Patterns.
New fields (newFeelings, pivotPrediction, postponeCount) go through
normalizeEntry, review, entry detail, Markdown export, search and draft
autosave. Regression block 32 covers all of it. Full suite green: lint,
check, crypto, smoke, flows, robustness, sync, regressions.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01N8j1Ct5L5H38YPLcFi7bfn
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.
This PR adds comprehensive regression tests and updates documentation to ensure proper handling of mobile keyboard interactions, UI element visibility, and distortion/reframe logic.
Summary
Extended the regression test suite with three new test blocks (28–30) covering critical mobile UX and clinical content updates, plus corresponding smoke test enhancements and README clarifications.
Key Changes
Test Block 28 (Keyboard handling): Validates that tapped input fields are lifted clear of both the Android keyboard and sticky chrome when
interactive-widget=resizes-contentshrinks the viewport. Ensures.kb-openclass switches on correctly even when keyboard height reads as 0px.Test Block 29 (Expander visibility): Confirms that
<details>elements opened near the bottom of a step unfold into view rather than being hidden under the sticky Continue bar.Test Block 30 (Distortion pairings & migrations):
Smoke test updates: Added assertions for the Socratic answer field on Step 4 and enhanced evidence capture validation.
README clarification: Updated the Thought Record description to reference the Mind Over Mood 7-column model and Burns/Beck distortion framework explicitly, and clarified behavioral activation and worry postponement features.
Implementation Details
DISTORTIONS,DISTORTION_DEFAULTS,INTENSITY_BANDS, etc.) withinpage.evaluate()contextsgetBoundingClientRect()to ensure fields and expanders remain visible above sticky footershttps://claude.ai/code/session_01N8j1Ct5L5H38YPLcFi7bfn