Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions .github/workflows/pr-check.yml
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,13 @@ jobs:
key: golangci-lint-${{ runner.os }}-${{ hashFiles('mise.toml', '.golangci.yaml') }}
restore-keys: golangci-lint-${{ runner.os }}-

- name: Cache prek hook environments
uses: actions/cache@v4
with:
path: ~/.cache/prek
key: prek-${{ runner.os }}-${{ hashFiles('mise.toml', '.pre-commit-config.yaml') }}
restore-keys: prek-${{ runner.os }}-

- name: Download Go dependencies
run: go mod download

Expand Down
68 changes: 65 additions & 3 deletions .pre-commit-config.yaml
Original file line number Diff line number Diff line change
@@ -1,9 +1,71 @@
# A green hook is not proof it checked anything: `--all-files` only guarantees prek
# hands the hook a file list, not that the hook consults it. Some check git state
# instead (staged files, mid-merge) and CI's clean checkout has neither -- so they
# run, pass, and weigh nothing. Read a hook's source before adding it.
repos:
# prek's built-in Rust implementations of the pre-commit-hooks checks. Naming
# the upstream repo URL here would run the same native code anyway (prek's
# fast path ignores `rev`), but would also clone the repo and build a Python
# environment that is never executed. prek-only: upstream `pre-commit`
# rejects this config with `Missing required key: rev`.
- repo: builtin
hooks:
- id: check-added-large-files
# Without this the hook intersects its file list with `git diff --staged
# --diff-filter=A`, which is empty on CI's clean checkout -- it would pass
# green having weighed nothing. Verified: a 900 KB file passes without it.
args: [--enforce-all]
- id: check-case-conflict
- id: check-illegal-windows-names
- id: check-merge-conflict
# Same shape: the hook returns 0 early unless .git/MERGE_MSG exists, and CI
# is never mid-merge. Verified: a file full of conflict markers passes
# without it.
args: [--assume-in-merge]
- id: check-symlinks
- id: check-yaml
- id: detect-private-key
- id: end-of-file-fixer
- id: mixed-line-ending
- id: trailing-whitespace

- repo: https://github.com/gitleaks/gitleaks
rev: v8.30.1
hooks:
# Its entry hard-codes --staged, so CI (nothing staged) scans an empty diff and
# is always green. Deliberate: this stays a local commit-time guard; GitHub
# secret scanning push protection (enabled on the repo) is the server-side net.
- id: gitleaks

# These entries must stay leaf targets. `make check` runs prek itself, so
# pointing a hook at it would make prek recurse into itself.
#
# `always_run: true` is required: these are repo-wide checks, and without it
# prek skips a hook whose file list comes back empty -- so a commit that only
# *deletes* files (no path survives the filter) would skip lint and test
# entirely, which is exactly when they matter most.
- repo: local
hooks:
- id: make-check
name: make-check
entry: make check
- id: check-tidy
name: check-tidy
entry: make check-tidy
language: system
always_run: true
pass_filenames: false
require_serial: true

- id: lint
name: lint
entry: make lint
language: system
always_run: true
pass_filenames: false
require_serial: true

- id: test
name: test
entry: make test
language: system
always_run: true
pass_filenames: false
require_serial: true
8 changes: 4 additions & 4 deletions .serena/memories/memory_maintenance.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,14 +12,14 @@
Folders can mirror project structure (e.g. modules like frontend/backend) or topics like debugging, architecture, etc.
- Memory references must use a mem: prefix inside backticks, e.g. `mem:frontend/core`.
The surrounding text should clearly indicate when to read the memory/which content to expect.
The text should provide more precise guidance than the memory name alone,
The text should provide more precise guidance than the memory name alone,
i.e. avoid a reference like "frontend debugging: `mem:frontend/debugging` and instead make clear which aspects of frontend debugging are covered.
- Memories themselves should not contain information about when to read them; this is the responsibility of the referring memory.

## Style

Dense agent notes, not prose docs. Prefer invariants, terse bullets.
Avoid obvious context, rationale, and examples unless they prevent likely mistakes.
Dense agent notes, not prose docs. Prefer invariants, terse bullets.
Avoid obvious context, rationale, and examples unless they prevent likely mistakes.
Keep guidance durable and generalizable, not task-local.

## Add/update threshold
Expand All @@ -30,4 +30,4 @@ Do not add: quick-read facts; generic language/framework knowledge; one-off task
## Maintenance Actions

- Renaming memories: References are updated automatically if handled via Serena's memory rename tool.
- Checking for stale memories (e.g. after deletion): Call `serena memories check` for a report.
- Checking for stale memories (e.g. after deletion): Call `serena memories check` for a report.
22 changes: 17 additions & 5 deletions AGENTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -19,17 +19,25 @@ go install github.com/min0625/mint/cmd/mint@latest # Go 1.26.4+; binary → $G

