This document outlines the code quality standards and best practices for the EU Parliament Monitor project.
- Overview
- Linting
- Code Formatting
- JSDoc Documentation
- Complexity Guidelines
- Security Standards
- Pre-commit Hooks
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.
We use ESLint with multiple plugins to enforce code quality:
@eslint/js- ESLint recommended ruleseslint-plugin-security- Security vulnerability detectioneslint-plugin-sonarjs- Code smell and complexity detectioneslint-plugin-jsdoc- JSDoc documentation validation
# Check for issues
npm run lint
# Auto-fix issues where possible
npm run lint:fix
# Generate JSON report
npm run lint:reportmax-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.
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/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)
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
We use Prettier for consistent code formatting:
- 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)
# Format all files
npm run format
# Check formatting without making changes
npm run format:checkAll exported functions must have complete JSDoc documentation.
@param- Every parameter with type, name, and description@returns- Return value with type and description@throws- Any exceptions that may be thrown
/**
* 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
}Maximum: 15 per function
- 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
eval()andnew Function(): Never use dynamic code evaluation- Unsafe regex: Avoid catastrophic backtracking patterns
- Hardcoded secrets: Never commit credentials or API keys
We use Husky and lint-staged to enforce quality gates before commits.
On every commit, the following are automatically run on staged files:
- ESLint with auto-fix
- Prettier formatting
- htmlhint for HTML files
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
| Metric | Threshold | Target |
|---|---|---|
| Lines | ≥ 88% | 92% |
| Functions | ≥ 88% | 92% |
| Branches | ≥ 78% | 84% |
| Statements | ≥ 88% | 92% |
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).
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).
- 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