canonical .golangci.yml emits a gomodguard deprecation warning under golangci-lint v2.12+ #25

Closed
opened 2026-08-09 06:56:21 +02:00 by clawbot · 6 comments
Collaborator

Filed by the dispatcher on behalf of the per-repo managers; this belongs upstream because the canonical config is untouchable by policy in the consuming repos, so the fix has to land here and propagate.

Problem

Under golangci-lint v2.12.0 and later, every lint run against the canonical .golangci.yml (sha256 021cc83f4e6fc7c31b95b34b846723dfcf20b66b7baeea1dc40406e643346bcb) prints:

gomodguard is deprecated (since v2.12.0), replaced by gomodguard_v2

The config uses default: all, so the deprecated linter is auto-enabled. It does not affect exit status, but it appears on every run in every Go repo that has migrated to v2.12.2 — currently dnswatcher, webhooker, vaultik, rgoue, cattbox, sfdupes, attrsum, upaas, simplelog, mfer, secret, bsfirehose, and pixa once PR #54 lands.

Per the global rule on deprecation warnings, this is an action item to remediate after work in flight, not noise to ignore.

Options

  1. Disable gomodguard explicitly, the same way wsl is already disabled. gomodguard_v2 stays enabled via default: all, so behavior is unchanged — no gomodguard settings are configured anywhere. This was the approach dnswatcher PR #96 took before the owner directed it back to the org-standard bytes, and it was verified to silence the warning with make lint reporting 0 issues.
  2. Accept the warning until the next canonical refresh.

Recommend option 1.

Definition of done

  • Canonical .golangci.yml no longer emits the deprecation warning under v2.12.2.
  • The new sha256 is recorded here and in REPO_POLICIES.md so consuming repos can verify by hash.
  • A follow-up issue exists (or is filed) to roll the new bytes into every consuming repo, since they verify by sha256 and will now mismatch.

Related: schema validity

While migrating netwatch, its manager found that repo's pre-migration .golangci.yml (sha256 33ba2bf7...) declared version: "2" while using v1 layout. golangci-lint silently fell back to defaults, so every configured threshold was ignored and the 0 issues. that repo reported was meaningless. Any repo still carrying that file has the same defect. golangci-lint config verify detects it.

CAUTION for whoever acts on that: golangci-lint config verify resolves its JSON schema over an unpinned live HTTPS fetch with a 2s timeout. It must NOT be wired into make lint or any CI gate — that would violate hash-pinning and make CI network-dependent. Use it as a one-off local check, or use an offline sha256 drift guard instead.

Filed by the dispatcher on behalf of the per-repo managers; this belongs upstream because the canonical config is untouchable by policy in the consuming repos, so the fix has to land here and propagate. ## Problem Under golangci-lint v2.12.0 and later, every lint run against the canonical `.golangci.yml` (sha256 `021cc83f4e6fc7c31b95b34b846723dfcf20b66b7baeea1dc40406e643346bcb`) prints: ``` gomodguard is deprecated (since v2.12.0), replaced by gomodguard_v2 ``` The config uses `default: all`, so the deprecated linter is auto-enabled. It does not affect exit status, but it appears on every run in every Go repo that has migrated to v2.12.2 — currently dnswatcher, webhooker, vaultik, rgoue, cattbox, sfdupes, attrsum, upaas, simplelog, mfer, secret, bsfirehose, and pixa once PR #54 lands. Per the global rule on deprecation warnings, this is an action item to remediate after work in flight, not noise to ignore. ## Options 1. Disable `gomodguard` explicitly, the same way `wsl` is already disabled. `gomodguard_v2` stays enabled via `default: all`, so behavior is unchanged — no gomodguard settings are configured anywhere. This was the approach dnswatcher PR #96 took before the owner directed it back to the org-standard bytes, and it was verified to silence the warning with `make lint` reporting 0 issues. 2. Accept the warning until the next canonical refresh. Recommend option 1. ## Definition of done - Canonical `.golangci.yml` no longer emits the deprecation warning under v2.12.2. - The new sha256 is recorded here and in `REPO_POLICIES.md` so consuming repos can verify by hash. - A follow-up issue exists (or is filed) to roll the new bytes into every consuming repo, since they verify by sha256 and will now mismatch. ## Related: schema validity While migrating netwatch, its manager found that repo's pre-migration `.golangci.yml` (sha256 `33ba2bf7...`) declared `version: "2"` while using v1 layout. golangci-lint silently fell back to defaults, so every configured threshold was ignored and the `0 issues.` that repo reported was meaningless. Any repo still carrying that file has the same defect. `golangci-lint config verify` detects it. CAUTION for whoever acts on that: `golangci-lint config verify` resolves its JSON schema over an unpinned live HTTPS fetch with a 2s timeout. It must NOT be wired into `make lint` or any CI gate — that would violate hash-pinning and make CI network-dependent. Use it as a one-off local check, or use an offline sha256 drift guard instead.
Author
Collaborator

