Files
kawaandClaude Sonnet 4.6 0a0a51b45a docs(05-tech-debt): create phase 5 plan — 4 plans across 2 waves
Wave 0 TDD stubs, Wave 1 parallel (registry + ReviewStep), Wave 2 act() fix.
Covers TECH-01 through TECH-05.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-30 09:26:17 +02:00

8.6 KiB

phase, plan, type, wave, depends_on, files_modified, autonomous, requirements, must_haves
phase plan type wave depends_on files_modified autonomous requirements must_haves
05-tech-debt 02 execute 1
05-00
src/components/wizard/ReviewStep.tsx
true
TECH-01
TECH-02
truths artifacts key_links
User who deselected RMM sees only the Intune output blocks in ReviewStep (RMM block is unmounted)
User who deselected Intune sees only the RMM output block in ReviewStep (Intune blocks are unmounted)
User with both targets deselected sees only the rclone.conf block
ZIP bundle respects scriptTargets — deselected targets are excluded from the ZIP file list
User can click Back on ReviewStep to dispatch SET_STEP(2)
path provides contains
src/components/wizard/ReviewStep.tsx scriptTargets-driven conditional rendering + Back button showIntune
from to via pattern
ReviewStep.tsx state.deployment.scriptTargets showIntune and showRmm booleans derived from scriptTargets.includes() scriptTargets.includes
from to via pattern
Back button dispatch({ type: 'SET_STEP', payload: 2 }) onClick handler using dispatch from useWizard() SET_STEP.*payload.*2
Modify ReviewStep to conditionally render output blocks based on state.deployment.scriptTargets, filter the ZIP bundle to match selected targets, and add a Back button that dispatches SET_STEP(2).

Purpose: TECH-01 eliminates visual noise from deselected script targets. TECH-02 provides the expected Back navigation consistent with the DeploymentStep pattern. Output: Modified ReviewStep.tsx only — no other files touched.

<execution_context> @C:/Users/SebastienQUEROL/.claude/get-shit-done/workflows/execute-plan.md @C:/Users/SebastienQUEROL/.claude/get-shit-done/templates/summary.md </execution_context>

@.planning/PROJECT.md @.planning/phases/05-tech-debt/05-CONTEXT.md @.planning/phases/05-tech-debt/05-RESEARCH.md @.planning/phases/05-tech-debt/05-00-SUMMARY.md

From src/store/types.ts:

export const INITIAL_STATE: WizardState = {
  deployment: {
    scriptTargets: ['intune', 'rmm'],  // default = both selected
  },
};
export type WizardAction =
  | { type: 'SET_STEP'; payload: number }
  | { type: 'SET_DEPLOYMENT'; payload: Partial<WizardState['deployment']> }
  // ...

From src/store/context.tsx:

export function useWizard(): { state: WizardState; dispatch: React.Dispatch<WizardAction> }

Current ReviewStep.tsx signature:

const { state } = useWizard();  // dispatch is NOT currently destructured — must add it

From CONTEXT.md — locked decisions:

  • Intune maps to: intuneInstall + intuneDetection blocks
  • RMM maps to: rmmScript block
  • rclone.conf OutputBlock is ALWAYS shown regardless of scriptTargets
  • Edge case: both deselected → only rclone.conf shown + ZIP has only rclone.conf
  • Unmount entirely (NOT CSS-hidden) — no state to preserve between show/hide

Back button pattern (from DeploymentStep.tsx):

<div className="flex gap-3 mt-6">
  <button
    type="button"
    onClick={() => dispatch({ type: 'SET_STEP', payload: 2 })}
    className="px-4 py-2 text-sm border border-gray-300 rounded-md hover:bg-gray-50"
  >
    Back
  </button>
</div>

Note: payload is 2 because DeploymentStep is step index 2.

Task 1: Add scriptTargets filtering and Back button to ReviewStep src/components/wizard/ReviewStep.tsx - showIntune = state.deployment.scriptTargets.includes('intune') — boolean - showRmm = state.deployment.scriptTargets.includes('rmm') — boolean - {showIntune && } — unmounted when false - {showIntune && } — unmounted when false - {showRmm && } — unmounted when false - rclone.conf OutputBlock always rendered (no condition) - handleDownloadZip builds files array dynamically: rclone.conf always, intune files if showIntune, rmm file if showRmm - Back button renders at bottom (before ZIP button) with label 'Back', dispatches SET_STEP(2) on click - useMemo calls for intuneInstall, intuneDetection, rmmScript are KEPT (used in ZIP handler even when hidden) Edit src/components/wizard/ReviewStep.tsx:
1. Change `const { state } = useWizard();` to `const { state, dispatch } = useWizard();`

