| name | development |
| description | Provides expertise on development practices and code quality standards for this repo |
Overview
This skill provides comprehensive guidance on development practices, code quality standards, and the proper approach to handling incomplete work during implementation.
Core Principles:
- Completeness over speed - Never leave TODO markers or stub implementations
- Design before code - Every TODO discovered requires technical design first
- Type-driven development - Types are not optional, they are the contract
- No technical debt - Address issues immediately, don't defer them
🚨 CRITICAL: TODO Markers Are FORBIDDEN
The Hard Rule
TODO/FIXME/XXX/HACK markers in committed code are UNACCEPTABLE.
When you discover a TODO marker (whether you created it or inherited it), this is NOT a reminder for later work. This is a BLOCKING SIGNAL that:
- ✅ There is incomplete design work
- ✅ There is missing implementation
- ✅ The code is broken or insufficient
- ✅ You must stop and address it NOW
Why TODO Markers Are Problematic
export type StripTags<T extends string> = T;
export function parseComplexData(input: string): ParsedResult {
return {} as ParsedResult;
}
export function validateConfig(config: unknown): boolean {
return true;
}
Problems with the above:
- Broken contracts - Users expect
StripTags to strip tags, but it doesn't
- Type lies - Return types promise something the implementation doesn't deliver
- Hidden bugs - Code appears to work but fails in production
- Compounding debt - One TODO leads to workarounds that create more TODOs
- Lost context - Future you won't remember why the TODO exists or what it needs
The Proper Workflow When You Encounter a TODO
When you find a TODO marker (in existing code or while planning new code), follow this workflow:
Step 1: STOP Immediately
Do not proceed with any other work. TODOs are blocking issues.
rg -i "TODO|FIXME|XXX|HACK" modules/lib/src/
echo "Found TODO in X: <description>" >> .ai/logs/current-phase.md
Step 2: Understand the Context
Ask yourself:
-
What is this TODO supposed to do?
- Read the surrounding code
- Check the function signature / type definition
- Look at how it's being used
- Review any related documentation
-
Why was it left incomplete?
- Was it a lack of knowledge?
- Was it complexity avoidance?
- Was it a placeholder during design?
- Was it genuinely forgotten?
-
What would a complete implementation look like?
- What are the inputs and outputs?
- What edge cases need handling?
- What type-level computation is needed?
- What tests would verify correctness?
Step 3: Technical Design
BEFORE writing any code, create a technical design for the complete solution.
For Type Utilities:
For Runtime Functions:
Step 4: Add to TODO List
Track this as a blocking task in your active todo list:
TodoWrite({
todos: [
{
content: "Implement StripSimpleTags type utility with recursive template literal parsing",
activeForm: "Implementing StripSimpleTags type utility",
status: "in_progress"
},
{
content: "Add comprehensive type tests for StripSimpleTags",
activeForm: "Adding type tests for StripSimpleTags",
status: "pending"
}
]
});
Step 5: Implement Completely
Implement the full, complete solution - no shortcuts, no new TODOs.
For Type Utilities:
export type StripSimpleTags<T extends string> =
T extends `${infer Before}<soft>${infer After}`
? StripSimpleTags<`${Before}${StripSimpleTags<After>}`>
: T extends `${infer Before}</soft>${infer After}`
? StripSimpleTags<`${Before}${StripSimpleTags<After>}`>
: T extends `${infer Before}<loud>${infer After}`
? StripSimpleTags<`${Before}${StripSimpleTags<After>}`>
: T extends `${infer Before}</loud>${infer After}`
? StripSimpleTags<`${Before}${StripSimpleTags<After>}`>
: T;
For Runtime Functions:
export function parseComplexData(input: string): ParsedResult {
if (!input || input.trim() === "") {
return {};
}
const pairs = input.split(",");
const result: Record<string, string> = {};
for (const pair of pairs) {
const [key, value] = pair.split("=");
if (!key || !value) {
throw new ParseError(`Invalid key-value pair: "${pair}"`);
}
result[key.trim()] = value.trim();
}
return result;
}
Step 6: Add Tests
Tests are not optional. Every implementation needs verification.
For Type Utilities:
describe("StripSimpleTags<T>", () => {
it("should strip <soft> tags", () => {
type Test1 = StripSimpleTags<"<soft>hello</soft>">;
type Test2 = StripSimpleTags<"world <soft>hello</soft> universe">;
type cases = [
Expect<AssertEqual<Test1, "hello">>,
Expect<AssertEqual<Test2, "world hello universe">>
];
});
it("should handle nested tags", () => {
type Test = StripSimpleTags<"<soft><loud>hello</loud></soft>">;
type cases = [
Expect<AssertEqual<Test, "hello">>
];
});
it("should handle no tags", () => {
type Test = StripSimpleTags<"hello world">;
type cases = [
Expect<AssertEqual<Test, "hello world">>
];
});
it("should handle empty string", () => {
type Test = StripSimpleTags<"">;
type cases = [
Expect<AssertEqual<Test, "">>
];
});
});
For Runtime Functions:
describe("parseComplexData()", () => {
it("should parse valid input", () => {
const result = parseComplexData("key1=value1,key2=value2");
expect(result).toEqual({
key1: "value1",
key2: "value2"
});
});
it("should handle empty string", () => {
const result = parseComplexData("");
expect(result).toEqual({});
});
it("should throw on invalid format", () => {
expect(() => parseComplexData("invalid")).toThrow(ParseError);
});
it("should handle duplicate keys (last wins)", () => {
const result = parseComplexData("key=first,key=second");
expect(result).toEqual({ key: "second" });
});
});
Step 7: Verify and Mark Complete
Only after implementation + tests both pass:
pnpm test
pnpm test:types
rg -i "TODO|FIXME" path/to/file.ts
TodoWrite({ todos: [...] })
Common Scenarios and Solutions
Scenario 1: "I don't know how to implement this"
❌ WRONG Response:
export function complexAlgorithm(): Result {
return {} as Result;
}
✅ CORRECT Response:
- Research first - Look for similar implementations in codebase or libraries
- Ask for help - Use documentation, search GitHub, ask the user
- Break it down - Decompose into smaller, manageable pieces
- Prototype - Try a simple version first, then refine
- Document - Write design notes explaining your approach
Scenario 2: "This is too complex for right now"
❌ WRONG Response:
export function slowFunction(): void {
}
✅ CORRECT Response:
- Implement it properly first - Even if not optimal, make it correct
- Add performance tests - Measure actual impact before optimizing
- Document tradeoffs - Explain why simple approach was chosen
- No TODO - If it works correctly, it's complete
export function processData(items: Item[]): Result {
}
Scenario 3: "This needs a major refactor"
❌ WRONG Response:
export class LegacyClass {
}
✅ CORRECT Response:
- File an issue - Document the refactor need in issue tracker
- Make it work - Ensure current code is correct, even if messy
- Plan the refactor - Create a separate refactor plan
- No FIXME - Working code doesn't get TODO markers
export class LegacyClass {
}
Type Utility Development Guidelines
The Type Utility Contract
When you write a type utility, you're making a compile-time promise to users:
export type ParseJSON<T extends string> = ;
Red Flags for Incomplete Type Utilities
export type MyUtility<T> = T;
export type HasProperty<T, K> = false;
export type ParseSomething<T> = any;
export type Incomplete<T> = T;
Proper Type Utility Implementation
export type StrictExtract<T, U> = T extends U ? T : never;
export type IsArray<T> = T extends readonly unknown[] ? true : false;
export type DeepReadonly<T> = {
readonly [K in keyof T]: T[K] extends object
? DeepReadonly<T[K]>
: T[K]
};
Runtime Implementation Guidelines
The Function Contract
When you write a function signature, you're making a runtime promise:
export async function fetchUser(id: number): Promise<User>;
Red Flags for Incomplete Functions
export function getRealData(): Data {
return { fake: "data" } as Data;
}
export function complexCalculation(): number {
return 0;
}
export function dangerousOperation(): void {
try {
} catch {
}
}
Proper Function Implementation
export async function fetchUser(id: number): Promise<User> {
if (!Number.isInteger(id) || id <= 0) {
throw new ValidationError("User ID must be positive integer");
}
try {
const response = await fetch(`/api/users/${id}`);
if (!response.ok) {
throw new ApiError(`Failed to fetch user: ${response.status}`);
}
const data = await response.json();
return validateUser(data);
} catch (error) {
if (error instanceof ApiError || error instanceof ValidationError) {
throw error;
}
throw new NetworkError("Failed to connect to API", { cause: error });
}
}
Quality Checklist
Before committing any code, verify:
Type Quality
Runtime Quality
Testing Quality
When You're Stuck
If you genuinely can't complete something:
1. Don't Leave a TODO
❌ WRONG:
export function incomplete(): void {}
2. Implement a Minimal Version
✅ CORRECT:
export function validateInput(input: unknown): ValidationResult {
if (!input || typeof input !== "object") {
return { valid: false, errors: ["Input must be an object"] };
}
return { valid: true, errors: [] };
}
3. Ask for Help
In your message to the user:
"I'm implementing X and need guidance on Y. I've researched Z and found A and B as potential approaches. Which direction should I take?"
NOT:
"I'll add a TODO and come back to this later."
Summary
The Golden Rule: No TODOs in Committed Code
Every TODO marker represents:
- ✅ Incomplete design work → Do the design now
- ✅ Missing implementation → Implement it now
- ✅ Insufficient knowledge → Research/ask now
- ✅ Deferred technical debt → Address it now
When you find a TODO:
- STOP - Don't proceed with other work
- DESIGN - Write technical design notes
- TRACK - Add to todo list as blocking task
- IMPLEMENT - Write complete solution
- TEST - Verify it works
- VERIFY - Confirm no TODOs remain
A phase with unresolved TODOs is an INCOMPLETE phase.
Quick Reference
rg -i "TODO|FIXME|XXX|HACK" modules/lib/src/
rg -i "TODO" modules/lib/src/types/
rg -i "FIXME" modules/lib/src/utils/
rg "export type.*= T;$"
rg "return.*as.*;"
rg "throw new Error\(\"Not implemented\"\)"