- roadmap-execution: phased roadmap execution with checkpoints - new-product-scaffold: scaffold new ByteLyst product repos - prd-to-implementation: convert PRDs to concrete plans - cross-repo-debug: systematic multi-repo debugging - backend-module-crud: Fastify CRUD modules (types/repo/routes/tests) - platform-integration: wire products into common platform - refactor-with-tests: test-first safe refactoring - test-gap-analysis: coverage gap identification and remediation - type-safety-sweep: TypeScript error triage and fix - dependency-health-check: cross-repo dependency audit - pre-release-validation: comprehensive release checklist - docker-production-prep: production Docker images - agents-md-sync: keep AI instruction files accurate - ecosystem-audit: full ecosystem health dashboard
147 lines
4.1 KiB
Markdown
147 lines
4.1 KiB
Markdown
---
|
|
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('<Module> — 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(<scope>): 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(<scope>): <what changed>"
|
|
```
|
|
|
|
### 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(<scope>): update docs after <module> 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.
|