Implementation brief. Option 1 adopted, as recommended.

Change

Add to the existing linters.disable block, in the same style as the wsl entry directly above it:

    - gomodguard       # Deprecated, replaced by gomodguard_v2

gomodguard_v2 stays enabled via default: all, and no gomodguard settings are configured anywhere, so behaviour is unchanged.

Confirmed present: main already carries the v2-layout config at sha256 021cc83f4e6fc7c31b95b34b846723dfcf20b66b7baeea1dc40406e643346bcb, matching the hash in this issue, so this applies cleanly.

Definition of done

  • Run golangci-lint v2.12.2 against the amended config on a real Go tree and confirm zero deprecation warnings — not merely that the gomodguard one is gone. wsl was disabled for the same reason previously and three managers rediscovered gomodguard independently, which suggests nobody has swept the full set. If other deprecated linters are auto-enabled by default: all under v2.12.2, disable them in the same commit and list them.
  • Record the new sha256 in this issue and in the PR body.
  • Per the issue DoD, record it in REPO_POLICIES.md too — and add an explicit note there that the recorded hash must be updated in the same commit as any .golangci.yml change, since a stale published hash is itself a false-verification mechanism of the same family as everything else in this batch.
  • TODO.md entry dated 2026-08-09.

Republishing changes the hash — enumerate the fallout in the PR body

Several open issues across the fleet assert 021cc83f... as the expected sha256, and every consuming repo verifies by hash. The PR body must state the old hash, the new hash, and that consuming repos must re-fetch. Search the tracker for the old hash and list the issues that will need updating; naming them is part of this unit, not a follow-up.

Explicitly out of scope

The golangci-lint config verify schema-validity item in this issue's "Related" section stays out. It resolves its JSON schema over an unpinned live HTTPS fetch with a 2-second timeout, so wiring it into make lint or any gate would violate the hash-pinning rule and make CI network-dependent. If a drift guard is wanted, it should be an offline sha256 comparison — file it separately rather than folding it in here.

**Implementation brief. Option 1 adopted, as recommended.** ## Change Add to the existing `linters.disable` block, in the same style as the `wsl` entry directly above it: ```yaml - gomodguard # Deprecated, replaced by gomodguard_v2 ``` `gomodguard_v2` stays enabled via `default: all`, and no `gomodguard` settings are configured anywhere, so behaviour is unchanged. Confirmed present: `main` already carries the v2-layout config at sha256 `021cc83f4e6fc7c31b95b34b846723dfcf20b66b7baeea1dc40406e643346bcb`, matching the hash in this issue, so this applies cleanly. ## Definition of done - Run golangci-lint v2.12.2 against the amended config on a real Go tree and confirm **zero deprecation warnings** — not merely that the `gomodguard` one is gone. `wsl` was disabled for the same reason previously and three managers rediscovered `gomodguard` independently, which suggests nobody has swept the full set. If other deprecated linters are auto-enabled by `default: all` under v2.12.2, disable them in the same commit and list them. - Record the **new sha256** in this issue and in the PR body. - Per the issue DoD, record it in `REPO_POLICIES.md` too — and add an explicit note there that the recorded hash must be updated in the same commit as any `.golangci.yml` change, since a stale published hash is itself a false-verification mechanism of the same family as everything else in this batch. - `TODO.md` entry dated 2026-08-09. ## Republishing changes the hash — enumerate the fallout in the PR body Several open issues across the fleet assert `021cc83f...` as the expected sha256, and every consuming repo verifies by hash. The PR body must state the old hash, the new hash, and that consuming repos must re-fetch. Search the tracker for the old hash and list the issues that will need updating; naming them is part of this unit, not a follow-up. ## Explicitly out of scope The `golangci-lint config verify` schema-validity item in this issue's "Related" section stays out. It resolves its JSON schema over an unpinned live HTTPS fetch with a 2-second timeout, so wiring it into `make lint` or any gate would violate the hash-pinning rule and make CI network-dependent. If a drift guard is wanted, it should be an offline sha256 comparison — file it separately rather than folding it in here.
sneak was assigned by clawbot 2026-08-09 19:40:13 +02:00
Author
Collaborator

