Skip to content

Share one screening session between Preview and published screeners - #586

Merged
prestoncabe merged 5 commits into
mainfrom
585-shared-screening-session
Nov 5, 2026
Merged

prestoncabe merged 5 commits into
mainfrom
585-shared-screening-session

Conversation

@prestoncabe

@prestoncabe prestoncabe commented Nov 5, 2026 •

Copy link
Copy Markdown
Collaborator

Closes #585.

Summary

Preview and the published screener each had their own copy of the screening session flow (form-js mount, debounce, the guard against out-of-date evaluations, stale/failed state, hidden questions). The copies had drifted. Now both pages create one screening session and keep only their chrome.

 builder-frontend/src/components/
 ├── screener/
-│   ├── FormRenderer.tsx            # public copy of the flow
 │   └── Screener.tsx                # CRM bridge + chrome
 ├── screenerEditor/preview/
-│   ├── FormRenderer.tsx            # preview copy of the flow
 │   └── Preview.tsx                 # chrome only
 └── shared/
-    ├── screeningCompletionFlow.test.tsx
+    └── screeningSession/
+        └── screeningSession.tsx    # the shared module
+src/testing/formJs.ts                # type into form-js like a person
const session = createScreeningSession({
  schema,
  evaluate,          // evaluateScreener | evaluatePublishedScreener
  initialAnswers?,   // a CRM host's prefill: missing answers stay null until answered
  evaluateOnLoad?,   // Preview, and published screeners with a connected host
  onResults?,        // latest evaluation only -> bridge.result
  onEvaluationFailed?, // latest evaluation only -> bridge.error
});
<session.Form />  // plus results, stale, failed, loading, answersSent,
                  // unneeded questions, nextStepsShown, projectNextSteps

Behaviour changes:

  • Published screeners evaluate 500ms after answers stop changing, not 1000ms, matching Preview.
  • Preview's form no longer attaches a listener when it unmounts before its first import finishes.
  • Preview still evaluates as soon as it opens. That used to happen only because form-js's first fill was mistaken for an edit. It is now the explicit evaluateOnLoad option (see the comment on #585).

Adds a root GLOSSARY.md defining Screener, Published screener, Preview and Screening session.

Evidence

  • Before: the page tests mocked both FormRenderers and called submitForm / onDataChange by hand. The real chain (form-js changed → debounce → evaluate → stale/failed) never ran for published screeners.
    After: screeningSession.test.tsx (18 tests) types into a real form-js form, with a fake evaluate adapter whose promises the test settles. It covers debounce, out-of-date responses and failures, hidden questions and re-import, prefill with unknown answers, evaluate on load, teardown, and the next steps projection. Screener.test.tsx and Preview.test.tsx drive the real form too.
  • builder-frontend npm test: 54 files, 389 tests passed. npm run build: passed.
  • Full bin/run-e2e-tests: 25 passed. During development, "User can Preview a Screener Form" caught the evaluate-on-open regression and now passes.

Merge Danger

Door: two-way

A frontend-only refactor. No API, schema or stored-data changes. A revert restores both renderers.

Blast Radius: screening

Every screening session, in Preview and on published screeners including CRM hosts, now runs through this module. The places most likely to show a regression are the faster published debounce (more evaluations sent to builder-api while someone types) and the timing of CRM results and next steps.

🤖 Generated with Claude Code

prestoncabe and others added 4 commits November 4, 2026 19:15
One module owns a person's answers, their evaluation, and the form-js
form they answer in, so both screening pages can share it. Name the
concept in a new glossary.

Part of #585.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Preview keeps only its chrome. Its form now stops listening when it
unmounts before the first import finishes. The results extension is
tested against a plain form-js form instead of through each renderer.

Part of #585.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The page keeps the CRM bridge and its chrome; the session's
latest-evaluation hooks report results and failures to the host.
Published screeners now evaluate 500ms after answers stop changing,
as Preview does.

The renderer tests move to the session, and the page tests drive a real
form instead of a mocked renderer.

Part of #585.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Preview used to evaluate as soon as it opened only because its renderer
mistook form-js's first fill for an edit. Make that an explicit
evaluateOnLoad option, separate from the unknown answers a host
provides, so Preview still evaluates unanswered checkboxes as unchecked.

Part of #585.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@prestoncabe
prestoncabe force-pushed the 585-shared-screening-session branch from 600fe33 to 20b8376 Compare November 5, 2026 00:16
Move the helpers that type into a real form-js form out of the
screening session, and explain in the README why they exist. Update the
README's screening results section for the shared screening session.

Part of #585.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@prestoncabe
prestoncabe merged commit efcd0a0 into main Nov 5, 2026
6 checks passed
@prestoncabe
prestoncabe deleted the 585-shared-screening-session branch November 5, 2026 19:54
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.

Share one screening session between Preview and published screeners

1 participant