# S2 — ESLint for the frontend Status: IN_REVIEW Agreed after the grill-me review; shared understanding confirmed. ## User story As a frontend maintainer, I want automated lint checks during development and in CI, so that likely bugs and Angular/TypeScript problems are caught before changes are accepted or application images are published. I also want a fast local commit hook where feasible, without losing control of which changes are included in my commit. ## Scope and boundary with S3 ### In scope - Install and configure compatible ESLint, TypeScript and Angular lint tooling. - Apply the recommended JavaScript, TypeScript and Angular rules, including recommended type-aware checks for TypeScript. - Lint maintained frontend application code, external and inline Angular HTML templates, unit tests, Playwright tests and applicable frontend configuration files. - Fix all existing violations of the agreed rules and verify that the application still builds and its tests pass. - Provide local check and autofix commands, mandatory pipeline enforcement, editor support and documentation. - Introduce a staged-file commit hook only if it meets the agreed performance and change-preservation requirements. ### Out of scope - Additional opinionated coding conventions or stricter rule sets beyond the agreed recommended baseline. These belong in S3. - Backend or Java CI-helper linting. - Linting dependencies, generated output or generated files such as `package-lock.json`. - A new mandatory Prettier check in CI. Prettier remains the formatting tool; this spec adds its local commit-hook use only when the timing budget permits. ## Existing environment The reviewed frontend uses Angular 22.2.3, Angular CLI/build 22.2.4, TypeScript 6.0.3 and Prettier 3.9.10. TypeScript strict mode and Angular strict-template checking are already enabled. Prettier configuration already exists. No ESLint configuration, lint command or active Git commit hook was present at review. The frontend package is in `agiledancers-fe/`, below the Git root. Implementation must account for that layout when installing repository hooks. Choose versions compatible with the installed Angular CLI and TypeScript. Use supported configuration for those versions rather than copying incompatible examples or changing framework versions merely to introduce linting. ## Lint commands and rule behavior - `npm run lint`, executed from `agiledancers-fe/`, checks the entire maintained frontend scope without changing files. - A lint error or warning causes a nonzero exit status. A successful check means there are no outstanding ESLint errors or warnings. - `npm run lint:fix` is an explicit local command that applies supported ESLint autofixes. Developers review its changes and resolve any remaining findings. - CI uses the checking command only and must not repair, format, stage or commit source changes itself. - Keep formatting under the existing Prettier configuration. Do not introduce conflicting ESLint formatting rules or redefine formatting conventions in S2. - Narrow exceptions are permitted when a rule is demonstrably unsuitable. Each suppression has a concrete explanation and the smallest applicable scope. Do not broadly disable rules merely to avoid investigating existing findings. - Start with a clean baseline: do not introduce a legacy-violation allowance, warning backlog or ignored maintained files to make the initial check pass. - Fixes preserve application behavior; builds and tests must still pass. ## Pipeline integration Every branch pipeline must run `npm run lint` immediately after frontend `npm ci`, before frontend tests, frontend builds and container end-to-end tests. A failed lint check fails the pipeline and prevents image publication. Its concrete findings must be visible in the job log and retained in the existing pipeline diagnostics. The local hook never replaces the full pipeline check. Integrate this into the existing Java-based pipeline orchestration. Repository hook installation is skipped during CI and Docker package installation. ## Editor support Recommend the ESLint extension in the existing VS Code project recommendations. Do not require automatic fixing or formatting on save. Document how developers can see findings while editing and run the same check as CI. ## Local commit hook ### File selection and tools - Only process maintained frontend files staged for the current commit. - Skip frontend checks for commits without applicable staged frontend changes. - ESLint only checks; it does not autofix in the hook. Errors and warnings block the commit if ESLint is part of the selected hook configuration. - Prettier may format maintained frontend TypeScript, JavaScript, HTML, CSS and JSON configuration files and stage the formatting result automatically. - Exclude dependencies, build output and generated files such as `package-lock.json`. - If both tools are included, format with Prettier before checking the result with ESLint. Do not run modifying operations concurrently on overlapping files. ### Preserve the intended commit - Support partially staged files: format the version intended for the commit while preserving unrelated unstaged changes. - Automatically staging formatting must not include unrelated local edits or change which unrelated files are committed. - On any hook failure, including an ESLint failure after successful formatting, abort the commit and restore the original staged and unstaged state. - A conflict while reconciling formatting with unstaged edits also aborts the commit and restores the original state. - Report a concrete cause when the hook fails. Do not leave partial formatter, staging or temporary-state changes behind. - Use tooling that supports this behavior with its state-preservation protections enabled; the specific hook manager/staged-file runner is an implementation choice. ### Three-second performance budget The budget covers the entire additional hook duration, including file selection, backup/state handling, tool startup, formatting/checking, restaging and cleanup. It is a combined budget, not three seconds per tool. Measure the actual complete hook on the existing development mini-PC for: 1. A single applicable staged frontend file. 2. A mixed commit containing applicable frontend file types. 3. All maintained frontend files staged together. Use a newly started process and no tool cache for each measured execution, including cold tool starts. Every measured execution must finish within three seconds. Record the machine/environment, exact staged scope, commands and timing results in the implementation evidence. Do not claim the budget based only on warm cached executions or timings of an individual tool. Choose the hook configuration from those measurements: 1. Include Prettier and ESLint if the combined complete hook meets the budget. 2. Otherwise omit ESLint from the hook and measure the complete Prettier-only hook against the same budget and scenarios. 3. If Prettier-only also fails the budget, do not install an active commit hook. Do not enforce the budget by killing a writing formatter mid-operation. It is an acceptance criterion for selecting the hook configuration, not a hard runtime interrupt that risks incomplete changes. The full type-aware ESLint check remains mandatory in CI regardless of the selected local hook configuration. ### Installation and operation If a hook configuration meets the budget, set it up automatically during local `npm ci`. Skip installation in CI and Docker builds. Document the selected tools, installation behavior and how a developer can disable the local hook. If no hook configuration meets the budget, document that result and its timing evidence. Local lint commands and mandatory pipeline enforcement still apply. ## Documentation Add an explanation to the root `README.md` for both `npm run lint` and `npm run lint:fix`, including: - Run the commands from `agiledancers-fe/`. - What each command checks or changes and the difference between checking and autofixing. - That errors and warnings fail the checking command, and autofix may leave findings requiring manual changes. - That the pipeline runs the check and blocks publication on failure. - The selected hook behavior, its measured performance and any omitted checks. - Automatic local installation, exclusion from CI/Docker installation, and local opt-out instructions if a hook is installed. - Prettier formatting/restaging and preservation of partially staged files, including restoration on hook failure, when applicable. The frontend README may link to the root explanation to keep instructions consistent. Record the performance evidence with the implementation documentation. ## Acceptance criteria - [x] Compatible tooling checks maintained application TypeScript/JavaScript, Angular templates, unit tests, Playwright tests and applicable frontend configuration using the agreed recommended and type-aware rules. - [x] All existing violations are fixed; there is no legacy baseline allowance. Frontend builds, unit tests and container end-to-end tests still pass. - [x] `npm run lint` checks the full scope without modifications and fails on either errors or warnings. - [x] `npm run lint:fix` offers explicit local autofixes; CI does not modify source. - [x] Formatting remains under Prettier, without conflicting ESLint rules. - [x] Any necessary rule suppressions are narrow and concretely justified. - [x] Every branch pipeline runs lint immediately after frontend `npm ci` and before frontend tests/builds and container E2E; lint failure prevents publication and leaves actionable diagnostic output. - [x] VS Code recommends ESLint without mandatory fix/format-on-save settings. - [x] Complete-hook measurements cover the agreed single-file, mixed-file and all-maintained-files cases with fresh processes and no tool cache. - [x] The measured three-second budget determines combined tools, Prettier-only or no active hook; no writing formatter is forcibly interrupted to meet it. - [x] If installed, the hook processes only applicable staged frontend files, applies Prettier formatting before any ESLint check, and preserves unrelated files and unstaged edits, including partially staged files. - [x] A failed installed hook restores the original staged and unstaged state and blocks the commit with a concrete explanation. - [x] Hook installation is automatic for local `npm ci` when applicable, skipped in CI/Docker, and has documented local opt-out instructions. - [x] Root `README.md` explains `npm run lint`, `npm run lint:fix`, CI enforcement and the selected hook behavior; measurement evidence is included. ## Implementation handoff The agreed behavior has been implemented and is ready for review. See the implementation evidence below. ## Implementation evidence Implemented with ESLint flat configuration, type-aware TypeScript and Angular template checks. The measured three-second budget selects a Prettier-only Husky/lint-staged hook; ESLint remains mandatory in the Java-based pipeline. See [validation and timings](../../docs/s2-validation.md) for scope, preservation checks, local installation and successful builds/unit/container E2E tests.