diff --git a/.clinerules/tech.md b/.clinerules/tech.md index a521fc367..63049b5ae 100644 --- a/.clinerules/tech.md +++ b/.clinerules/tech.md @@ -5,7 +5,7 @@ ## Primary -- **Go 1.26+**, statically linked (`CGO_ENABLED=0`). The `ctx` +- **Go 1.27+**, statically linked (`CGO_ENABLED=0`). The `ctx` binary is the entire deliverable for the core; everything else ships as embedded bytes inside it. - **Cobra** for the CLI command surface. diff --git a/.context/steering/tech.md b/.context/steering/tech.md index 3281ee511..5dc366954 100644 --- a/.context/steering/tech.md +++ b/.context/steering/tech.md @@ -9,7 +9,7 @@ priority: 10 ## Primary -- **Go 1.26+**, statically linked (`CGO_ENABLED=0`). The `ctx` +- **Go 1.27+**, statically linked (`CGO_ENABLED=0`). The `ctx` binary is the entire deliverable for the core; everything else ships as embedded bytes inside it. - **Cobra** for the CLI command surface. diff --git a/.cursor/rules/tech.mdc b/.cursor/rules/tech.mdc index 42f17dfe5..41523c317 100644 --- a/.cursor/rules/tech.mdc +++ b/.cursor/rules/tech.mdc @@ -8,7 +8,7 @@ alwaysApply: true ## Primary -- **Go 1.26+**, statically linked (`CGO_ENABLED=0`). The `ctx` +- **Go 1.27+**, statically linked (`CGO_ENABLED=0`). The `ctx` binary is the entire deliverable for the core; everything else ships as embedded bytes inside it. - **Cobra** for the CLI command surface. diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 817b18d41..7d3d29bf5 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -20,7 +20,7 @@ jobs: - name: Set up Go uses: actions/setup-go@v7 with: - go-version: '1.26' + go-version: '1.27' - name: Build run: CGO_ENABLED=0 go build ./... @@ -59,14 +59,20 @@ jobs: - name: Set up Go uses: actions/setup-go@v7 with: - go-version: '1.26' + go-version: '1.27' - name: Run golangci-lint uses: golangci/golangci-lint-action@v9 with: - version: v2.11.4 + version: v2.13.2 args: --timeout=5m + - name: Check Go toolchain version sync + run: make check-go-version + + - name: Check steering outputs freshness + run: make check-steering + typecheck-opencode-plugin: name: Typecheck OpenCode plugin runs-on: ubuntu-latest diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 5e4bd92cd..60adc0d63 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -21,7 +21,7 @@ jobs: - name: Set up Go uses: actions/setup-go@v7 with: - go-version: '1.26' + go-version: '1.27' - name: Run tests run: CGO_ENABLED=0 go test ./... @@ -54,7 +54,7 @@ jobs: - name: Set up Go uses: actions/setup-go@v7 with: - go-version: '1.26' + go-version: '1.27' - name: Test run: CGO_ENABLED=0 go test -v ./... diff --git a/.kiro/steering/tech.md b/.kiro/steering/tech.md index 60acc7e03..42b8a13de 100644 --- a/.kiro/steering/tech.md +++ b/.kiro/steering/tech.md @@ -8,7 +8,7 @@ mode: always ## Primary -- **Go 1.26+**, statically linked (`CGO_ENABLED=0`). The `ctx` +- **Go 1.27+**, statically linked (`CGO_ENABLED=0`). The `ctx` binary is the entire deliverable for the core; everything else ships as embedded bytes inside it. - **Cobra** for the CLI command surface. diff --git a/Makefile b/Makefile index b85bdfca0..881f638fc 100644 --- a/Makefile +++ b/Makefile @@ -6,7 +6,7 @@ clean all release build-all help \ test-coverage smoke site site-guard site-feed site-serve site-serve-lan site-setup audit check plugin-reload \ journal journal-serve journal-serve-lan gpg-fix gpg-test register-mcp reinstall check-tools \ -sync-version check-version-sync sync-why check-why sync-copilot-skills check-copilot-skills sync-codex-skills check-codex-skills codex-plugin-install sync-opencode-skills check-opencode-skills sync-pi-skills check-pi-skills sync-steering check-steering gemini-search \ +sync-version check-version-sync check-go-version sync-why check-why sync-copilot-skills check-copilot-skills sync-codex-skills check-codex-skills codex-plugin-install sync-opencode-skills check-opencode-skills sync-steering check-steering gemini-search \ gitnexus-version gitnexus-update gitnexus-index gitnexus-mcp strip-gitnexus install-ctxctl reinstall-ctxctl # Default binary name and output @@ -175,6 +175,8 @@ audit: fi @echo "==> Checking version sync..." @$(MAKE) --no-print-directory check-version-sync + @echo "==> Checking Go toolchain version sync..." + @$(MAKE) --no-print-directory check-go-version @echo "==> Checking why docs freshness..." @$(MAKE) --no-print-directory check-why @echo "==> Checking Copilot skills freshness..." @@ -398,6 +400,10 @@ check-version-sync: fi; \ echo "Version sync OK ($$V)." +## check-go-version: Verify every Go toolchain pin agrees with the go.mod directive +check-go-version: + @./hack/check-go-version.sh + ## sync-copilot-skills: Sync Copilot CLI skills from canonical ctx skills sync-copilot-skills: @./hack/sync-copilot-skills.sh @@ -432,14 +438,23 @@ sync-steering: @CGO_ENABLED=0 go run ./cmd/ctx steering sync --all ## check-steering: Verify tracked steering outputs match .context/steering source +# Snapshot-then-regenerate (same shape as check-copilot-skills): compares +# the working-tree outputs against a fresh sync, not against HEAD, so an +# uncommitted-but-consistent source/output pair passes locally. check-steering: - @CGO_ENABLED=0 go run ./cmd/ctx steering sync --all > /dev/null - @if ! git diff --quiet -- .cursor .clinerules .kiro/steering; then \ + @TMPDIR=$$(mktemp -d) && \ + mkdir -p "$$TMPDIR/before" "$$TMPDIR/after" && \ + cp -r .cursor/rules .clinerules .kiro/steering "$$TMPDIR/before/" && \ + CGO_ENABLED=0 go run ./cmd/ctx steering sync --all > /dev/null && \ + cp -r .cursor/rules .clinerules .kiro/steering "$$TMPDIR/after/" && \ + if ! diff -rq "$$TMPDIR/before" "$$TMPDIR/after" > /dev/null 2>&1; then \ echo "FAIL: steering outputs are stale — run 'make sync-steering' and commit"; \ - git --no-pager diff --stat -- .cursor .clinerules .kiro/steering; \ + diff -rq "$$TMPDIR/before" "$$TMPDIR/after" || true; \ + rm -rf "$$TMPDIR"; \ exit 1; \ - fi - @echo "Steering outputs are in sync." + fi; \ + rm -rf "$$TMPDIR"; \ + echo "Steering outputs are in sync." ## check-copilot-skills: Verify Copilot CLI skills match ctx source skills check-copilot-skills: diff --git a/go.mod b/go.mod index 61fa5f4f9..44e961faf 100644 --- a/go.mod +++ b/go.mod @@ -1,6 +1,6 @@ module github.com/ActiveMemory/ctx -go 1.26.3 +go 1.27.1 require ( github.com/hashicorp/raft v1.8.0 diff --git a/go.work b/go.work index d8529f0e5..506dd3891 100644 --- a/go.work +++ b/go.work @@ -1,4 +1,4 @@ -go 1.26.3 +go 1.27.1 // ctx (the shipped user binary) and tools/ctxctl (maintainer-only) // are separate modules. ctx never requires tools/ctxctl, so it can diff --git a/go.work.sum b/go.work.sum index 75101a70b..5c917984d 100644 --- a/go.work.sum +++ b/go.work.sum @@ -24,6 +24,7 @@ github.com/circonus-labs/circonusllhist v0.1.3 h1:TJH+oke8D16535+jHExHj4nQvzlZrj github.com/cncf/xds/go v0.0.0-20260202195803-dba9d589def2 h1:aBangftG7EVZoUb69Os8IaYg++6uMOdKK83QtkkvJik= github.com/cncf/xds/go v0.0.0-20260202195803-dba9d589def2/go.mod h1:qwXFYgsP6T7XnJtbKlf1HP8AjxZZyzxMmc+Lq5GjlU4= github.com/cpuguy83/go-md2man/v2 v2.0.6 h1:XJtiaUW6dEEqVuZiMTn1ldk455QWwEIsMIJlo5vtkx0= +github.com/creack/pty v1.1.9 h1:uDmaGzcdjhF4i/plgjmEsriH11Y0o7RKapEf/LDaM3w= github.com/davecgh/go-xdr v0.0.0-20161123171359-e6a2ba005892 h1:qg9VbHo1TlL0KDM0vYvBG9EY0X0Yku5WYIPoFWt8f6o= github.com/davecgh/go-xdr v0.0.0-20161123171359-e6a2ba005892/go.mod h1:CTDl0pzVzE5DEzZhPfvhY/9sPFMQIxaJ9VAMs9AagrE= github.com/envoyproxy/go-control-plane v0.14.0 h1:hbG2kr4RuFj222B6+7T83thSPqLjwBIfQawTkC++2HA= @@ -74,6 +75,7 @@ github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjY github.com/mwitkow/go-conntrack v0.0.0-20190716064945-2f068394615f h1:KUppIJq7/+SVif2QVs3tOP0zanoHgBEVAwHxUSIzRqU= github.com/philhofer/fwd v1.1.2 h1:bnDivRJ1EWPjUIRXV5KfORO897HTbpFAQddBdE8t7Gw= github.com/philhofer/fwd v1.1.2/go.mod h1:qkPdfjR2SIEbspLqpe1tO4n5yICnr2DY7mqEx2tUTP0= +github.com/pkg/diff v0.0.0-20210226163009-20ebb0f2a09e h1:aoZm08cpOy4WuID//EZDgcC4zIxODThtZNPirFr42+A= github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= github.com/planetscale/vtprotobuf v0.6.1-0.20240319094008-0393e58bdf10 h1:GFCKgmp0tecUJ0sJuv4pzYCqS9+RGSn52M3FUwPs+uo= github.com/planetscale/vtprotobuf v0.6.1-0.20240319094008-0393e58bdf10/go.mod h1:t/avpk3KcrXxUnYOhZhMXJlSEyie6gQbtLq5NM3loB8= @@ -91,6 +93,8 @@ github.com/spiffe/go-spiffe/v2 v2.6.0/go.mod h1:gm2SeUoMZEtpnzPNs2Csc0D/gX33k1xI github.com/spiffe/go-spiffe/v2 v2.7.0 h1:uXe1MflJoHw58wAUvxVlcM7WpKtijWG7I1UidcGh6g4= github.com/spiffe/go-spiffe/v2 v2.7.0/go.mod h1:47Q0Q9/AqGha8QLHp+kxpH4Wca7X7EnOtlIJy3mxZ3U= github.com/stretchr/objx v0.1.1 h1:2vfRuCMp5sSVIDSqO8oNnWJq7mPa6KVP3iPIwFBuy8A= +github.com/stretchr/objx v0.5.2 h1:xuMeJ0Sdp5ZMRXx/aWO6RZxdr3beISkG5/G/aIRr3pY= +github.com/stretchr/objx v0.5.2/go.mod h1:FRsXN1f5AsAjCGJKqEizvkpNtU+EGNCLh3NxZ/8L+MA= github.com/tinylib/msgp v1.1.8 h1:FCXC1xanKO4I8plpHGH2P7koL/RzZs12l/+r7vakfm0= github.com/tinylib/msgp v1.1.8/go.mod h1:qkpG+2ldGg4xRFmx+jfTvZPxfGFhi64BcnL9vkCm/Tw= github.com/tv42/httpunix v0.0.0-20150427012821-b75d8614f926 h1:G3dpKMzFDjgEh2q1Z7zUUtKa8ViPtH+ocF0bE0g00O8= @@ -109,6 +113,8 @@ golang.org/x/crypto v0.53.0 h1:QZ4Muo8THX6CizN2vPPd5fBGHyogrdK9fG4wLPFUsto= golang.org/x/crypto v0.53.0/go.mod h1:DNLU434OwVakk9PzuwV8w62mAJpRJL3vsgcfp4Qnsio= golang.org/x/crypto v0.55.0 h1:+KWHjbgOaAQ66dh/YlkZKHlz9ZUlq61AFirAR9ntP8M= golang.org/x/crypto v0.55.0/go.mod h1:uq0V9dE/fzQuJtbnL+2EhWOE63vo164FY8xqEnV9xis= +golang.org/x/crypto v0.57.0 h1:3ZVCjf8Ggz7zneR/EHRVx68Ctf+2pmIMP2UFhh9cC6M= +golang.org/x/crypto v0.57.0/go.mod h1:Fdz0i5U6CoizGwLda9DttjSk6qlZo25zYNtR+ycvuZA= golang.org/x/mod v0.37.0 h1:vF1DjpVEshcIqoEaauuHebaLk1O1forxjxBaVn884JQ= golang.org/x/mod v0.37.0/go.mod h1:m8S8VeM9r4dzDwjrKO0a1sZP3YjeMamRRlD+fmR2Q/0= golang.org/x/net v0.56.0 h1:Rw8j/hFzGvJUZwNBXnAtf5sVDVt+65SK2C7IxCxZt5o= @@ -125,12 +131,16 @@ golang.org/x/telemetry v0.0.0-20260625142307-59b4966ccb57 h1:nwGZBCt+FnXUrGsj5vj golang.org/x/telemetry v0.0.0-20260625142307-59b4966ccb57/go.mod h1:3AWMyWHS+caVoiEXpiq6+tzKA40J4vQT3MYr80ZtQpc= golang.org/x/telemetry v0.0.0-20260811182544-a038080d80e5 h1:ZUSxONxc981v7AW7QUg+I9WwZzSTTJ019ENBYr5pV/Q= golang.org/x/telemetry v0.0.0-20260811182544-a038080d80e5/go.mod h1:LVehoXe41cL5SCVQilsV7Gg6BNG+Js6P9PhSbYTIUkQ= +golang.org/x/telemetry v0.0.0-20260908163034-4bcc4b2ee518 h1:F5BWKvW126NXR74uxkxuc1jQHhm/rwm/J3rSiFyuRs4= +golang.org/x/telemetry v0.0.0-20260908163034-4bcc4b2ee518/go.mod h1:i+ivNqjDnTF3WTElsdk5g9V5DTSBYgdNo7xTU9SDwYA= golang.org/x/term v0.43.0 h1:S4RLU2sB31O/NCl+zFN9Aru9A/Cq2aqKpTZJ6B+DwT4= golang.org/x/term v0.43.0/go.mod h1:lrhlHNdQJHO+1qVYiHfFKVuVioJIheAc3fBSMFYEIsk= golang.org/x/term v0.44.0 h1:0rLvDRCtNj0gZkyIXhCyOb2OAzEhLVqc4B+hrsBhrmc= golang.org/x/term v0.44.0/go.mod h1:7ze4MdzUzLXpSAoFP1H0bOI9aXDqveSvatT5vKcFh2Y= golang.org/x/term v0.45.0 h1:NwWyBmoJCbfTHpxrWoZ9C6/VxOf7ic219I8xZZFdrf0= golang.org/x/term v0.45.0/go.mod h1:9aqxs0blBcrm/n0L9QW0aRVD+ktan8ssZromtqJC43w= +golang.org/x/term v0.46.0 h1:3+OXuTbaKDgwk8jTi3aSLHRlmWqHEUDUtxnbFigO4YE= +golang.org/x/term v0.46.0/go.mod h1:+K02xbkittuwc0Am4abfA3Fc+XRGXkvBXNO88NCXPoc= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543 h1:E7g+9GITq07hpfrRu66IVDexMakfv52eLZ2CXBWiKr4= google.golang.org/appengine v1.6.7 h1:FZR1q0exgwxzPzp/aF+VccGrSfxfPpkBqjIIEq3ru6c= google.golang.org/appengine v1.6.7/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc= diff --git a/hack/check-go-version.sh b/hack/check-go-version.sh new file mode 100755 index 000000000..5f3dfa869 --- /dev/null +++ b/hack/check-go-version.sh @@ -0,0 +1,96 @@ +#!/usr/bin/env bash +# / ctx: https://ctx.ist +# ,'`./ do you remember? +# `.,'\ +# \ Copyright 2026-present Context contributors. +# SPDX-License-Identifier: Apache-2.0 + + +# check-go-version.sh — one Go version, many pins, zero drift. +# +# The `go` directive in the root go.mod is the single source of truth. +# Every other place the toolchain version is written down must agree +# with it, or a hurried bump ships a stale pin: +# +# exact (major.minor.patch must match go.mod): +# go.work +# tools/ctxctl/go.mod +# floor (major.minor must match go.mod): +# .github/workflows/*.yml every `go-version:` pin +# hack/tool-versions.txt the `go bin required ` row +# .context/steering/tech.md the "**Go X.Y+**" prose (tool-native +# copies are covered by `make check-steering`) +# +# Portable: bash 3.2 + BSD awk/grep (see specs/hack-script-portability.md). +# +# Exit code: number of mismatches (0 = clean). + +set -euo pipefail + +ROOT="$(cd "$(dirname "$0")/.." && pwd)" +cd "$ROOT" + +issues=0 + +fail() { + echo "FAIL: $1" + issues=$((issues + 1)) +} + +# First `go ` directive in a go.mod / go.work file. +go_directive() { + awk '$1 == "go" { print $2; exit }' "$1" +} + +FULL="$(go_directive go.mod)" +if [ -z "$FULL" ]; then + echo "FAIL: no 'go' directive in go.mod" >&2 + exit 1 +fi +MINOR="$(printf '%s\n' "$FULL" | awk -F. '{ print $1 "." $2 }')" + +# --- exact pins ----------------------------------------------------------- + +for f in go.work tools/ctxctl/go.mod; do + got="$(go_directive "$f")" + if [ "$got" != "$FULL" ]; then + fail "$f: go $got != go.mod $FULL" + fi +done + +# --- floor pins ----------------------------------------------------------- + +# Workflows: every go-version pin, quoted or bare. +found=0 +for wf in .github/workflows/*.yml; do + while IFS= read -r line; do + found=$((found + 1)) + got="$(printf '%s\n' "$line" | sed -e "s/.*go-version:[[:space:]]*//" -e "s/['\"]//g" -e 's/[[:space:]]*$//')" + if [ "$got" != "$MINOR" ]; then + fail "$wf: go-version '$got' != go.mod $MINOR" + fi + done < <(grep -E '^[[:space:]]*go-version:' "$wf" || true) +done +if [ "$found" -eq 0 ]; then + fail ".github/workflows: no go-version pins found (grep pattern drifted?)" +fi + +# Tool manifest: the go row's minimum. +got="$(awk '$1 == "go" && $2 == "bin" { print $4; exit }' hack/tool-versions.txt)" +if [ "$got" != "$MINOR" ]; then + fail "hack/tool-versions.txt: go minimum '$got' != go.mod $MINOR" +fi + +# Steering source prose: "**Go X.Y+**". +got="$(grep -o -E 'Go [0-9]+\.[0-9]+\+' .context/steering/tech.md | head -1 | sed -e 's/^Go //' -e 's/+$//')" +if [ "$got" != "$MINOR" ]; then + fail ".context/steering/tech.md: 'Go ${got:-?}+' != go.mod $MINOR" +fi + +# --- verdict -------------------------------------------------------------- + +if [ "$issues" -gt 0 ]; then + echo "Go version drift: $issues mismatch(es) — go.mod says $FULL; align the sites above." + exit "$issues" +fi +echo "Go version sync OK ($FULL / floor $MINOR)." diff --git a/hack/check-tools.sh b/hack/check-tools.sh index 96dc3552e..af3875f4a 100755 --- a/hack/check-tools.sh +++ b/hack/check-tools.sh @@ -76,7 +76,7 @@ with_timeout() { fi } -# First dotted-number token in a version banner ("go1.26.3", +# First dotted-number token in a version banner ("go1.27.1", # "v24.18.0", "jq-1.7.1" all yield the bare number). extract_version() { grep -oE '[0-9]+(\.[0-9]+)+' | head -1 diff --git a/hack/tool-versions.txt b/hack/tool-versions.txt index b74bd3fea..6e0f44c3d 100644 --- a/hack/tool-versions.txt +++ b/hack/tool-versions.txt @@ -10,7 +10,9 @@ # Version minimums live here so bumps are one-line diffs. # Build / lint core — the check fails without these. -go bin required 1.26 +# The go minimum must match the go.mod directive's major.minor; +# hack/check-go-version.sh (make check-go-version) enforces it. +go bin required 1.27 git bin required - golangci-lint bin required - diff --git a/specs/check-tools.md b/specs/check-tools.md index 7807586b0..704b929a3 100644 --- a/specs/check-tools.md +++ b/specs/check-tools.md @@ -60,7 +60,7 @@ Three pieces: | Manifest value | Semantics | Below | Above | |----------------|-----------|-------|----------| -| `1.26` | minimum | `OUTDATED` | `OK` | +| `1.27` | minimum | `OUTDATED` | `OK` | | `=0.0.51` | exact pin | `OUTDATED` | `DRIFT` | | `-` | presence | — | — | diff --git a/specs/go-version-sync.md b/specs/go-version-sync.md new file mode 100644 index 000000000..1b2b6c5eb --- /dev/null +++ b/specs/go-version-sync.md @@ -0,0 +1,102 @@ +# Go Toolchain Version Sync + +The Go version is written down in eight tracked places. A bump is +a hand-edit of each one, and nothing cross-checked them, so a +hurried bump could leave a stale pin behind and ship it silently. +This spec names the single source of truth, enumerates every +dependent site, and adds a gate that fails when any site disagrees. + +## Problem + +The Go 1.26 → 1.27 bump (2026-09) touched thirteen files. The +working-tree diff updated the steering source and two of its three +tool-native copies, but `.cursor/rules/tech.mdc` still said +`Go 1.26+`. `make check-steering` would have caught that one, but +only if someone ran `make audit`; CI did not run it. And no check +of any kind tied the remaining sites together: + +| Site | Kind | What it pins | +|-----------------------------------|-------|-------------------------| +| `go.mod` | exact | `go 1.27.1` (source) | +| `go.work` | exact | must equal `go.mod` | +| `tools/ctxctl/go.mod` | exact | must equal `go.mod` | +| `.github/workflows/ci.yml` | floor | two `go-version` pins | +| `.github/workflows/release.yml` | floor | two `go-version` pins | +| `hack/tool-versions.txt` | floor | `go bin required 1.27` | +| `.context/steering/tech.md` | floor | `**Go 1.27+**` prose | +| `.cursor`, `.clinerules`, `.kiro` | floor | generated from steering | + +The only version-consistency check in the repo, +`make check-version-sync`, covers `VERSION` against the plugin +manifests. It knows nothing about the toolchain. + +## Source of Truth + +The `go` directive in the root `go.mod`. It is the value the Go +toolchain itself enforces, `go mod tidy` maintains it, and every +other site is downstream of it. Its `major.minor` is the *floor* +the other sites must state; its full `major.minor.patch` is what +the workspace and the ctxctl module must repeat exactly. + +## Gate + +`hack/check-go-version.sh`, exposed as `make check-go-version`: + +1. Read the `go` directive from `go.mod`; derive the floor. +2. **Exact:** `go.work` and `tools/ctxctl/go.mod` directives must + equal the full version. +3. **Floor:** every `go-version:` pin in `.github/workflows/*.yml`, + the `go bin required ` row in `hack/tool-versions.txt`, and + the first `Go X.Y+` token in `.context/steering/tech.md` must + equal the floor. Finding zero workflow pins is itself a failure, + so a renamed key cannot silently blind the check. +4. Print one `FAIL:` line per mismatch naming the site and both + values; exit with the mismatch count. + +Tool-native steering copies are not re-checked here. They are +generated, and `make check-steering` already fails when they +diverge from the source. Checking the source is sufficient. + +The script is bash 3.2 and BSD awk/grep clean, per +`specs/hack-script-portability.md`. + +## Wiring + +- `make audit` runs `check-go-version` right after + `check-version-sync`. +- The CI `lint` job runs `make check-go-version` **and** + `make check-steering`. The steering gate existed but was + local-only; the failure that motivated this spec is exactly the + kind that reaches a PR from an agent that skipped `make audit`. +- `check-steering` now snapshots the tool-native outputs, regenerates, + and diffs snapshot against regenerated (the `check-copilot-skills` + shape). It used to diff against `HEAD`, so it failed on any + uncommitted steering change even when source and outputs agreed, + which made `make audit` unpassable in the middle of a bump. + +## Bump Procedure + +1. Change the `go` directive in `go.mod` (and let `go mod tidy` + settle `go.sum`). +2. Run `make check-go-version`; fix each `FAIL:` line it prints. +3. Run `make sync-steering` if the steering prose changed. +4. Run `make audit`; commit everything together citing this spec. + +## Non-Goals + +- Example values in prose, such as the `1.27` row in the + `specs/check-tools.md` scenario table or the version banner + sample in a `hack/check-tools.sh` comment. They illustrate + output shape; a stale example there misleads no tool. +- `golangci-lint` or other action pins in the workflows. Those + have one site each and nothing to drift against. +- Rewriting the check in Go. The sibling `hack/lint-*.sh` gates + are shell for the same reason: they are grep-shaped checks over + text files, and `make audit` already assumes a POSIX shell. + +## See Also + +- `specs/check-tools.md` — the manifest whose `go` row this gate + reads. +- `specs/steering-sync-drift-respects-configured-tools.md` — the + `check-steering` gate this spec promotes into CI. diff --git a/tools/ctxctl/go.mod b/tools/ctxctl/go.mod index 00e036269..410edaf05 100644 --- a/tools/ctxctl/go.mod +++ b/tools/ctxctl/go.mod @@ -1,6 +1,6 @@ module github.com/ActiveMemory/ctx/tools/ctxctl -go 1.26.3 +go 1.27.1 require ( github.com/ActiveMemory/ctx v0.0.0