From d1ebc00ad019cd03b3df3ff93429c9ef07c00231 Mon Sep 17 00:00:00 2001 From: Tunglies <77394545+Tunglies@users.noreply.github.com> Date: Wed, 28 Oct 2026 06:03:11 +0800 Subject: [PATCH] docs(agents): add frontend liveness constraints Add six liveness rules to the frontend guardrails covering dead state, unused exposed surface, unreachable fallback paths, duplicate side effects per interaction, unreachable mounts and unbounded resource lifecycles. These target defect classes that the existing CI gates (knip, eslint, arch:check) cannot detect mechanically. --- src/AGENTS.md | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) diff --git a/src/AGENTS.md b/src/AGENTS.md index 51a3b125d..ccddd08ef 100644 --- a/src/AGENTS.md +++ b/src/AGENTS.md @@ -21,3 +21,27 @@ These rules supplement the repository's root `AGENTS.md`. - **Command ownership.** `services` owns backend command invocation and transport wrappers. Components and hooks use those boundaries; plugin mutations follow the same intent ownership as backend commands. +- **State liveness.** Every `useState`/`useRef` member has a reachable write + that differs from its initial value and a read that observes the difference. + A value that can only ever hold its initial value is a constant: declare the + constant and delete the state. A ref nothing reads is deleted, not kept. +- **Surface liveness.** Anything a module exposes — props, parameters, context + members, imperative-handle methods — ships with at least one external caller + in the same change. "Reserved for future use" fields, `_`-prefixed params + that callers still pass, and error or callback channels that every receiver + ignores are removed, not maintained. +- **Path liveness.** A fallback or branch names the concrete runtime condition + that reaches it. If no supported runtime can reach it, the branch is not + added — or it replaces the primary path. Constant subexpressions and cleanup + of resources that cannot exist yet are simplified away. +- **Effect economy.** One user interaction produces one state write and one + command. A handler does not re-apply a value its wrapper already applied, + and an effect does not re-run a refresh another branch of the same effect + just ran. +- **Mount economy.** Components that issue commands or subscriptions on mount + are mounted only where their UI is reachable. A dialog no rendered control + can open stays unmounted, not mounted-and-idle. +- **Resource bounds.** Every cache key, timer and subscription a feature + allocates is reused or released on refresh; refresh never allocates an + unbounded sequence of new keys. Retries re-create per-attempt resources so + a retry can actually succeed.