--- name: refactor-with-tests description: 'Safely refactor code with test-first methodology — capture behavior, refactor, verify nothing broke.' argument-hint: 'Target module/file and refactor goal, e.g. "backend/src/modules/auth — extract token service", "simplify scheduler engine in FlowMonk"' agent: agent --- # Refactor with Tests Prompt Safely refactor code by first capturing existing behavior in tests, then restructuring while keeping all tests green. ## Context — ByteLyst Conventions - **Test runner:** Vitest (TypeScript), pytest (Python) - **Test location:** Same module directory or `__tests__/` - **Never modify tests to make them pass** — fix the code - **Commit format:** `refactor(scope): description` ## Refactor Protocol ### Step 1: Understand Current Behavior Before touching any code: 1. **Read the code** — understand what it does, not just the structure 2. **Read existing tests** — understand what's already covered 3. **Run existing tests** — confirm they pass: ```bash pnpm test pnpm typecheck ``` 4. **Identify the API surface** — what do consumers depend on? - Exported functions/types - REST endpoint contracts - Side effects (database writes, events emitted) ### Step 2: Add Missing Tests (Before Refactoring) If test coverage is insufficient, add tests for current behavior FIRST: ```typescript // Capture existing behavior before refactoring describe(' — pre-refactor behavior capture', () => { it('should return X when given Y', () => { // Test current behavior, even if the implementation is ugly }); it('should throw NotFoundError for missing items', () => { // Edge cases that must be preserved }); it('should include productId in all created documents', () => { // Ecosystem invariants }); }); ``` **Commit these tests separately:** ```bash git add . git commit -m "test(): capture pre-refactor behavior (N tests)" ``` ### Step 3: Plan the Refactor Document what will change and what must stay the same: - **Changing:** Internal structure, file organization, naming - **Preserving:** API surface, behavior, test contracts - **New patterns:** What you're moving toward (e.g., extract service class, split module) ### Step 4: Refactor in Small Steps For each step: 1. Make ONE structural change 2. Run tests: `pnpm test` 3. Run typecheck: `pnpm typecheck` 4. If tests pass → commit 5. If tests fail → undo and retry with smaller step ```bash # After each small refactor step pnpm test && pnpm typecheck && \ git add . && git commit -m "refactor(): " ``` ### Step 5: Verify Completeness After all refactoring: ```bash # Full validation pnpm build && pnpm typecheck && pnpm test # Check no exports were broken # If this is a @bytelyst/* package: cd learning_ai_common_plat && pnpm build && pnpm test ``` ### Step 6: Update Documentation If the refactor changed: - File locations → update AGENTS.md repo layout - API surface → update README.md or API docs - Module structure → update any roadmap or architecture docs ```bash git add . git commit -m "docs(): update docs after refactor" git push ``` ## Common Refactor Patterns ### Extract Service Class ``` Before: routes.ts has business logic mixed with HTTP handling After: routes.ts → service.ts → repository.ts (routes are thin) ``` ### Split Module ``` Before: modules/schedule/ has 500-line routes.ts After: modules/schedule/ + modules/schedule-entries/ (each focused) ``` ### Extract Shared Package ``` Before: Two products have duplicate utility code After: New @bytelyst/* package consumed by both ``` ### Consolidate Re-exports ``` Before: Each file imports from @bytelyst/* directly After: src/lib/ re-exports, internal files import from src/lib/ ``` ## Guardrails - **Test first, refactor second.** Never refactor without test coverage. - **Small commits.** Each commit should be revertible without losing other changes. - **No behavior changes.** Refactoring changes structure, not behavior. If you're fixing bugs, that's a separate commit. - **No export changes** without updating all consumers. - **Run the full suite** after every commit, not just the changed module's tests.