Skip to content

Feat/pbyr 4321 continue blocked italy apl#1189

Open
jordividaller wants to merge 3 commits into
mainfrom
feat/pbyr-4321-continue-blocked-italy-apl
Open

Feat/pbyr 4321 continue blocked italy apl#1189
jordividaller wants to merge 3 commits into
mainfrom
feat/pbyr-4321-continue-blocked-italy-apl

Conversation

@jordividaller

@jordividaller jordividaller commented Jul 25, 2026

Copy link
Copy Markdown
Collaborator

Problem

On the Italy APL onboarding schema, the continue button appeared dead: clicking it did nothing, with no visible error. The validation was rejecting non_compete_clause_compensation_amount — a computed field that was never rendered, so no error message could be shown.

Root causes (two unit mismatches in the same chain)

1. Visibility vs validation disagree on number types.
react-hook-form stores number inputs as strings ("50"). The jsfVersion 1 engine evaluates type: 'number' guards in if conditionals strictly, so the conditional revealing the computed field never matched — while validation (parseJSFToValidate) does coerce, and required the field. v0 schemas were never affected because that engine casts strings via yup, which is why this never surfaced before.

Fix: createHeadlessForm now coerces number-field values before evaluating the schema, mirroring the existing money coercion (top-level properties, empty/invalid input left untouched).

2. Money consts double-converted to cents.
Once visible, the forced-value field failed with "The only accepted value is X": ForcedValueField injected the schema const raw (cents) into the form state, and the submit path re-applied convertToCents, producing a 100x value.

Fix: getForcedFieldValue() converts money consts to units at both injection call sites (JSONSchemaForm, FieldSetField).

Tests

  • src/common/tests/createHeadlessForm.test.ts — locks the visibility bug on a minimal jsfVersion 1 schema (verified to fail without the fix).
  • src/components/form/tests/utils.test.ts — locks the cents conversion.
  • Full suite green (829/829). Manually verified end-to-end in the JSON schema playground with the Italy APL schema (added as a playground sample in the second commit).

Notes

  • Number coercion covers top-level properties only, same scope as the existing money coercion; no current schema uses a number guard inside a fieldset.
  • To reproduce with a hand-written schema, x-rmt-meta.jsfVersion: "1" is required — without it the schema silently goes through the v0 engine and the bug disappears.

Note

Medium Risk
Touches headless form initial values and forced-value injection on submit/validation paths; changes are scoped and covered by new tests but affect conditional schema behavior for all jsf v1 forms with number guards.

Overview
Fixes Italy APL–style dead Continue behavior where validation failed on a hidden computed money field.

jsfVersion 1 conditional visibility: createHeadlessForm now injects coerced top-level number fields into initial values (same pattern as money), using strict isNumericValue so empty/whitespace/ambiguous values are not treated as 0 before if/allOf evaluation. That aligns visibility with validation when react-hook-form still has number inputs as strings ("50").

Forced money consts: ForcedValueField accepts fieldType and converts money schema consts from cents to display units before setValue, so submit no longer double-applies convertToCents. Call sites pass fieldType from JSONSchemaForm and FieldSetField.

Adds isNumericValue / shared castNumberValue for API number transforms, plus tests for number-guard visibility and money forced values.

Reviewed by Cursor Bugbot for commit 28be947. Bugbot is set up for automated code reviews on this repo. Configure here.

@github-actions

github-actions Bot commented Jul 25, 2026

Copy link
Copy Markdown
Contributor

📦 Bundle Size Report

Metric Current Previous Change Status
Total (gzip) 256.65 kB 256.65 kB -4 B (-0.0%) 🟢
Total (raw) 704.52 kB 704.16 kB +362 B (+0.1%) 🔴
CSS (gzip) 21.69 kB 21.69 kB 0 B (0%) 🟢
CSS (raw) 112.66 kB 112.66 kB 0 B (0%) 🟢

Size Limits

  • ✅ Total gzipped: 256.65 kB / 350 kB (73.3%)
  • ✅ Total raw: 704.52 kB / 850 kB (82.9%)
  • ✅ CSS gzipped: 21.69 kB / 25 kB (86.7%)

Largest Files (Top 5)

  1. chunk-IDN5WH7H.js - 14 kB (new)
  2. styles.css - 10.84 kB (0 B (0%))
  3. index.css - 10.84 kB (0 B (0%))
  4. chunk-AVIZTG4K.js - 8.54 kB (0 B (0%))
  5. index.js - 6.55 kB (-9 B (-0.1%))
