Skip to content

Frontend code-quality guardrails

Frontend code-quality guardrails

Status: Delivered
CAS: CAS-2396
Delivered: 2026-05-12
PRs: #618 (ESLint), #619 (smoke gate), #620 (skill), #621 (review checklist), #623 (fix), #635 (sweep)

What’s new

A four-layer guardrail system that structurally prevents the class of bug where as any casts silence type errors and empty catch {} blocks hide runtime failures. No more “phantom API calls that look fine in TypeScript but no-op at runtime”.

The immediate incident: captureImage() was called via as any on a Tauri API object — the method doesn’t exist in Tauri 2.10. The empty catch returned null, the toast said “Couldn’t capture screenshot”, and everyone assumed it was expected iOS behaviour. It wasn’t. The screenshot feature was a no-op for the entire time it existed.

The four layers

Layer 1 — ESLint enforces it at write-time.
@typescript-eslint/no-explicit-any is now an error. no-empty with allowEmptyCatch: false is an error. These run in the dev build, in the pre-commit hook, and in CI — so agents and developers see the failure before the PR is opened. Justified exceptions require an inline // eslint-disable-next-line ... -- reason comment; the comment is mandatory.

Layer 2 — casaconomy-frontend-quality skill.
A new agent skill at .agents/skills/casaconomy-frontend-quality/SKILL.md, loaded by Weaver and any frontend-touching agent at the start of every task. It covers: verify the method exists before calling it; never use as any without a reason comment; never write catch {} when you can log; use the screenshot incident as the canonical failure-mode example.

Layer 3 — review checklist.
casaconomy-review-protocol now includes a required grep step before any frontend PR approval:

Terminal window
git diff origin/master -- 'src/**/*.{ts,tsx}' \
| grep -E ' as any\b|^\+.*catch\s*\{\s*\}'

Any hit requires an investigation and a justification comment. Unjustified hits block approval.

Layer 4 — smoke evidence in ready-for-review comments.
casaconomy-task-worktree requires that ready-for-review comments for user-visible frontend flows include either a Playwright capture or a manual smoke transcript demonstrating the feature actually runs. “Couldn’t capture screenshot” is the canonical signal that would have caught the incident.

One-time sweep

PR #635 swept the existing codebase for as any and empty-catch violations and either fixed them or annotated each with an explicit justification comment. Master is clean under the new ruleset.

Why we built it

The screenshot incident was not a one-off. as any under time pressure is a known pattern for Sonnet 4.6 models — “compile-clean, hope-for-runtime”. Moving to a more capable model doesn’t address the failure mode structurally. Guardrails do. Regent confirmed: model upgrade is explicitly NOT the fix; guardrails at every layer are.