Standards for authoring SDD plugin agents — frontmatter, self-containment, skill references, and no-user-interaction rules.
日本語の概要は準備中です。原文の説明を表示しています。
Shared TypeScript coding standards for strict, immutable, type-safe code.
インストールする前に、エージェントに与えられる指示の中身を確認できます。
Shared standards for all TypeScript code in this methodology (backend and frontend).
All projects must use these TypeScript compiler options:
// tsconfig.json requirements
{
"strict": true,
"noImplicitAny": true,
"strictNullChecks": true,
"strictFunctionTypes": true,
"strictPropertyInitialization": true,
"noImplicitThis": true,
"alwaysStrict": true
}
Rules:
any unless absolutely unavoidable (must be justified)unknown over anyUse readonly on all properties, ReadonlyArray<T> for arrays, Readonly<T> / ReadonlyMap / ReadonlySet for generic types. Use const exclusively (never let or var). Use spread operators for updates — never mutate.
See immutability.md for full examples and functional alternatives to let.
CRITICAL: .push(), .pop(), .shift(), .unshift(), .splice(), .sort(), .reverse(), .fill() on arrays; obj.prop = x, delete obj.prop, Object.assign(target, ...) on objects; .set(), .delete(), .add(), .clear() on Maps/Sets — all strictly forbidden. Use spread operators and immutable patterns instead.
See banned-operations.md for the complete reference tables with alternatives.
// GOOD: Arrow functions
const createUser = async (deps: Dependencies, args: CreateUserArgs): Promise<CreateUserResult> => {
// ...
};
const handleClick = () => {
// ...
};
// BAD: function keyword
async function createUser(deps: Dependencies, args: CreateUserArgs): Promise<CreateUserResult> {
// ...
}
function handleClick() {
// ...
}
Rule: Use arrow functions exclusively. Never use the function keyword.
CRITICAL: Never use classes or inheritance unless creating a subclass of Error.
// GOOD: Types and functions
type User = {
readonly id: string;
readonly email: string;
readonly createdAt: Date;
};
const createUser = (args: CreateUserArgs): User => ({
id: generateId(),
email: args.email,
createdAt: new Date(),
});
// GOOD: Error subclass (only valid use of class)
class ValidationError extends Error {
constructor(
message: string,
readonly field: string,
readonly code: string
) {
super(message);
this.name = 'ValidationError';
}
}
class NotFoundError extends Error {
constructor(resource: string, id: string) {
super(`${resource} with id ${id} not found`);
this.name = 'NotFoundError';
}
}
// BAD: Classes for domain objects
class User {
constructor(
public id: string,
public email: string
) {}
updateEmail(email: string) {
this.email = email; // Mutation!
}
}
// BAD: Inheritance hierarchies
class Animal { /* ... */ }
class Dog extends Animal { /* ... */ }
// BAD: Service classes
class UserService {
constructor(private db: Database) {}
async createUser(args: CreateUserArgs) { /* ... */ }
}
Why:
this)instanceof, stack traces)// GOOD: Native methods
const filtered = users.filter(u => u.active);
const updated = { ...user, email: newEmail };
const mapped = Object.fromEntries(
Object.entries(obj).map(([k, v]) => [k, v * 2])
);
// BAD: External utility libraries
import { map } from 'lodash'; // Never
import { produce } from 'immer'; // Never
import * as R from 'ramda'; // Never
Rule: Use only native JavaScript/TypeScript features. No utility libraries like lodash, ramda, or immer.
Why: Reduces bundle size, eliminates dependencies, forces understanding of native methods, ensures code remains maintainable without external library knowledge.
Named exports only (never default exports). ES modules only (never CommonJS). index.ts files contain only imports/exports (no logic). Always import through index.ts (never bypass to implementation files). Inside a module, never import from its own index.ts — use relative paths to siblings. No file extensions in imports. Use @/ path alias for deep imports (2+ directory levels). Use import type for type-only imports.
See module-system.md for full rules with examples.
Rule: interface for function-only contracts (callbacks, loggers, handlers). type for everything else. Data types should not contain functions.
// GOOD: interface for function-only contracts
interface Logger {
readonly info: (message: string, data?: unknown) => void;
readonly warn: (message: string, data?: unknown) => void;
readonly error: (message: string, data?: unknown) => void;
}
// GOOD: type for data shapes
type User = {
readonly id: string;
readonly email: string;
readonly createdAt: Date;
};
type ServerMode = 'api' | 'worker' | 'cron';
type HelmSettings = HelmServerSettings | HelmWebappSettings;
// BAD: interface for data
interface User {
readonly id: string;
readonly email: string;
}
// BAD: type for function contracts
type Logger = {
readonly info: (message: string) => void;
};
// BAD: functions inside data types
type User = {
readonly id: string;
readonly getDisplayName: () => string; // Data types should not have methods
};
Use type aliases to give meaning to primitives. A function accepting Milliseconds is self-documenting; a function accepting number is not.
// GOOD: Semantic aliases
type Milliseconds = number;
type Pixels = number;
type DatabaseProvider = 'postgresql';
type ServerMode = 'api' | 'worker' | 'cron';
type SpecStatus = 'pending' | 'in_progress' | 'ready_for_review' | 'approved';
type AnimationConfig = {
readonly duration: Milliseconds;
readonly delay: Milliseconds;
readonly width: Pixels;
};
// BAD: Raw primitives with no meaning
type AnimationConfig = {
readonly duration: number; // Seconds? Milliseconds? Frames?
readonly delay: number;
readonly width: number; // Pixels? Rem? Percent?
};
Type guards for discriminated union narrowing. as const for literal arrays with typeof X[number] to derive union types. Generics for type-safe operations. keyof and indexed access types for type-safe property access. Object.entries / Object.fromEntries for immutable object transformations.
See advanced-types.md for full examples.
Every function should return a meaningful value. Void functions are extremely rare and should be avoided — they hide information from callers and make code harder to compose.
// GOOD: Return a result that callers can use
const saveSettings = async (path: string, settings: SddConfig): Promise<CommandResult> => {
try {
await writeJson(path, settings);
return { success: true, output: `Settings saved to ${path}` };
} catch (err) {
const message = err instanceof Error ? err.message : String(err);
return { success: false, error: `Failed to save settings: ${message}` };
}
};
// GOOD: Even simple operations can return useful info
const addToCache = (cache: ReadonlyMap<string, string>, key: string, value: string): ReadonlyMap<string, string> =>
new Map([...cache, [key, value]]);
// BAD: Void function hides outcome from caller
const saveSettings = async (path: string, settings: SddConfig): Promise<void> => {
await writeJson(path, settings); // Caller can't tell if it worked
};
// BAD: Side-effect-only function
const logMetrics = (data: Metrics): void => {
console.log(JSON.stringify(data));
};
Rule: All functions should return values. If a function has nothing meaningful to return, that's a signal the design should be reconsidered.
Exception: Callback signatures in interface contracts (like Logger) may use void return types, since the caller doesn't consume the return value. This is the only acceptable use of void.
Result unions over null — discriminated union return types for failable operations (never return null or throw for expected failures). Error catch blocks narrow with instanceof Error. External data validated at system boundaries.
See error-handling.md for full patterns with examples.
// GOOD: Explicit Promise<T> return type
const loadSettings = async (path: string): Promise<CommandResult> => {
// ...
};
// GOOD: Promise.all for concurrent independent operations
const validationResults = await Promise.all(
specs.map((spec) => validateSpecFile(spec.path))
);
// GOOD: Promise.all with typed results
const results = await Promise.all(
entries.map(async (entry): Promise<ReadonlyArray<string>> => {
if (entry.isDirectory()) {
return walkDir(fullPath, filter);
}
return [];
})
);
// BAD: Sequential when parallel is possible
const result1 = await validateSpec(spec1);
const result2 = await validateSpec(spec2); // Waits unnecessarily
// BAD: Missing return type annotation
const loadSettings = async (path: string) => { // Return type unclear
// ...
};
For function return types, prefer result unions (see Error Handling). This section covers the distinction between null and undefined in type fields and when interacting with external APIs.
// GOOD: undefined via optional fields ("not provided")
type HelmServerSettings = {
readonly deploy_modes?: ReadonlyArray<ServerMode>; // Optional = may be undefined
};
// GOOD: Handling undefined from native APIs
const first = items.find(i => i.active); // Returns T | undefined natively
if (first === undefined) {
return { success: false, error: 'No active items found' };
}
// GOOD: Handling null from external/DOM APIs
const element = document.getElementById('root'); // Returns HTMLElement | null
if (element === null) {
return { success: false, error: 'Root element not found' };
}
// BAD: Mixing null and undefined in your own types
type Config = {
readonly host: string | null; // Sometimes null
readonly port: string | undefined; // Sometimes undefined
// Inconsistent — use optional fields (undefined) for "not provided"
};
// BAD: Returning null from your own functions
const findComponent = (name: string): Component | null => {
return components.find(c => c.name === name) ?? null;
// Use a result union instead (see Error Handling)
};
Rule: Use undefined (via ?:) for optional type fields. Handle null/undefined from external APIs by converting to result unions. Never return null from your own functions — use result unions instead.
Record<string, never> for Empty Types// GOOD: Record<string, never> for placeholder types
type ConfigSettings = Record<string, never>;
type TestingSettings = Record<string, never>;
type CicdSettings = Record<string, never>;
// These can be used in unions without accepting arbitrary data:
type ComponentSettings = ServerSettings | DatabaseSettings | ConfigSettings;
// BAD: Using {} or object for empty types
type ConfigSettings = {}; // Accepts any non-nullish value
type ConfigSettings = object; // Too broad
??) vs Logical OR (||)// GOOD: ?? for defaults (preserves 0, '', false)
const port = config.port ?? 3000; // Only falls through on null/undefined
const name = config.name ?? 'default'; // '' is a valid name, kept as-is
const verbose = config.verbose ?? false;
// GOOD: || only when 0/''/false should also trigger the default
const displayName = user.nickname || user.email; // Empty string -> use email
// BAD: || when 0 or '' are valid values
const port = config.port || 3000; // port=0 becomes 3000 — wrong!
const count = config.count || 10; // count=0 becomes 10 — wrong!
Rule: Default to ??. Only use || when you intentionally want to fall through on all falsy values.
For detailed guidance, read these on-demand:
Before committing TypeScript code, verify:
tsconfig.json has all strict mode options enabledreadonlyReadonlyArray<T>Readonly<T>, ReadonlyMap, ReadonlySetfunction keyword).push(), .pop(), .shift(), .unshift(), .splice(), .sort(), .reverse())obj.prop = x, obj['key'] = x, delete obj.prop).set(), .delete(), .add(), .clear())export const, export interface, etc.)import/export, never require/module.exports)index.ts files contain only imports/exports (no logic)index.ts - never import implementation files directly.js, .ts, .tsx@/ instead of ../../../any types without justificationconst declarations (never let, never var)interface for function contracts only, type for everything elseas const for literal arrays; derive union types with typeof X[number]instanceof ErrorPromise<T> return typesimport type for type-only imports?? for defaults (not ||)let — use const with .map/.reduce/ternariesThis skill defines no input parameters or structured output.
まだレビューはありません。使ってみた感想をお寄せください。
概要と使いどころ
Standards for authoring SDD plugin agents — frontmatter, self-containment, skill references, and no-user-interaction rules.
日本語の概要は準備中です。原文の説明を表示しています。
Scaffolds Node.js/TypeScript backend components with CMDO architecture, driven by component settings.
日本語の概要は準備中です。原文の説明を表示しています。
CMDO architecture standards for Node.js/TypeScript backends with strict layer separation.
日本語の概要は準備中です。原文の説明を表示しています。
Intent-to-command mappings for fullstack-typescript tech pack features.
日本語の概要は準備中です。原文の説明を表示しています。
Create change specification and implementation plan with dynamic phase generation. Supports feature, bugfix, refactor, and epic types.
日本語の概要は準備中です。原文の説明を表示しています。
Orchestrates the full change lifecycle — routes actions to phase-specific sub-files.
日本語の概要は準備中です。原文の説明を表示しています。