Conversation
Bundle sizes [mpdx-react]Compared against 169bcfb No significant changes found |
wjames111
left a comment
There was a problem hiding this comment.
Multi-Agent Code Review — /quality:agent-review (standard mode)
Verdict: BLOCKERS_FOUND — 1 high-priority blocker, plus 7 medium-priority items and ~13 informational suggestions.
Agents: Architecture, Testing, Standards, UX, Financial Reporting (+ dependency-impact). Security and Data Integrity skipped (no auth/API/Apollo-cache paths touched).
Risk: 10/10 by formula (driven by file count — 10 production components touched), but the actual changes are narrow per-file (UI text + a few calc tweaks). Blast radius is fully contained in src/components/HrTools/PdsGoalCalculator/; no external API or index.ts re-exports affected. The titleTooltip → description interface rename has zero orphaned callers.
Highlights
🔴 High Priority Blocker (sev 8.0)
HoursPerWeekGrid: displayed average can differ from applied average. HoursPerWeekGrid.tsx:493 uses .toFixed(2), but line 512 applies Math.round(x*100)/100. These diverge on .xx5 floating-point boundaries — verified with concrete inputs (totalHours=9.1 → user sees 0.17, but 0.18 is saved). The drifted value propagates through saveField → calculateSalaryTotals → goal totals. Also a documented Standards violation per .CLAUDE/rules/code-review.md (.toFixed in calculation paths). See inline comment for the fix. Cross-agent consensus (Financial, Architecture, Testing, UX, Standards).
🟡 Medium Priority (sev 5.0-6.9)
- Missing test for multi-line Form Type helperText —
SetupStep.tsx - Untested
getLocationLabel0%/undefined fallback branch —SetupStep.tsx - Pay Type TextField departs from
AutosaveTextFieldpattern undocumented —SetupStep.tsx - Over-max reimbursable value retained in cell with red border despite "will not be saved" description —
MonthlyReimbursableSection.tsx+ReimbursableExpensesGrid.tsx - Non-descriptive translation key
t('({{location}})')—salaryBreakdown.tsx - Heading hierarchy: step + subsection both use
variant="h6"(a11y) — multiple step components
All details + before/after code blocks are in the inline review comments below.
🟢 Suggestions (sev < 5)
- Pay Type switch silently clears
payRate— consider visible inline feedback. - Move SummaryReportStep heading above the loading guard.
- Extract a shared
roundToCentshelper tosrc/lib/intlFormat.ts(addresses root cause of the blocker — 3 sites already use this pattern). MonthlyReimbursableSection.fieldsrebuilt every render;getLocationLabelnot memoized.- 5 new heading+description blocks lack render tests (low risk — presentational JSX behind translation keys).
- InfoIcon
aria-labelmay double-announce with the visible(max $35/mo)label. - Various small testing edge cases (undefined max, negative multiplier, empty-string location).
Pre-existing (informational)
HoursPerWeekGrid.test.tsxuses severalawait waitFor(() => getBy*)patterns where the project prefersfindBy*. Not introduced by this PR.
Unresolved Debate
UX flagged Pay Type TextField's disabled-state visual treatment may differ from surrounding AutosaveTextField peers (sev 6.0). Architecture countered factually that AutosaveTextField has no saving adornment / spinner, so the visuals match (sev 3.5). The two arguments address different aspects. Recommendation: a visual check with isMutating=true will resolve it conclusively.
Generated by /quality:agent-review — multi-agent review with cross-examination debate. 5 agents + dependency impact. Mode: standard, model: opus.
There was a problem hiding this comment.
Multi-Agent Code Review — PR #1780
Mode: Standard · Agents: Architecture, Testing, Standards, UX, Financial Reporting (+ Coverage-Gap Review) · Risk: 10/10 (CRITICAL, breadth-driven across 13 non-test files in a single feature)
Verdict: APPROVED_WITH_SUGGESTIONS
No CRITICAL (≥9.0) or HIGH-priority (≥8.0) blockers were found. The PR is well-scoped, the WYSIWYS rounding in HoursPerWeekGrid is correctly implemented (display = applied = persisted to hoursWorkedPerWeek), and i18n discipline is generally strong (static keys, no template-literal interpolation inside t()).
Findings summary (post-debate consensus):
| Tier | Count | Notes |
|---|---|---|
| Critical (≥9.0) | 0 | — |
| High (8.0–8.9) | 0 | — |
| Important (7.0–7.9) | 1 | Cannot be /dismiss'd — strongly recommended |
| Medium (5.0–6.9) | 5 | Block CLEAN verdict but not merge |
| Suggestions (<5.0) | ~20 | Informational only |
⚠️ 1 Important finding (severity 7.0–7.9) — strongly recommended but doesn't block merge and can't be/dismiss'd. Consider addressing in this PR or creating a follow-up ticket.
Risk Assessment
Risk score is capped at 10/10 but the nature of the changes is low-blast-radius: 12 medium-risk component files in a single feature (PdsGoalCalculator) plus 1 shared lib (intlFormat.ts) with a backward-compatible signature extension. No auth, no API, no schema, no migrations.
Dependency Impact
src/lib/intlFormat.ts— 144 importers across the app.numberFormatsignature is extended with an optionaloptionsparam (backward compatible). 9 files importnumberFormatdirectly; signature change is non-breaking.- All other changes are leaf or internally-encapsulated within
src/components/HrTools/PdsGoalCalculator/**.
Cross-Examination Highlights
The debate round produced significant re-calibration:
- Silent over-max clipping (
ReimbursableExpensesGrid.tsx): Financial (3.0) vs UX (6.0) vs Architecture (4.0 post-debate). UX argues description text ≠ in-context feedback per WCAG 3.3.1; Architecture/Financial argue the documented contract (section description + per-row tooltip + new test) is adequate. Consensus: medium-priority UX clarity concern, not a financial bug. - Autosave divergence (
HoursPerWeekGrid.tsx:287, 340): Financial originally 6.5; revised DOWN to 3.0 after verifyingaverageHoursPerWeekis a scratch column never read by salary math (downstream pay useshoursWorkedPerWeekwhich receives the rounded value via Apply). - Pay Type bypass of AutosaveTextField (
SetupStep.tsx:214): Architecture's 6.5 revised DOWN to 4.5 (Yup rule is only.required()andMenuItemprevents empty value, so the validity gate is functionally inert here). BUT Testing'sisMutatingtest gap went UP to 7.5 because it's now the only validity gate left. - Translation nesting (
MonthlyReimbursableSection.tsx:26-32): Standards revised DOWN to 3.5 (not a literal Checklist violation — uses{{}}placeholders, not template-literal interpolation). UX held at 6.5 (translator-grammar concern). Consensus: 6.0 (translator-context smell, not a hard violation).
Important Issues (Severity 7.0–7.9)
See inline comment on SetupStep.tsx:214.
Medium-Priority Issues (Severity 5.0–6.9)
See inline comments on:
SetupStep.tsx:219— Pay Type clears Pay Rate without warningMonthlyReimbursableSection.tsx:28—buildCappedLabeltranslation nestingintlFormat.ts:16—numberFormatoptions not unit-testedReimbursableExpensesGrid.tsx:105— Silent over-max clipping
Suggestions (Severity <5.0)
Lower-priority findings inline on ReimbursableExpensesGrid.tsx:133, HoursPerWeekGrid.tsx:122, HoursPerWeekGrid.tsx:521.
Other suggestions (not inlined — informational only)
- Step-intro duplication across
SupportItemStep,SummaryReportStep, andReimbursableExpensesStep— same<Box pb={4}><Typography variant="h6" component="h2">…</Typography><Typography pt={1}>…</Typography></Box>pattern in 3 files. Extract<StepIntro title description />toShared/. (3.5/10) OtherSection.tsxmissing description test — sibling sections (Annual/Total/Monthly Reimbursable) added description-render assertions in this PR;OtherSectiondid not. (2.5/10)- Heading hierarchy nit —
ReimbursableExpensesGrid.tsx:181andTotalReimbursableSection.tsxrendervariant="h6"withoutcomponent="h3", producing a muddled outline under the step'sh2. (4.0/10) - AmountSuffix screen reader gap —
salaryBreakdown.tsx:160-164renders0%(Atlanta)without whitespace separation in screen-reader output. (4.0/10) getLocationLabeltemplate literal —SetupStep.tsx:87-93builds Autocomplete label with`${location} (${percent})`; not a violation (wraps data only, no English copy) but inconsistent with neighboringt()usage. (2.5/10)geographicMultiplierSuffixtemplate literal —salaryBreakdown.tsx:1194-1196same pattern. (2.5/10)- Description tests —
SupportItemStep,SalarySection,SummaryReportStep,ReimbursableExpensesStepadd new description copy without colocated assertions. Static i18n strings without branching are low-value to test, butSalarySectionhas no test file at all. (2.5/10) - HoursPerWeekGrid locale-formatted average not tested — new
numberFormatcall withminimumFractionDigits: 2lacks non-US-locale assertion. (3.5/10)
Pre-debate findings that were withdrawn
HoursPerWeekGrid autosave divergence at lines 287/340 (severity 6.5)— Financial Agent verifiedaverageHoursPerWeekis never consumed by salary math; downgraded to 3.0. A one-line fix would still tighten data hygiene for any future server-side consumer (PDFs, exports).
Standards Checklist
All mandatory items in .CLAUDE/rules/code-review.md pass:
- Named exports only · PascalCase file naming · Colocated tests ✓
- i18n via
useTranslation/t(), static keys,{{}}interpolation ✓ - No
any, no@ts-ignore, nonew Date(), no debug output, no emptycatch✓ - Apollo
optimisticResponseincludes__typenameandid(pre-existing pattern) ✓ - No
.graphql/migration changes (N/A items) ✓
How to respond
- For severity <7 findings you disagree with, reply
/dismiss: <reason>on the comment. - For the Important finding (severity 7.5), address in this PR or open a follow-up ticket — it can't be
/dismiss'd.
There was a problem hiding this comment.
AI Review Auto-Approval
Risk Level: MEDIUM (5/10)
Verdict: APPROVED_WITH_SUGGESTIONS (suggestions posted, no blockers)
This PR was auto-approved because:
- The multi-agent AI review determined it is medium risk
- No blocking issues were found
- All suggestions have been posted as review comments for the developer to consider
If you believe this PR needs human review, dismiss this approval and request a review manually.
Description
Bundles UI/text refinements across the PDS Goal Calculator from six related Jira tickets, plus a small Pay Type bug fix.
4.0% (Atlanta)), update the Gross Monthly Pay formula to include the location, and append each location's percentage to the options in the Location dropdown.$300/monthminimum. On the Monthly Reimbursable grid, show the per-month maximums inline with the Ministry Cell Phone and Ministry Internet field names and add a description above the grid clarifying that amounts above the max will not be saved.Defaultdescription and theSimpledescription render on separate lines.Additional minor fix:
Related Jira tickets: MPDX-9569, MPDX-9568, MPDX-9567, MPDX-9564, MPDX-9563, MPDX-9474.
Testing
Navigate to the PDS Goal Calculator (HR Tools → PDS Goal Calculator) and walk through each step:
Setup step
Defaultsentence andSimplesentence on two separate lines.Orlando, FL (6%).37.46).Reimbursable Expenses step
(max $35/mo)/(max $30/mo)inline with the field name and an info icon whose tooltip reads "Pre-filled with the maximum allowed amount. Edit to a lower value if needed."$300minimum description in place of the previous info tooltip; the floor still applies (totals below$300snap to$300).Support Items step
(Atlanta)next to the percentage and the Gross Monthly Pay formula readsMonthly Base × (1 + Geographic Multiplier (Atlanta)).Summary step
Checklist:
/pr-reviewcommand locally and fixed any relevant suggestions