SuperAPI AI Directory

coding-rules

Coding & development

View repository

Updated 10-16 05:52

About this skill

Coding Rules

Behavioral guidelines that apply to all work involving code. When implementing, modifying, refactoring, or reviewing code, follow the rules below and the instructions specific to the target repository.

Trade-off: These guidelines prioritize caution over speed. For trivial tasks, use your own judgment.

1. Think before coding

Do not guess. Do not hide what you do not know. Make trade-offs explicit.

Before implementation:

  • Explicitly state your assumptions. Ask questions when uncertain.
  • If multiple interpretations exist, present them. Do not silently choose one.
  • If there is a simpler approach, say so. Push back if necessary.
  • If anything is unclear, stop. Clarify what you do not understand and ask questions.

2. Prioritize simplicity

The minimum amount of code needed to solve the problem. Do not write anything based on speculation.

  • Do not build features beyond what was requested.
  • Do not introduce abstraction into code that is used only once.
  • Do not build unrequested "flexibility" or "configurability."
  • Do not write error handling for scenarios that cannot occur.
  • Trim unnecessary complexity, but do not cram processing, declarations, or branches together just to reduce line count. Prioritize code that humans can read and understand later over brevity.

Ask yourself: "If a senior engineer saw this, would they say 'this is overcomplicated'?" If the answer is Yes, simplify it.

3. Surgical changes

Touch only what is necessary. Clean up only what you made messy.

When editing existing code:

  • Do not arbitrarily "improve" surrounding code, comments, or formatting.
  • Do not refactor things that are not broken.
  • Match the existing style even if you would not write it that way yourself.
  • If you notice unrelated dead code, report it. Do not delete it on your own.

For things that became unnecessary because of your changes (orphans):

  • Delete imports, variables, and functions that became unused because of your changes.
  • Unless requested, do not delete pre-existing dead code.

Criterion: Every line you changed must be directly tied to the user's request.

4. Goal-driven execution

Define success criteria. Loop until it can be verified.

Turn tasks into verifiable goals:

  • "Add validation" → "Write tests for invalid input and make them pass"
  • "Fix the bug" → "Write a test that reproduces the bug and make it pass"
  • "Refactor X" → "Confirm that tests pass before and after the refactoring"

For multi-step tasks, present a concise plan:

1. [ステップ] → 検証: [チェック内容]
2. [ステップ] → 検証: [チェック内容]
3. [ステップ] → 検証: [チェック内容]

With strong success criteria, you can loop autonomously. With weak criteria ("make it work"), constant confirmation is required.

These guidelines can be said to be working when there are few unnecessary changes in the diff, few rewrites due to added complexity, and clarifying questions are asked before implementation rather than after a mistake.

5. Separate each meaningful unit with a blank line

Readability is a mandatory completion condition. Merely passing the formatter does not satisfy it.

When the implementation continues over multiple lines, treat the processing as meaningful units and insert one blank line between units.

  • Always insert one blank line between functions, methods, constructors, independent event handlers, and test cases. Attach explanatory comments to the declaration they refer to, and place the blank line before the comment.
  • Separate at points where the purpose of the processing changes, such as preparing input, validation, calculation/conversion, state update/saving, and returning results.
  • Apply the same standard not only at the top level of a function but also inside branches, loops, try/catch, and callbacks. If actual processing or a return follows a guard clause, separate them.
  • Group closely related lines that serve the same purpose, and do not mechanically separate based only on line count or insert blank lines between every line.
  • A unit here refers to a logical separation for readability. Do not add blocks or functions solely for the sake of separation.
  • In TypeScript / JavaScript, do not omit braces even if the body of a branch or loop is one line. Do not join multiple variables with commas; separate the declarations.
  • If nesting asynchronous processing or transformations makes the order of processing hard to read, express the stages with meaningfully named intermediate variables.
  • Apply to new and changed parts, and do not change blank lines in unrelated existing code.

Example: Separate input preparation, validation, update, and return with blank lines.

const name = input.name.trim();
const email = input.email.trim();

validateName(name);
validateEmail(email);

