docs(02-generators): create phase 2 plan — 4 plans in 2 waves
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,236 @@
|
||||
---
|
||||
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"
|
||||
---
|
||||
|
||||
<objective>
|
||||
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.
|
||||
</objective>
|
||||
|
||||
<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>
|
||||
|
||||
<context>
|
||||
@.planning/PROJECT.md
|
||||
@.planning/ROADMAP.md
|
||||
@.planning/STATE.md
|
||||
|
||||
@src/store/types.ts
|
||||
@src/schemas/registry.ts
|
||||
</context>
|
||||
|
||||
<interfaces>
|
||||
<!-- Key types the test files will import. Extracted from Phase 1 artifacts. -->
|
||||
|
||||
From src/store/types.ts:
|
||||
```typescript
|
||||
export interface WizardState {
|
||||
currentStep: number;
|
||||
remote: {
|
||||
name: string;
|
||||
backendType: BackendType | null;
|
||||
params: Record<string, string>;
|
||||
};
|
||||
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';
|
||||
```
|
||||
</interfaces>
|
||||
|
||||
<tasks>
|
||||
|
||||
<task type="auto" tdd="true">
|
||||
<name>Task 1: Write test stubs for all four generators</name>
|
||||
<files>
|
||||
src/generators/rclone-conf.test.ts,
|
||||
src/generators/intune-install.test.ts,
|
||||
src/generators/intune-detection.test.ts,
|
||||
src/generators/rmm-script.test.ts
|
||||
</files>
|
||||
<behavior>
|
||||
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)
|
||||
</behavior>
|
||||
<action>
|
||||
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.
|
||||
</action>
|
||||
<verify>
|
||||
<automated>npm test 2>&1 | head -50</automated>
|
||||
</verify>
|
||||
<done>
|
||||
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.
|
||||
</done>
|
||||
</task>
|
||||
|
||||
<task type="auto">
|
||||
<name>Task 2: Create index.ts barrel</name>
|
||||
<files>src/generators/index.ts</files>
|
||||
<action>
|
||||
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.
|
||||
</action>
|
||||
<verify>
|
||||
<automated>test -f src/generators/index.ts && echo "exists"</automated>
|
||||
</verify>
|
||||
<done>
|
||||
src/generators/index.ts exists with all four named re-exports. File contains no implementation logic.
|
||||
</done>
|
||||
</task>
|
||||
|
||||
</tasks>
|
||||
|
||||
<verification>
|
||||
- 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)
|
||||
</verification>
|
||||
|
||||
<success_criteria>
|
||||
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.
|
||||
</success_criteria>
|
||||
|
||||
<output>
|
||||
After completion, create `.planning/phases/02-generators/02-01-SUMMARY.md`
|
||||
</output>
|
||||
Reference in New Issue
Block a user