{"id":"699975f9fe87d302aeac409a","title":"2026 02 21 Issue 116","path":"how-to/committee/release-notes/2026-02-21-issue-116","contentMarkdown":"# 21-Feb-2026 — Migrations and Errors: 1 feature, 4 fixes, 1 build change and 1 chore [#116](https://github.com/nbarrett/ngx-ramblers/issues/116)\n\n## [build 484](https://github.com/nbarrett/ngx-ramblers/actions/runs/22253910814) — [commit 8fcd499](https://github.com/nbarrett/ngx-ramblers/commit/8fcd4996bb57181559a4775c33275aab9c699e44)\n\n_____\n\n### enforce lint consistently across frontend and server, fix all violations ([#116](https://github.com/nbarrett/ngx-ramblers/issues/116))\n\n- Add lint:frontend, lint:server, and lint:all scripts to package.json\n- Update .githooks/pre-push to run lint:all (frontend + server) before push\n- Add lint step to GitHub Actions CI workflow before unit tests\n- Add server/ts-gen/** and CLI implementation files to ESLint ignores\n- Fix all 213 server-side violations across 75 files:\n- Object.keys/values → keys/values from es-toolkit/compat\n- Array.isArray → isArray from es-toolkit/compat\n- typeof checks → isString/isObject/isNumber from es-toolkit/compat\n- console.log → cliLogger.log in CLI scripts\n- new Date() → dateTimeNow() from server/lib/shared/dates\n- Inline comments removed, logic expressed through named constructs\n- All for/while/do-while loops replaced with recursive or declarative equivalents\n\n### resolve 104 pre-existing ESLint violations to unblock pre-push hook\n\n- Remove Object.entries() lint rule (entries() not exported by es-toolkit/compat)\n- Replace Object.keys/values and Array.isArray with es-toolkit/compat equivalents\n- Replace typeof string/number checks with isString/isNumber from es-toolkit/compat\n- Rewrite imperative for/while loops declaratively (Array.from, reduce, for...of, recursion)\n- Extract named functions in place of inline explanatory comments\n- Fix broken imports and TypeScript errors from previous incomplete fix attempt\n- All 585 frontend and 499 server tests pass\n\n### **migrations**: handle invalid Brevo API key\n\nSkip Brevo migrations gracefully on 401 unauthorised responses\ninstead of throwing. Added both Brevo migrations to the pre-applied\nlist so they are not re-run on environments that have already applied\nthem.\n\n### **migrations**: skip Brevo migrations gracefully when no API key is configured\n\nEnvironments without a Brevo config document caused configuredBrevo()\nto throw when accessing .value on null, failing the migration instead\nof skipping it. Separated the config lookup from the main migration\nlogic so missing config is handled gracefully.\n\n### **errors**: handle ChunkLoadError after deployments with auto-reload\n\nAdd custom ErrorHandler that detects ChunkLoadError (caused by stale\nchunk references after deployment) and triggers a page reload. Uses\nsessionStorage with a 10-second cooldown per path to prevent infinite\nreload loops.\n\n### add claude-swarm lifecycle management and timed git hooks\n\n- Add @annix/claude-swarm 0.1.12 as devDependency\n- Add dev/stop npm scripts backed by claude-swarm\n- Add claude-swarm.sh launcher (npm-based, no pnpm)\n- Add .claude-swarm/config.json: frontend (port 4200) and server (port 5001)\nwith logs directed to cli-output/logs\n- Add run-frontend.sh: wraps npm run serve\n- Add run-server.sh: loads secrets from non-vcs/secrets/secrets.${NGX_APP}.env\nsafely (handles & in URLs), sets runtime env vars, starts tsx watch server\n- Replace pre-push hook with timed version using @annix/claude-swarm/timer.sh:\nlint -> frontend tests -> server tests with ms-precision timing summary\n\n### sync package-lock.json with @annix/claude-swarm 0.1.12","contentHtml":"<h1>21-Feb-2026 — Migrations and Errors: 1 feature, 4 fixes, 1 build change and 1 chore <a href=\"https://github.com/nbarrett/ngx-ramblers/issues/116\">#116</a></h1>\n<h2><a href=\"https://github.com/nbarrett/ngx-ramblers/actions/runs/22253910814\">build 484</a> — <a href=\"https://github.com/nbarrett/ngx-ramblers/commit/8fcd4996bb57181559a4775c33275aab9c699e44\">commit 8fcd499</a></h2>\n<hr>\n<h3>enforce lint consistently across frontend and server, fix all violations (<a href=\"https://github.com/nbarrett/ngx-ramblers/issues/116\">#116</a>)</h3>\n<ul>\n<li>Add lint:frontend, lint:server, and lint:all scripts to package.json</li>\n<li>Update .githooks/pre-push to run lint:all (frontend + server) before push</li>\n<li>Add lint step to GitHub Actions CI workflow before unit tests</li>\n<li>Add server/ts-gen/** and CLI implementation files to ESLint ignores</li>\n<li>Fix all 213 server-side violations across 75 files:</li>\n<li>Object.keys/values → keys/values from es-toolkit/compat</li>\n<li>Array.isArray → isArray from es-toolkit/compat</li>\n<li>typeof checks → isString/isObject/isNumber from es-toolkit/compat</li>\n<li>console.log → cliLogger.log in CLI scripts</li>\n<li>new Date() → dateTimeNow() from server/lib/shared/dates</li>\n<li>Inline comments removed, logic expressed through named constructs</li>\n<li>All for/while/do-while loops replaced with recursive or declarative equivalents</li>\n</ul>\n<h3>resolve 104 pre-existing ESLint violations to unblock pre-push hook</h3>\n<ul>\n<li>Remove Object.entries() lint rule (entries() not exported by es-toolkit/compat)</li>\n<li>Replace Object.keys/values and Array.isArray with es-toolkit/compat equivalents</li>\n<li>Replace typeof string/number checks with isString/isNumber from es-toolkit/compat</li>\n<li>Rewrite imperative for/while loops declaratively (Array.from, reduce, for...of, recursion)</li>\n<li>Extract named functions in place of inline explanatory comments</li>\n<li>Fix broken imports and TypeScript errors from previous incomplete fix attempt</li>\n<li>All 585 frontend and 499 server tests pass</li>\n</ul>\n<h3><strong>migrations</strong>: handle invalid Brevo API key</h3>\n<p>Skip Brevo migrations gracefully on 401 unauthorised responses\ninstead of throwing. Added both Brevo migrations to the pre-applied\nlist so they are not re-run on environments that have already applied\nthem.</p>\n<h3><strong>migrations</strong>: skip Brevo migrations gracefully when no API key is configured</h3>\n<p>Environments without a Brevo config document caused configuredBrevo()\nto throw when accessing .value on null, failing the migration instead\nof skipping it. Separated the config lookup from the main migration\nlogic so missing config is handled gracefully.</p>\n<h3><strong>errors</strong>: handle ChunkLoadError after deployments with auto-reload</h3>\n<p>Add custom ErrorHandler that detects ChunkLoadError (caused by stale\nchunk references after deployment) and triggers a page reload. Uses\nsessionStorage with a 10-second cooldown per path to prevent infinite\nreload loops.</p>\n<h3>add claude-swarm lifecycle management and timed git hooks</h3>\n<ul>\n<li>Add @annix/claude-swarm 0.1.12 as devDependency</li>\n<li>Add dev/stop npm scripts backed by claude-swarm</li>\n<li>Add claude-swarm.sh launcher (npm-based, no pnpm)</li>\n<li>Add .claude-swarm/config.json: frontend (port 4200) and server (port 5001)\nwith logs directed to cli-output/logs</li>\n<li>Add run-frontend.sh: wraps npm run serve</li>\n<li>Add run-server.sh: loads secrets from non-vcs/secrets/secrets.${NGX_APP}.env\nsafely (handles &amp; in URLs), sets runtime env vars, starts tsx watch server</li>\n<li>Replace pre-push hook with timed version using @annix/claude-swarm/timer.sh:\nlint -&gt; frontend tests -&gt; server tests with ms-precision timing summary</li>\n</ul>\n<h3>sync package-lock.json with @annix/claude-swarm 0.1.12</h3>\n"}