Skip to content

Commit 446f2c0

Browse files
chore: refresh checksums and converge the limen baseline
Signed-off-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
1 parent 5d75fbc commit 446f2c0

5 files changed

Lines changed: 226 additions & 18 deletions

File tree

‎.aqua/aqua-checksums.json‎

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -46,28 +46,28 @@
4646
"algorithm": "sha256"
4747
},
4848
{
49-
"id": "github_release/github.com/farcloser/limen/v0.8.0/limen_0.8.0_darwin_arm64.tar.gz",
50-
"checksum": "E73ED78C7076867ACE43D7EBC1A1254CCAE50D5992095B405CAD7F2F10787B89",
49+
"id": "github_release/github.com/farcloser/limen/v0.9.0/limen_0.9.0_darwin_arm64.tar.gz",
50+
"checksum": "BB92510A0019EE03BC520C58528EE828D108BD9D15279FA26F5BE99E23D53FCE",
5151
"algorithm": "sha256"
5252
},
5353
{
54-
"id": "github_release/github.com/farcloser/limen/v0.8.0/limen_0.8.0_linux_amd64.tar.gz",
55-
"checksum": "63A637D15AB78CE8C1ED4CC64CBEE419E467BAADB4FF290C04228D106B0BFF22",
54+
"id": "github_release/github.com/farcloser/limen/v0.9.0/limen_0.9.0_linux_amd64.tar.gz",
55+
"checksum": "7828CCC8019C6E7E582A16E9D29BB9A00F8F00F73A7B95005597129121AFCB1B",
5656
"algorithm": "sha256"
5757
},
5858
{
59-
"id": "github_release/github.com/farcloser/limen/v0.8.0/limen_0.8.0_linux_arm64.tar.gz",
60-
"checksum": "E2D2BB0DE0D81092D2D590DAB80E71979A0EA883E5F81A3DF59F034703F4E0ED",
59+
"id": "github_release/github.com/farcloser/limen/v0.9.0/limen_0.9.0_linux_arm64.tar.gz",
60+
"checksum": "845F202D468F23ED2FF4D8BA7E2B3328F98B40AD555B5C651F223F568065C9B7",
6161
"algorithm": "sha256"
6262
},
6363
{
64-
"id": "github_release/github.com/farcloser/limen/v0.8.0/limen_0.8.0_windows_amd64.tar.gz",
65-
"checksum": "9FF90A269A63C6739FD1AB73FD5262BB98D36145916E0D28D3E873453BDD6D57",
64+
"id": "github_release/github.com/farcloser/limen/v0.9.0/limen_0.9.0_windows_amd64.tar.gz",
65+
"checksum": "250B810AC310B3A4083BB589BDB694512FB4CBD2E172B8DE000AAD698DDEB99C",
6666
"algorithm": "sha256"
6767
},
6868
{
69-
"id": "github_release/github.com/farcloser/limen/v0.8.0/limen_0.8.0_windows_arm64.tar.gz",
70-
"checksum": "EF61BC2AD757370C00AD313F2BBD247D7847E8C1A1F8E14FB72EBBCB19FEB12A",
69+
"id": "github_release/github.com/farcloser/limen/v0.9.0/limen_0.9.0_windows_arm64.tar.gz",
70+
"checksum": "2DA4558D67D975137800E35005374A3523F79F2D70D19A9FFAC47B75E73A9874",
7171
"algorithm": "sha256"
7272
},
7373
{
Lines changed: 198 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,198 @@
1+
# DO NOT EDIT MANUALLY: content-pinned by limen, reset by `limen fix`.
2+
# The shared CI lanes every repository runs, called from its own ci.yaml
3+
# (`uses: ./.github/workflows/limen-verify.yaml`). A change here reaches every
4+
# repository with its limen bump; the project's own jobs live in its ci.yaml.
5+
#
6+
# Minimal glue: GitHub's own actions pinned by SHA, aqua at .aqua/aqua.yaml's
7+
# pins, `just` running the recipes a laptop runs. No third-party actions,
8+
# hence no egress-filtering action either.
9+
name: limen-verify
10+
11+
on:
12+
workflow_call:
13+
inputs:
14+
os:
15+
# Pinned images, never -latest. macOS is not redundant: its /bin/bash
16+
# is 3.2, the floor the recipes target. Both windows legs run under
17+
# git-bash. These names are NOT the ruleset's required contexts (the
18+
# caller's `gate` is), so a project may trim or extend the list.
19+
description: The verify matrix's runners, as a JSON list.
20+
type: string
21+
default: '["ubuntu-24.04", "ubuntu-24.04-arm", "macos-15", "windows-2025", "windows-11-arm"]'
22+
23+
# No default token permissions: each job states what it needs, within what
24+
# the caller grants (contents: read).
25+
permissions: {}
26+
27+
# Explicit bash everywhere: windows defaults to PowerShell and never sees
28+
# git-bash's environment; explicit bash also brings -eo pipefail.
29+
defaults:
30+
run:
31+
shell: bash
32+
33+
jobs:
34+
verify:
35+
strategy:
36+
fail-fast: false
37+
matrix:
38+
os: ${{ fromJSON(inputs.os) }}
39+
runs-on: ${{ matrix.os }}
40+
# Generous for the windows legs, which are markedly slower.
41+
timeout-minutes: 45
42+
permissions:
43+
contents: read
44+
steps:
45+
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
46+
with:
47+
# The token is not left behind in .git/config: nothing in this
48+
# workflow talks to GitHub after checkout.
49+
persist-credentials: false
50+
# Full history and refs: `just do lint commits` validates the commit
51+
# range against the PR's base branch, which a shallow clone lacks.
52+
fetch-depth: 0
53+
54+
# Windows keeps every cache below in one disk image, cached as a single
55+
# file: restored as files, they cost minutes of small-file writes there.
56+
# Before setup-aqua, which takes the AQUA_ROOT_DIR it sets; the hash is
57+
# taken here because hashFiles cannot walk into the attached image.
58+
- id: image
59+
if: runner.os == 'Windows'
60+
uses: ./.github/actions/windows-cache-image
61+
with:
62+
mode: attach
63+
prefix: win-image-${{ runner.os }}-${{ runner.arch }}-
64+
hash: ${{ hashFiles('.aqua/aqua.yaml', '.aqua/aqua-checksums.json', '.limen/aqua.yaml', '.limen/aqua-registry.yaml', '**/go.sum') }}
65+
66+
- name: Install aqua (pinned, checksum-verified)
67+
uses: ./.github/actions/setup-aqua
68+
69+
# aqua's package store, keyed on the exact pins and per architecture
70+
# (the store holds native binaries). A warm store turns every lazy first
71+
# use below into a link; the fallback key keeps the tools a pin bump did
72+
# not touch, and the changed one downloads and verifies as before.
73+
- if: runner.os != 'Windows'
74+
uses: actions/cache@55cc8345863c7cc4c66a329aec7e433d2d1c52a9 # v6.1.0
75+
with:
76+
path: ${{ env.AQUA_ROOT_DIR }}/pkgs
77+
key: aqua-pkgs-${{ runner.os }}-${{ runner.arch }}-${{ hashFiles('.aqua/aqua.yaml', '.aqua/aqua-checksums.json', '.limen/aqua-registry.yaml') }}
78+
restore-keys: |
79+
aqua-pkgs-${{ runner.os }}-${{ runner.arch }}-
80+
81+
- name: Install pinned tools
82+
# Link-only: tools download lazily on first use, checksum-verified; a
83+
# job pays only for what its recipes run.
84+
run: aqua install --only-link
85+
86+
# The Go build and module caches, plus the linter's (build/cache/, see
87+
# main.just). The per-platform analysis legs compile the whole module
88+
# graph five times, cold, on every run without this. Paths come from the
89+
# pinned go itself — they differ per OS — and the key carries its version
90+
# and every go.sum; a stale restore is harmless (the build cache is
91+
# content-addressed, the module cache is checksum-verified), so the
92+
# fallback key is always worth taking.
93+
- id: gocache
94+
if: runner.os != 'Windows'
95+
run: |
96+
echo "build=$(go env GOCACHE)" >> "$GITHUB_OUTPUT"
97+
echo "mod=$(go env GOMODCACHE)" >> "$GITHUB_OUTPUT"
98+
echo "version=$(go env GOVERSION)" >> "$GITHUB_OUTPUT"
99+
- if: runner.os != 'Windows'
100+
uses: actions/cache@55cc8345863c7cc4c66a329aec7e433d2d1c52a9 # v6.1.0
101+
with:
102+
path: |
103+
${{ steps.gocache.outputs.build }}
104+
${{ steps.gocache.outputs.mod }}
105+
build/cache
106+
key: go-${{ runner.os }}-${{ runner.arch }}-${{ steps.gocache.outputs.version }}-${{ hashFiles('**/go.sum') }}
107+
restore-keys: |
108+
go-${{ runner.os }}-${{ runner.arch }}-${{ steps.gocache.outputs.version }}-
109+
go-${{ runner.os }}-${{ runner.arch }}-
110+
111+
- name: Lint
112+
run: just lint
113+
114+
- name: Test
115+
run: just test
116+
117+
# On a miss, the image this run filled becomes the key's; a hit needs no
118+
# save, since a cache key is never overwritten.
119+
- if: runner.os == 'Windows' && steps.image.outputs.cache-hit != 'true'
120+
uses: ./.github/actions/windows-cache-image
121+
with:
122+
mode: save
123+
key: ${{ steps.image.outputs.key }}
124+
125+
# One linux leg, not the matrix: fuzzing explores the same corpus wherever
126+
# it runs, so more legs cost CPU and add nothing. The recipe passes on a
127+
# tree with no targets or no Go module, so this job is safe in every
128+
# repository.
129+
fuzz:
130+
runs-on: ubuntu-24.04
131+
timeout-minutes: 30
132+
permissions:
133+
contents: read
134+
steps:
135+
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
136+
with:
137+
persist-credentials: false
138+
139+
- name: Install aqua (pinned, checksum-verified)
140+
uses: ./.github/actions/setup-aqua
141+
142+
- name: Install pinned tools
143+
run: aqua install --only-link
144+
145+
# The cached corpus is what makes fuzzing cumulative across runs. Keyed
146+
# on the fuzz sources so a changed target restarts its corpus;
147+
# restore-keys keep the rest.
148+
- id: fuzzdir
149+
run: echo "dir=$(go env GOCACHE)/fuzz" >> "$GITHUB_OUTPUT"
150+
- uses: actions/cache@55cc8345863c7cc4c66a329aec7e433d2d1c52a9 # v6.1.0
151+
with:
152+
path: ${{ steps.fuzzdir.outputs.dir }}
153+
key: fuzz-corpus-${{ runner.os }}-${{ hashFiles('**/*_fuzz_test.go', '**/fuzz_test.go') }}
154+
restore-keys: |
155+
fuzz-corpus-${{ runner.os }}-
156+
157+
- name: Fuzz
158+
run: just do test go fuzz
159+
160+
# A crasher is a bug with a reproducer attached; the log names the
161+
# target, the input file is what reproduces it locally. Uploaded only
162+
# on failure, and only if any was written.
163+
- uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
164+
if: failure()
165+
with:
166+
name: fuzz-crashers
167+
path: '**/testdata/fuzz/'
168+
if-no-files-found: ignore
169+
170+
# Every pin resolves. The verify legs link only, and a link verifies
171+
# nothing: an asset that is missing from a release, or that fails its
172+
# checksum, would merge green and fail at first use. One linux leg pays for
173+
# the real install; aqua's package store is cached on the exact pins, so a
174+
# warm key costs seconds and a changed pin is always a real install. (The
175+
# Go-built tools are tools/go.mod directives, built by the verify legs.)
176+
tools:
177+
runs-on: ubuntu-24.04
178+
timeout-minutes: 30
179+
permissions:
180+
contents: read
181+
steps:
182+
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
183+
with:
184+
persist-credentials: false
185+
186+
- name: Install aqua (pinned, checksum-verified)
187+
uses: ./.github/actions/setup-aqua
188+
189+
- uses: actions/cache@55cc8345863c7cc4c66a329aec7e433d2d1c52a9 # v6.1.0
190+
with:
191+
path: ${{ env.AQUA_ROOT_DIR }}/pkgs
192+
# The same key as the verify legs', so this job and the linux leg
193+
# share one store — and no fallback key here: a changed pin must be
194+
# a real install, which is what this job exists to prove.
195+
key: aqua-pkgs-${{ runner.os }}-${{ runner.arch }}-${{ hashFiles('.aqua/aqua.yaml', '.aqua/aqua-checksums.json', '.limen/aqua-registry.yaml') }}
196+
197+
- name: Install every pinned tool
198+
run: aqua install

‎.github/workflows/security.yaml‎

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
1-
# Seeded once by `limen fix`, then the project's own: limen never updates it.
2-
# Realign it by hand when limen's canonical moves, and comment every project
3-
# line so the next alignment keeps it.
1+
# DO NOT EDIT MANUALLY: content-pinned by limen, reset on drift. A project's
2+
# own scans go in its `security` recipe in the root .justfile, which this runs.
43
#
54
# The security lane, apart from ci: a scan's verdict moves with the
65
# vulnerability database, not with the tree, so this runs on a schedule as
@@ -51,7 +50,7 @@ jobs:
5150
- name: Install aqua (pinned, checksum-verified)
5251
uses: ./.github/actions/setup-aqua
5352

54-
# aqua's package store, keyed on the exact pins (see ci.yaml).
53+
# aqua's package store, keyed on the exact pins (see limen-verify.yaml).
5554
- uses: actions/cache@55cc8345863c7cc4c66a329aec7e433d2d1c52a9 # v6.1.0
5655
with:
5756
path: ${{ env.AQUA_ROOT_DIR }}/pkgs
@@ -64,7 +63,7 @@ jobs:
6463
run: aqua install --only-link
6564

6665
# The Go build and module caches: the scan compiles the module graph
67-
# once per supported platform, cold without this (see ci.yaml).
66+
# once per supported platform, cold without this (see limen-verify.yaml).
6867
- id: gocache
6968
run: |
7069
echo "build=$(go env GOCACHE)" >> "$GITHUB_OUTPUT"

‎.limen/renovate.json‎

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@
99
"vulnerabilityAlerts: fix PRs from GitHub's Dependabot alerts (the baseline keeps the alerts on for exactly this; Dependabot's own update PRs are off, Renovate is the one bot). Stated explicitly because enabled: true here is what reaches // indirect Go modules, which the gomod manager skips by default. Fix PRs skip the cooldown and take the lowest fixed version, both Renovate defaults for this object.",
1010
"postUpdateOptions gomodTidy: a Go module bump rewrites go.mod; without tidy, go.sum keeps the old module's lines and `just do lint go mod` (go mod tidy, diffed) fails every gomod PR. gomodUpdateImportPaths is what keeps tidy running on a MAJOR bump: without it Renovate skips tidy on every major (its guard for the /vN import-path rewrite, which must precede tidy), and a v0 to v1 bump is major while changing no path, so the PR landed a go.sum with the new go.mod hash, no h1 line and the old pseudo-version lines still in it, green for Renovate and red on the tidy diff. With the option, v0 to v1 does no path rewrite and tidies; a real /vN bump rewrites the imports with marwan-at-work/mod (which Renovate go-installs at run time, no image support needed) and then tidies.",
1111
"constraints gomodMod: the version Renovate go-installs marwan-at-work/mod at for that rewrite; without it the install is @latest, a third-party binary that rewrites import paths across the tree fetched at whatever is newest the day a /vN bump lands. Pinned means by digest, and this lever takes only a v-prefixed tag, so this is the nearest the lever allows: a version pin, its content fixed and transparency-logged by the checksum database that go install verifies against. Named here as that exception rather than left implicit. Renovate's own config manager marks this constraint unsupported and never scans a preset, so limen's renovate.json watches the value with a custom manager and proposes its bumps there.",
12-
"packageRules, content-pinned files: the checksum-update workflow, the setup-aqua action and everything under .limen/ are limen's byte for byte; a bump Renovate makes inside one is drift the next `limen check` rejects. Their pins move in limen's own repository, the one place Renovate keeps touching them, and reach every other repository through a limen release.",
12+
"packageRules, content-pinned files: the checksum-update workflow, the shared CI lanes (limen-verify.yaml), the security workflow, the setup-aqua and windows-cache-image actions and everything under .limen/ are limen's byte for byte; a bump Renovate makes inside one is drift the next `limen check` rejects. Their pins move in limen's own repository, the one place Renovate keeps touching them, and reach every other repository through a limen release.",
1313
"packageRules, Go-built tools: the tool directives under tools/ (git-validation, godolint, dot, the Go-source analyzers deadcode, govulncheck, go-licenses, and golangci-lint in tools/golangci-lint/go.mod, a module of its own so its analyzers' dependencies stay upstream's), which Go lists as // indirect and the gomod manager would skip; re-enabled exactly, by module. dot is forkcloser's own tagged module (upstream's cmd/dot is a nested module without tags), so it moves like the others, and as one of ours it is proposed without the cooldown.",
1414
"packageRules, groups: one pull request per repository per kind, not one per dependency — a registry ref that moves most days and a dozen tool pins were arriving as a dozen pull requests a month per repository, each reviewed alone. Three groups: `aqua tools` (every third-party pin in .aqua/aqua.yaml, the standard-registry ref and aqua itself included), `github actions`, and `go modules` (non-major gomod bumps, the tools/go.mod directives included). Renovate keeps the one open pull request current as further versions arrive instead of opening another. Grouped, not scheduled: a bump still arrives as soon as its cooldown ends. Outside the groups on purpose: our own releases (immediate and alone, so a limen bump is its own reviewed change), major Go bumps (code may have to move), pins.yaml entries (each a deliberate supply-chain change), and security fixes, which Renovate's vulnerabilityAlerts defaults keep ungrouped. A repository that wants a dependency out of a group adds a later packageRule with groupName null.",
1515
"packageRules, lychee: releases are tagged lychee-vX.Y.Z next to lychee-lib-vX.Y.Z and nightly; regex versioning that carries the prefix parses the pin and the candidates alike and excludes the others by construction.",
@@ -61,6 +61,9 @@
6161
"matchFileNames": [
6262
".github/workflows/update-aqua-checksum.yaml",
6363
".github/actions/setup-aqua/**",
64+
".github/actions/windows-cache-image/**",
65+
".github/workflows/limen-verify.yaml",
66+
".github/workflows/security.yaml",
6467
".limen/**"
6568
],
6669
"matchRepositories": [

‎AGENTS.md‎

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,10 @@ chapter; the procedure is limen's `skills/contribute`.
2929
human's own work, the human is the author. No scratchpads (`AUDIT.md` and its kind):
3030
they live under `_scratch/` at the repository root, which `.gitignore` ignores, and
3131
nowhere else in the tree.
32+
- **The pull request's title is its release note.** A release's notes are the titles of
33+
the pull requests it merged, so a title says what changed for a consumer; no
34+
`CHANGELOG.md` is kept by hand. One that breaks a consumer carries the `breaking` label
35+
(`gh label create breaking` the first time a repository needs it).
3236
- **One commit per thing.** Different things get different commits; iteration on the
3337
same thing — a review round, a fix to your own commit — is squashed into the commit it
3438
amends before the review is requested. Never a stack of fix-ups for one change.
@@ -59,8 +63,9 @@ chapter; the procedure is limen's `skills/contribute`.
5963
- **A flake is fixed when it is noticed.** A check that fails, then passes on a rerun, gets
6064
its root cause and its fix at once, in a pull request of its own: by whoever noticed it,
6165
or by the owning session when it is another repository's. The rerun found the flake; it
62-
did not fix it. The one exception is a flake whose cause is known and whose fix was
63-
declined, documented as such (windows-11-arm's silent exit 4 or 127): it is rerun, and named.
66+
did not fix it. The exceptions are flakes whose cause is known and whose fix was
67+
declined, documented as such in the book's known upstream bugs (windows-11-arm's silent
68+
exit 4 or 127, an aqua download that stalls with no timeout): each is rerun, and named.
6469
- **Doctrine can lose the argument, never silently.** A fix that cuts against the book is
6570
named as such and argued; it is decided, not discovered.
6671
- **Broken tooling is reported, never worked around in silence.** The rig — limen, the
@@ -77,6 +82,9 @@ chapter; the procedure is limen's `skills/contribute`.
7782
`just lint` and `just test` green, the commit message written — ready to commit and push
7883
when the human is back, and say so once. Signing that never worked in the session is
7984
broken tooling (above).
85+
- **Read what the work needs, never the whole disk.** A targeted read outside the
86+
repositories is fine when the work calls for it; a filesystem-wide walk is not: no
87+
`find /`, `find ~`, disk-wide `mdfind`, or recursive grep over `/` or `~`.
8088

8189
## Communication
8290

0 commit comments

Comments
 (0)