kaizen

Use when Code implementation and refactoring, architecturing or designing systems, process and workflow improvements, error handling and validation. Provide…

INSTALLATION
npx skills add https://github.com/neolabhq/context-engineering-kit --skill kaizen
Run in your project or agent environment. Adjust flags if your CLI version differs.

SKILL.md

Kaizen: Continuous Improvement

Apply continuous improvement mindset - suggest small iterative improvements, error-proof designs, follow established patterns, avoid over-engineering; automatically applied to guide quality and simplicity

Overview

Small improvements, continuously. Error-proof by design. Follow what works. Build only what's needed.

Core principle: Many small improvements beat one big change. Prevent errors at design time, not with fixes.

When to Use

Always applied for:

  • Code implementation and refactoring
  • Architecture and design decisions
  • Process and workflow improvements
  • Error handling and validation

Philosophy: Quality through incremental progress and prevention, not perfection through massive effort.

The Four Pillars

1. Continuous Improvement (Kaizen)

Small, frequent improvements compound into major gains.

#### Principles

Incremental over revolutionary:

  • Make smallest viable change that improves quality
  • One improvement at a time
  • Verify each change before next
  • Build momentum through small wins

Always leave code better:

  • Fix small issues as you encounter them
  • Refactor while you work (within scope)
  • Update outdated comments
  • Remove dead code when you see it

Iterative refinement:

  • First version: make it work
  • Second pass: make it clear
  • Third pass: make it efficient
  • Don't try all three at once

// Iteration 2: Make it clear (refactor)

const calculateTotal = (items: Item[]): number => {

return items.reduce((total, item) => {

return total + (item.price * item.quantity);

}, 0);

};

// Iteration 3: Make it robust (add validation)

const calculateTotal = (items: Item[]): number => {

if (!items?.length) return 0;

return items.reduce((total, item) => {

if (item.price < 0 || item.quantity < 0) {

throw new Error('Price and quantity must be non-negative');

}

return total + (item.price * item.quantity);

}, 0);

};

Each step is complete, tested, and working

</Good>

<Bad>

// Trying to do everything at once

const calculateTotal = (items: Item[]): number => {

// Validate, optimize, add features, handle edge cases all together

if (!items?.length) return 0;

const validItems = items.filter(item => {

if (item.price < 0) throw new Error('Negative price');

if (item.quantity < 0) throw new Error('Negative quantity');

return item.quantity > 0; // Also filtering zero quantities

});

// Plus caching, plus logging, plus currency conversion...

return validItems.reduce(...); // Too many concerns at once

};


Overwhelming, error-prone, hard to verify

#### In Practice

**When implementing features:**

- Start with simplest version that works

- Add one improvement (error handling, validation, etc.)

- Test and verify

- Repeat if time permits

- Don't try to make it perfect immediately

**When refactoring:**

- Fix one smell at a time

- Commit after each improvement

- Keep tests passing throughout

- Stop when "good enough" (diminishing returns)

**When reviewing code:**

- Suggest incremental improvements (not rewrites)

- Prioritize: critical → important → nice-to-have

- Focus on highest-impact changes first

- Accept "better than before" even if not perfect

### 2. Poka-Yoke (Error Proofing)

Design systems that prevent errors at compile/design time, not runtime.

#### Principles

**Make errors impossible:**

- Type system catches mistakes

- Compiler enforces contracts

- Invalid states unrepresentable

- Errors caught early (left of production)

**Design for safety:**

- Fail fast and loudly

- Provide helpful error messages

- Make correct path obvious

- Make incorrect path difficult

**Defense in layers:**

- Type system (compile time)

- Validation (runtime, early)

- Guards (preconditions)

- Error boundaries (graceful degradation)

#### Type System Error Proofing

// Good: Only valid states possible
type OrderStatus = 'pending' | 'processing' | 'shipped' | 'delivered';
type Order = {
status: OrderStatus;
total: number;
};

// Better: States with associated data
type Order =
| { status: 'pending'; createdAt: Date }
| { status: 'processing'; startedAt: Date; estimatedCompletion: Date }
| { status: 'shipped'; trackingNumber: string; shippedAt: Date }
| { status: 'delivered'; deliveredAt: Date; signature: string };

// Now impossible to have shipped without trackingNumber

Type system prevents entire classes of errors

</Good>

<Good>


// Make invalid states unrepresentable

type NonEmptyArray<T> = [T, ...T[]];

const firstItem = <T>(items: NonEmptyArray<T>): T => {

  return items[0]; // Always safe, never undefined!

};

// Caller must prove array is non-empty

const items: number[] = [1, 2, 3];

if (items.length > 0) {

  firstItem(items as NonEmptyArray<number>); // Safe

}

Function signature guarantees safety

#### Validation Error Proofing

// Good: Validate immediately

