# gb4.7mfe Coding Standards — Enforcement Checklist

Status: **v1.2 — Phase 0/1 landed.** Tooling is live (`eslint.config.js`, `.prettierrc.json`,
Husky + lint-staged, CI `lint` stage). Pilot wave (`common`, `ecp`, `idms`, `qms`, `hrms`) is
gated in CI — see `docs/lint-rollout.md` for exact status and known per-project deferrals.

Concrete, enforceable rule list derived from `FECLAUDE.md` plus measured backlog data from a live
repo audit. `FECLAUDE.md` stays the narrative reference; this doc is the checklist ESLint config
gets built against. Numbers below are measured, not estimated (4,882 `.ts` files, 52 projects: 51
apps + `common`).

Severity legend:
- **Error (day one)** — small measured backlog, safe to block immediately.
- **Warning (burn-in)** — large measured backlog or real judgment calls; stays a warning per
  project until that project's cleanup pass is done, then promotes to error for that project.

---

## 1. Module / Import Conventions

| ID | Rule | Severity | Measured backlog | Notes |
|----|------|----------|-------------------|-------|
| FE-001 | Never import an individual directive component (`GbinputComponent`, `GbcomboboxComponent`, `GbcheckboxComponent`, `GbpicklistComponent`, `GbDateComponent`, `GbFormGridComponent`) directly in a `@Component`/`@Directive` `imports` array — use `GbDirectivesModule` or the relevant focused sub-module (`GbFormControlsModule`/`GbPicklistModule`/`GbFormGridModule`/`GbFormioModule`) instead | Error (day one) | 7 files (5 workspace-wide + 2 in `hrms`) | Custom rule `gb/no-bare-directive-in-component-imports` (`tools/eslint-rules/`) — deliberately scoped to the decorator's `imports` array only, not the import statement itself: `@ViewChild(GbFormGridComponent)`-style query tokens legitimately need the class imported directly and must not be flagged (an earlier `no-restricted-imports`-based design did flag these as false positives — see git history). The library's own `libs/gbdirectives/src/directives.ts` barrel no longer even re-exports the monolithic `GbDirectivesModule` facade (removed in a prior commit) — 12 files still reach it via a deep, non-barrel import path; not addressed this round, flagged as a follow-up. |
| FE-002 | No `@ngx-translate/core` imports — use `@jsverse/transloco` | Error (day one) | 4 files (675 already migrated) | `no-restricted-imports`; also closes out a near-finished migration |

## 2. Internationalization

| ID | Rule | Severity | Measured backlog | Notes |
|----|------|----------|-------------------|-------|
| FE-010 | No hardcoded English text in templates or component TypeScript — all display strings go through Transloco keys | Warning (indefinite, per-project promotion) | Confirmed real instances (e.g. `sqlworkbench/dashboard.component.html`); not yet counted repo-wide | Needs a real custom rule (`gb/no-hardcoded-template-text`) — HTML text nodes aren't expressible via existing-rule config. Real false-positive risk (brand names, currency symbols, technical IDs) — needs an inline-suppression convention with a required reason comment |

## 3. Logging

| ID | Rule | Severity | Measured backlog | Notes |
|----|------|----------|-------------------|-------|
| FE-020 | No `console.log` — use `GbConsoleService` | Warning (burn-in, per-project promotion) | 303 files | `no-console`; needs a manual swap (different API), not auto-fixable |

## 4. Naming Conventions

| ID | Rule | Severity | Measured backlog | Notes |
|----|------|----------|-------------------|-------|
| FE-030 | Component/directive selectors use `gb-` (workspace default) or `app-` (the standard Angular bootstrap-root convention, allowed everywhere) | Warning (burn-in, per-project promotion) | 250+ non-conforming instances across `app-`, `ent-`, `gb5-`, `collab-`, `eip-`, and one-offs | `@angular-eslint/component-selector`/`directive-selector`, prefix `["gb", "app"]`; renaming a selector is a breaking change to every parent template using it — needs an IDE/`ts-morph`-assisted pass, not blind `--fix`. `libs/common` needed real project-specific handling, not a simple `lib-` override — see notes below. |
| FE-031 | File naming convention (flat lowercase, dot-separated: `port.component.ts`, `port.db.service.ts`) | Not committed this round | — | Needs a quick repo-wide spot-check on multi-word entity files before picking `filename-case` config — kebab-case vs. flat-lowercase are different things and picking wrong would false-flag broadly |
| FE-032 | `*.db.service.ts` files export a class suffixed `DbService`, not just `Service` | Not committed this round | — | Angular-eslint only knows the generic `Service` suffix; would need a small custom rule or regex-keyed `naming-convention` config — lower priority than FE-010/FE-020/FE-030 |

