Repository navigation
Draft blank screener forms with AI - #545
Merged
Merged
Conversation
Require complete input bindings, preserve drafts for review, and announce completion once all benefits have decisions. Include regression coverage and user documentation. Refs #544
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Both services now send structured-output requests through GeminiClient, so the endpoint, auth header, status handling and response parsing live in one place. Alias generation also gains the finishReason check that form drafting already had. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The controller already extracts the input paths to check that a draft is possible, so it now passes them to the draft service instead of having it walk every check schema again. The question ID mapping is built once and shared by the prompt, response schema and ordering, so all three always use the same ID-to-path mapping. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Field keys come from the server's question ID mapping, never from the model, so the separate ordering step and the key existence, duplicate, count and reserved-segment checks could never fail. toFormSchema now reads the model's keyed questions directly, and its remaining checks are the ones that guard model output: coverage, ordering, labels, descriptions and option values. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Custom check inputs without a declared type are extracted as "any", and the example screener's own custom checks use them. Drafting previously failed for these after the full Gemini call and blamed the Gemini configuration. The model now picks an answer type (yes_no, number, date or text) for each untyped input, and array:any inputs become checklists like array:string. Each question gets its own response schema, so choice arrays must have at least one option and typed scalar questions cannot have options. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
A check without an input definition, or an input type drafting cannot build a field for (such as array:number), used to surface as a 503 telling the builder to check the Gemini configuration, which retrying never fixed. A missing input definition failed before any Gemini call; an unsupported type failed only after the full call. The draft service now checks both up front and throws UndraftableFormException, which the endpoint returns as a 400 naming the check or inputs to fix. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Radio and checklist option values from the model were only checked for being non-blank and unique, so a value like "Spouse" for the enum value "spouse", or "Homestead" for the code "PhlHomesteadExemption", passed validation and silently made the check never match. Option values now come from the input's schema enum or, for arrays without one such as enrollments, from the string parameters of the checks that read the input. Gemini's response schema restricts option values to that list, and the server rejects drafts that use any other value or leave such a question without choices. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
form-js assigns a random key such as textfield_k3j9a before formField.add fires, so the !field.key guard stopped the handler from ever setting a new field's key to its ID. The guard was meant to keep keys during draft imports, which also emit formField.add, so the handler now skips events while a draft is being imported instead. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
onDataChange set resultsLoading, which also drives the Results panel, so the panel switched to "Loading results..." on every edit and stayed that way through the debounce. A separate resultsStale signal now hides the completion message from the first edit until results for the latest answers arrive, and resultsLoading is only set while an evaluation request is in flight. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
A single failed evaluation cleared the results, which removed the public results panel and brought back every hidden question with no explanation. The public screener and Preview now keep the last successful results and hidden questions, show an alert that the latest answers could not be evaluated, and keep the completion message hidden until an evaluation of the latest answers succeeds. Co-Authored-By: Claude Opus 5.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.
Summary
Closes #544.
Blank screener forms now offer Draft with AI after benefits and checks are configured. Gemini drafts one question per unique required input, with server-assigned bindings and field types. The draft stays editable and unsaved for review; incomplete drafts are rejected, and unsupported or unconfigured checks report an actionable error before calling Gemini. Choice values are constrained to schema enums or configured check values.
Preview and published screeners show Screening complete only after every benefit has an eligibility decision for the latest answers. Failed evaluations preserve the last results, display an error, and suppress completion. Alias generation and form drafting share the Gemini client, with a separate form-drafting feature toggle.
Verification
npm test— 178 tests passed.npm run build— passed.ScreenerFormDraftServiceTest,ScreenerResourceTest, andEligibilityCheckAliasServiceTest— 25 tests passed.npm run build— passed after the final manual documentation edits.Documentation impact
.env.examplewith the drafting configuration.