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

11 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 01 execute 1
05-00
src/schemas/registry.ts
src/schemas/index.ts
src/components/wizard/RemoteConfigStep.tsx
src/components/wizard/BackendSelectionStep.tsx
true
TECH-03
TECH-04
truths artifacts key_links
BACKEND_REGISTRY entries each have displayName, description, and fields properties
BackendSelectionStep renders cards using Object.entries(BACKEND_REGISTRY) — no hardcoded BACKENDS array
All consumers of BACKEND_REGISTRY access field arrays via .fields
BackendFormValues<T> export is absent from src/schemas/index.ts
TypeScript compiles with zero errors after changes
path provides contains
src/schemas/registry.ts Enriched BACKEND_REGISTRY with displayName, description, fields displayName
path provides contains
src/components/wizard/BackendSelectionStep.tsx Registry-driven card list Object.entries(BACKEND_REGISTRY)
from to via pattern
src/schemas/registry.ts src/schemas/index.ts buildZodSchema accesses BACKEND_REGISTRY[backendType].fields .fields
from to via pattern
src/schemas/registry.ts src/components/wizard/RemoteConfigStep.tsx field iteration uses BACKEND_REGISTRY[backendType].fields BACKEND_REGISTRY[backendType].fields
from to via pattern
src/schemas/registry.ts src/components/wizard/BackendSelectionStep.tsx Object.entries(BACKEND_REGISTRY) replaces BACKENDS const Object.entries(BACKEND_REGISTRY)
Enrich BACKEND_REGISTRY with display metadata, wire BackendSelectionStep to derive its card list from the registry, update all consumers to use .fields access, and remove the dead BackendFormValues export.

Purpose: TECH-03 makes the registry the single source of truth for both field definitions AND display metadata — Phase 6 backend additions auto-surface with zero additional UI code. TECH-04 removes dead code. Output: registry.ts with new shape, BackendSelectionStep.tsx driven by registry, schemas/index.ts clean.

<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/ROADMAP.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/schemas/registry.ts (CURRENT shape — executor REPLACES this):

export type BackendType = 'azureblob' | 's3' | 's3-compatible';
export interface FieldDef { key, label, inputType, required, placeholder?, helpText?, options? }
export const BACKEND_REGISTRY: Record<BackendType, FieldDef[]> = { ... }

New shape (TECH-03 target):

export const BACKEND_REGISTRY: Record<BackendType, {
  displayName: string;
  description: string;
  fields: FieldDef[];
}> = {
  azureblob: {
    displayName: 'Azure Blob Storage',
    description: 'Microsoft Azure cloud storage',
    fields: [ /* existing FieldDef[] content unchanged */ ],
  },
  s3: {
    displayName: 'Amazon S3',
    description: 'AWS Simple Storage Service',
    fields: [ /* existing FieldDef[] content unchanged */ ],
  },
  's3-compatible': {
    displayName: 'S3-Compatible',
    description: 'Wasabi, MinIO, Cloudflare R2, and others',
    fields: [ /* existing FieldDef[] content unchanged */ ],
  },
};

Display strings MUST match existing BackendSelectionStep card text exactly (test assertions check these strings).

From src/schemas/index.ts line 10 (consumer 1 — must update):

const fields = BACKEND_REGISTRY[backendType]; // CHANGE TO: BACKEND_REGISTRY[backendType].fields

From src/components/wizard/RemoteConfigStep.tsx (consumers 2 and 3 — must update):

// Line 58: BACKEND_REGISTRY.azureblob.find(f => f.key === 'account')
//   CHANGE TO: BACKEND_REGISTRY.azureblob.fields.find(f => f.key === 'account')
// Line 73: BACKEND_REGISTRY[backendType].map(field => ...)
//   CHANGE TO: BACKEND_REGISTRY[backendType].fields.map(field => ...)

From src/components/wizard/BackendSelectionStep.tsx (TECH-03 — replace hardcoded BACKENDS):

// Remove: const BACKENDS: { type: BackendType; name: string; description: string }[] = [...]
// Replace rendering with:
import { BACKEND_REGISTRY } from '../../schemas/registry';
// ...
{Object.entries(BACKEND_REGISTRY).map(([type, entry]) => (
  <BackendCard
    key={type}
    name={entry.displayName}
    description={entry.description}
    selected={state.remote.backendType === type}
    onClick={() => handleCardClick(type as BackendType)}
  />
))}

From src/schemas/index.ts lines 27-28 (TECH-04 — remove entirely):

// REMOVE these two lines:
export type BackendFormValues<T extends BackendType> =
  z.infer<typeof BACKEND_SCHEMAS[T]>;
