Search/Add Features to an Extensible Go Service With Tests That Survive Config Overrides

Add Features to an Extensible Go Service With Tests That Survive Config Overrides

Use when changing a Go service that downstream builds rename or customize. It keeps trace context in logs, registers new tools in the right group, tests public behavior under config overrides, and updates generated docs.

To use this AI rule
## Find the Package That Owns the Change Before Editing Classify the change and locate the source of truth before modifying code. - Identify the command entry point, domain packages, configuration layer, transport and authorization layer, protocol implementation, output layer, capability registry, and version metadata. - Keep business logic in the owned source packages rather than command wiring or distribution wrappers. - Treat language-package and installer directories as thin binary-distribution adapters; change them only for packaging or version work. - Read the build definitions, test configuration, nearby implementations, and user-facing documentation that govern the affected area. - Distinguish authored sources from generated files and build artifacts before editing. - List every affected handler, public type, registration point, configuration path, test, document, and package surface. Use the repository's established layout and naming conventions instead of introducing a parallel structure. ## Log Through the Context Wrapper So Logs Stay Linked to Traces Use the repository's contextual logging wrapper whenever production code emits a log. - Thread the request context to the point where logging occurs; add a context parameter when the call chain does not already carry one. - Do not call the framework's base context logger directly when the wrapper enriches records for telemetry correlation. - If a function starts a new trace span, acquire the contextual logger again after the span starts; a previously captured logger retains the older span context. - Keep structured values attached to the active context so the logging bridge can associate logs with the correct trace. - Check and handle every returned error in production code instead of discarding it. - Preserve the repository's established redaction, authorization, and observability boundaries when adding diagnostics. Verify correlation and error behavior through observable results rather than relying only on the presence of a log statement. ## Add New Tools Through a Handler, a Group, and Registration Design a new capability before implementing it: confirm its name, grouping, input schema, behavior, and evaluation coverage. 1. Implement the handler that owns the capability's logic. 2. Define its public tool or command contract and connect it to the handler. 3. Add it to the appropriate capability group, or create a focused group when none fits. 4. Register a new group through the repository's initialization path. 5. Update behavior tests, configuration references, generated catalogs, and user documentation together. Keep each capability group in its own owned directory. Avoid duplicate registration paths or names that expose internal implementation details. ## Use the Declared Build Targets and Never Deploy Unless Asked Use the repository's declared build targets rather than reconstructing commands from memory. - Know which build target formats source, tidies modules, compiles one platform, or builds every supported platform before running it. - Inspect the resulting diff because a build target may intentionally rewrite dependency metadata or generated files. - Keep dependency declarations tidy after introducing a module, and run the repository's pinned static-analysis target. - Preserve supported local and remote execution modes, including the documented precedence among explicit flags, environment variables, default files, and in-cluster configuration. - Document test or lint targets that download tools or environments on first use; absence of network access may cause setup failures rather than code failures. - Keep package-manager wrappers thin and synchronized with the compiled binary instead of duplicating service logic. Treat targets that download, publish, push, or deploy as external-operation boundaries. Inspect their contracts first, and never publish or deploy unless the task explicitly includes release work. ## Test Public Behavior and Edge Cases, Not Private Functions Exercise the public API as a black box and prefer real implementations or integration tests when practical. - Organize tests with the repository's suite convention and give each test file a corresponding suite. - Use nested subtests to group related scenarios and give every case a descriptive behavior-based name. - Let each case ideally prove one behavior with one focused assertion. - Cover successful paths, callbacks, state changes, and observable outputs without coupling tests to private functions. - Add edge cases for nil or null values, empty collections, invalid indices, type mismatches, malformed input, and error paths. - Use prerequisite assertions for setup operations that must succeed, then assert expected errors or values explicitly. - Never ignore an error merely to keep a test concise. Start with a focused failing test for a defect, run the affected package or suite after the fix, and finish with the repository's required full test target. ## Keep Config Tests Passing When Defaults and Names Are Overridden Configuration tests must remain valid when downstream builds override defaults, feature names, or enabled capability sets. - Start ordinary test suites from an override-free base configuration, then layer test-specific settings onto it. - For simple configuration, merge decoded values into the suite's existing configuration so runtime fields already established by the harness remain intact. - When a section stores deferred or primitive values, use the metadata-aware two-phase reader required to parse those sections fully. - After a full configuration read, explicitly restore runtime-only fields such as connection paths, output choices, and read-only state. - For reload tests, deliberately construct the candidate from the override-aware defaults used by the running service, then inherit the active runtime fields. - Append required capabilities to the existing list; never replace the list with assumed upstream defaults. - Resolve rebrandable public names dynamically, but keep a parser's literal registration key fixed when the parser contract requires it. - Never hardcode override-prone defaults, public names, or feature sets in assertions. Test both the base behavior and at least one override path whenever configuration changes cross these boundaries. ## Keep Shared Test Helpers in One Place and Separate Setup Failures Place generic test helpers in the repository's shared internal test area and document them with clear purpose, inputs, and examples. - Keep helpers independent of one feature so multiple packages can reuse them. - Prefer realistic user or protocol interactions over low-level shortcuts that bypass production behavior. - Make test prerequisites explicit, including local cluster simulators, downloaded environments, credentials, or required network access. - Separate a setup failure from a product failure in diagnostics. - Aim for high coverage of the public API, especially boundary conditions and failure paths, without padding metrics with low-value cases. - Keep test configuration, aliases, and generated fixtures aligned with the active test runner. When downstream customization exists, include representative tests for renamed capabilities, changed defaults, and configuration reloads. ## Update Docs Through the Generator and Keep Packages on the Same Version Update every authoritative surface affected by a code or configuration change. - Use lowercase filenames for new documentation when that is the repository convention. - Update indexes, configuration references, prompts, logging, observability, authentication, and integration guides according to the feature's impact. - Treat generated tables and reference sections as generated content; preserve their marker pairs and update them through the approved generator. - Do not edit generated sections directly or commit build artifacts unless repository policy explicitly requires it. - Keep native binaries, container images, and language-package wrappers aligned with the same versioned service behavior. - Run the documented build, test, lint, documentation-generation, and focused packaging checks relevant to the change. Before presenting the change, confirm that the final diff contains only intended source, test, documentation, and package updates. Run release or publication targets only when the task explicitly includes them, and report any broader checks intentionally left out of scope.