Makes the CI fast-checks lint step a real, failing gate (it was a no-op that exited 0 with no linter installed). Closes Phase-8 review finding IN-02 ("lint step is a documented no-op that masks lint failures — ESLint gate is Phase 13's deliverable").
What ships
ESLint 9.39.4 flat config (eslint.config.js): typescript-eslint recommendedTypeChecked (type-aware via projectService), React + react-hooks scoped to apps/pwa, eslint-config-prettier last. ESLint pinned to 9.39.4 (10.x breaks eslint-plugin-react@7.37.5).
CI: new Format check step in fast-checks; stale no-op comment removed.
119 first-run violations fixed (address-not-mask, D-13-06) + whole-repo Prettier reformat as one isolated commit (982438d).
Includes quick-fix WR-01 (sw.ts notificationclick openWindow fallback) from this phase's own code review.
Verification
Green baseline (verified independently, post-merge with main): pnpm lint = 0, pnpm format:check = 0, pnpm typecheck = 0.
Tests: API 238/238, PWA 191/191. No regressions.
gsd-verifier: passed 9/9 must-haves. Code review of the lint fixes: clean — no floating-promise fix masked a bug.
Reviewer notes
The diff is large because of the one-time repo-wide Prettier reformat (commit 982438d, ~398 files) — that commit is purely mechanical and isolated; review the other commits for substance.
2 SC items are live-CI only: confirm this PR's fast-checks lint + format steps actually block on a violation (push a deliberate-violation branch to see them fail). Tracked in 13-VERIFICATION.md / /gsd-verify-work 13.
Merged origin/main in (resolved ROADMAP.md; ci.yml auto-merged with PR #7's harness/publish fixes).
Makes the CI `fast-checks` lint step a real, failing gate (it was a no-op that exited 0 with no linter installed). Closes Phase-8 review finding **IN-02** ("lint step is a documented no-op that masks lint failures — ESLint gate is Phase 13's deliverable").
## What ships
- **ESLint 9.39.4 flat config** (`eslint.config.js`): typescript-eslint `recommendedTypeChecked` (type-aware via `projectService`), React + react-hooks scoped to `apps/pwa`, `eslint-config-prettier` last. ESLint pinned to 9.39.4 (10.x breaks eslint-plugin-react@7.37.5).
- **Per-app `lint` scripts** + root `format`/`format:check` (`--max-warnings 0`). `.planning/` excluded from Prettier (tool-generated docs).
- **CI**: new `Format check` step in `fast-checks`; stale no-op comment removed.
- **119 first-run violations fixed** (address-not-mask, D-13-06) + whole-repo Prettier reformat as one isolated commit (`982438d`).
- Includes quick-fix **WR-01** (sw.ts notificationclick openWindow fallback) from this phase's own code review.
## Verification
- Green baseline (verified independently, post-merge with main): `pnpm lint` = 0, `pnpm format:check` = 0, `pnpm typecheck` = 0.
- Tests: API 238/238, PWA 191/191. No regressions.
- gsd-verifier: passed 9/9 must-haves. Code review of the lint fixes: clean — no floating-promise fix masked a bug.
## Reviewer notes
- The diff is large because of the **one-time repo-wide Prettier reformat** (commit `982438d`, ~398 files) — that commit is purely mechanical and isolated; review the other commits for substance.
- 2 SC items are **live-CI only**: confirm this PR's `fast-checks` lint + format steps actually block on a violation (push a deliberate-violation branch to see them fail). Tracked in `13-VERIFICATION.md` / `/gsd-verify-work 13`.
- Merged `origin/main` in (resolved `ROADMAP.md`; `ci.yml` auto-merged with PR #7's harness/publish fixes).
SC-1 smoke revealed flat.recommended enables react/react-in-jsx-scope (error),
while the legacy recommended disables it. This codebase uses jsx:"react-jsx"
(React 17+ automatic transform) so React does not need to be in scope. Disable
the rule explicitly alongside react/prop-types in the pwa-react config block.
Also proved both gate halves:
- pnpm lint exits 1 on no-floating-promises deliberate violation (SC-1 lint)
- pnpm format:check exits 1 listing _format-gate-test.ts (SC-1 format)
Both throwaway files deleted; neither staged nor committed.
Plan 13-01 complete: ESLint flat config + Prettier installed and wired,
SC-1 gate proven (exit 1 on deliberate violations), 119 real violations
inventoried for Plan 02 (api:42, pwa:77). STATE advanced to Plan 2 of 3.
- eslint.config.js: disable React Compiler rules (v7 flat.recommended enables
them; codebase does not use the Compiler); add e2e/ to disableTypeChecked
block; promote exhaustive-deps to error
- API broker: remove redundant as-casts (outboxWorker, poller, reminderScheduler,
expand, sync, vevent, spike); add targeted ical.js no-unsafe-assignment/argument
disables with justifying comments inside try blocks
- API routes/sse.ts: fix no-misused-promises on async writeSSE callback with
void+IIFE+catch pattern
- API routes/lists.ts: let → const for updateValues
- API tests: remove unused imports (beforeEach, eq, vi); rename unused vars
with _ prefix; remove unused lastActiveId assignment
- PWA components: void navigate() and void queryClient.invalidateQueries() on
all fire-and-forget call sites; fix CalendarShell explicit-type-casts;
Couldn't → HTML entity
- PWA test files: as unknown as Response for partial mock objects; string | null
type annotation on mockLastSyncedUid; remove async from test callbacks without
await; act(() => {}) not await act(async () => {}) for sync ops
- sw.ts: restructure Notification.data?.url access as let+if so disable
comments land on the exact violation lines; void self.skipWaiting()
- Replace inline 'as string | null' assertion with an explicit typed const
declaration inside the vi.hoisted() callback body
- 'value: string | null' typed const satisfies both ESLint (no assertion) and
tsc (null assignment on line 82 is type-safe)
- Insert 'Format check: pnpm format:check' after Lint in fast-checks job
- Remove the 3-line comment that said lint was a no-op (no longer true)
- Step order: Install → Lint → Format check → Typecheck → PWA unit tests
- Branch-protection contexts (name:CI, fast-checks, api, harness) unchanged
GSD planning artifacts (.planning/**) are rewritten by tooling on every workflow
run and are never hand-formatted. Including them in Prettier scope caused
pnpm format:check to exit 1 on virtually every future PR, making the SC-3
green baseline impossible to hold. Add .planning/ to .prettierignore, mirroring
the same rationale as dist/ and apps/api/src/db/migrations/.
Real source docs (README.md, docs/**) remain in Prettier scope.
No playwright-report/, test-results/, or coverage/ directories exist to ignore.
- Add .then(navigated) check: opens new window when client.navigate() resolves null
- Add .catch(): opens new window when client.focus() or client.navigate() rejects
- Both branches guarded by self.clients.openWindow per spec
- Returned chain (not floating) satisfies no-floating-promises gate
- All other behaviour preserved: close(), url extraction, post-loop fallback
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.
Makes the CI
fast-checkslint step a real, failing gate (it was a no-op that exited 0 with no linter installed). Closes Phase-8 review finding IN-02 ("lint step is a documented no-op that masks lint failures — ESLint gate is Phase 13's deliverable").What ships
eslint.config.js): typescript-eslintrecommendedTypeChecked(type-aware viaprojectService), React + react-hooks scoped toapps/pwa,eslint-config-prettierlast. ESLint pinned to 9.39.4 (10.x breaks eslint-plugin-react@7.37.5).lintscripts + rootformat/format:check(--max-warnings 0)..planning/excluded from Prettier (tool-generated docs).Format checkstep infast-checks; stale no-op comment removed.982438d).Verification
pnpm lint= 0,pnpm format:check= 0,pnpm typecheck= 0.Reviewer notes
982438d, ~398 files) — that commit is purely mechanical and isolated; review the other commits for substance.fast-checkslint + format steps actually block on a violation (push a deliberate-violation branch to see them fail). Tracked in13-VERIFICATION.md//gsd-verify-work 13.origin/mainin (resolvedROADMAP.md;ci.ymlauto-merged with PR #7's harness/publish fixes).- eslint.config.js: disable React Compiler rules (v7 flat.recommended enables them; codebase does not use the Compiler); add e2e/ to disableTypeChecked block; promote exhaustive-deps to error - API broker: remove redundant as-casts (outboxWorker, poller, reminderScheduler, expand, sync, vevent, spike); add targeted ical.js no-unsafe-assignment/argument disables with justifying comments inside try blocks - API routes/sse.ts: fix no-misused-promises on async writeSSE callback with void+IIFE+catch pattern - API routes/lists.ts: let → const for updateValues - API tests: remove unused imports (beforeEach, eq, vi); rename unused vars with _ prefix; remove unused lastActiveId assignment - PWA components: void navigate() and void queryClient.invalidateQueries() on all fire-and-forget call sites; fix CalendarShell explicit-type-casts; Couldn't → HTML entity - PWA test files: as unknown as Response for partial mock objects; string | null type annotation on mockLastSyncedUid; remove async from test callbacks without await; act(() => {}) not await act(async () => {}) for sync ops - sw.ts: restructure Notification.data?.url access as let+if so disable comments land on the exact violation lines; void self.skipWaiting()