Search/Make Small Changes to a Stateful UI Library Without Breaking Its Users

Make Small Changes to a Stateful UI Library Without Breaking Its Users

Use when an AI fixes or changes a browser UI library that holds state. It finds who owns the state, keeps public APIs and saved data working, writes a failing test first, picks unit or real-browser tests, and reviews the diff and release note before finishing.

To use this AI rule
## Find the State Owner and Change State Only Where the Library Allows Begin by locating the state owner, update boundary, and public contract affected by the request. In an immutable state model, read through a consistent snapshot and mutate only within the library's sanctioned update context. Treat node or entity handles as versioned references; do not retain mutable assumptions across update boundaries. Keep feature registration, commands, transforms, and listeners within their documented lifecycle. Prefer the current extension or composition mechanism for new work while maintaining any supported legacy integration path. Ensure every registration has a clear cleanup path, and preserve serialization formats that existing consumers may still load. ## Use Syntax-Aware Search and Keep the Patch Small Use syntax-aware search and rewriting when a change concerns imports, call sites, type annotations, or structured code. Line-oriented regular expressions can miss multiline forms and match unrelated identifiers. Confirm candidate matches in the syntax tree before applying a broad rewrite. Keep the change behavior-shaped and local. Use domain-specific names, guard clauses for invalid or already-handled states, and a visible success path. Extract helpers only when they name a responsibility or simplify the caller. Do not mix opportunistic refactoring, debug logging, temporary names, or unrelated formatting into the final patch. When a side-effect-free factory is created at module scope, preserve the project's tree-shaking annotation convention and update the enforcing rule if the factory family itself expands. ## Keep Public APIs Compatible and Use the Element's Own document and window Assume external code depends on existing public names, signatures, behavior, and serialized data. Prefer additive APIs and optional parameters. When a breaking change is unavoidable, retain and deprecate the old path before removal, and verify both the current and compatibility paths. Maintain every supported type system and generated declaration surface touched by the API. Browser-facing code must obtain the owning document and window from the relevant root or element rather than relying on ambient globals. Use realm-aware selection, focus, event-target, and parent traversal helpers so shadow roots and embedded documents do not silently read from the wrong environment. For serialization, request handling, URLs, HTML or script output, filesystem paths, authentication, or dependency changes, identify the untrusted input and the nearest validating guard. Prefer fail-closed behavior, keep secrets out of logs and artifacts, and verify both the writer and reader sides of any protocol. ## Write a Failing Test First and Choose Unit or Real-Browser Tests For a behavior change or bug fix, define the observable invariant first. Add or update the closest focused test, run it before the implementation when feasible, and confirm that it fails for the expected reason. Make the smallest change that satisfies it, rerun the focused test, then expand only to verification required by the touched surface. Use simulated-environment unit tests for logic that does not depend on real layout or selection behavior. Use real-browser tests for layout, selection, focus, shadow-root, or cross-document behavior. Reserve end-to-end tests for navigation, full application integration, or protocols that require a running system. Build the specific artifact consumed by the test before relying on its result. Do not substitute a broad repository-wide command for a focused test without cause. A passing unrelated suite does not prove the changed boundary. ## Review the Diff and Add a Release Note Before Finishing Before finishing, review the diff as a new contributor would. Confirm that names expose domain meaning, edge cases use explicit guards, the main path is readable, cleanup is complete, and no public contract changed accidentally. Run the formatter, linter, type checker, or API snapshot task required by the affected package. Add the repository's release note or changeset when published behavior changes. Describe the user-facing fix or feature rather than implementation mechanics. Keep commit and pull-request text free of private session links, credentials, or internal-only references, and record the focused test evidence that supports the change.