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:
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.