fix(reports): remove dead attachmentsNote override and refactor ReportWizardPage to useReducer - #1988
Conversation
…tWizardPage to useReducer #1967: Remove the dead attachmentsNote override path from applyOverrides.ts and overrideKeys.ts. The field became read-only in PR #1959 (static inline meta suffix); no EditableField exists for it and no UI path can produce its override key. Adds a regression test that pins the removal and a positive control proving the remaining usageText path still applies. #1947: Refactor ReportWizardPage from 38 useState/useRef hooks to a useReducer state machine (wizardReducer.ts). Fixes four staleness defects caused by hand-maintained clear/keep lists. Staleness is now structural: opaque request-id tokens make the M1 (getSourceReport) and M2 (AI generation) classes of bug unrepresentable. Named tier types with explicit factory return-type annotations enforce that adding a new cascade-owned field is a compile error in any factory that omits it (AC4). The refactor is behaviour-preserving: existing ReportWizardPage tests pass unchanged (AC3). Fixes #1967 Fixes #1947 Co-Authored-By: Claude dev-team-lead <noreply@anthropic.com> Co-Authored-By: Claude frontend-developer <noreply@anthropic.com> Co-Authored-By: Claude qa-integration-tester <noreply@anthropic.com>
|
[ux-designer] Design review of PR #1988 (stories #1967 + #1947). Verdict: APPROVED Scope reviewed
Token adherenceNo CSS files are modified. No hardcoded colors, spacing, radii, or font sizes are introduced anywhere. All existing Dark modeNo color values changed. Unaffected. AccessibilityAll existing ARIA attributes are preserved in
Discard modal condition changeThe condition change from the inline expression AI elapsed timer effectThe cleanup restructure — moving Component reuseNo new components or CSS patterns introduced. No component reuse violations. No non-blocking findings. |
|
[product-architect] Verdict: CHANGES_REQUESTEDOne blocking finding (HIGH, ~4 lines, zero behaviour change). Everything else below is non-blocking. This is a strong refactor overall — the tier partition is exactly the shape I asked for in the action-set review (named tier interfaces, explicit factory return-type annotations, total object literals), the opaque-nullable-token model is implemented correctly, BlockingH1 — AC4's forcing function has a hole in exactly the two cases that need it most
Adding a fifth field to The fix is to compose from the factory and name the single exception, which is byte-for-byte behaviour-identical and keeps every existing test (including the M-I case 'SELECT_SOURCE':
return {
...state,
...freshReportTier(),
...freshContentTier(),
// M-I: handleSourceChange never cleared aiError — the ONLY ContentTier field kept.
aiError: state.aiError,
reportRequestId: action.payload.requestId,
sourceId: action.payload.sourceId,
currentStep: Math.min(state.currentStep, 3),
maxReachedStep: 3,
};case 'DISCARD_EDITS':
return {
...state,
...freshContentTier(),
// Cleared only when a generation was in flight (original guardedUpdate behaviour).
aiError: state.aiRequestId !== null ? '' : state.aiError,
};After this, a new Same structural note, informational only: Non-blocking (follow-ups / nits)M1 — const hasEdits = hasManualEdits(wizardState);
// ...
}, [hasEdits, runAiGeneration]);No user-visible impact today (the callback goes to a plain M2 — L1 — duplicated status union. L2 — default: {
const _exhaustive: never = action;
return state;
}L3 — Prettier drift. L4 — L5 — docblock count. L6 — #1967 AC1 not satisfied. AC1 requires the option-(a) decision recorded as a comment on #1967. The reconciliation comment was posted on #1941 (satisfying AC5), but #1967 itself currently has zero comments. Please post the decision there for traceability. Verified (no action needed)Behaviour-equivalence checks I walked line by line, since AC3 makes this a behaviour-preserving refactor:
Re-request me once H1 is addressed; I do not need another full pass on the rest. |
…hContentTier() Spread ...freshContentTier() in SELECT_SOURCE and DISCARD_EDITS before overriding aiError with per-case logic. A future ContentTier field added to freshContentTier() now produces a compile error in both cases instead of being silently preserved — the AC4 enforcement guarantee is now complete. Also format wizardReducer.test.ts per Prettier (lines 766-794). Co-Authored-By: Claude dev-team-lead <noreply@anthropic.com> Co-Authored-By: Claude frontend-developer <noreply@anthropic.com> Co-Authored-By: Claude qa-integration-tester <noreply@anthropic.com>
|
[product-architect] Verdict: APPROVEDRe-reviewed H1 verified resolved
AC4 is now total for Behaviour is unchanged: L3 verified resolved
Verification run
Non-blocking items carried forward from round 1Unchanged and explicitly not blocking; either fold into a follow-up or drop as you see fit: M1 One new informational nit, not worth a commit on its own: in Still owed outside this PR#1967 AC1 — the option-(a) decision is recorded on #1941 (AC5) but #1967 itself still has no comment. Please post it there before closing the issue; it is the traceability artifact the AC asks for, and it does not block the merge. |
Co-Authored-By: Claude product-architect <noreply@anthropic.com> Co-Authored-By: Claude qa-integration-tester <noreply@anthropic.com>
|
🎉 This PR is included in version 2.13.1-beta.10 🎉 The release is available on GitHub release Your semantic-release bot 📦🚀 |
|
🎉 This PR is included in version 2.14.0 🎉 The release is available on GitHub release Your semantic-release bot 📦🚀 |
Summary
attachmentsNoteoverride fromapplyOverrides.tsandoverrideKeys.ts; field has been static read-only text since PR fix(reports): improve report PDF UX — paragraph breaks, inline meta, inline notes, column toggles #1959, no UI path can produce its override key; adds regression test pinning the removalReportWizardPagefrom 38useState/useRefhooks to auseReducerstate machine inwizardReducer.ts; staleness now enforced via opaque request-id tokens (M1/M2 fixes); named tier types with explicit factory return-type annotations enforce AC4 at compile time; 57 unit tests at 100% coverage; behaviour-preserving (existing tests unchanged per AC3)Fixes #1967
Fixes #1947
Test plan
wizardReducer.test.ts— 57 tests, 100% coverageapplyOverrides.test.ts/overrideKeys.test.ts— regression test pins dead-code removalnpm run lint— zero findings in all PR files🤖 Generated with Claude Code
Co-Authored-By: Claude dev-team-lead noreply@anthropic.com
Co-Authored-By: Claude frontend-developer noreply@anthropic.com
Co-Authored-By: Claude qa-integration-tester noreply@anthropic.com