lightsoutAlpha

class-graduation

Flags a folder created for a class that bundles no private companions.

Agent checkAdvises by default

Why this rule

File vs Folder — The Graduation Rule

Classes follow the same graduation rule as everything else (see architecture-decisions.md):

  • A class starts as a single file — RateLimiter.ts with its test beside it; non-exported helpers may co-locate.
  • A class graduates to a folder — HttpClient/ — only when it needs private companions (bundled utils, types, or constants that serve only it). Companions live under common/ by category (utils/, types/, constants/), and callers import the class from its own file — HttpClient/HttpClient.ts.
  • Do NOT create a folder for a class with no companions — that is ceremony, not structure.

Examples

The agent flags code like the incorrect example and accepts code like the correct one.

Incorrect

src/rate/RateLimiter/RateLimiter.ts
interface ConstructorParams {
tokens: number;
}
// A folder and a barrel around a class that bundles nothing — ceremony, not
// structure. `RateLimiter.ts` beside its test is the whole module.
export class RateLimiter {
private remaining: number;
constructor({ tokens }: ConstructorParams) {
this.remaining = tokens;
}
take(): boolean {
const allowed = this.remaining > 0;
if (allowed) {
this.remaining -= 1;
}
return allowed;
}
}

Correct

src/rate/RateLimiter.ts
interface ConstructorParams {
tokens: number;
}
// No companions, so no folder: the file is the module and the compiler enforces
// its boundary for free.
export class RateLimiter {
private remaining: number;
constructor({ tokens }: ConstructorParams) {
this.remaining = tokens;
}
take(): boolean {
const allowed = this.remaining > 0;
if (allowed) {
this.remaining -= 1;
}
return allowed;
}
}

Configure

  • Block"blocking"Stops a run when a file the run changed breaks the rule.
  • Advise"advisory"Reports it and hands it to the refactor agent. Never stops a run.
    Default
  • Off"off"Not checked. Use it when your own linter already enforces the rule.

Add this to your lightsout.config.json, then change the value.

lightsout.config.json
{
"standards-checks": {
"class-graduation": "advisory"
}
}