From e049e6eefde0054966e839c5825335947c2bf983 Mon Sep 17 00:00:00 2001 From: Matt Silverlock Date: Tue, 10 Feb 2026 09:17:22 -0500 Subject: [PATCH 1/3] add AGENTS.md, rename default branch to main --- .github/workflows/test.yml | 4 +- AGENTS.md | 139 +++++++++++++++++++++++++++++++++++++ 2 files changed, 141 insertions(+), 2 deletions(-) create mode 100644 AGENTS.md diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 5e499a8..e6f7623 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -2,9 +2,9 @@ name: Test on: push: - branches: [master] + branches: [main] pull_request: - branches: [master] + branches: [main] jobs: test: diff --git a/AGENTS.md b/AGENTS.md new file mode 100644 index 0000000..96f7e35 --- /dev/null +++ b/AGENTS.md @@ -0,0 +1,139 @@ +# AGENTS.md + +Guidelines for AI agents operating in the `simple-scrypt` repository. + +## Project overview + +Single-package Go library wrapping `golang.org/x/crypto/scrypt` for password hashing. +Module path: `github.com/elithrar/simple-scrypt`. One external dependency (`golang.org/x/crypto`). + +Two source files at the repo root: +- `scrypt.go` — library implementation (public API mirrors Go's `bcrypt` package) +- `scrypt_test.go` — tests (standard `testing` package, no third-party frameworks) + +Hash format: `N$R$P$hexsalt$hexdk` (dollar-separated, hex-encoded salt and derived key). + +Default branch is **`main`**. + +## Build and test commands + +```sh +# build +go build ./... + +# run full test suite (CI uses this exact command) +go test -v -race ./... + +# run a single test +go test -v -race -run TestCompareHashAndPassword ./... + +# run a single sub-test (table-driven) +go test -v -race -run TestCalibrate/512 ./... + +# formatting check — CI rejects any diff +gofmt -l . + +# apply formatting fixes +gofmt -w . + +# static analysis — CI runs this +go vet ./... +``` + +CI runs on push/PR to `main` across Go 1.20, 1.21, 1.22, 1.23 on Ubuntu. +All three checks must pass: `gofmt`, `go vet`, `go test -v -race ./...`. + +Always run `go test -v -race ./...` before committing to catch data races and regressions. + +## Code style + +### Formatting + +`gofmt` is the only formatter. No custom config. CI enforces zero diff — run `gofmt -w .` before committing. + +### Imports + +Standard library first, blank line, then external packages: + +```go +import ( + "crypto/rand" + "errors" + "fmt" + + "golang.org/x/crypto/scrypt" +) +``` + +### Naming + +- Exported types/functions: `PascalCase` — `Params`, `GenerateFromPassword`, `CompareHashAndPassword` +- Unexported functions/constants: `camelCase` — `decodeHash`, `maxInt`, `minDKLen` +- Sentinel errors: `Err` prefix — `ErrInvalidHash`, `ErrInvalidParams`, `ErrMismatchedHashAndPassword` +- Receiver names: short, single letter — `p` for `*Params` + +### Error handling + +- Sentinel errors as package-level `var` using `errors.New()` +- Functions return `error` as the last return value +- Early return on error (guard clauses) — no nested else blocks +- No error wrapping in this codebase; return sentinel errors or upstream errors directly +- `CompareHashAndPassword` returns `nil` on success (bcrypt convention) + +```go +var ErrInvalidHash = errors.New("scrypt: the provided hash is not in the correct format") + +func Cost(hash []byte) (Params, error) { + params, _, _, err := decodeHash(hash) + return params, err +} +``` + +### Comments + +- Godoc comments on all exported types, functions, and variables +- Internal comments explain *why*, not *what* — save them for I/O, validation, and edge cases +- Don't comment single variables or trivial functions + +### Testing + +Standard `testing` package only. Tests are in `package scrypt` (white-box, same package). + +Patterns used in this codebase: + +- **Table-driven tests** with `pass bool` fields for expected outcomes: + ```go + var testParams = []struct { + pass bool + params Params + }{ + {true, Params{16384, 8, 1, 32, 64}}, + {false, Params{-1, 8, 1, 16, 32}}, + } + ``` +- `t.Fatal` / `t.Fatalf` for hard failures that should stop the test +- `t.Errorf` for soft failures (test continues to check remaining cases) +- `t.Logf` for informational output (e.g., timing data) +- `Example*` functions for godoc examples + +Do not add third-party test frameworks or assertion libraries. +Avoid tests that merely exercise language features — focus on validation, state, and error handling. + +### Types + +- Do not use type casts to work around type issues; fix the underlying problem +- Zero-value structs (e.g., `Params{}`) are used as signals for default behavior (see `Calibrate`) + +## Dependencies + +Minimize new dependencies. The library has one external dependency by design. +Install dependencies using `go get`. Ensure `go.sum` is committed alongside `go.mod` changes. + +## Git and PR conventions + +- Short, imperative commit messages: `add calibration benchmarks` not `feat(scrypt): added calibration benchmarks` +- Do not commit, push, or create PRs without explicit instruction +- Use `gh` CLI for creating PRs and issues +- Branch off `main` for new work; never commit directly to `main` +- PRs: short opening sentence with the "why", bullet points for major changes, mention related docs/tests +- Do not list changed files in PR descriptions — the diff shows that From 83765fc0faf9b7ffe50054ce07e46b730037cbb4 Mon Sep 17 00:00:00 2001 From: Matt Silverlock Date: Tue, 10 Feb 2026 09:19:35 -0500 Subject: [PATCH 2/3] update CI matrix to Go 1.21-1.24 plus tip --- .github/workflows/test.yml | 29 ++++++++++++++++++++++++++++- AGENTS.md | 2 +- 2 files changed, 29 insertions(+), 2 deletions(-) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index e6f7623..dbb6cce 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -11,7 +11,7 @@ jobs: runs-on: ubuntu-latest strategy: matrix: - go-version: ['1.20', '1.21', '1.22', '1.23'] + go-version: ['1.21', '1.22', '1.23', '1.24'] steps: - uses: actions/checkout@v4 @@ -29,3 +29,30 @@ jobs: - name: Run tests run: go test -v -race ./... + + test-tip: + runs-on: ubuntu-latest + continue-on-error: true + + steps: + - uses: actions/checkout@v4 + + - name: Set up Go stable (for gotip bootstrap) + uses: actions/setup-go@v5 + with: + go-version: stable + + - name: Install gotip + run: | + go install golang.org/dl/gotip@latest + gotip download + echo "$(gotip env GOROOT)/bin" >> $GITHUB_PATH + + - name: Verify formatting + run: gotip fmt -l . + + - name: Run go vet + run: gotip vet ./... + + - name: Run tests + run: gotip test -v -race ./... diff --git a/AGENTS.md b/AGENTS.md index 96f7e35..e0fc03d 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -40,7 +40,7 @@ gofmt -w . go vet ./... ``` -CI runs on push/PR to `main` across Go 1.20, 1.21, 1.22, 1.23 on Ubuntu. +CI runs on push/PR to `main` across Go 1.21, 1.22, 1.23, 1.24 plus tip on Ubuntu. All three checks must pass: `gofmt`, `go vet`, `go test -v -race ./...`. Always run `go test -v -race ./...` before committing to catch data races and regressions. From 34aec571c2c0c1f21eaec672b874cf43aa41def3 Mon Sep 17 00:00:00 2001 From: Matt Silverlock Date: Tue, 10 Feb 2026 10:46:46 -0500 Subject: [PATCH 3/3] fix gotip formatting check in CI (#30) gotip fmt -l . is invalid (go fmt doesn't accept -l). The step always exits 2, silently swallowed by continue-on-error. Use gofmt -l . via the gotip-provided PATH instead, matching the stable job's approach. --- .github/workflows/test.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index dbb6cce..404a6ce 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -49,7 +49,7 @@ jobs: echo "$(gotip env GOROOT)/bin" >> $GITHUB_PATH - name: Verify formatting - run: gotip fmt -l . + run: test -z "$(gofmt -l .)" - name: Run go vet run: gotip vet ./...