dunn.dev/pipeline 4.1.0

Minor: additive plus fixes. No input removed or renamed, no existing default
behaviour changed. Consumers pick this up by bumping their component pins.

Added
- model-id-drift (new, opt-in): fails when a consumer's tracked working tree
  carries a hardcoded claude-(opus|sonnet|haiku) major below the declared
  current_ga_major (default "5"). No network access; pure regex over the
  already-checked-out tree. No repo is auto-enrolled. There is no Renovate
  datasource for Claude model ids, so a hardcoded id rots invisibly --
  confirmed stale on dunn.dev/pi and dunn.dev/skald.md while Opus 5 was GA.
- ci-go bakes osv-scanner, ci bakes hadolint (both checksum-verified release
  binaries). osv-verdict now runs on ci-go, so the gate binary is no longer
  fetched fresh on every MR across the estate.

Changed -- renovate-config preset
- go.mod indirect dependencies now propose an MR only when they carry an
  active OSV/GHSA alert (security:gomodIndirectSecurityUpdates). Surfaced by
  bairn's kin-openapi indirect dep needing a hand-diagnosed fix.
- Internal-artifact MAJORs exempt from minimumReleaseAge; automerge stays
  false (age delay and human review are separate knobs). Closed two coverage
  gaps while widening: the bare-catalog depName form was never matched, and
  the gitlab-releases exemption is now scoped by package name so it no longer
  silently covered upstream gitlab-org/cli.
- mergeConfidence:all-badges, display-only, for the human majors-review queue.
- minimumReleaseAge:null for four evidenced timestamp-less packages (envoy via
  mirror.gcr.io, two immich images, @dunn.dev/reference on GitLab's npm
  registry) -- a strand fix by exact package name, with explicit
  automerge:false, not a registry-wide trust exemption.

Fixed -- osv-verdict
- Go call analysis runs for real now that the job is on ci-go. The gate blocks
  on called=true or called=unknown; a finding call analysis proves unreachable
  is still logged and kept in the artifact, just not gate-blocking.
- Default-branch pushes diff against CI_COMMIT_BEFORE_SHA instead of
  full-scanning, closing the green-MR-then-red-main asymmetry.
- The MR diff base was a silent no-op: git stash swept up the untracked
  head-scan outputs and nothing ever popped it, so the verdict was pass
  regardless of whether a new finding existed. Fail-open under a fail-closed
  gate, on every diff-mode run. Head scan outputs now survive outside the tree.

Fixed -- automerge-gate, osv-verdict
- Both jobs now instantiate on a bare branch pipeline with no open MR yet. The
  prior rules matched only merge_request_event or the default branch; audited
  across 97 consumer projects, ~25 had zero gate coverage in exactly that gap,
  where the job never emitted and needs:optional read absent rather than
  failed.
- The clause shipped in a two-rule form and was then consolidated to one
  (CI_COMMIT_BRANCH && CI_OPEN_MERGE_REQUESTS == null). That is a
  simplification, not a behaviour change -- both forms render identically.

Verified pre-tag: a synthetic consumer POSTed to ci/lint at three refs with
components pinned by SHA, carrying probes that prove the rendered variable
context. Gate jobs instantiate on a no-MR branch, are correctly suppressed on
a branch with an open MR, and main is unchanged. A grandparent control at the
commit before the branch clause existed confirms the harness discriminates:
the gate jobs are absent there on the same ref and present after.

Also: baked tool versions advanced (cosign 3.1.2, syft 1.49.0, just 1.57.0;
ci-iac uv 0.11.32, sops 3.13.3), image ARG and template spec-input default
moving in lockstep.