This file is the canonical contributor contract for this repository.
It is intentionally concise. Focus on stable engineering rules, not volatile repository snapshots.
Use this document to align all contributors (human + AI) on:
- Code quality standards
- TDD workflow
- Type discipline
- Error handling expectations
- Verification gates before handoff
If a detail is likely to drift quickly (counts, exhaustive inventories, long endpoint/tool lists), it does not belong here.
When explaining work to Wags (or other non-implementation stakeholders), default to functional-first:
- Direct answer first (yes/no or recommendation in first line)
- Functional impact (what changes for user/operator behavior)
- Why it matters (risk avoided or outcome improved)
- Implementation details last (only as needed)
Style rules:
- Don’t lead with file paths or internal jargon
- Prefer plain language over internal abstractions
- Be concise and concrete
- If tradeoffs exist, list options and clearly mark the recommendation
This requirement is mandatory and must remain in this file.
Always follow red → green → refactor in vertical slices:
- Confirm the next behavior slice and any interface change
- RED: write exactly one failing test (public interface)
- GREEN: implement the minimal code to pass that one test
- Repeat one-test/one-implementation cycles
- REFACTOR: only after tests are green
TDD rules:
- No horizontal slicing (no bulk tests then bulk implementation)
- Test behavior, not internals
- Test through public interfaces only
- Mock true boundaries only (external APIs, time/randomness, fs/db when needed)
- No refactor while red
- Test names should describe outcomes, not implementation
- No
anywithout explicit justification comment - Prefer
unknownand narrow explicitly - Design types first, implementation second
- Explicit return types on exported/top-level functions
- Make invalid states unrepresentable where practical
- Prefer discriminated unions over optional fields for state variants
- Use branded types (
string & { __brand: "UserId" }) for domain IDs that must not be swapped - Use
satisfiesfor config/constant validation — neverasfor type assertion - Every async operation must accept
AbortSignalfor cancellation - Clean up resources in
finallyblocks; useusing(TS 5.2+) for disposables - Exhaustive
switchmust end withdefault: neverguard
- Narrow
try/catchto the specific throwing call - Never swallow errors silently
- Prefer typed errors or discriminated unions
- If throwing, make failure mode clear and intentional
Hard rules:
- No nested ternaries
- No dense one-liners for multi-step logic
- Prefer early returns over deep nesting
- One responsibility per function
- Flatten async flows (
async/awaitover nested.then()chains) - No dead code (unused imports, commented blocks, unreachable paths)
- Comments explain why, not what
- No preemptive abstractions
- Extract only after 2–3 real repetitions
- Composition over inheritance
- Keep import chains shallow
- TypeScript + ESM (
"type": "module") - 2-space indent, double quotes, semicolons
- Sorted imports: stdlib → external → internal (with
.jsextensions in imports) - Use
functionkeyword for named/exported functions - Use the repo-pinned runtime/tooling (
.nvmrc,package.json#packageManager,.npmrc); do not mix Node/pnpm versions across install/build/run - React: explicit
Propstypes, named exports, one component per file - Co-locate tests with source (
foo.ts/foo.test.ts) - Prefer small cohesive modules (~200 lines target)
For new or substantially modified .ts files under src/, start with:
// File: {filename} | Module: {module-name}
- Run focused tests for touched modules
- Re-run focused tests after each green step in TDD cycles
Always run:
pnpm test
pnpm build
pnpm readiness:debt:gateIf dashboard/UI changed:
pnpm dashboard:buildIf readiness tooling/docs changed:
pnpm readiness:audit- Would a new team member understand this in ~30 seconds?
- Are tests present for new behavior and passing?
- Any nested ternaries, silenced errors, or dead code left?
- Does each function have one clear responsibility?
- Did we preserve existing conventions rather than inventing new patterns?
To avoid drift and context bloat, do not store these here:
- Snapshot counts (test files, plugin counts, package version)
- Exhaustive endpoint/tool command inventories
- Long runtime/service boot sequences that change frequently
- Path caveat lists that require ongoing bookkeeping
When those details are needed, verify directly from source with repo tooling (rg, tests, and focused code reads).
If you change contributor workflow, quality rules, or verification requirements, update this file in the same PR.