const processPayment = (amount: number) => {

if (amount <= 0) {

throw new Error('Payment amount must be positive');

}

if (amount > 10000) {

throw new Error('Payment exceeds maximum allowed');

}

const fee = amount * 0.03;

// ... now safe to use

};

// Better: Validation at boundary with branded type

type PositiveNumber = number &#x26; { readonly __brand: 'PositiveNumber' };

const validatePositive = (n: number): PositiveNumber => {

if (n <= 0) throw new Error('Must be positive');

return n as PositiveNumber;

};

const processPayment = (amount: PositiveNumber) => {

// amount is guaranteed positive, no need to check

const fee = amount * 0.03;

};

// Validate at system boundary

const handlePaymentRequest = (req: Request) => {

const amount = validatePositive(req.body.amount); // Validate once

processPayment(amount); // Use everywhere safely

};

Validate once at boundary, safe everywhere else

</Good>

#### Guards and Preconditions

<Good>

// Early returns prevent deeply nested code

const processUser = (user: User | null) => {

if (!user) {

logger.error('User not found');

return;

}

if (!user.email) {

logger.error('User email missing');

return;

}

if (!user.isActive) {

logger.info('User inactive, skipping');

return;

}

// Main logic here, guaranteed user is valid and active

sendEmail(user.email, 'Welcome!');

};


Guards make assumptions explicit and enforced

#### Configuration Error Proofing

const client = new APIClient({ timeout: 5000 }); // apiKey missing!

// Good: Required config, fails early
type Config = {
apiKey: string;
timeout: number;
};

const loadConfig = (): Config => {
const apiKey = process.env.API_KEY;
if (!apiKey) {
throw new Error('API_KEY environment variable required');
}

return {
apiKey,
timeout: 5000,
};
};

// App fails at startup if config invalid, not during request
const config = loadConfig();
const client = new APIClient(config);

Fail at startup, not in production

</Good>

#### In Practice

When designing APIs:

  • Use types to constrain inputs
  • Make invalid states unrepresentable
  • Return Result<T, E> instead of throwing
  • Document preconditions in types

When handling errors:

  • Validate at system boundaries
  • Use guards for preconditions
  • Fail fast with clear messages
  • Log context for debugging

When configuring:

  • Required over optional with defaults
  • Validate all config at startup
  • Fail deployment if config invalid
  • Don't allow partial configurations

3. Standardized Work

Follow established patterns. Document what works. Make good practices easy to follow.

#### Principles

Consistency over cleverness:

  • Follow existing codebase patterns
  • Don't reinvent solved problems
  • New pattern only if significantly better
  • Team agreement on new patterns

Documentation lives with code:

  • README for setup and architecture
  • CLAUDE.md for AI coding conventions
  • Comments for "why", not "what"
  • Examples for complex patterns

Automate standards:

  • Linters enforce style
  • Type checks enforce contracts
  • Tests verify behavior
  • CI/CD enforces quality gates

#### Following Patterns

<Good>


// Existing codebase pattern for API clients

class UserAPIClient {

  async getUser(id: string): Promise<User> {

    return this.fetch(`/users/${id}`);

  }

}

// New code follows the same pattern

class OrderAPIClient {

  async getOrder(id: string): Promise<Order> {

    return this.fetch(`/orders/${id}`);

  }

}

Consistency makes codebase predictable

// New code introduces different pattern without discussion

const getOrder = async (id: string): Promise => {

// Breaking consistency "because I prefer functions"

};

Inconsistency creates confusion

</Bad>

#### Error Handling Patterns

<Good>

// Project standard: Result type for recoverable errors

type Result<T, E> = { ok: true; value: T } | { ok: false; error: E };

// All services follow this pattern

const fetchUser = async (id: string): Promise<Result<User, Error>> => {

try {

const user = await db.users.findById(id);

if (!user) {

return { ok: false, error: new Error('User not found') };

}

return { ok: true, value: user };

} catch (err) {

return { ok: false, error: err as Error };

}

};

// Callers use consistent pattern

const result = await fetchUser('123');

if (!result.ok) {

logger.error('Failed to fetch user', result.error);

return;

}

const user = result.value; // Type-safe!


Standard pattern across codebase

#### Documentation Standards

#### In Practice

**Before adding new patterns:**

- Search codebase for similar problems solved

- Check CLAUDE.md for project conventions

- Discuss with team if breaking from pattern

- Update docs when introducing new pattern

**When writing code:**

- Match existing file structure

- Use same naming conventions

- Follow same error handling approach

- Import from same locations

**When reviewing:**

- Check consistency with existing code

- Point to examples in codebase

- Suggest aligning with standards

- Update CLAUDE.md if new standard emerges

### 4. Just-In-Time (JIT)

Build what's needed now. No more, no less. Avoid premature optimization and over-engineering.

#### Principles

