- Fix MD040 (11 bare fences): add language tags (text/bash) across 7 files
- Fix MD031 (2 violations): add blank lines around fence in GETTING-STARTED.md
- Wire 'Markdown lint' step to fast-checks job (after Format check, before Typecheck)
- Reformat .markdownlint-cli2.jsonc per Prettier (trailing commas in JSONC)
- pnpm md:lint exits 0; pnpm format:check exits 0; gate can fail on bare fence (verified)
- Updated calendar.spec.ts header to list all three profiles (iphone/pixel/desktop)
- Updated lists.spec.ts header to list all three profiles (iphone/pixel/desktop)
- Updated e2e/README.md preamble to add 'Desktop Chrome (1280x720)'
- Added --project=desktop example to README run-commands block
- Updated README full-suite command comment to name all three profiles
- Cosmetic: ci.yml step-name and comment updated to mention desktop (no plumbing change)
- Full suite verified: 85 passed, 5 skipped (3 desktop geometry + 2 parity guards), 0 failed
- Added test.skip(testInfo.project.name === 'desktop') to the two safe-area-inset
BottomTabBar in-viewport tests (BottomTabBar returns null at >=768px on desktop)
- Added test.skip(testInfo.project.name === 'desktop') to the 56x56 FAB geometry test
(on desktop 'New Event' resolves to the toolbar button, not the 56px FAB)
- Added desktop-only D-04 parity test asserting 'New Event' toolbar button height >=44px
guarded by test.skip(testInfo.project.name !== 'desktop')
- Updated header jsdoc to list all three profiles including desktop
- All mobile assertions preserved (toBeGreaterThanOrEqual(56) and (44) still present)
- 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
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.
- 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
- 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)
- 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()
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.
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.