const user = await updateUser({ name, email });

return toUserResponse(user);

6. Leave the purpose and reason for the processing in comments

Enable first-time readers to understand the intent without conversation history or the implementer's memory.

  • Add an overview of the role to functions and methods. As needed, also explain input assumptions, return values, and external writes. Do not add mechanical explanations to self-evident accessors or callbacks with simple expressions.
  • Start the function comment with a short, definitive sentence stating what the function does, such as "Retrieve the appraisal record." or "Notify the processing result by email." Do not begin with reasons, constraints, or implementation methods; the first sentence alone should make the role clear.
  • Write the purpose, rationale, and constraints from the line after the overview onward. Do not add lead-ins such as "In a word" or "a function that ...". Apply the same standard to the main body, test helper functions, and named arrow functions.
  • For authentication/authorization, state transitions, save order, exclusive control, retries, timeouts, exception handling, cleanup, and similar matters, write at the relevant location what the instruction is for and why it is executed at that position or in that order.
  • Do not write comments that merely replace code with Japanese; explain the conditions to uphold and the problems to avoid. Do not guarantee in comments what the code does not guarantee.
  • In tests as well, leave the situation being verified and the reason, and separate preparation, execution, and expected value verification with blank lines. When verifying multiple situations in sequence, indicate the purpose of each.
  • Also format embedded scripts and fixtures for tests so they are readable, and do not compress them into long single lines.
  • When you modify code, also check consistency with comments, and do not leave old explanations behind.
/**
 * 本人の鑑定レコードを取得する。
 * 所有者が一致しない場合は、他人の鑑定の存在を知らせないため404として扱う。
 */
async function getJob(uid: string, id: string) {
  // 実装
}

7. Make it clear from the name alone what it does

Function names should state "what" and "how" definitively. Make it a completion condition that the processing content is clear just by reading the caller.

  • Name functions and methods with a verb + object.call・invoke・handle・run・get・put・send・api・result Do not use names that lack either the action or the target, such ascallPersistence・uploadJobFile・sendResultNotification Use names that make clear what is done by supplying the target, such as
  • Even with the same verb, use different names when the target differs.download Do not use "fetch" for both "fetch a job file via MCP" and "fetch an object directly from Storage"; distinguish them asdownloadJobFile と downloadObject .
  • For a function that validates and throws an exception, use a name that makes it clear it will stop on failure, such as validateOwnership・assertActive . If it only returns a judgment result, use a form that returns a boolean, such as isInsideDirectory .
  • For variables that return a Promise or functions used for waiting, include in the name what is being waited for, such as cancellationWatch・waitForExit・waitUntil .
  • Name test helpers by the same standard.seed・until・id For short names such asseedQueuedReading・waitUntil・readingIdFor , include the purpose, such as
  • Exceptions are names whose meaning is fixed by standard convention. Use the entry point main、Route Handler の GET・POSTand method names required by frameworks as they are.
  • When you change a name, update all old names remaining in callers, tests, and documentation. Do not leave explanations of old names in function comments.
// 悪い例:何を呼ぶのか、何を返すのかが名前から分からない
const record = await call(uid, 'get', id);
await put(ctx, 'conversation.jsonl', data);

// 良い例:MCPの永続化操作を呼ぶこと、ジョブのファイルを上げることが読める
const record = await callPersistence(uid, 'get', id);
await uploadJobFile(ctx, 'conversation.jsonl', data);

8. Reread from a human perspective before completion

  • After formatting, actually reread the entire modified functions and tests. Do not judge based only on the added lines in the diff.
  • Check function boundaries, separation of processing within nesting, comments on purpose and rationale, and whether the processing content can be understood from the names alone. Fix any places where a first-time reader cannot follow the processing order or side effects before reporting completion.
  • A formatter is a tool for tidying indentation and notation; do not use it as a substitute for judging logical separation or the adequacy of comments.
  • For readability-only fixes, preserve the processing order, exceptions, and asynchronous processing lifetimes, and verify with type checking and tests according to the changes. Do not treat a successful check alone as grounds for completion while readability violations remain.