**YAGNI (You Aren't Gonna Need It):**

- Implement only current requirements

- No "just in case" features

- No "we might need this later" code

- Delete speculation

**Simplest thing that works:**

- Start with straightforward solution

- Add complexity only when needed

- Refactor when requirements change

- Don't anticipate future needs

**Optimize when measured:**

- No premature optimization

- Profile before optimizing

- Measure impact of changes

- Accept "good enough" performance

#### YAGNI in Action

class ConsoleTransport implements LogTransport { /... / }
class FileTransport implements LogTransport { / ... / }
class RemoteTransport implements LogTransport { / .../ }

class Logger {
private transports: LogTransport[] = [];
private queue: LogEntry[] = [];
private rateLimiter: RateLimiter;
private formatter: LogFormatter;

// 200 lines of code for "maybe we'll need it"
}

const logError = (error: Error) => {
Logger.getInstance().log('error', error.message);
};

Building for imaginary future requirements

</Bad>

When to add complexity:

  • Current requirement demands it
  • Pain points identified through use
  • Measured performance issues
  • Multiple use cases emerged

<Good>


// Start simple

const formatCurrency = (amount: number): string => {

  return `$${amount.toFixed(2)}`;

};

// Requirement evolves: support multiple currencies

const formatCurrency = (amount: number, currency: string): string => {

  const symbols = { USD: '$', EUR: '€', GBP: '£' };

  return `${symbols[currency]}${amount.toFixed(2)}`;

};

// Requirement evolves: support localization

const formatCurrency = (amount: number, locale: string): string => {

  return new Intl.NumberFormat(locale, {

    style: 'currency',

    currency: locale === 'en-US' ? 'USD' : 'EUR',

  }).format(amount);

};

Complexity added only when needed

#### Premature Abstraction

class GenericRepository { /300 lines / }

class QueryBuilder { / 200 lines/ }

// ... building entire ORM for single table

Massive abstraction for uncertain future

</Bad>

<Good>

// Simple functions for current needs

const getUsers = async (): Promise<User[]> => {

return db.query('SELECT * FROM users');

};

const getUserById = async (id: string): Promise<User | null> => {

return db.query('SELECT * FROM users WHERE id = $1', [id]);

};

// When pattern emerges across multiple entities, then abstract


Abstract only when pattern proven across 3+ cases

#### Performance Optimization

// Benchmark shows: 50ms for 1000 users (acceptable)
// ✓ Ship it, no optimization needed

// Later: After profiling shows this is bottleneck
// Then optimize with indexed lookup or caching

Optimize based on measurement, not assumptions

</Good>

<Bad>


// Premature optimization

const filterActiveUsers = (users: User[]): User[] => {

  // "This might be slow, so let's cache and index"

  const cache = new WeakMap();

  const indexed = buildBTreeIndex(users, 'isActive');

  // 100 lines of optimization code

  // Adds complexity, harder to maintain

  // No evidence it was needed

};

Complex solution for unmeasured problem

#### In Practice

When implementing:

  • Solve the immediate problem
  • Use straightforward approach
  • Resist "what if" thinking
  • Delete speculative code

When optimizing:

  • Profile first, optimize second
  • Measure before and after
  • Document why optimization needed
  • Keep simple version in tests

When abstracting:

  • Wait for 3+ similar cases (Rule of Three)
  • Make abstraction as simple as possible
  • Prefer duplication over wrong abstraction
  • Refactor when pattern clear

Integration with Commands

The Kaizen skill guides how you work. The commands provide structured analysis:

  • **/why**: Root cause analysis (5 Whys)
  • **/cause-and-effect**: Multi-factor analysis (Fishbone)
  • **/plan-do-check-act**: Iterative improvement cycles
  • **/analyse-problem**: Comprehensive documentation (A3)
  • **/analyse**: Smart method selection (Gemba/VSM/Muda)

Use commands for structured problem-solving. Apply skill for day-to-day development.

Red Flags

Violating Continuous Improvement:

  • "I'll refactor it later" (never happens)
  • Leaving code worse than you found it
  • Big bang rewrites instead of incremental

Violating Poka-Yoke:

  • "Users should just be careful"
  • Validation after use instead of before
  • Optional config with no validation

Violating Standardized Work:

  • "I prefer to do it my way"
  • Not checking existing patterns
  • Ignoring project conventions

Violating Just-In-Time:

  • "We might need this someday"
  • Building frameworks before using them
  • Optimizing without measuring

Remember

Kaizen is about:

  • Small improvements continuously
  • Preventing errors by design
  • Following proven patterns
  • Building only what's needed

Not about:

  • Perfection on first try
  • Massive refactoring projects
  • Clever abstractions
  • Premature optimization

Mindset: Good enough today, better tomorrow. Repeat.

BrowserAct

Let your agent run on any real-world website

Bypass CAPTCHA & anti-bot for free. Start local, scale to cloud.

Explore BrowserAct Skills →

Stop writing automation&scrapers

Install the CLI. Run your first Skill in 30 seconds. Scale when you're ready.

Start free
free · no credit card