Repository navigation
v0.0.2.1 feat: pause direct booking behind a flag - #81
Merged
jamescruisepalmer merged 6 commits intoOct 5, 2026
Merged
Conversation
Onboarding-call volume outran the time we have to run the calls, so no profile submitter is routed to the Calendly scheduling panel anymore -- not even one who clears all three qualifiers. This is a capacity limit, not a fit one, so nothing about the qualifier was loosened or deleted: `qualifies` is still scored on every submission and the panel markup stays in welcome.html. The routing now reads `routedToBooking` (`qualifies && DIRECT_BOOKING_OPEN`), so reopening is one flag flip back to `true` with no other edits. Both analytics events carry `routed_to_booking` alongside the existing `qualified`, so the people we would have booked stay visible while the pause is on. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Executes the real post-submit block with the flag injected, so the same source runs both paused and reopened. Covers the pause today, the one-flag-flip rollback, both analytics events (so `qualified` cannot be quietly dropped), and the booking panel staying present-but-hidden. Also guards the two ways the pause could be silently undone: flipping the flag, or re-pointing the panel choice back at `qualifies`. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
The gh-pages deploy rsynced the repo root with only a handful of exclusions, so tests/ was being served at grandeldercare.com/tests/ -- HTTP 200, no X-Robots-Tag, and robots.txt says Allow: /. A test that asserted on the booking URL would therefore have published that link on a crawlable path, defeating the noindex on welcome.html that was the pause's only real containment. Excludes tests/ from the deploy, and drops the bookable event path from the test file in favour of the Calendly host, so the file stays harmless even if that exclusion is ever reverted. Also adds a test workflow. The only workflow before this was the Pages deploy, so nothing ran the suite -- which made the new guard against silently reopening booking a guard that never fired. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
"A few quick questions to help us match you with the right next step" was written when the qualifier routed people to two different places. Every submitter now lands on the same panel, so the promise no longer matches what happens. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
The direct-booking pause changed behavior that several README sections still described as current, so the docs contradicted the code in ways a reader would have acted on. - Add a `## Tests` section. The branch added CI for a suite the README never mentioned, so there was no way to learn the suite existed, how to run it, or that `node --test tests/` fails on Node 22 and needs the glob. - Add `tests/` to the documented deploy exclusions, with the reason: a `.cjs` file served at `/tests/` cannot carry a `noindex`, so publishing it would route crawlers past the protection on `welcome.html`. - Note that `website_onboarding_call_clicked` is dormant, not broken. Its only trigger is the Calendly button on the now-unreachable panel, so it goes to zero for the duration of the pause. - Disambiguate the analytics names in the Status bullet and the 0.0.2.1 changelog entry. `profile_completed` reaches PostHog as `website_profile_completed`; searching the bare name finds nothing. - Mark the two superseded Status entries that still claimed qualifiers see the scheduling panel and that "Back to home" was removed. Supersession pointers rather than rewrites, matching how this section already handles history. Co-Authored-By: Claude Opus 5 (1M context) <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.
Summary
Pauses direct booking: nobody is routed to the Calendly scheduling page anymore, including people who clear every qualifier. Onboarding-call volume outran the time we have to run the calls.
The pause
script.jsgains one module-level kill switch,DIRECT_BOOKING_OPEN = false. The post-profile panel choice now readsroutedToBooking(qualifies && DIRECT_BOOKING_OPEN) instead ofqualifies, so every profile submitter lands on the "You're on the list." panel.routed_to_bookingalongside the existingqualified— so we can still see exactly who we would have booked.welcome.html, commented as intentionally unreachable.Containment fixes found during review
tests/was being served live. Verified:grandeldercare.com/tests/waitlist-phone.test.cjsreturns HTTP 200, noX-Robots-Tag, androbots.txtisAllow: /. A test asserting on the booking URL would have published that link on a crawlable path, defeating thenoindexonwelcome.htmlthat was the pause's only real containment. The deploy now excludestests/, and the test file asserts on the Calendly host rather than the bookable event path..github/workflows/test.yml.Copy
Before / After
A perfect-fit candidate (iPhone, loved one lives alone, no pets) submitting the profile form:
Profile intro copy:
Deploy surface:
grandeldercare.com/tests/*.cjsserved live, HTTP 200, crawlable.tests/excluded. A simulated rsync confirmswelcome.html(which isnoindex) is the only deployed file still carrying the booking URL.No other visual change: both panels already existed and are unmodified.
Test Coverage
Tests: 56 → 71 (+15). Coverage gate: PASS (82%, target 80%).
Mutation testing during the audit found the original tests would have passed with
qualifieddeleted from the event, and with the flag gate replaced by a literalfalse(which silently kills the rollback). Both are now caught behaviourally.Pre-Landing Review
Checklist passes clean (no SQL, no auth, no migrations, no LLM boundary in this diff). Adversarial review raised 11 findings; 5 were acted on in this PR, the rest are recorded below as judgment calls.
Acted on:
tests/published to the live site with the booking URL — fixed (deploy exclusion + host-only assertion).Open judgment calls, not blockers:
qualifiedas a proxy for "was offered a call" now over-report. The two populations used to be identical and are now disjoint.routed_to_bookingis the correct field for "offered"; existing PostHog insights should be checked.website_onboarding_call_clickedwill flatline to zero for the duration of the pause. Dormant, not broken — useful as a deploy canary.CHANGELOG.mdis published to the live site and now names the flag. Pre-existing deploy behaviour, flagged rather than changed unilaterally.Design Review
Design Review (lite): 0 findings. The only shipped markup changes are an HTML comment and one copy edit; both panels and all CSS are unmodified. Verified the hiding mechanism is sound —
welcome.css:5.profile-done[hidden]{display:none}at specificity (0,2,0) beats.profile-doneatwelcome.css:35, which sets nodisplay.Eval Results
No prompt-related files changed — evals skipped.
Plan Completion
No plan file detected.
Documentation
Doc diff preview
## Testssection. This branch added.github/workflows/test.yml, but nothing in the README mentioned the suite existed. The new section covers the run command, what the 71 tests cover, whytests/direct-booking-pause.test.cjsis a guard rather than a feature test (reopening booking is a deliberate two-step: flip the flag, update the guard), and the Node 22 trap wherenode --test tests/resolves the directory as a module entry point and fails before running anything — CI uses the glob for the same reason.tests/added to the documented deploy exclusions. The SEO & Indexing section listed onlyREADME.mdandgoogle-apps-script/. Now carries the reason: a.cjsfile served at/tests/cannot hold anoindexthe waywelcome.htmldoes, so publishing it would route crawlers straight past that protection.website_onboarding_call_clickedmarked dormant, not broken. Its only trigger is the Calendly button on the panelDIRECT_BOOKING_OPENnow hides, so the event drops to zero for the duration of the pause and returns on its own. A flat line there is the pause working, not instrumentation coming loose — don't alert on it until booking reopens.profile_completedandwaitlist_profile_submit_successare call-site names.profile_completedreaches PostHog aswebsite_profile_completed(searching the bare name returns nothing) andwaitlist_profile_submit_successis sheet-side only. Anyone chartingrouted_to_bookingwould have hit this.workflow_dispatchdocumented — the shipped workflow has a manual trigger the first draft of the Tests section omitted.CHANGELOG entries were preserved verbatim apart from one additive clarifying parenthetical; nothing was deleted, reordered, or regenerated. VERSION (
0.0.2.1) was already bumped and its entry covers every commit on the branch, so it was left as-is.Documentation Debt
Both items are pre-existing, predate this branch, and were not touched by it — flagged rather than fixed to keep this PR focused:
script.js:721aborts at 45000ms.full_name,zipcode,phone_type,lives_alone,has_pets) in Qualify Grand signups before showing the scheduling call link #55, and no alpha-tester field is collected. README:336 is in the present-tense## Current Sectionssection, so it reads as a live claim.Backend
No Apps Script change ships with this.
routed_to_bookingrides inside the existingraw_payloadJSON column exactly asqualifiedalready does, so there is no sheet migration and no redeploy dependency. Sheet-side it needs a JSON extract to chart; PostHog gets it as a first-class property.Test plan
node --test tests/*.test.cjs), 0 failuresfetchstubbed (no real waitlist row created) — booking panel stayed hidden, waitlist panel shown, no console errorstests/excluded,welcome.htmlthe only deployed file carrying the booking URL/tests/exposure before the fix (HTTP 200, noX-Robots-Tag)🤖 Generated with Claude Code