BLOCKED ON OWNER AUTHORIZATION — not on analysis. Assigned to sneak. One line, ten seconds, but an agent may not be the one to type it.

REPO_POLICIES.md line 261 states, in this repo, of this exact file:

> .golangci.yml is standardized and must NEVER be modified by an agent, only manually by the user.

That is unqualified and this is the canonical copy, where the rule binds hardest. The framing in the issue body — "untouchable by policy in the consuming repos, so the fix has to land here" — assumed the restriction applied only downstream. It does not say that. So I am not committing this, and I am not opening a speculative branch either: the standing permission to build ahead of your ruling covers changes you can close and delete, not a rule that names the file and forbids the actor.

The exact change, ready to apply

In the linters.disable block, matching the existing wsl entry directly above:

    - gomodguard       # Deprecated, replaced by gomodguard_v2

gomodguard_v2 remains enabled via default: all, and no gomodguard settings are configured anywhere, so linting behaviour is unchanged. Independently corroborated during #30's implementation, which saw the warning on every run against the current canonical config.

Three ways to unblock, pick one

  1. Apply it yourself. One line. Then say so here and I will handle the sha256 recording and the propagation issue.
  2. Authorize me for this change specifically. Reply "go ahead on #25" and I will land it as the sixth commit on #34 with the same review loop as the other five.
  3. Amend the policy if the intent was always "agents may not modify it in consuming repos, but the canonical copy is maintained here" — which is what the issue's original framing assumed. That is the broader fix and would unblock this class of work permanently.

What else is waiting on it

  • The new sha256 must be recorded in this issue and in REPO_POLICIES.md. Several open issues across the fleet assert the current 021cc83f4e6fc7c31b95b34b846723dfcf20b66b7baeea1dc40406e643346bcb, and every consuming repo verifies by hash, so they all mismatch the moment this lands.
  • A propagation issue for the Go repos, separate from #35 — that one covers the Docker build-context trio and this has a different scope and blast radius.
  • Whoever implements it should also confirm zero deprecation warnings under v2.12.2, not merely that this one is gone. wsl was disabled for the same reason previously and nobody has swept the full set; three managers rediscovered gomodguard independently, which suggests the sweep has never been done.

Everything else in this cycle is complete or in review. This is the only unit that cannot proceed without you.

**BLOCKED ON OWNER AUTHORIZATION — not on analysis. Assigned to `sneak`. One line, ten seconds, but an agent may not be the one to type it.** `REPO_POLICIES.md` line 261 states, in this repo, of this exact file: > `.golangci.yml` is standardized and must _NEVER_ be modified by an agent, only manually by the user. That is unqualified and this is the canonical copy, where the rule binds hardest. The framing in the issue body — "untouchable by policy in the consuming repos, so the fix has to land here" — assumed the restriction applied only downstream. It does not say that. So I am not committing this, and I am not opening a speculative branch either: the standing permission to build ahead of your ruling covers changes you can close and delete, not a rule that names the file and forbids the actor. ## The exact change, ready to apply In the `linters.disable` block, matching the existing `wsl` entry directly above: ```yaml - gomodguard # Deprecated, replaced by gomodguard_v2 ``` `gomodguard_v2` remains enabled via `default: all`, and no `gomodguard` settings are configured anywhere, so linting behaviour is unchanged. Independently corroborated during #30's implementation, which saw the warning on every run against the current canonical config. ## Three ways to unblock, pick one 1. **Apply it yourself.** One line. Then say so here and I will handle the sha256 recording and the propagation issue. 2. **Authorize me for this change specifically.** Reply "go ahead on #25" and I will land it as the sixth commit on https://git.eeqj.de/sneak/prompts/pulls/34 with the same review loop as the other five. 3. **Amend the policy** if the intent was always "agents may not modify it in consuming repos, but the canonical copy is maintained here" — which is what the issue's original framing assumed. That is the broader fix and would unblock this class of work permanently. ## What else is waiting on it - The **new sha256 must be recorded** in this issue and in `REPO_POLICIES.md`. Several open issues across the fleet assert the current `021cc83f4e6fc7c31b95b34b846723dfcf20b66b7baeea1dc40406e643346bcb`, and every consuming repo verifies by hash, so they all mismatch the moment this lands. - A **propagation issue** for the Go repos, separate from https://git.eeqj.de/sneak/prompts/issues/35 — that one covers the Docker build-context trio and this has a different scope and blast radius. - Whoever implements it should also confirm **zero** deprecation warnings under v2.12.2, not merely that this one is gone. `wsl` was disabled for the same reason previously and nobody has swept the full set; three managers rediscovered `gomodguard` independently, which suggests the sweep has never been done. Everything else in this cycle is complete or in review. This is the only unit that cannot proceed without you.
Author
Collaborator

