synaptic-labs-ai/pact-plugin/pact-coding-standards

Claude Code and agent skill by synaptic-labs-ai/pact-plugin

Trust tier 2
  • community
LLM review pending
Source check pending

Checking that the SKILL.md file is still in the repository.

Clean code principles, error handling patterns, and coding standards for PACT Code phase. Use when: implementing features, refactoring code, reviewing code quality, establishing coding conventions, or handling errors and exceptions. Triggers on: code quality, clean code, refactoring, error handling, logging patterns, naming conventions, code review, code phase.

Install

npx vskill@latest install synaptic-labs-ai/pact-plugin/pact-coding-standards

SKILL.md

PACT Coding Standards

Clean code principles for the Code phase of PACT. This skill provides essential coding guidelines and links to detailed patterns for implementation.

Core Principles

1. Single Responsibility Principle

Each function, class, or module should have exactly one reason to change.

javascript
// BAD: Multiple responsibilities
class UserManager {
createUser(data) { }
validateEmail(email) { }
sendWelcomeEmail(user) { }
generateReport() { }
updateUserPreferences(userId, prefs) { }
}
// GOOD: Single responsibility each
class UserService {
createUser(data) { }
updateUser(userId, data) { }
}
class EmailValidator {
validate(email) { }
}
class NotificationService {
sendWelcomeEmail(user) { }
}
class UserReportGenerator {
generate(criteria) { }
}
2. DRY (Don't Repeat Yourself)

Extract duplicated logic into reusable functions.

javascript
// BAD: Duplicated validation logic
function createUser(data) {
if (!data.email || !data.email.includes('@')) {
throw new Error('Invalid email');
}
// ...
}
function updateUser(id, data) {
if (data.email && !data.email.includes('@')) {
throw new Error('Invalid email');
}
// ...
}
// GOOD: Extracted validation
function validateEmail(email) {
if (!email || !email.includes('@')) {
throw new ValidationError('Invalid email format');
}
}
function createUser(data) {
validateEmail(data.email);
// ...
}
function updateUser(id, data) {
if (data.email) {
validateEmail(data.email);
}
// ...
}
3. KISS (Keep It Simple, Stupid)

Choose the simplest solution that works.

javascript
// BAD: Over-engineered
class ConfigurationFactoryBuilderManager {
static getInstance() {
return new ConfigurationFactoryBuilder()
.withDefaults()
.withEnvironment()
.build()
.getConfiguration();
}
}
// GOOD: Simple and direct
const config = {
port: process.env.PORT || 3000,
dbUrl: process.env.DATABASE_URL,
debug: process.env.NODE_ENV !== 'production'
};
4. Defensive Programming

Validate inputs, handle edge cases, and fail gracefully.

javascript
function processOrder(order) {
// Guard clauses
if (!order) {
throw new ValidationError('Order is required');
}
if (!order.items || order.items.length === 0) {
throw new ValidationError('Order must have at least one item');
}
if (order.total < 0) {
throw new ValidationError('Order total cannot be negative');
}
// Safe property access
const customerEmail = order.customer?.email ?? 'no-email@placeholder.com';
// Proceed with valid data
return {
id: generateOrderId(),
items: order.items.map(item => ({
...item,
price: Math.max(0, item.price) // Ensure non-negative
})),
total: order.total,
customerEmail
};
}

Naming Conventions

Functions
javascript
// Use verb + noun pattern
function getUser(id) { } // Retrieval
function createOrder(data) { } // Creation
function updateProfile(id, data) { } // Mutation
function deleteComment(id) { } // Deletion
function validateEmail(email) { } // Validation
function calculateTotal(items) { } // Calculation
function formatDate(date) { } // Transformation
function isActive(user) { } // Boolean check
function hasPermission(user, action) { } // Boolean check
function canEdit(user, resource) { } // Boolean check
Variables
javascript
// Descriptive nouns
const userCount = 42; // Not: n, count, uc
const activeUsers = users.filter(); // Not: arr, filtered
const maxRetryAttempts = 3; // Not: max, retries
// Boolean variables
const isActive = true; // is/has/can/should prefix
const hasPermission = false;
const canEdit = user.role === 'admin';
const shouldRetry = attempts < maxRetryAttempts;
// Collections are plural
const users = []; // Not: userList, userArray
const orderItems = []; // Not: items (too generic)
// Maps/objects describe content
const userById = {}; // Not: userMap
const priceByProductId = {}; // Describes key-value relationship
Constants
javascript
// SCREAMING_SNAKE_CASE for true constants
const MAX_RETRY_ATTEMPTS = 3;
const DEFAULT_PAGE_SIZE = 20;
const API_BASE_URL = 'https://api.example.com';
// Configuration objects
const CONFIG = Object.freeze({
database: {
host: process.env.DB_HOST,
port: parseInt(process.env.DB_PORT, 10)
}
});
Classes
javascript
// PascalCase, noun-based
class UserRepository { } // Not: UsersRepo, UserRepo
class OrderService { } // Not: OrdersService
class EmailValidator { } // Not: ValidateEmail
class PaymentGateway { } // Not: PaymentGatewayService
// Interface names (TypeScript)
interface Cacheable { } // Adjective for capabilities
interface UserRepository { } // Noun for contracts

Error Handling

Fail Fast, Recover Gracefully
javascript
async function createUser(data) {
// Validate early
if (!data.email) {
throw new ValidationError('Email is required');
}
if (!isValidEmail(data.email)) {
throw new ValidationError('Invalid email format');
}
// Check business rules
const existing = await userRepo.findByEmail(data.email);
if (existing) {
throw new ConflictError('Email already registered');
}
// Proceed with operation
try {
const user = await userRepo.save(data);
await emailService.sendWelcome(user.email);
return user;
} catch (error) {
// Handle specific errors
if (error instanceof DatabaseError) {
logger.error('Database error creating user', { error, data });
throw new ServiceError('Unable to create user, please try again');
}
throw error; // Re-throw unexpected errors
}
}
Custom Error Classes
javascript
// Base application error
class AppError extends Error {
constructor(message, code, statusCode = 500) {
super(message);
this.name = this.constructor.name;
this.code = code;
this.statusCode = statusCode;
Error.captureStackTrace(this, this.constructor);
}
}
// Specific error types
class ValidationError extends AppError {
constructor(message, details = []) {
super(message, 'VALIDATION_ERROR', 400);
this.details = details;
}
}
class NotFoundError extends AppError {
constructor(resource, id) {
super(`${resource} with id ${id} not found`, 'NOT_FOUND', 404);
this.resource = resource;
this.resourceId = id;
}
}
class ConflictError extends AppError {
constructor(message) {
super(message, 'CONFLICT', 409);
}
}
class UnauthorizedError extends AppError {
constructor(message = 'Authentication required') {
super(message, 'UNAUTHORIZED', 401);
}
}

For comprehensive error patterns: See references/error-handling-patterns.md


Logging

Log Levels
LevelWhen to UseExample
ERRORFailures requiring attentionDatabase connection failed
WARNPotentially harmful situationsRate limit approaching
INFONormal operational eventsUser created, order placed
DEBUGDetailed debugging infoFunction parameters, intermediate values
Structured Logging
javascript
const logger = require('./logger');
// BAD: Unstructured logging
console.log('User created: ' + user.id);
console.log('Error: ' + error.message);
// GOOD: Structured logging
logger.info('User created', {
userId: user.id,
email: user.email,
source: 'signup'
});
logger.error('Failed to process payment', {
orderId: order.id,
amount: order.total,
error: error.message,
errorCode: error.code,
stack: error.stack
});
// Request logging middleware
app.use((req, res, next) => {
const requestId = req.headers['x-request-id'] || uuidv4();
req.requestId = requestId;
logger.info('Request received', {
requestId,
method: req.method,
path: req.path,
userAgent: req.headers['user-agent'],
ip: req.ip
});
res.on('finish', () => {
logger.info('Request completed', {
requestId,
statusCode: res.statusCode,
duration: Date.now() - req.startTime
});
});
next();
});

Code Organization

File Size Guidelines
  • Maximum file size: 500 lines
  • Maximum function size: 50 lines
  • Maximum line length: 100 characters
Module Structure
javascript
// 1. Imports (external first, then internal)
const express = require('express');
const { validate } = require('class-validator');
const { UserService } = require('../services/UserService');
const { logger } = require('../utils/logger');
// 2. Constants and configuration
const MAX_PAGE_SIZE = 100;
const DEFAULT_PAGE_SIZE = 20;
// 3. Main exports (class, function, or router)
class UserController {
constructor(userService) {
this.userService = userService;
}
async getUsers(req, res, next) {
// Implementation
}
}
// 4. Helper functions (private to module)
function validatePagination(page, limit) {
// Implementation
}
// 5. Export statement
module.exports = { UserController };

Interpreting design-doc optionals

When a design doc spec'd an OPTIONAL cross-link sentence, closing paragraph, or sister-section reference, the CODE author MUST evaluate the optional content's logical relationship to the preceding paragraph before deciding how to render it.

  • Strengthening clause — the optional content reinforces, qualifies, or extends the directive in the preceding paragraph (e.g., a cross-link that tells the reader where the next degree of detail lives). FOLD it inline into the preceding paragraph for tighter prose flow.
  • Discursive observation — the optional content introduces a new framing, raises a separate point, or pivots to an adjacent concern. KEEP it as a standalone paragraph.

The judgment lives at write time: read the preceding paragraph and ask "does this optional content add to that paragraph's directive, or does it start a new one?" Strengthening = fold; discursive = keep.

Detection signature

Design-doc phrasings like "CODE may include or drop", "optional closing cross-link", or "optional discursive paragraph" mark the entry condition. Apply the strengthening-vs-discursive judgment before composing the section; do not default to either form mechanically.

Worked example — fold-in cross-link

In pact-plugin/skills/pact-testing-strategies/SKILL.md, the section "Sibling-file convention for parametrized noise-budget regression" closes its canonical-mitigation paragraph with an inline cross-reference to the sister "Author-blindness in HANDOFF arithmetic" section rather than a standalone closing paragraph. The cross-link functions as a strengthening clause on the elevated-priority directive that precedes it — telling the reader where the pair-with-cross-stream-verifier rule lives — so it folds into the same paragraph instead of opening a new one. The fold preserves the cross-reference content while keeping the canonical mitigation a single tight directive.


Code Quality Checklist

Before completing CODE phase:

Structure
  • [ ] Functions under 50 lines
  • [ ] Files under 500 lines
  • [ ] Single responsibility per function/class
  • [ ] No deeply nested code (max 3 levels)
Naming
  • [ ] Descriptive variable names
  • [ ] Consistent naming conventions
  • [ ] No abbreviations (except common ones: id, url, api)
  • [ ] Boolean variables have is/has/can prefix
Error Handling
  • [ ] All async operations have error handling
  • [ ] Errors include relevant context
  • [ ] No silent failures
  • [ ] User-facing errors are friendly
Documentation
  • [ ] Complex logic has comments
  • [ ] Public APIs have JSDoc/docstrings
  • [ ] No commented-out code
  • [ ] No TODO comments without tickets

This is the start of the file. Read the full SKILL.md on GitHub.

Security

  • Security scanPassed, 100 of 100Pattern checks on the skill's files.
  • Model reviewNot runA model review is scheduled for the next rescan.

Quality evaluation

  • Task evaluationNot runNo evaluation yet. Run one in Skill Studio.

Source

Popularity

7-day trend score
0

Not refreshed yet.

Works with

Any agent vskill installs to: 56 targets in all. These 39 have a page on this site.

  • Claude Code
  • Cursor
  • GitHub Copilot
  • Windsurf
  • Codex
  • Gemini CLI
  • Cline
  • Amp
  • Roo Code
  • Goose
  • Continue
  • Kilo Code
  • Junie
  • Trae
  • OpenHands
  • Qwen Code
  • AI Agent
  • Tabnine Chat
  • Sourcegraph Cody
  • Amazon Q
  • Firebase Genkit
  • Sweep
  • Devin
  • Phind
  • Mentat
  • Claude Desktop
  • Aider
  • GPT Pilot
  • Plandex
  • bolt.new
  • v0
  • Replit Agent
  • Anse
  • TypingMind
  • BetterChatGPT
  • LibreChat
  • Warp AI
  • Pieces
  • Fig AI
Embed badge
vskill VERIFIED badge
[![vskill VERIFIED](https://verified-skill.com/api/v1/skills/synaptic-labs-ai/pact-plugin/pact-coding-standards/badge)](https://verified-skill.com/skills/synaptic-labs-ai/pact-plugin/pact-coding-standards)

Something wrong with this skill or its page? Tell us.