2. After the useMemo calls, add two boolean derivations:
   ```tsx
   const showIntune = state.deployment.scriptTargets.includes('intune');
   const showRmm = state.deployment.scriptTargets.includes('rmm');
   ```

3. Replace handleDownloadZip with the dynamic version:
   ```tsx
   async function handleDownloadZip() {
     const files: { name: string; content: string }[] = [
       { name: 'rclone.conf', content: rcloneConf },
     ];
     if (showIntune) {
       files.push({ name: 'intune-install.ps1', content: intuneInstall });
       files.push({ name: 'intune-detection.ps1', content: intuneDetection });
     }
     if (showRmm) {
       files.push({ name: 'rmm-script.ps1', content: rmmScript });
     }
     await downloadZip(files, 'rclone-deployment.zip');
   }
   ```

4. Wrap Intune OutputBlocks with showIntune condition (unmount entirely):
   ```tsx
   {showIntune && (
     <OutputBlock label="Intune Install Script" content={intuneInstall} filename="intune-install.ps1" disabled={!acknowledged} />
   )}
   {showIntune && (
     <OutputBlock label="Intune Detection Script" content={intuneDetection} filename="intune-detection.ps1" disabled={!acknowledged} />
   )}
   ```

5. Wrap RMM OutputBlock with showRmm condition:
   ```tsx
   {showRmm && (
     <OutputBlock label="RMM Script" content={rmmScript} filename="rmm-script.ps1" disabled={!acknowledged} />
   )}
   ```

6. Add Back button before the ZIP button, following DeploymentStep's established pattern:
   ```tsx
   <div className="flex gap-3 mt-6">
     <button
       type="button"
       onClick={() => dispatch({ type: 'SET_STEP', payload: 2 })}
       className="px-4 py-2 text-sm border border-gray-300 rounded-md hover:bg-gray-50"
     >
       Back
     </button>
   </div>
   ```

Do NOT remove any existing comment lines (SECU-01, SECU-02, etc.).
Do NOT touch any useMemo calls — they are needed for ZIP handler even when the blocks are hidden.
The existing DOWN-05 test (both targets selected = 4 files in ZIP) still passes because INITIAL_STATE has scriptTargets=['intune','rmm'].
The existing DOWN-02, DOWN-03, DOWN-04 tests still pass because they use default state with both targets.

Anti-patterns to avoid:
- Do NOT use CSS `hidden` class — must unmount (conditional render with &&)
- Do NOT wrap rclone.conf OutputBlock in a condition — it is always shown
cd /c/Users/SebastienQUEROL/Documents/projets/Ready2Blob && npx vitest run src/components/wizard/ReviewStep.test.tsx 2>&1 | tail -20 All ReviewStep tests pass (green), including: - Pre-existing CONF-02, CONF-03, DOWN-01 through DOWN-06, SECU-01, SECU-02 - New TECH-01 filtering cases (intune-only, rmm-only, neither, ZIP-neither) - New TECH-02 Back button case Zero act() warnings in output (existing tests use fireEvent on checkbox/download buttons which do not trigger async state updates outside the component). Run full suite to confirm ReviewStep is green and no regressions: ``` cd /c/Users/SebastienQUEROL/Documents/projets/Ready2Blob && npx vitest run ``` Expected: All ReviewStep tests green. TECH-01 and TECH-02 stubs from Plan 00 now pass.

<success_criteria>

  • ReviewStep conditionally renders Intune blocks based on showIntune boolean (conditional render, not CSS)
  • ReviewStep conditionally renders RMM block based on showRmm boolean
  • rclone.conf OutputBlock always renders
  • handleDownloadZip builds files array filtered by showIntune/showRmm
  • Back button renders and dispatches SET_STEP(2) via dispatch
  • All pre-existing ReviewStep tests still pass (DOWN-02/03/04 positional index tests unaffected — default state has both targets)
  • New TECH-01 and TECH-02 tests from Plan 00 now pass (GREEN state) </success_criteria>
After completion, create `.planning/phases/05-tech-debt/05-02-SUMMARY.md`