View All Files (400 total)
File Size (gzip) Change
chunk-IDN5WH7H.js 14 kB new
styles.css 10.84 kB 0 B (0%)
index.css 10.84 kB 0 B (0%)
chunk-AVIZTG4K.js 8.54 kB 0 B (0%)
index.js 6.55 kB -9 B (-0.1%)
chunk-HI4J2GNO.js 6.44 kB new
chunk-AS7SJDU5.js 6.4 kB 0 B (0%)
chunk-KYDGZUYQ.js 5.38 kB new
chunk-2B65YE3E.js 4.86 kB new
chunk-SGSUZXHB.js 4.8 kB new

✅ Bundle size check passed

@github-actions

github-actions Bot commented Jul 25, 2026

Copy link
Copy Markdown
Contributor

📊 Coverage Report

✅ Coverage increased! 🎉

Metric Current Previous Change Status
Lines 83.53% 83.48% +0.04% 🟢
Statements 82.90% 82.86% +0.04% 🟢
Functions 81.45% 81.41% +0.04% 🟢
Branches 75.81% 75.72% +0.09% 🟢

Detailed Breakdown

Lines Coverage
  • Covered: 3990 / 4777
  • Coverage: 83.53%
  • Change: +0.04% (12 lines)
Statements Coverage
  • Covered: 4054 / 4890
  • Coverage: 82.90%
  • Change: +0.04% (12 statements)
Functions Coverage
  • Covered: 1076 / 1321
  • Coverage: 81.45%
  • Change: +0.04% (3 functions)
Branches Coverage
  • Covered: 2498 / 3295
  • Coverage: 75.81%
  • Change: +0.09% (12 branches)

✅ Coverage check passed

@github-actions

github-actions Bot commented Jul 25, 2026

Copy link
Copy Markdown
Contributor

Deploy preview for adp-cost-calculator ready!

Project:adp-cost-calculator
Status: ✅  Deploy successful!
Preview URL:https://adp-cost-calculator-dnnhsymh8-remotecom.vercel.app
Latest Commit:28be947

Deployed with vercel-action

@github-actions

github-actions Bot commented Jul 25, 2026

Copy link
Copy Markdown
Contributor

Deploy preview for remote-flows ready!

Project:remote-flows
Status: ✅  Deploy successful!
Preview URL:https://remote-flows-jdg03avm9-remotecom.vercel.app
Latest Commit:28be947

Deployed with vercel-action

@cursor cursor Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Cursor Bugbot has reviewed your changes and found 1 potential issue.

Fix All in Cursor

❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, have a team admin enable autofix in the Cursor dashboard.

Reviewed by Cursor Bugbot for commit 96b3332. Configure here.

Comment thread example/e2e/add-estimation.spec.js Outdated
…lidation

Fixes two unit mismatches that silently blocked the Italy APL onboarding
continue button (PBYR-4321):

1. Number inputs are stored as strings by react-hook-form, and the
   jsfVersion 1 engine evaluates `type: 'number'` guards in conditionals
   strictly (v0 casts via yup, which is why this never surfaced before).
   Visibility and validation disagreed: a conditional computed field was
   required by validation but never rendered. createHeadlessForm now
   coerces number field values before evaluating the schema, mirroring
   the existing money coercion.

2. ForcedValueField injected money consts raw (cents) into the form
   state, and the submit path re-applied convertToCents, producing a
   100x value rejected by the const check. getForcedFieldValue converts
   money consts to units at both injection call sites.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@jordividaller
jordividaller force-pushed the feat/pbyr-4321-continue-blocked-italy-apl branch 2 times, most recently from 20fae34 to 28f356a Compare July 25, 2026 09:20
…sion

Review follow-ups on the PBYR-4321 fix:

- Extract castNumberValue and use it in both the validation transform and
  the visibility coercion in createHeadlessForm, so the two paths cannot
  drift apart again.
- Move the money const cents-to-units conversion into ForcedValueField
  itself instead of duplicating getForcedFieldValue at each call site.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@jordividaller
jordividaller force-pushed the feat/pbyr-4321-continue-blocked-italy-apl branch from 28f356a to 401e1ec Compare July 25, 2026 09:22
@jordividaller jordividaller self-assigned this Jul 25, 2026
Number() turns ' ', true and [] into 0, so the coercion added for JSF v1
number guards opened conditionals the user never filled in. Measured
against the base commit, a whitespace-only value flipped the dependent
field from hidden to visible.

Add isNumericValue(), which rejects booleans, arrays and blank strings,
and use it in createHeadlessForm instead of the '' / null / undefined
check plus the typeof guard it needed afterwards.

castNumberValue keeps its lenient behaviour: it also backs the submit
path, where an empty number field currently sends 0 to the API, and
tightening it there would change the payload. Restore the comment
explaining its NaN passthrough, lost when it was extracted.

Cover whitespace and non-scalar values, plus a v0 schema locking in that
the coercion stays a no-op there, since nothing branches on jsfVersion.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
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.

1 participant