diff --git a/docs/releases/v0.4.2.md b/docs/releases/v0.4.2.md new file mode 100644 index 0000000..425c989 --- /dev/null +++ b/docs/releases/v0.4.2.md @@ -0,0 +1,45 @@ +# ConfigKit v0.4.2 + +This patch release simplifies and safeguards source publication and aligns +maintainer policy and licensing guidance. Library behavior is unchanged. + +## Summary + +Maintainers can now publish a prepared release with one guarded command. It +validates the exact committed candidate, checks the authoritative destination, +and pushes only the candidate on `main` and its annotated version tag. The +[release procedure](../release.md) explains preparation and partial-publication +recovery; successful tag publication completes the source-only release without +waiting for CI or consumer retrieval. + +## Compatibility + +No Go code, public API, configuration semantics, diagnostic behavior, or +dependencies changed from v0.4.1. The minimum Go version remains 1.25. Linux +amd64 and arm64 remain release-validated; macOS remains best-effort. The YAML +dependency remains `go.yaml.in/yaml/v4 v4.0.0-rc.6`. + +## Upgrade + +Select this version and rebuild: + +```sh +go get gitea.maximumdirect.net/eric/ConfigKit@v0.4.2 +``` + +No application-code or configuration migration is required from v0.4.1. + +## Changes + +- Add guarded single-command publication with exact candidate, version, and + remote checks; note-derived annotated tags; and bounded failed-push recovery. +- Keep one offline race suite, one full vet pass, and Linux amd64/arm64 builds + as release gates. Formatting and whitespace remain development checks; + dependency tidiness is reviewed when dependencies change. +- Align adopted policies and contributor guidance with their pinned upstream + revision, and include the CC BY-SA 4.0 license text and attribution for + adapted policy material. The project grant remains LGPL-3.0-or-later. +- Retire completed release-workflow and policy-alignment planning records while + preserving their history in Git. Deferred scope remains documented. + +[COPYRIGHT](https://gitea.maximumdirect.net/eric/ConfigKit/src/tag/v0.4.2/COPYRIGHT) | [LICENSE](https://gitea.maximumdirect.net/eric/ConfigKit/src/tag/v0.4.2/LICENSE) | [ATTRIBUTION](https://gitea.maximumdirect.net/eric/ConfigKit/src/tag/v0.4.2/docs/oss/attribution.md) diff --git a/docs/roadmap/implementation.md b/docs/roadmap/implementation.md deleted file mode 100644 index 2ac5843..0000000 --- a/docs/roadmap/implementation.md +++ /dev/null @@ -1,222 +0,0 @@ -# Release Workflow Implementation Plan - -Status: implemented on 2026-09-28. All stages are complete. - -Implement the [release roadmap](release.md) in the numbered order below. Each -stage is a bounded work unit for a gpt-5.6-terra coding agent; finish its tests -and current documentation before committing it. The completed policy-alignment -record formerly at this path is preserved at -`faf5ff8:docs/roadmap/implementation.md`; use `git show` to read it. - -## Scope and settled decisions - -Start from completed policy alignment at `faf5ff8`. Follow the -[development guide](../development.md) and applicable adopted policies. Preserve -library behavior, dependencies, the everyday checker, historical release notes, -licensing, and support commitments. This plan authorizes no real release or push. - -Use release policy 1.4 and the adoption guide at upstream commit -`d84a38ebab26f048cafbe59a2246700c35d29843`, available from `../policy` or the -existing pinned upstream links. Do not add an upstream-version review. Use shared -wording verbatim unless a substantive ConfigKit decision warrants adaptation. -Preserve exact source metadata; update the local date when revising policy. - -The interface is `./scripts/release.sh vMAJOR.MINOR.PATCH`, with the existing -`CONFIGKIT_BASELINE_TOOLCHAIN` prerequisite. Resolve the repository root from the -script location. Retain `scripts/release-check.sh` as its validator and an optional -diagnostic command, never a required prior run. No skip-validation option, -persistent cache, routine confirmation, or automatic commit is needed. Stop using -`.git/configkit-release-candidate`; ignore any old record without deleting it. - -Use sequential explicit main-then-tag pushes, not atomic-push negotiation. Keep -Bash 3.2 and existing Git/Go prerequisites; no new release framework is needed. - -## Stage 1 — Simplify the release checker and select its gates - -**Completed 2026-09-28.** The checker now runs one readonly offline race suite -with test-time vet disabled, one full vet pass, and CGO-disabled Linux amd64/arm64 -builds. The disposable module audit and release formatting/whitespace scans were -removed. Focused checker tests, Bash syntax checks, and the real Go 1.25.14 -release checker passed on Linux. - -Change `scripts/release-check.sh`, checker tests in `release_check_test.go`, and -the affected descriptions in `docs/policy/release.md`, `docs/release.md`, and -`docs/development.md` together. The existing guarded publication blocks remain -operational until Stage 2; do not describe the new command as available yet. - -Use this exact gate set with the selected maintained Go 1.25 baseline: - -| Gate | Command and rationale | -| --- | --- | -| Full offline race suite | One `go test -mod=readonly -vet=off -race -v ./...`; protects library behavior, ownership, and concurrent use. Includes examples, consumer fixtures, documentation links, and boundary tests. | -| Static analysis | One `go vet -mod=readonly ./...`; full vet provides checks beyond the subset normally run by tests. Disabling test-time vet avoids duplicating that subset. | -| Supported target compilation | `go build -mod=readonly ./...` for Linux amd64 and arm64 with `CGO_ENABLED=0`; these configurations are not covered by native race compilation. | - -Keep `GOPROXY=off`, baseline availability/cache diagnostics, fail-fast behavior, -and verbose skip reporting. Dependency/toolchain acquisition is explicit -preparation; there is no automatic upgrade or latest-version survey. Readonly -module commands prevent incidental manifest edits, not impose a new tidy policy. - -Remove the disposable-copy module-tidiness audit, release formatting/whitespace -scans, and their unused machinery. Formatting/whitespace remain ordinary -development checks in `scripts/check.sh`; module tidiness is reviewed when -dependencies change. Offline tests/builds establish that the candidate compiles -and works with its declared dependencies. Remove policy wording that makes the -removed checks mandatory release gates. Shell syntax checks belong to development -validation, not a separate publication gate. Do not change the everyday checker. - -Split the shared checker regression expectations where their contracts differ. -Retain unusual-filename and whitespace tests for the everyday checker. Controlled -Go subprocesses should verify the release toolchain/offline settings, one suite, -one vet pass, the two target builds, and stopping after failure. Do not recursively -execute the real full suite in a checker-orchestration test. - -Acceptance: focused `TestCheckScripts` tests and Bash syntax checks pass. Run the -real revised checker with prepared baseline dependencies on Linux. Do not also -run the everyday suite just to repeat its checks. macOS and newer-toolchain -validation remain optional. - -## Stage 2 — Implement single-command publication and recovery - -**Completed 2026-09-28.** Added the executable single-command publisher, exact -candidate and destination guards, one checker invocation, explicit main-then-tag -pushes, note-derived annotated tags, and bounded failed-push state checks. -Disposable Git fixtures covered success, refusals, branch-only progress, -conflicting tags, and unknown outcomes without contacting the real remote. -Bash syntax checks, focused tests, the offline default suite, local links, and -whitespace review passed. - -Add executable `scripts/release.sh`, calling the existing validator once rather -than duplicating it. Replace `TestReleaseRunbookGuards` with tests of the actual -script: prose headings cease to be an executable interface. Update the release -policy and runbook in this stage to describe implemented behavior and recovery. - -### Candidate and publication flow - -1. Accept exactly one stable version argument using the existing no-leading-zero - Semantic Version format. Require `main` and a clean index/worktree including - nonignored untracked files. Ignored local files alone do not block release. - Verify the existing authoritative `origin` endpoint and ensure pushes actually - target it, accounting for separately configured push URLs and multiple push - destinations. Do not publish to an unnoticed additional destination or print - credentials in diagnostics. -2. Capture the full candidate commit ID. Read `docs/releases/.md` from - that commit and require the first line `# ConfigKit `. Meaningful - summary and applicable compatibility/upgrade content are ordinary preparation, - not automated prose judgments or four mandatory headings. Retain the existing - footer and local note-review requirements without a new network check. -3. Require the version unused locally and on the authoritative remote. Query the - exact remote tag, distinguishing absence from query failure. Read remote main - and check that publication can advance it without discarding history; main - already at the candidate is acceptable. No all-remotes or all-tags survey. -4. Run `scripts/release-check.sh` once. Failure stops before any push/tag creation. - Recheck branch, cleanliness, candidate identity, and unused version state after - validation. Changed candidates require a fresh invocation after correction and - commit; do not automatically commit or repair the checkout. -5. Push the captured commit explicitly to `refs/heads/main`, without force or - incidental follow-tags publication. Override broad configured push defaults - through explicit destinations/refspecs. A successful push establishes branch - publication without a separate read-back gate. Recheck local candidate and - clean state before tagging; ordinary concurrent local edits must not leak - into publication. -6. Create an annotated tag at the captured commit, using the captured checked-in - note as its message (`git tag -a -F`). Verify its peeled target and capture its - tag-object ID. Push only `refs/tags/:refs/tags/`, without - force or implicit publication of unrelated tags. -7. On successful tag push, report the version/candidate and return success - immediately. No CI polling, remote read-back, module retrieval, hosted release - creation, or routine human sign-off gates completion. - -Use straightforward private helpers. These are ordinary release guards, not a -guarantee against hostile local processes or concurrent administrators. Do not -add locks, snapshots, signing requirements, or unrelated Git configuration rules. - -### Failure outcomes - -After a failed or ambiguous push, perform one bounded authoritative-state check; -do not poll or blindly retry: - -| State observed | Behavior | -| --- | --- | -| Main push failed, but remote main equals candidate | Continue through remaining guards and tagging. | -| Main push failed, remote differs or cannot be queried | Stop before tagging; distinguish rejection from unknown outcome and explain recovery. | -| Tag push failed, but remote tag-object ID equals the created annotated tag | Report confirmed publication success; main publication was already established. | -| Tag push failed, remote tag confirmed absent | Report branch-only progress and the unpublished local tag; retain it. | -| Remote tag conflicts | Stop; never replace published contents. | -| Remote tag cannot be queried | Report unknown status; retain local state, do not claim success or safe version reuse. | - -Document exact-ref recovery commands that distinguish absence from query failure. -Only after confirming a local tag was never published or used by another channel -may a maintainer delete that unpublished tag and rerun with the same version. -A fresh invocation revalidates; this is failure recovery, not a mandatory double -successful-path run. A correctly published tag needs no rerun. Published source -defects need a new version; transient transport failures do not. Never roll back -main or automatically delete tags to recover. - -### Regression coverage and acceptance - -Use disposable real Git working repositories and bare remotes. Reuse the existing -fixture-only authoritative-URL substitution or Git URL rewriting, with local-file -transports and isolated identity/signing configuration. No production test-only -bypass flags. Stub the expensive validator with a loggable result; use real -rejection hooks and narrow Git-process wrappers for lost responses/unavailable -queries. Tests must never contact the actual remote or recurse into the suite. - -Cover success with main initially behind the candidate and already equal; -single validation; note-derived annotated tag/commit identity; ignored files; -and unrelated local tags remaining unpublished. Cover malformed version, wrong -branch/destination, dirty/changed candidate, missing/mismatched note, local/remote -tag collision, failed validation, non-fast-forward main, and the meaningful -failure outcomes above. A note without empty boilerplate headings must pass. -Assert resulting refs and exit status, not helper structure or exact diagnostics. -Verify completion has no CI/consumer-tool dependency. - -Acceptance: Bash syntax checks, focused checker/publication tests, and the offline -default suite pass. The script is tested only against fixtures. Current docs must -no longer require a manually recorded candidate before single-command publication. - -## Stage 3 — Complete documentation alignment and integrated validation - -**Completed 2026-09-28.** Reconciled the adopted release policy with its pinned -upstream source and ConfigKit decisions; aligned the runbook, development guide, -and roadmap records with the implemented command. Bash syntax, focused release -tests, local documentation links, whitespace review, and the final real baseline -release checker passed on Linux. No publication or push was performed. - -Reconcile `docs/policy/release.md` with the pinned upstream release policy. Adopt -shared paragraphs verbatim except for substantive local decisions. Remove the -temporary deferral, all-remotes freshness rule, and stale prospective v0.3.0 note -instruction. Preserve known-published-version nonreuse, ConfigKit compatibility, -source-only deliverables, annotated tags, selected gate rationale, Linux support, -best-effort macOS, no-CI completion, and historical exceptions. No compensating -controls are required merely to use successful-tag-push completion. - -Keep base version 1.4 and its existing pinned source; update the local date. -Existing attribution and license scope already cover these edits. Do not change -other policies, copyright/license grants, or historical release notes unnecessarily. - -Review `docs/release.md` as the operational owner: preparation, one publication -command, completion, partial/unknown-state recovery, and distinctly optional -diagnostics. Retain exact version-specific licensing footer URLs and optional -consumer retrieval; neither adds a network gate. Remove duplicate manual publish -instructions. Update `docs/development.md` navigation, gate summary, and test map. -Search active documentation/scripts for stale candidate-file, section-template, -module-tidiness gate, CI-wait, and manual publication instructions. Fix affected -links without rewriting historical records. - -Correct the completed policy roadmap's implementation-record reference to -`faf5ff8:docs/roadmap/implementation.md`, since this path now owns the new plan. -Mark release-roadmap implementation status accurately after acceptance. Preserve -unfinished/deferred work; retirement belongs to actual release preparation. - -Run Bash syntax checks, focused orchestration tests, documentation-link tests, -and `git diff --check`. Run the revised real release checker once on the final -implementation with prepared baseline dependencies. Reuse that successful suite -result instead of separately repeating examples, boundaries, vet, builds, or the -everyday suite. Report missing prerequisites rather than claiming success. Never -invoke publication against origin as an acceptance test. - -Acceptance: scripts, policy, and runbook agree; tests protect selected behavior -without extra contracts; current docs describe only implemented behavior. Commit -each completed unit with a plain-English message and report validation/workspace -state without publishing. No product decisions remain open in this plan. diff --git a/docs/roadmap/policy.md b/docs/roadmap/policy.md deleted file mode 100644 index c510080..0000000 --- a/docs/roadmap/policy.md +++ /dev/null @@ -1,19 +0,0 @@ -# Standard Policy Documentation Alignment - -Status: implemented on 2026-09-28. The completed implementation record and -validation evidence are preserved at `faf5ff8:docs/roadmap/implementation.md`. - -ConfigKit's seven [adopted policies](../policy/meta.md) now identify the pinned -Standard Repository Policies revision -`d84a38ebab26f048cafbe59a2246700c35d29843` and their local adaptations. -The [developer guide](../development.md#policy-reading-guide) routes tasks to -applicable policies. [COPYRIGHT](../../COPYRIGHT) and the -[attribution notices](../oss/attribution.md) identify the separately licensed -adapted policy and orientation material. - -The [release policy](../policy/release.md) and -[maintainer runbook](../release.md) own current release requirements and -operations. The separate [release-workflow roadmap](release.md) records the -subsequent publication-automation work. - -These completed records remain until normal release preparation retires them. diff --git a/docs/roadmap/release.md b/docs/roadmap/release.md deleted file mode 100644 index 2a43311..0000000 --- a/docs/roadmap/release.md +++ /dev/null @@ -1,126 +0,0 @@ -# Single-Command Release Workflow and Gate Review - -Status: implemented on 2026-09-28. The -[implementation plan](implementation.md) records the completed work and checks. - -## Intent and baseline - -Make source releases simple for humans and agents: one publication command -validates the final committed candidate, checks publication state, and publishes -only the intended refs. Keep the minimum gates justified by ConfigKit's actual -risks, with no routine human intervention or waiting for CI. - -Local baseline: `0adb94f59e44827908eff401d4381a398fe17107` (v0.4.1). -The upstream reference is release policy v1.4 at -`d84a38ebab26f048cafbe59a2246700c35d29843`: -[standard release policy](https://gitea.maximumdirect.net/eric/policy/src/commit/d84a38ebab26f048cafbe59a2246700c35d29843/docs/policy/release.md). - -At the planning baseline, `scripts/release-check.sh` performed local validation; the runbook separately -records a candidate commit and executes shell blocks for guards, branch push, -annotated tagging, and tag push. The checker runs module hygiene, formatting and -whitespace checks, one race-enabled suite, vet, and Linux amd64/arm64 cross-builds -using a maintained Go 1.25 patch. Publication completes on successful tag push. - -The implementation plan records the subsequent gate selection and publication -command. Current requirements belong to the -[release policy](../policy/release.md) and [runbook](../release.md). - -## Target release contract - -ConfigKit remains a source-only Go module hosted at its authoritative Gitea -remote. Releases identify a final committed source revision on `main`, one fresh -immutable annotated version tag, and a matching checked-in release note. -No binary distribution, hosted release object, or registry publication is added. - -The publication command owns validation, candidate identity, guards, and explicit -ref publication. Preparation still supplies the version, committed release note, -and dependencies/toolchain; the command must not silently edit or commit source, -choose a version, or upgrade dependencies. Publication remains subject to user -authorization, not the standing local-commit policy. - -The command validates the exact candidate once. An optional validation-only mode -may support diagnosis but is not a prerequisite followed by duplicate validation. -Do not require both everyday and release checkers. An implementation need not -introduce a persistent validation cache merely to replace the former manual record. - -Mechanical guards ensure a clean worktree/index on the primary branch, an unused -valid version locally and on the authoritative remote, a matching release note, -and exact agreement between validated source and tagged source. Publish only -intended refs without discarding remote history. Ignored local files are not -release content and do not alone prevent publication. - -A successful intended tag push, with the source commit available on authoritative -main, completes the release. Never wait for or poll CI, module availability, -consumer installation, or optional verification. Do not add a successful-push -remote read-back gate. If future artifact channels are adopted, delivery status -must remain separate; this task introduces none. - -## Selected gate rationale - -Keep the full deterministic offline suite as the core check. The selected gates -below provide distinct protection without repeating validation. Their rationale -belongs in the adopted release policy, with commands in the runbook and tooling. - -| Check | Selected end state and rationale | -| --- | --- | -| Race detector | One full race-enabled suite protects ownership and concurrent loads; no second ordinary suite. | -| Vet | One full vet pass provides additional static analysis; disable the smaller test-time vet pass to avoid overlap. | -| Module hygiene | Tidiness belongs to dependency-change review, not a recurring release audit. Offline tests/builds use readonly module mode to avoid incidental manifest edits. | -| Formatting and whitespace | Ordinary development checks, not publication gates; the everyday checker remains unchanged. | -| Linux amd64/arm64 builds | Retain both CGO-disabled builds: they cover supported configurations distinct from native race compilation. | -| Toolchain selection | One maintained Go 1.25 patch, with no second-toolchain gate or per-release latest-version research. | - -Examples, consumer fixtures, documentation links, and import/public boundary tests -are already in the suite; they must not become separately repeated release checks. -macOS remains best-effort. No human sign-off, new linter, hardware requirement, -scanner, credentials-dependent test, or remote application probe is introduced. - -## Documentation and recovery - -Align `docs/policy/release.md` with upstream shared wording, preserving explicit -ConfigKit decisions and the selected gate rationale. The successful-tag-push rule -is a normal supported choice under the new upstream policy, not an exception -requiring newly invented compensating controls. - -Make `docs/release.md` a short executable runbook for preparation and the single -command. New notes use a proportionate summary and applicable compatibility and -upgrade information rather than mandatory empty sections. Preserve the licensing -footer and version-specific immutable links. Derive annotated-tag summary content -from the checked-in note. Keep historical notes unchanged. - -Validation or guard failure stops publication with actionable diagnostics and no -force updates. A failed or ambiguous push requires resolving authoritative remote -state before retrying or reporting success. A transient failure does not itself -require a new version. Published tags remain immutable; removing an unpublished -local tag requires confirmation it was never published. Explain partial progress -such as a successful branch push followed by a failed tag push. - -## Changes needed and scope - -The work affects `docs/policy/release.md`, `docs/release.md`, release shell tooling, -`release_check_test.go`, and relevant contributor guidance. Reuse existing -validation mechanisms where appropriate; avoid a general release framework. -Tests should exercise success and meaningful failure/recovery paths in disposable -local repositories, without real publication or credentials. Match coverage to -the chosen push strategy and protect against unintended refs or stale candidates. - -Preserve provenance and licensing established by the completed -[policy roadmap](policy.md). -Operational documentation changes land with the implementation they describe. -No library behavior, dependency update, release tag, or push is authorized by -implementing this roadmap alone. - -## Publication strategy - -Use explicit main-then-tag pushes inside the command. This matches the proven -local workflow and avoids a new dependency on atomic-push support. A branch-only -intermediate result is possible; recovery distinguishes it from completed or -unknown publication. Atomic publication is not part of this target. - -## Completion criteria - -One documented command publishes a prepared candidate with the reviewed minimum -gate set, no duplicate suite runs, and automated exact-source safeguards. Local -regression tests demonstrate successful publication and safe failure handling. -The policy, runbook, and scripts agree, and successful tag publication is reported -without waiting for external completion evidence. diff --git a/docs/roadmap/remediation.md b/docs/roadmap/remediation.md deleted file mode 100644 index 7c0a61e..0000000 --- a/docs/roadmap/remediation.md +++ /dev/null @@ -1,84 +0,0 @@ -# Release Workflow Review Findings - -Status: both findings addressed. The original findings below are retained as -review history until normal release-preparation retirement. - -## Resolution and verification - -- Publication, fetch, and recovery now use the same validated named `origin`. - Pushes retain exact refspecs and disabled implicit tags, and override the - remote's mirror default for that invocation only. No new gate was introduced. -- A disposable-Git regression failed against the original publisher and passes - with the fix for normal publication and lost main/tag push responses. It also - checks that broad push defaults do not publish or delete unrelated refs and - that the rewrite destination receives no refs. -- Optional consumer verification explicitly initializes the selected version. - Executing the documented block with a local Go stub verified the exact module - argument with both an initially unset and an initially stale version variable, - without network retrieval. -- Focused publication tests passed. Final validation passed: Bash syntax, - whitespace review, and the Go 1.25.14 release checker (race suite including - documentation links, full vet, and both Linux target builds). - -Reviewed implementation through `3d0093e` against the release roadmap and -completed implementation plan. The ordinary Go 1.25.14 release checker passed -(offline race suite, full vet, Linux amd64/arm64 builds), as did Bash syntax -checks. These findings concern publication destination integrity and a runbook -example; no library changes or additional release gates are needed. - -## 1. Align destination validation with actual push resolution (high priority) - -**Locations:** `scripts/release.sh:56–59`, `:91`, and `:116`; -regression coverage in `release_publish_test.go`. - -The guard inspects `git remote get-url --push --all origin`, but both pushes use -the literal URL instead of the inspected remote. Git treats these differently -when `origin` has an explicit push URL and a matching `url..pushInsteadOf` -rule. The explicit remote push URL bypasses that rule for the guard; passing the -literal URL to `git push` applies the rule. - -Reproduced with two disposable bare repositories A (authoritative) and B: - -1. Set origin's fetch URL and explicit push URL to A. -2. Configure `url..pushInsteadOf` to match A. -3. Prepare main and a matching release note. Run a fixture copy of the actual - publisher with A substituted for the authoritative URL and a successful - checker stub, as in the existing publication fixtures. - -Both guard queries return A. The publisher nevertheless pushes main and the -annotated tag to B and reports `Published`; A still has the old main and no -release tag. Recovery queries also inspect A rather than the push destination. -This violates the already-selected authoritative-destination and completion -contract; it is not a request for broader Git hardening. - -**Required correction:** make guard, push, and recovery destination resolution -agree. Use a consistent validated target rather than assuming a literal URL -bypasses Git URL rewriting. Preserve explicit refspecs, non-force publication, -and suppression of unrelated tags/configured broad push behavior. Do not add -successful-push read-back, blanket Git configuration bans, or new human gates. - -**Acceptance:** add a real local-Git regression for the configuration above. -Publication must either use the confirmed authoritative destination or refuse -before any publication; B must receive no refs. Preserve existing ordinary -success, multiple-destination refusal, and ambiguous-push recovery coverage. - -## 2. Initialize the version in optional consumer verification (low priority) - -**Location:** `docs/release.md:177–194`. - -The optional `go get` example expands `$release_version`, but the successful -publication example passes a literal version to the script and never initializes -that shell variable. Its only assignment is in the failure-recovery section, -which successful releases do not need to execute. The optional example therefore -uses an unset variable (or a stale version from the caller's shell) instead of -the release just published. - -**Required correction:** explicitly set the selected version in the optional -example, or consistently establish it in the normal preparation/publication -instructions and explain that prerequisite. Keep verification optional and -non-gating. - -**Acceptance:** follow the successful path in a fresh shell without running -recovery instructions and confirm that the optional example constructs the -intended exact module/version argument. A local stub is sufficient; no production -module retrieval or new recurring test/gate is needed.