## 5. Type Safety

| ID | Rule | Severity | Measured backlog | Notes |
|----|------|----------|-------------------|-------|
| FE-040 | No `: any` type annotations — use a real interface/type | Warning (indefinite, per-project promotion) | **~2,400 of 4,882 files (~half the codebase)** | `@typescript-eslint/no-explicit-any`; never auto-fixable (a bad auto-generated type is worse than an honest `any`) — realistically a multi-quarter background effort, not a quick pass |

## 6. Formatting

| ID | Rule | Severity | Notes |
|----|------|----------|-------|
| FE-050 | Prettier formatting (2-space indent, single quotes, LF, trailing commas) matching the existing `.editorconfig` | Error (day one, workspace-wide) | Fully auto-fixable (`prettier --write`) — no reason any project should fail only on formatting, so this is never gated by the per-project rollout list |

---

## Rollout tiers (maps directly to the phased-migration plan)

| Tier | Rules | Launch posture |
|------|-------|-----------------|
| A — cheap | FE-001, FE-002, FE-050 | `error` workspace-wide from day one |
| B — moderate | FE-020, FE-030 | `warn` until a project's cleanup pass is done, then `error` for that project |
| C — expensive | FE-010, FE-040 | `warn` for the full duration of the rollout; promoted per-project only after deliberate triage |

## Not building custom tooling for (explicitly out of scope this round)

- FE-031/FE-032 (file-naming, `DbService` suffix) — real conventions but lower value than the i18n/
  `any`/console/selector items; revisit after Tier A–C rules are live.

## What shipped vs. what was planned — lessons from the pilot

- **Extending `typescript-eslint`'s `recommended`/`stylistic` and `angular-eslint`'s
  `tsRecommended`/`templateRecommended`/`templateAccessibility` presets pulls in far more rules
  than the 6 named here** (`prefer-inject`, `no-inferrable-types`, `consistent-indexed-object-style`,
  `prefer-const`, accessibility rules, etc.) — all at `error` by default. `hrms` alone surfaced
  1,800+ preset-rule errors on first run, almost none of them FE-001–050. These were deliberately
  downgraded to advisory `warn` in `eslint.config.js` rather than fixed — fixing them (e.g.
  `prefer-inject` alone is a 40+ call-site constructor-injection refactor in `common`) is real,
  separate work never scoped or approved for this round. `prefer-const`/`no-inferrable-types`
  were auto-fixed in `common` via `eslint --fix` where safe; left as `warn` in `hrms` given its
  size. This is the single biggest gap between the original plan and what actually shipped —
  budget for it explicitly in any future gate expansion.
- **`common`'s real selector convention isn't a single `lib-` prefix** — it's `ent-` for the
  `entitlement/` sub-module, `gb-`/`lib-` elsewhere. The rule config reflects this with a
  directory-scoped override rather than forcing an unsafe rename.
- **`common`'s `no-console` backlog is larger and structurally different than measured** — see
  `docs/lint-rollout.md` for why it's deferred there specifically.
- **4 real selector bugs found and fixed in `hrms`** during this pass: two components had literal
  backtick characters typed into the selector string (`'gb-\`employeemovement\`'`), and two used
  PascalCase/camelCase instead of kebab-case. All four had zero template usages anywhere in the
  workspace (dead code or route-matched, not selector-matched) — safe, zero-blast-radius fixes.

## Next steps

1. Continue the domain-grouped rollout to the remaining ~50 projects (`tools/lint-migration-status.json`).
2. Revisit whether any of the downgraded preset rules (`prefer-inject` especially) deserve their
   own dedicated cleanup initiative, separate from this checklist.
3. Address the 12 files still doing a deep, non-barrel `GbDirectivesModule` import (FE-001 note).