Task 1: Enrich BACKEND_REGISTRY and update all consumers src/schemas/registry.ts, src/schemas/index.ts, src/components/wizard/RemoteConfigStep.tsx - registry.test.ts 'each backend entry has displayName and description metadata' passes - registry.test.ts 'each backend has at least one field definition' passes (via .fields.length) - registry.test.ts 'Azure Blob has account field' passes (via .fields.find) - schemas/index.ts buildZodSchema receives FieldDef[] from .fields — all BACKEND_SCHEMAS build correctly - RemoteConfigStep renders fields correctly (existing RemoteConfigStep.test.tsx passes) 1. Edit src/schemas/registry.ts: - Change BACKEND_REGISTRY value type from `FieldDef[]` to `{ displayName: string; description: string; fields: FieldDef[] }` - Wrap each backend's existing FieldDef array in the new object shape, adding displayName and description - displayName and description strings MUST match the existing BACKENDS array in BackendSelectionStep.tsx exactly: - azureblob: displayName='Azure Blob Storage', description='Microsoft Azure cloud storage' - s3: displayName='Amazon S3', description='AWS Simple Storage Service' - s3-compatible: displayName='S3-Compatible', description='Wasabi, MinIO, Cloudflare R2, and others' - All existing FieldDef content is preserved unchanged inside fields
2. Edit src/schemas/index.ts line 10:
   - Change `const fields = BACKEND_REGISTRY[backendType];` to `const fields = BACKEND_REGISTRY[backendType].fields;`

3. Edit src/components/wizard/RemoteConfigStep.tsx:
   - Line 58: Change `BACKEND_REGISTRY.azureblob.find(f => f.key === 'account')` to `BACKEND_REGISTRY.azureblob.fields.find(f => f.key === 'account')`
   - Line 73: Change `BACKEND_REGISTRY[backendType].map(field =>` to `BACKEND_REGISTRY[backendType].fields.map(field =>`
cd /c/Users/SebastienQUEROL/Documents/projets/Ready2Blob && npx vitest run src/schemas/registry.test.ts src/components/wizard/RemoteConfigStep.test.tsx 2>&1 | tail -15 registry.test.ts passes with all tests green (including new displayName/description test and .fields access tests). RemoteConfigStep.test.tsx still passes. TypeScript sees no errors on the modified files. Task 2: Wire BackendSelectionStep to registry + remove dead export src/components/wizard/BackendSelectionStep.tsx, src/schemas/index.ts - BackendSelectionStep renders 'Azure Blob Storage', 'Amazon S3', 'S3-Compatible' cards (from registry, not hardcoded) - Azure Blob card appears before S3 in DOM order (Object.entries insertion order preserved) - Clicking a card with a valid remote name still dispatches SET_BACKEND_TYPE and SET_STEP (existing WIZD-01 test passes) - BackendFormValues type is absent from src/schemas/index.ts - npx tsc --noEmit exits with code 0 1. Edit src/components/wizard/BackendSelectionStep.tsx: - Add import: `import { BACKEND_REGISTRY } from '../../schemas/registry';` - Remove the `BACKENDS` constant entirely (lines 21-37) - In the JSX rendering section, replace `{BACKENDS.map((backend) => (` block with: ```tsx {Object.entries(BACKEND_REGISTRY).map(([type, entry]) => ( handleCardClick(type as BackendType)} /> ))} ``` - Remove the now-unused local type import for BackendType from '../../store/types' IF it is only used by the BACKENDS const (check — it may still be needed for pendingBackend.current type annotation). If BackendType is still needed, keep the import.
2. Edit src/schemas/index.ts:
   - Remove lines 27-28: the `export type BackendFormValues<T extends BackendType> = z.infer<typeof BACKEND_SCHEMAS[T]>;` export
   - Also remove the blank comment line above it (line 26: `// Utility type: infer TypeScript type from a backend's Zod schema`) to avoid orphan comment

3. Run TypeScript check to confirm no consumers of BackendFormValues exist:
   `npx tsc --noEmit`
cd /c/Users/SebastienQUEROL/Documents/projets/Ready2Blob && npx vitest run src/components/wizard/BackendSelectionStep.test.tsx && npx tsc --noEmit 2>&1 | tail -10 BackendSelectionStep.test.tsx passes (WIZD-01 card text assertions still green — display strings match). npx tsc --noEmit exits with zero errors. BackendFormValues export is absent from src/schemas/index.ts. Full suite green except pre-existing RED stubs (TECH-01, TECH-02 ReviewStep stubs remain RED — implemented in Plan 02): ``` cd /c/Users/SebastienQUEROL/Documents/projets/Ready2Blob && npx vitest run && npx tsc --noEmit ``` Expected: All registry tests green, all BackendSelectionStep tests green, RemoteConfigStep tests green. Only TECH-01/TECH-02 ReviewStep stubs still RED.

<success_criteria>

  • BACKEND_REGISTRY shape is Record<BackendType, { displayName, description, fields: FieldDef[] }>
  • BackendSelectionStep uses Object.entries(BACKEND_REGISTRY) — no hardcoded BACKENDS array
  • schemas/index.ts uses .fields access and has no BackendFormValues export
  • RemoteConfigStep uses .fields access
  • registry.test.ts fully green
  • BackendSelectionStep.test.tsx fully green
  • npx tsc --noEmit: zero errors </success_criteria>
After completion, create `.planning/phases/05-tech-debt/05-01-SUMMARY.md`