Speculative PR up: #47. Branch only, not merged — close it and the branch goes away.

Three corrections to what this issue and its briefs assumed:

  1. The v2 settings schema is genuinely different, not a renameallowed/blocked become flat lists of {module, version, match-type, ...}, blocked.versions folds into blocked, and local-replace-directives moves to the top level of the settings block. Irrelevant here only because the canonical config configures no gomodguard settings at all. Full table in the PR.

  2. The deprecation sweep is now complete. DeprecatedWarning appears on exactly two linters in v2.12.2: gomodguard and wsl. wsl is already disabled, so this change takes the canonical config to zero deprecated linters enabled. No others were hiding.

  3. REPO_POLICIES.md does not publish the config sha256 anywhere. The DoD item asking for it to be recorded there has nothing to update. The hash assertions live in issues and consuming repos instead.

New sha256: 9dc33938311bd7319b21585cba45052f6edb1ab4305dafcd3816abd7ffd18a5b (old: 021cc83f4e6fc7c31b95b34b846723dfcf20b66b7baeea1dc40406e643346bcb).

The PR carries a negative control proving the migrated config actually applies — a deliberately blocked module producing gomodguard_v2 findings and a non-zero exit — plus a demonstration that mistyping the settings key by one character yields a silent 0 issues. green. A passing lint alone would not have been evidence.

Note the standing policy question is unresolved: REPO_POLICIES.md line 261 forbids agents from modifying .golangci.yml, unqualified. This PR was explicitly requested, so it exists for you to rule on, but options 2 and 3 from my earlier comment (apply it yourself, or amend the policy to scope it to consuming repos) are still the durable fixes.

Speculative PR up: https://git.eeqj.de/sneak/prompts/pulls/47. Branch only, not merged — close it and the branch goes away. Three corrections to what this issue and its briefs assumed: 1. **The v2 settings schema is genuinely different, not a rename** — `allowed`/`blocked` become flat lists of `{module, version, match-type, ...}`, `blocked.versions` folds into `blocked`, and `local-replace-directives` moves to the top level of the settings block. Irrelevant here only because the canonical config configures **no** gomodguard settings at all. Full table in the PR. 2. **The deprecation sweep is now complete.** `DeprecatedWarning` appears on exactly two linters in v2.12.2: `gomodguard` and `wsl`. `wsl` is already disabled, so this change takes the canonical config to zero deprecated linters enabled. No others were hiding. 3. **`REPO_POLICIES.md` does not publish the config sha256 anywhere.** The DoD item asking for it to be recorded there has nothing to update. The hash assertions live in issues and consuming repos instead. New sha256: `9dc33938311bd7319b21585cba45052f6edb1ab4305dafcd3816abd7ffd18a5b` (old: `021cc83f4e6fc7c31b95b34b846723dfcf20b66b7baeea1dc40406e643346bcb`). The PR carries a negative control proving the migrated config actually applies — a deliberately blocked module producing `gomodguard_v2` findings and a non-zero exit — plus a demonstration that mistyping the settings key by one character yields a silent `0 issues.` green. A passing lint alone would not have been evidence. Note the standing policy question is unresolved: `REPO_POLICIES.md` line 261 forbids agents from modifying `.golangci.yml`, unqualified. This PR was explicitly requested, so it exists for you to rule on, but options 2 and 3 from my earlier comment (apply it yourself, or amend the policy to scope it to consuming repos) are still the durable fixes.
Author
Collaborator

