--- phase: 02-generators plan: 01 type: execute wave: 1 depends_on: [] files_modified: - src/generators/rclone-conf.test.ts - src/generators/intune-install.test.ts - src/generators/intune-detection.test.ts - src/generators/rmm-script.test.ts - src/generators/index.ts autonomous: true requirements: - CONF-01 - DEPL-01 - DEPL-02 - DEPL-03 - DEPL-04 - DEPL-05 must_haves: truths: - "All four generator test files exist and fail RED (imports resolve, implementations missing)" - "The index.ts barrel file exports all four generator functions" - "npm test passes (passWithNoTests configured; stubs may skip or fail)" artifacts: - path: "src/generators/rclone-conf.test.ts" provides: "Failing unit tests for CONF-01" contains: "buildRcloneConf" - path: "src/generators/intune-install.test.ts" provides: "Failing unit tests for DEPL-01, DEPL-04, DEPL-05" contains: "buildIntuneInstall" - path: "src/generators/intune-detection.test.ts" provides: "Failing unit tests for DEPL-02, DEPL-05" contains: "buildIntuneDetection" - path: "src/generators/rmm-script.test.ts" provides: "Failing unit tests for DEPL-03, DEPL-04, DEPL-05" contains: "buildRmmScript" - path: "src/generators/index.ts" provides: "Re-export barrel for all generators" exports: - buildRcloneConf - buildIntuneInstall - buildIntuneDetection - buildRmmScript key_links: - from: "src/generators/rclone-conf.test.ts" to: "src/generators/rclone-conf.ts" via: "import { buildRcloneConf } from './rclone-conf'" pattern: "from './rclone-conf'" - from: "src/generators/index.ts" to: "src/generators/*.ts" via: "named re-exports" pattern: "export.*from" --- Write all four generator test files (failing) and the index.ts barrel before any implementation exists. Purpose: Nyquist rule — tests must exist before implementations. Plans 02, 03, 04 implement against these stubs. The barrel establishes the public API that Phase 4 will import from. Output: Four test files (RED), one barrel file, all four generator module paths defined. @C:/Users/SebastienQUEROL/.claude/get-shit-done/workflows/execute-plan.md @C:/Users/SebastienQUEROL/.claude/get-shit-done/templates/summary.md @.planning/PROJECT.md @.planning/ROADMAP.md @.planning/STATE.md @src/store/types.ts @src/schemas/registry.ts From src/store/types.ts: ```typescript export interface WizardState { currentStep: number; remote: { name: string; backendType: BackendType | null; params: Record; }; deployment: { includeInstall: boolean; configPath: 'machine-wide' | 'user-profile'; scriptTargets: ('intune' | 'rmm')[]; }; } export const INITIAL_STATE: WizardState = { currentStep: 0, remote: { name: '', backendType: null, params: {} }, deployment: { includeInstall: false, configPath: 'machine-wide', scriptTargets: ['intune', 'rmm'], }, }; ``` From src/schemas/registry.ts: ```typescript export type BackendType = 'azureblob' | 's3' | 's3-compatible'; ``` Task 1: Write test stubs for all four generators src/generators/rclone-conf.test.ts, src/generators/intune-install.test.ts, src/generators/intune-detection.test.ts, src/generators/rmm-script.test.ts rclone-conf.test.ts: - imports buildRcloneConf from './rclone-conf' (file does not exist yet — RED) - azureblob: output contains '[my-azure]', 'type = azureblob', 'account = mystorageaccount', 'key = BASE64KEY', does NOT contain 'sas_url' (empty field omitted) - s3: output contains '[my-s3]', 'type = s3', 'provider = AWS', 'access_key_id = AKID', 'secret_access_key = SKEY', 'region = us-east-1' - s3-compatible: output contains 'type = s3' (NOT 'type = s3-compatible'), 'provider = Other', 'endpoint = https://s3.wasabisys.com', does NOT contain 'region' (empty field omitted) - throws if backendType is null - throws if remote name is empty string intune-install.test.ts: - imports buildIntuneInstall from './intune-install' (file does not exist yet — RED) - machine-wide path: output contains 'C:\ProgramData\rclone' - user-profile path: output contains '%APPDATA%\rclone' - includeInstall=true: output contains 'https://downloads.rclone.org/rclone-current-windows-amd64.zip' - includeInstall=false: output does NOT contain 'downloads.rclone.org' - output contains '[System.IO.File]::WriteAllText' (UTF-8 no-BOM idiom present) - output contains 'exit 0' - output does NOT contain credential variable interpolation inside config content (no $account, $key inside here-string block) intune-detection.test.ts: - imports buildIntuneDetection from './intune-detection' (file does not exist yet — RED) - machine-wide path: output contains 'C:\ProgramData\rclone' - user-profile path: output contains '%APPDATA%\rclone' - output contains 'exit 0' and 'exit 1' - output contains 'Write-Output' (STDOUT signal) - output does NOT contain '$ErrorActionPreference' (STDERR contamination risk) - output does NOT contain 'Write-Error' or 'Write-Host' (no STDERR leakage) rmm-script.test.ts: - imports buildRmmScript from './rmm-script' (file does not exist yet — RED) - machine-wide path: output contains 'C:\ProgramData\rclone' - user-profile path: output contains '%APPDATA%\rclone' - includeInstall=true: output contains 'https://downloads.rclone.org/rclone-current-windows-amd64.zip' - includeInstall=false: output does NOT contain 'downloads.rclone.org' - output contains '$ErrorActionPreference = ''Stop''' (RMM scripts DO use Stop — unlike detection) - output contains '[System.IO.File]::WriteAllText' (UTF-8 no-BOM) Create all four test files. Use INITIAL_STATE + overrides to build typed WizardState fixtures. Import from '../store/types' for WizardState and INITIAL_STATE. Use Vitest globals (describe, it, expect — no import needed, globals: true in vitest.config.ts). Representative fixture pattern (replicate across all four files): ```typescript import { buildRcloneConf } from './rclone-conf'; import { INITIAL_STATE } from '../store/types'; import type { WizardState } from '../store/types'; const azureState: WizardState = { ...INITIAL_STATE, remote: { name: 'my-azure', backendType: 'azureblob', params: { account: 'mystorageaccount', key: 'BASE64KEY', sas_url: '' }, }, }; ``` Tests will fail at import (module not found) until Plans 02-04 create implementations. This is intentional RED state. Vitest with passWithNoTests:true will still pass overall suite; individual test files will error. That is correct behavior for Wave 0 stubs. Keep test descriptions concise and specific to the substring being asserted. No mocking needed — these are pure string functions. npm test 2>&1 | head -50 All four test files exist. npm test runs without crashing the runner (passWithNoTests:true). Individual generator test files show import errors or failing tests — RED state is correct. TypeScript compilation of test files is the only requirement at this stage. Task 2: Create index.ts barrel src/generators/index.ts Create `src/generators/index.ts` that re-exports all four generator functions. The module files do not exist yet — use type-only re-exports or forward-compatible syntax that will resolve once Plans 02-04 create the implementations. Since the generator files don't exist yet, write the barrel with the final export shape. Vitest will see the import error from test files; the barrel itself need not be tested. ```typescript // src/generators/index.ts // Re-exports all generator functions. // Phase 4 imports generators from this barrel — do not remove exports. export { buildRcloneConf } from './rclone-conf'; export { buildIntuneInstall } from './intune-install'; export { buildIntuneDetection } from './intune-detection'; export { buildRmmScript } from './rmm-script'; ``` No implementation logic in this file. The barrel is purely structural. test -f src/generators/index.ts && echo "exists" src/generators/index.ts exists with all four named re-exports. File contains no implementation logic. - All four test files exist in src/generators/ - src/generators/index.ts exists with four re-export lines - npm test runs without runner crash - Test files correctly import from sibling modules (not yet implemented — RED is expected) Wave 0 is complete: test stubs define every assertion that Plans 02, 03, 04 must satisfy. The barrel defines the public API contract. No implementation exists yet — all generator imports are RED. After completion, create `.planning/phases/02-generators/02-01-SUMMARY.md`