coding-standards — independently scanned and version-tracked by SaferSkills.
SaferSkills independently audited coding-standards (Agent Skill) and scored it 100/100 (green). The audit ran 55 deterministic rules across Security, Supply Chain, Maintenance, Transparency, and Community; it found 0 high-severity and 0 lower-severity findings. The full rule-by-rule trace and per-finding evidence are below. Free, methodology-open.
Findings & checks · 0 flagged
Every scanned point with the score it earned and what moved between them.
First recorded scan — no prior version to compare against.
The primary manifest — the file an agent reads to learn what this artifact does.
Baseline coding conventions applicable across projects.
This skill is the shared floor, not the detailed framework playbook.
frontend-patterns for React, state, forms, rendering, and UI architecture.backend-patterns or api-design for repository/service layers, endpoint design, validation, and server-specificconcerns.
rules/common/coding-style.md when you need the shortest reusable rule layer instead of a full skill walkthrough.Activate this skill for:
Do not use this skill as the primary source for:
These are the engineering floor for every project. A request or an existing pattern that breaks one of them is a defect, the same as a failing test. Say so and propose the version that respects them.
add behaviour by extending, not by editing working code. Liskov substitution: a subtype works anywhere its base type is expected. Interface segregation: many small focused interfaces over one large one. Dependency inversion: depend on abstractions, never on concrete implementations.
programming.
The detailed testing playbook lives in the tdd-workflow, python-testing, golang-testing, and springboot-tdd skills; this hub only states the principle.
comment to explain what it does, extract it into a well-named function instead.
calculateTotalRevenue, fetchMarketData), never a bare noun or a singleletter. Booleans start with is, has, or can.
requires inference (for example Go short variable declarations).
is a smell to split.
#### 5. Functional Pipelines Over Imperative Cascades
When transforming a collection, filter, then map, then aggregate - prefer a pipeline (one operation per step, top-down) over an imperative for loop with if-else cascading and an explicit accumulator. The pipeline reads as "what we're doing to the data"; the cascade reads as "how the bookkeeping goes."
This is a code-shape rule, not a syntax-level formatting one. The sibling code-formatter skill says "one chain step per line"; this skill says "reach for the chain in the first place."
##### Dart
// BAD — imperative cascade
final activeNames = <String>[];
for (final e in exercises) {
if (e.isActive) {
activeNames.add(e.name);
}
}
// GOOD — pipeline
final activeNames = exercises
.where((e) => e.isActive)
.map((e) => e.name)
.toList();##### Java
Java's Stream API and Optional are explicitly designed for this. A for + if + list.add block where a stream would do is a code smell in modern Java.
// BAD
List<String> activeNames = new ArrayList<>();
for (Exercise e : exercises) {
if (e.isActive()) {
activeNames.add(e.name());
}
}
// GOOD
List<String> activeNames = exercises.stream()
.filter(Exercise::isActive)
.map(Exercise::name)
.toList();
// Same principle for nullable values: reach for Optional, not if-null
// BAD
Exercise e = repository.findById(id);
if (e != null) {
return e.name();
} else {
return "unknown";
}
// GOOD
return repository.findById(id)
.map(Exercise::name)
.orElse("unknown");##### Python
Python's idiomatic equivalent is a comprehension (or, for lazy streams, a generator expression). Reach for them before you reach for an explicit for + if + list.append.
# BAD
active_names = []
for e in exercises:
if e.is_active:
active_names.append(e.name)
# GOOD
active_names = [e.name for e in exercises if e.is_active]
# When the transformation is heavier than a single expression, a
# generator + sum/max/min/any/all keeps the pipeline shape:
total_reps = sum(s.reps for s in series if s.reps > 0)##### When NOT to convert
with an index-dependent argument, mutating an outside variable) belong in an explicit for, pipelines should be pure.
takeWhile/first cleanly.
with the codebase's style, clarity outranks compactness.
The point is prefer, not always.
hides the failure.
an error into the correct response.
to the correct status code and never leak internal detail (no stack trace, no disclosure of whether an account exists).
with meaningful levels and a correlation or trace identifier. Never log secrets, credentials, or personal data; mask sensitive fields.
The full logging and observability playbook lives in the observability-and-logging skill.
and moved without dragging the rest along.
where the toolchain supports it.
time, never as a loose bag of flags that can contradict each other.
The detailed ports-and-adapters treatment lives in the hexagonal-architecture skill.
Gate risky, incomplete, or experimental work behind a feature flag rather than a long-lived branch that drifts from the main line.
reviewed in small pieces.
dead branches once the feature is fully shipped.
Record every significant design decision as a short architecture decision record with the context, the decision, and the consequences. Keep design rationale and decision history out of source files. The format and workflow live in the architecture-decision-records skill.
#### Variable Naming
// PASS: GOOD: Descriptive names
const marketSearchQuery = 'election'
const isUserAuthenticated = true
const totalRevenue = 1000
// FAIL: BAD: Unclear names
const q = 'election'
const flag = true
const x = 1000#### Function Naming
// PASS: GOOD: Verb-noun pattern
async function fetchMarketData(marketId: string) { }
function calculateSimilarity(a: number[], b: number[]) { }
function isValidEmail(email: string): boolean { }
// FAIL: BAD: Unclear or noun-only
async function market(id: string) { }
function similarity(a, b) { }
function email(e) { }#### Immutability Pattern (CRITICAL)
// PASS: ALWAYS use spread operator
const updatedUser = {
...user,
name: 'New Name'
}
const updatedArray = [...items, newItem]
// FAIL: NEVER mutate directly
user.name = 'New Name' // BAD
items.push(newItem) // BAD#### Error Handling
// PASS: GOOD: Comprehensive error handling
async function fetchData(url: string) {
try {
const response = await fetch(url)
if (!response.ok) {
throw new Error(`HTTP ${response.status}: ${response.statusText}`)
}
return await response.json()
} catch (error) {
throw new Error('Failed to fetch data', { cause: error })
}
}
// FAIL: BAD: No error handling
async function fetchData(url) {
const response = await fetch(url)
return response.json()
}#### Async/Await Best Practices
// PASS: GOOD: Parallel execution when possible
const [users, markets, stats] = await Promise.all([
fetchUsers(),
fetchMarkets(),
fetchStats()
])
// FAIL: BAD: Sequential when unnecessary
const users = await fetchUsers()
const markets = await fetchMarkets()
const stats = await fetchStats()#### Type Safety
// PASS: GOOD: Proper types
interface Market {
id: string
name: string
status: 'active' | 'resolved' | 'closed'
created_at: Date
}
function getMarket(id: string): Promise<Market> {
// Implementation
}
// FAIL: BAD: Using 'any'
function getMarket(id: any): Promise<any> {
// Implementation
}#### When to Comment
Default to no comments. Identifiers and structure already say what the code does. Add a comment only when the why is non-obvious, a hidden invariant, a workaround for a specific defect with a stable external reference (CVE, RFC section), or behavior that would surprise a future reader.
Do not write comments that reference ticket numbers, PR numbers, or review section numbers (// PHA-270 fix, // per review §4.4, // Regression guard for §1.1). Nobody remembers what §1.1 means six months later; the PR description and commit message already carry that context. The one exception is a TODO tied to an open ticket: // TODO(PHA-265): <what's missing>.
// PASS: GOOD: Explain WHY, not WHAT
// Use exponential backoff to avoid overwhelming the API during outages
const delay = Math.min(1000 * Math.pow(2, retryCount), 30000)
// FAIL: BAD: Stating the obvious
// Increment counter by 1
count++
// Set name to user's name
name = user.name
// FAIL: BAD: Ticket / review-section references
// PHA-270 §4.4 — switch to ArrayList
// PR #15 review comment fix
// added for the cleanup pass#### JSDoc for Public APIs
/**
* Searches markets using semantic similarity.
*
* @param query - Natural language search query
* @param limit - Maximum number of results (default: 10)
* @returns Array of markets sorted by similarity score
* @throws {Error} If OpenAI API fails or Redis unavailable
*
* @example
* ```typescript
* const results = await searchMarkets('election', 5)
* console.log(results[0].name) // "Trump vs Biden"
* ```
*/
export async function searchMarkets(
query: string,
limit: number = 10
): Promise<Market[]> {
// Implementation
}Measure before optimising, fix the one real bottleneck, avoid the N+1 query problem, fetch only the columns you need, cache where reads dominate and staleness is tolerable, and run independent input and output work concurrently. The full treatment lives in the performance-optimization skill.
#### Test Structure (AAA Pattern)
test('calculates similarity correctly', () => {
// Arrange
const vector1 = [1, 0, 0]
const vector2 = [0, 1, 0]
// Act
const similarity = calculateCosineSimilarity(vector1, vector2)
// Assert
expect(similarity).toBe(0)
})#### Test Naming
// PASS: GOOD: Descriptive test names
test('returns empty array when no markets match query', () => { })
test('throws error when OpenAI API key is missing', () => { })
test('falls back to substring search when Redis unavailable', () => { })
// FAIL: BAD: Vague test names
test('works', () => { })
test('test search', () => { })Watch for these anti-patterns:
#### 1. Long Functions
// FAIL: BAD: Function > 50 lines
function processMarketData() {
// 100 lines of code
}
// PASS: GOOD: Split into smaller functions
function processMarketData() {
const validated = validateData()
const transformed = transformData(validated)
return saveData(transformed)
}#### 2. Deep Nesting
// FAIL: BAD: 5+ levels of nesting
if (user) {
if (user.isAdmin) {
if (market) {
if (market.isActive) {
if (hasPermission) {
// Do something
}
}
}
}
}
// PASS: GOOD: Early returns
if (!user) return
if (!user.isAdmin) return
if (!market) return
if (!market.isActive) return
if (!hasPermission) return
// Do something#### 3. Magic Numbers
// FAIL: BAD: Unexplained numbers
if (retryCount > 3) { }
setTimeout(callback, 500)
// PASS: GOOD: Named constants
const MAX_RETRIES = 3
const DEBOUNCE_DELAY_MS = 500
if (retryCount > MAX_RETRIES) { }
setTimeout(callback, DEBOUNCE_DELAY_MS)Remember: Code quality is not negotiable. Clear, maintainable code enables rapid development and confident refactoring.
~30 seconds. Free. No account. Every finding cites a rule and a line of evidence.