Survey and probe results behind
#55, moved here out of the PR body.

Which recorded rejections could not ship

Each vendoring repo's go.mod was read through the API and checked against the
candidate block list. Three recorded rejections are required by at least one
repo today, so blocking them canonically would redden a repo that has done
nothing wrong on its next re-vendor:

  • github.com/mattn/go-sqlite3 — direct in bsfirehose and upaas, indirect in
    webhooker
  • gorm.io/gorm — direct in webhooker, indirect in bsfirehose
  • github.com/pmezard/go-difflib — indirect only, via testify, in dnswatcher,
    mfer, secret, upaas, vaultik and webhooker

All three were dropped. None of the four entries that did ship is required
anywhere in the fleet.

The settings block is actually applied

A mistyped settings key is silently ignored, and a config that applies nothing
is indistinguishable from a clean run. Against a Go corpus through its own
dockerized lint entrypoint at the pinned v2.12.2, the committed config plus
three temporary probe entries produced gomodguard_v2 findings and a non-zero
exit; the probe entries were then removed. Two facts fell out of the same run:

  • An exact-match entry catches a subpackage import, so blocking
    github.com/sergi/go-diff also catches .../go-diff/diffmatchpatch.
  • A module that is only an indirect requirement, never imported, produces no
    finding. That is why pmezard/go-difflib would probably have been safe to
    ship. It was dropped anyway, under the rule "required by any repo, direct or
    indirect, means drop", and it is the cheapest entry to add back later.

Caveats: golangci-lint config verify resolves its JSON schema over a live
network fetch, so its pass corroborates the schema rather than proving it. The
probe was not re-run after the rebase onto current main; that rebase changed
only the depguard conflict resolution, not the gomodguard_v2 block. This
repo has no Go code, so its own checks never execute golangci-lint against this
config.

Model: opus-5

Survey and probe results behind https://git.eeqj.de/sneak/prompts/pulls/55, moved here out of the PR body. ## Which recorded rejections could not ship Each vendoring repo's `go.mod` was read through the API and checked against the candidate block list. Three recorded rejections are required by at least one repo today, so blocking them canonically would redden a repo that has done nothing wrong on its next re-vendor: - `github.com/mattn/go-sqlite3` — direct in bsfirehose and upaas, indirect in webhooker - `gorm.io/gorm` — direct in webhooker, indirect in bsfirehose - `github.com/pmezard/go-difflib` — indirect only, via testify, in dnswatcher, mfer, secret, upaas, vaultik and webhooker All three were dropped. None of the four entries that did ship is required anywhere in the fleet. ## The settings block is actually applied A mistyped settings key is silently ignored, and a config that applies nothing is indistinguishable from a clean run. Against a Go corpus through its own dockerized lint entrypoint at the pinned v2.12.2, the committed config plus three temporary probe entries produced `gomodguard_v2` findings and a non-zero exit; the probe entries were then removed. Two facts fell out of the same run: - An exact-match entry catches a **subpackage** import, so blocking `github.com/sergi/go-diff` also catches `.../go-diff/diffmatchpatch`. - A module that is only an indirect requirement, never imported, produces no finding. That is why `pmezard/go-difflib` would probably have been safe to ship. It was dropped anyway, under the rule "required by any repo, direct or indirect, means drop", and it is the cheapest entry to add back later. Caveats: `golangci-lint config verify` resolves its JSON schema over a live network fetch, so its pass corroborates the schema rather than proving it. The probe was not re-run after the rebase onto current `main`; that rebase changed only the `depguard` conflict resolution, not the `gomodguard_v2` block. This repo has no Go code, so its own checks never execute golangci-lint against this config. Model: opus-5
Author
Collaborator

The hash-recording item in the definition of done, settled.

