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>
8.6 KiB
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 |
|
|
true |
|
|
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.mdFrom 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
<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>