From harness-claude
Implements the Chain of Responsibility pattern with linked handler chains and async middleware pipelines. Useful for request routing, validation, and event processing.
How this skill is triggered — by the user, by Claude, or both
Slash command
/harness-claude:gof-chain-of-responsibilityThe summary Claude sees in its skill listing — used to decide when to auto-load this skill
> Pass requests along a handler chain with short-circuit and async chain support.
Pass requests along a handler chain with short-circuit and async chain support.
Linked handler chain:
interface Handler<T> {
setNext(handler: Handler<T>): Handler<T>;
handle(request: T): T | null;
}
abstract class AbstractHandler<T> implements Handler<T> {
private nextHandler: Handler<T> | null = null;
setNext(handler: Handler<T>): Handler<T> {
this.nextHandler = handler;
return handler; // enables chaining: a.setNext(b).setNext(c)
}
handle(request: T): T | null {
if (this.nextHandler) return this.nextHandler.handle(request);
return null;
}
}
// Concrete handlers
interface SupportTicket {
level: 'basic' | 'advanced' | 'expert';
description: string;
}
class BasicSupportHandler extends AbstractHandler<SupportTicket> {
handle(ticket: SupportTicket): SupportTicket | null {
if (ticket.level === 'basic') {
console.log(`BasicSupport handling: ${ticket.description}`);
return ticket;
}
return super.handle(ticket); // pass to next
}
}
class AdvancedSupportHandler extends AbstractHandler<SupportTicket> {
handle(ticket: SupportTicket): SupportTicket | null {
if (ticket.level === 'advanced') {
console.log(`AdvancedSupport handling: ${ticket.description}`);
return ticket;
}
return super.handle(ticket);
}
}
class ExpertSupportHandler extends AbstractHandler<SupportTicket> {
handle(ticket: SupportTicket): SupportTicket | null {
console.log(`ExpertSupport handling: ${ticket.description}`);
return ticket; // always handles — final in chain
}
}
// Build the chain
const basic = new BasicSupportHandler();
const advanced = new AdvancedSupportHandler();
const expert = new ExpertSupportHandler();
basic.setNext(advanced).setNext(expert);
// Route tickets
basic.handle({ level: 'advanced', description: 'DB crash' });
// → AdvancedSupport handling: DB crash
Async middleware chain (Express-style):
type Middleware<T> = (ctx: T, next: () => Promise<void>) => Promise<void>;
class Pipeline<T> {
private middlewares: Middleware<T>[] = [];
use(middleware: Middleware<T>): this {
this.middlewares.push(middleware);
return this;
}
async execute(ctx: T): Promise<void> {
const run = async (index: number): Promise<void> => {
if (index >= this.middlewares.length) return;
await this.middlewares[index](ctx, () => run(index + 1));
};
await run(0);
}
}
// Usage
interface RequestContext {
userId?: string;
body: unknown;
response?: unknown;
errors: string[];
}
const pipeline = new Pipeline<RequestContext>()
.use(async (ctx, next) => {
// Auth middleware
ctx.userId = 'user-123'; // decode JWT in reality
if (!ctx.userId) {
ctx.errors.push('Unauthorized');
return;
} // short-circuit
await next();
})
.use(async (ctx, next) => {
// Validation middleware
if (!ctx.body) {
ctx.errors.push('Body required');
return;
} // short-circuit
await next();
})
.use(async (ctx, next) => {
// Handler middleware
ctx.response = { message: 'OK', userId: ctx.userId };
await next();
})
.use(async (ctx, _next) => {
// Logging middleware — always runs
console.log(`Request by ${ctx.userId}, errors: ${ctx.errors.length}`);
});
const ctx: RequestContext = { body: { name: 'test' }, errors: [] };
await pipeline.execute(ctx);
Short-circuiting: Handlers can stop the chain by not calling next() or returning without calling super.handle(). This is the key advantage over Decorator — the chain can terminate early based on conditions.
Difference from Decorator: Decorator always delegates to the wrapped object. Chain of Responsibility can stop delegation. If all handlers must run, use Decorator. If any handler might absorb the request, use Chain.
Anti-patterns:
Request logging for debuggability:
abstract class LoggingHandler<T> extends AbstractHandler<T> {
private readonly name: string;
constructor(name: string) {
super();
this.name = name;
}
handle(request: T): T | null {
console.log(`[${this.name}] Received request`);
const result = this.handleRequest(request);
if (result !== null) {
console.log(`[${this.name}] Handled request`);
return result;
}
console.log(`[${this.name}] Passing to next`);
return super.handle(request);
}
protected abstract handleRequest(request: T): T | null;
}
refactoring.guru/design-patterns/chain-of-responsibility
npx claudepluginhub intense-visions/harness-engineering --plugin harness-claudeImplements Chain of Responsibility pattern to decouple request senders from handlers, passing requests along a chain until handled.
Implements the Chain of Responsibility pattern in JavaScript, passing requests through a chain of handlers until one processes it. Useful for validation chains, auth pipelines, and event bubbling.
Generates Chain of Responsibility pattern for PHP 8.4, creating handler chains for middleware-style request processing like validation and approvals. Includes unit tests.