Recorded here, as this issue asks. Once
#55 merges, the canonical
.golangci.yml is sha256
59eaf8b924a3684baae2163d9f3903166e22774a1d147af3be3ffe0fa9d92d99, replacing
d10f47ef5e0d8620efd62275b016a7de8fd5abedf333922eec86fe4abc06176e on main
today. (The 021cc83f... in the issue body predates two later changes to the
file and is no longer the value to compare against.)

The other half — recording it in REPO_POLICIES.md "so consuming repos can
verify by hash" — is struck, not deferred, because its premise no longer holds.
Since this issue was written, #59 made
the deny list of the test-support depguard rule explicitly exempt from
byte-identity: a consuming repo names its own test-support packages there. A
correct vendored copy in any repo that uses the exemption therefore does not
hash to canonical, so a published canonical sha256 would report compliant repos
as drifted. That is the same false-verification family this issue is about, and
publishing it in the policy document would spread it to every repo at once.

What takes its place: the propagation brief
#60 carries both hashes and tells
implementers to diff against canonical and confirm the only difference is that
deny list. If an automated drift guard is still wanted, it has to hash the file
with that list normalised out — a different mechanism and a separate decision,
worth its own issue rather than a line in REPO_POLICIES.md.

Model: opus-5

**The hash-recording item in the definition of done, settled.** Recorded here, as this issue asks. Once https://git.eeqj.de/sneak/prompts/pulls/55 merges, the canonical `.golangci.yml` is sha256 `59eaf8b924a3684baae2163d9f3903166e22774a1d147af3be3ffe0fa9d92d99`, replacing `d10f47ef5e0d8620efd62275b016a7de8fd5abedf333922eec86fe4abc06176e` on `main` today. (The `021cc83f...` in the issue body predates two later changes to the file and is no longer the value to compare against.) The other half — recording it in `REPO_POLICIES.md` "so consuming repos can verify by hash" — is struck, not deferred, because its premise no longer holds. Since this issue was written, https://git.eeqj.de/sneak/prompts/pulls/59 made the `deny` list of the `test-support` `depguard` rule explicitly exempt from byte-identity: a consuming repo names its own test-support packages there. A correct vendored copy in any repo that uses the exemption therefore does not hash to canonical, so a published canonical sha256 would report compliant repos as drifted. That is the same false-verification family this issue is about, and publishing it in the policy document would spread it to every repo at once. What takes its place: the propagation brief https://git.eeqj.de/sneak/prompts/issues/60 carries both hashes and tells implementers to diff against canonical and confirm the only difference is that deny list. If an automated drift guard is still wanted, it has to hash the file with that list normalised out — a different mechanism and a separate decision, worth its own issue rather than a line in `REPO_POLICIES.md`. Model: opus-5
Author
Collaborator

Correction to the hash-recording settlement above: the new sha256 has
changed.

The 59eaf8b924a3684baae2163d9f3903166e22774a1d147af3be3ffe0fa9d92d99 recorded
earlier is stale — it predates two later changes to the block list on
#55. Once that PR merges, the canonical
.golangci.yml is sha256
a79b63a254602a5318db5d0e9a06bc71b84bf0c1d896305229d8bfed1d1b1776, replacing
d10f47ef5e0d8620efd62275b016a7de8fd5abedf333922eec86fe4abc06176e on main
today. The "The bytes" section of
#60 now carries the same value.

Everything else in that settlement stands, including striking the
REPO_POLICIES.md half of the item.

Model: opus-5

**Correction to the hash-recording settlement above: the new sha256 has changed.** The `59eaf8b924a3684baae2163d9f3903166e22774a1d147af3be3ffe0fa9d92d99` recorded earlier is stale — it predates two later changes to the block list on https://git.eeqj.de/sneak/prompts/pulls/55. Once that PR merges, the canonical `.golangci.yml` is sha256 `a79b63a254602a5318db5d0e9a06bc71b84bf0c1d896305229d8bfed1d1b1776`, replacing `d10f47ef5e0d8620efd62275b016a7de8fd5abedf333922eec86fe4abc06176e` on `main` today. The "The bytes" section of https://git.eeqj.de/sneak/prompts/issues/60 now carries the same value. Everything else in that settlement stands, including striking the `REPO_POLICIES.md` half of the item. Model: opus-5
sneak closed this issue 2026-09-09 14:04:20 +02:00
Sign in to join this conversation.
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: sneak/prompts#25