Search/Change a Multi-Language Automation Monorepo Without Breaking Compatibility

Change a Multi-Language Automation Monorepo Without Breaking Compatibility

Use when AI edits a large automation monorepo with bindings in several languages. It keeps public APIs compatible, builds and tests the smallest affected target with the pinned build tool, checks another binding behaves the same, and asks before touching high-risk shared areas.

To use this AI rule
## Read Repo-Wide Rules, Then the Instructions Nearest the Changed Files Begin with the repository-level rules, then read the instructions nearest to the files you will change. Language bindings, shared infrastructure, native components, and release tooling may each define narrower constraints. If the repository provides an ignored local area for contributor preferences, generated artifacts, scratch work, or isolated build output, inspect its documented instruction overlay before starting. Treat user-defined local instructions as additional context within the current task and higher-level safety rules. Map the repository by responsibility: - language bindings own language-specific APIs, tests, and style; - shared protocol, transport, build, fixture, and script areas affect multiple consumers; - native managers, grid or routing services, and dependency definitions have elevated blast radius; - third-party sources are read-only unless the task explicitly requires vendor maintenance; - generated output is never a hand-edit target. Do not assume that end-user documentation, contributor guidance, and generated API references share the same home. ## Keep Public APIs Compatible and Changes Small Enough to Undo Maintain public API and binary compatibility unless the task explicitly authorizes a break. Users should normally be able to upgrade by changing only the version. Avoid repository-wide refactors, formatting sweeps, or unrelated cleanup. Prefer a small, reversible diff that solves one problem. Before removing public behavior, mark it deprecated and provide a clear migration alternative. Do not treat the absence of semantic versioning as permission to remove functionality without a transition. Prefer moving or copying tracked files over deleting and recreating them when that preserves history. Request verification before modifying high-risk areas unless the user has already instructed the change. High-risk areas include shared protocol semantics, wire serialization, capability parsing, dependency repinning, shared test fixtures, build wiring, routing, distribution queues, and code consumed by multiple bindings. ## Build Only the Smallest Affected Target with the Pinned Build Tool Use the repository's pinned, hermetic build entry point instead of assuming a language-specific local environment is configured. Explore the build graph before reading large portions of the tree. Query target labels and dependencies, then build or test the smallest target that covers the change. Attempt the canonical build command directly. If sandbox, network, or toolchain restrictions prevent execution, report the blocker and provide the exact command the user can run separately. When the default output directory is restricted or a secondary working tree is in use, isolate the build output: - place the output-base startup option before the build, test, or query command; - anchor the path to the repository root so it resolves consistently from every directory; - keep isolated output under the ignored local area. Do not run destructive cache purges as a routine troubleshooting step. Prefer targeted rebuilds and explain any cache invalidation that is actually necessary. ## Check That Other Language Bindings Behave the Same Way When user-visible behavior changes, compare the implementation with at least one other language binding. Check parity especially for: - public method names, arguments, defaults, and return behavior; - protocol commands and serialization; - remote transport and error mapping; - capabilities and option parsing; - deprecations and migration paths; - documentation examples and user-facing logs. For shared low-level behavior, identify every binding or service that may consume the change. If the current task cannot update them all safely, report the follow-up parity work or recommend a tracked issue. Do not force identical internal structure across languages. Preserve shared behavior while respecting each binding's established idioms and test conventions. ## Start with a Small Failing Test That Uses Real Parts, Not Mocks Prefer writing a failing test before implementing changed behavior. Start with a small unit or contract test; use browser or end-to-end tests only when the behavior cannot be verified reliably at a lower level. Avoid mocks when they can misrepresent a public protocol or binding contract. Prefer real parsers, serializers, local fixtures, lightweight servers, or existing integration harnesses. Use the build graph to select the narrowest relevant test target. Useful controls include: - filtering to small tests; - displaying full test output when debugging; - disabling cached test results when a true rerun is required; - consulting language-specific instructions for the correct target and flags. Verify that the expected tests actually ran. A successful build-tool exit with no matching tests is not proof of correctness. After the focused test passes, broaden only to the directly affected binding, shared target, or integration surface. ## Keep Logs and Comments Useful, and Format Only What Changed Add logging where users or operators need visibility into important state, retries, routing, or failure causes. Follow the language-specific logging conventions and avoid noisy messages that duplicate lower-level diagnostics. Write comments to explain why a constraint or workaround exists, not what well-named code already says. Use the repository's canonical formatter. If a pre-commit or pre-push hook already runs the relevant formatting scope, let the hook handle it rather than running duplicate formatting. When no hook covers the change, run the narrowest formatter mode that matches the intended handoff. Do not format the whole repository because one file changed. Keep each proposed change focused on one purpose so review, rollback, and cross-binding impact remain understandable. ## Confirm the Build and Tests Actually Ran, and Report What Could Not Run Before completion: 1. confirm the changed target builds with the hermetic toolchain; 2. run the focused tests and verify that they exercised the intended behavior; 3. run the relevant formatting or lint check; 4. inspect the diff for unrelated changes and generated output; 5. review compatibility and deprecation implications; 6. compare at least one other binding for user-visible changes; 7. identify every high-risk shared area touched. Report what was changed, which targets and tests actually ran, what could not run, and why. Call out high-risk files, shared behavior, cross-binding impact, and any follow-up work. Do not claim broad compatibility from a single binding test. Do not claim completion when the hermetic toolchain was unavailable without clearly marking verification as incomplete.