```bash
make build # compile → bin/mint (CGO_ENABLED=0, trimpath, ldflags injected)
make test # go test -race -failfast ./...
make test # go test -race -failfast ./... (use this to watch output; prek buffers it)
make lint # golangci-lint (only new violations since HEAD)
make fix # golangci-lint --fix + go mod tidy
make check # check-tidy + lint + test (CI gate)
make check # every prek hook over all tracked files (CI gate); may rewrite
# files -- the formatting fixer hooks run here too
make check-tidy # verify go.mod/go.sum are tidy
make release-snapshot # goreleaser release --snapshot --clean (test release locally)
```

Tool versions are pinned in [mise.toml](./mise.toml) (Go 1.26.4, golangci-lint 2.12.2, goreleaser 2.16.0, prek 0.4.6).
Run `mise install` to set up the exact toolchain. Pre-commit hooks run `make check` via
`prek` (config: [.pre-commit-config.yaml](./.pre-commit-config.yaml)).
Run `mise install` to set up the exact toolchain. [.pre-commit-config.yaml](./.pre-commit-config.yaml)
is the single source of truth for what gets checked: `prek` runs it on `git commit` (staged files),
and `make check` runs the same hooks over **all** tracked files, which is what CI runs. `check-tidy`,
`lint` and `test` are hooks in there too — `make check` must never be used as a hook entry, since it
runs prek and would recurse. The hygiene checks come from `repo: builtin` — prek's own Rust
implementations, versioned with prek itself rather than a `rev:` pin, and unreadable by upstream
`pre-commit`. The `gitleaks` hook only scans *staged* changes, so it is a no-op in CI by design —
a local commit-time guard, not a CI secret scan — GitHub secret scanning push
protection is the server-side net.

## Distribution

Expand Down Expand Up @@ -94,7 +102,11 @@ bin/mint # compiled binary (gitignored)
- **Pipe-friendly** — translation input via args or stdin; results to stdout; errors to stderr.
- **Unix philosophy** — do one thing well; composable with `grep`, `sed`, `xargs`, etc.
- **No unnecessary dependencies** — keep `go.mod` minimal.
- Lint is checked only for *new* violations (`--new-from-rev=HEAD`); always run `make lint` before committing.
- Lint is checked only for *new* violations (`--new-from-rev=$(NEW_FROM_REV)`, default `HEAD`; CI passes
the PR base branch). `make lint` and `make fix` hard-fail if that revision does not resolve (shared
`check-rev` guard) — `golangci-lint` itself only warns and exits 0, which would let CI pass having
linted nothing. The pre-commit hook already runs
lint on every commit, so running it by hand is only needed to re-check a different rev.
- **Release workflow** — push a tag matching `v*.*.*` to automatically trigger GoReleaser CI; creates GitHub Release with multi-platform binaries.
- **Local snapshot testing** — run `goreleaser release --snapshot --clean` to validate build configuration before publishing.

Expand Down
19 changes: 16 additions & 3 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -10,13 +10,21 @@ build:
mkdir -p ./bin/
CGO_ENABLED=0 go build -trimpath -ldflags="$(LDFLAGS)" -o ./bin/ ./cmd/mint

# golangci-lint only *warns* and exits 0 when --new-from-rev does not resolve,
# so a typo'd or unfetched rev would silently lint nothing and report success.
# Both --new-from-rev callers below depend on this guard.
.PHONY: check-rev
check-rev:
@git rev-parse --verify --quiet '$(NEW_FROM_REV)^{commit}' >/dev/null || \
{ echo "NEW_FROM_REV=$(NEW_FROM_REV) is not a valid revision" >&2; exit 1; }

.PHONY: fix
fix:
fix: check-rev
go mod tidy
golangci-lint run --new-from-rev=$(NEW_FROM_REV) --fix ./...

.PHONY: lint
lint:
lint: check-rev
golangci-lint config verify
golangci-lint run --new-from-rev=$(NEW_FROM_REV) ./...

Expand All @@ -37,8 +45,13 @@ cover-html: cover
check-tidy:
go mod tidy -diff

# The full gate: every hook in .pre-commit-config.yaml -- check-tidy, lint and
# test included -- over every tracked file, i.e. the same suite `git commit`
# runs, but repo-wide instead of staged. NEW_FROM_REV is set on the command
# line, so make exports it and prek passes it through to the nested make.
.PHONY: check
check: check-tidy lint test
check:
prek run --all-files --show-diff-on-failure

.PHONY: release
release:
Expand Down
Loading