Code Standards
May 20, 2026 · View on GitHub
This document outlines the code quality standards and best practices for the EU Parliament Monitor project.
Table of Contents
- Overview
- Linting
- Code Formatting
- JSDoc Documentation
- Complexity Guidelines
- Security Standards
- Pre-commit Hooks
Overview
The EU Parliament Monitor project maintains high code quality standards through automated tooling and best practices. All code must pass linting, formatting, and documentation checks before being merged.
Linting
We use ESLint with multiple plugins to enforce code quality:
Installed Plugins
@eslint/js- ESLint recommended ruleseslint-plugin-security- Security vulnerability detectioneslint-plugin-sonarjs- Code smell and complexity detectioneslint-plugin-jsdoc- JSDoc documentation validation
Running ESLint
# Check for issues
npm run lint
# Auto-fix issues where possible
npm run lint:fix
# Generate JSON report
npm run lint:report
Key Rules
File Size
max-lines(drift-guard test): Everysrc/**/*.tsfile must be ≤ 600 raw lines (including blank lines and comments —wc -lsemantics). This is the canonical acceptance gate from the Refactor 8/8 series (#2029–#2036), enforced bytest/unit/source-file-size.test.js.max-lines(ESLint): ESLint additionally enforces a 600 code-line ceiling (blank lines and comment-only lines excluded viaskipBlankLines: true, skipComments: true). Per-area sub-ceilings of 400 code lines apply to bounded-context sub-directories:src/types/**,src/config/**,src/aggregator/{clean,run,html,generator}/**,src/templates/sections/**, andsrc/mcp/transport/**— see per-area overrides ineslint.config.js.
Best Practices
eqeqeq: Always use===and!==instead of==and!=prefer-const: Useconstfor variables that are never reassignedno-eval: Never useeval()ornew Function()require-await: Async functions must useawait
Security
security/detect-unsafe-regex: Prevent ReDoS vulnerabilities (ERROR)security/detect-eval-with-expression: Prevent eval-like code (ERROR)security/detect-object-injection: Warn about potential object injection (WARNING - false positives acceptable for safe code)
Code Smells
sonarjs/cognitive-complexity: Max complexity of 15 per functionsonarjs/no-duplicate-string: Max 3 occurrences of same string literalsonarjs/no-identical-functions: Prevent duplicate function implementationssonarjs/prefer-immediate-return: Return directly instead of storing in variable
Code Formatting
We use Prettier for consistent code formatting:
Configuration
- Print Width: 100 characters
- Tab Width: 2 spaces
- Quotes: Single quotes for strings
- Semicolons: Always required
- Trailing Commas: ES5 style
- Line Ending: LF (Unix style)
Running Prettier
# Format all files
npm run format
# Check formatting without making changes
npm run format:check
JSDoc Documentation
All exported functions must have complete JSDoc documentation.
Required Tags
@param- Every parameter with type, name, and description@returns- Return value with type and description@throws- Any exceptions that may be thrown
Example
/**
* Generate complete HTML for a news article
* @param {object} options - Article options
* @param {string} options.title - Article title
* @returns {string} Complete HTML document
*/
export function generateArticleHTML(options) {
// implementation
}
Complexity Guidelines
Cognitive Complexity
Maximum: 15 per function
Reducing Complexity
- Extract methods: Break large functions into smaller ones
- Use early returns: Exit early instead of nesting
- Strategy pattern: Use objects/maps instead of large switch statements
- Guard clauses: Validate inputs at the start
Security Standards
Prohibited Patterns
eval()andnew Function(): Never use dynamic code evaluation- Unsafe regex: Avoid catastrophic backtracking patterns
- Hardcoded secrets: Never commit credentials or API keys
Pre-commit Hooks
We use Husky and lint-staged to enforce quality gates before commits.
Automatic Checks
On every commit, the following are automatically run on staged files:
- ESLint with auto-fix
- Prettier formatting
- htmlhint for HTML files
CI/CD Quality Gates
All pull requests must pass these checks:
- ESLint: Zero errors (warnings acceptable)
- Prettier: All code must be formatted
- HTML validation: Pass htmlhint checks
- npm audit: No high/critical vulnerabilities
Quality Gates — Test Coverage & Agentic Workflows
Coverage Thresholds (vitest.config.js)
| Metric | Threshold | Target |
|---|---|---|
| Lines | ≥ 88% | 92% |
| Functions | ≥ 88% | 92% |
| Branches | ≥ 78% | 84% |
| Statements | ≥ 88% | 92% |
Agentic Workflow Lint Rules (scripts/lint-prompts.js)
Every news-*.md gh-aw workflow must pass the following structural assertions:
- Single-PR rule:
safeoutputs___create_pull_requestappears at most once (news-translate.mdexempt). - Forbidden phrases: No
checkpoint pr,keep-alive,keepalive,heartbeat,progressive safe output, or references to purged modules. - No push_repo_memory:
safeoutputs___push_repo_memoryis banned (news-translate.mdexempt). - Analysis-awareness: Must reference the analysis guide + completeness
gate anchors, or import
.github/agents/news-generation.agent.md. - Canonical imports: Must import
.github/agents/news-generation.agent.mdANDshared/mcp/news-mcp-servers.mdin canonical order (news-translate.mdexempt).
Stage A→E Discipline
All article-generating workflows follow the fixed stage order:
| Stage | Purpose | Budget (standard slugs) |
|---|---|---|
| A | Data collection (EP MCP + IMF) | ≤ 5 min |
| B | Analysis (Pass 1 + Pass 2) | ≤ 22 min |
| C | Completeness gate | ≤ 4 min |
| D | Deterministic article render | ≤ 2 min |
| E | Single-PR safe-output | ≤ 2 min |
Source of truth: src/config/article-horizons.ts (per-slug budgets).
Mandatory 2-Pass Improvement
- Pass 1 (~60% of Stage B time): Write all mandatory artifacts
- Pass 2 (~40% of Stage B time): Read-back every file, expand shallow sections, add evidence citations, fill placeholders, verify IMF data
Last Updated: 2026-05-03 Version: 2.0.0