Skip to main content

Development

task setup # Go modules + web pnpm + docs pnpm
task tools:install # air, golangci-lint, govulncheck, deadcode, lefthook, git-cliff -> ./bin
task hooks:install # lefthook pre-commit / pre-push (or: lefthook install)
task doctor # toolchain, optional tools, ports
task dev # Vite :5173 + Go live reload (air) on :8080
task build # frontend + single binary -> ./bin/athenaeum
task build:slim # same without in-browser Kokoro -> ./bin/athenaeum-slim
# Full web builds download q8 ONNX weights via scripts/fetch-kokoro-models.sh
task run # build then run local server
task demo # Go server with --demo seeded library
task reset:data # wipe ./data
task reset:demo # wipe ./data and start --demo
task build:web # production SPA into internal/assets/dist
task build:demo # static SPA -> ./site (offline / GitHub Pages)
task docs:dev # Docusaurus at http://localhost:3000
task docs:build # docs/build
task docs:serve # preview production docs build
task showcase # Playwright screenshots -> ./showcase
task generate # OpenAPI JSON + typed web/src/lib/api/generated
task generate:check # assert generated artifacts are up to date
task i18n:sync # fill missing locale keys from en.json
task i18n:check # locale key parity
task changelog # draft unreleased notes via git-cliff
task fmt # gofmt
task vendor # go mod vendor
task clean # remove build artifacts
task fetch-samples # optional sample media
task test # Go + Vitest
task test:race # Go tests with the race detector
task test:property # Go testing/quick + frontend fast-check properties
task test:contract # OpenAPI/route/i18n/env drift + generate/i18n checks
task test:fuzz # Go native fuzz targets (FUZZTIME=10s)
task test:fuzz:long
task test:coverage # Go coverage (fails below COVERAGE_MIN, default 45)
task test:coverage:web # Vitest coverage with thresholds
task test:bench # Go benchmarks
task test:mutation # Gremlins mutation testing (Go)
task test:mutation:web # Stryker mutation testing (web utils)
task test:e2e # Playwright UI tests (builds binary first)
task test:all # unit + race + property + contract + short fuzz + coverage
task test:lighthouse # Lighthouse CI vs production binary (needs Chromium)
task lint # gofmt + golangci-lint + eslint + prettier + svelte-check
task lint:go # Go linters only
task lint:web # frontend linters only
task security # gosec + govulncheck + pnpm audit
task deadcode # unused Go symbols
task knip # unused frontend dependency scan
task profile # CPU profile from ATHENAEUM_PPROF (default 127.0.0.1:6060)
task docker:build # docker compose build
task docker:up # docker compose up -d --build
task docker:down # docker compose down
task docker:logs # follow container logs

See also CONTRIBUTING.md and .devcontainer/ for a full devcontainer. VS Code / Cursor debug configs live in .vscode/launch.json.

task test:lighthouse builds the binary if needed, serves it on :18080, and runs Lighthouse CI (web/lighthouserc.cjs) with performance / accessibility / best-practices / SEO score gates (default 90 or higher). Reports land in web/.lighthouseci/. Override with LIGHTHOUSE_MIN_SCORE or CHROME_PATH.

For a production-style UI without re-embedding into the binary, build the frontend (task build:web) and run with --web-dir ./internal/assets/dist (or any Vite output directory that contains index.html).

Local profiling: start with --pprof 127.0.0.1:6060 (or ATHENAEUM_PPROF), then task profile or go tool pprof http://127.0.0.1:6060/debug/pprof/profile.

Testing methods

MethodHow to runNotes
Unittask testGo testing + Vitest
Racetask test:raceAlso on Linux in CI
Propertytask test:propertytesting/quick (Go), fast-check (web)
Contract / drifttask test:contractOpenAPI vs routes, FE API paths, i18n keys, .env.example, generated client
Fuzztask test:fuzzGo native fuzz (Fuzz* in internal/)
Coveragetask test:coverage / test:coverage:webAtomic Go profile; Vitest v8 thresholds
Benchtask test:benchExisting Benchmark* targets
Mutation (Go)task test:mutationGremlins on auth/library
Mutation (web)task test:mutation:webStryker on sanitize/password/format utils
Oracleincluded in task test*_oracle_test.go / *.oracle.test.ts
E2E / UItask test:e2ePlaywright (also a CI job)
Lighthousetask test:lighthouseScore budgets

Fuzz duration defaults to 10s per target (FUZZTIME, minimum 5s). Mutation efficacy / coverage thresholds are in .gremlins.yaml and web/stryker.config.js (override with MUTATION_EFFICACY, MUTATION_MCOVER, or MUTATION_DIFF for changed-files-only runs). Go coverage minimum defaults to 45% (COVERAGE_MIN).

Continuous integration

Workflows live under .github/workflows/ (actions pinned to full commit SHAs):

WorkflowTriggerWhat it does
ci.ymlpush / PR / manualLint (gofmt, golangci-lint, eslint, prettier, svelte-check), Go tests, fuzz, coverage gate, cross-compile (Linux/macOS/Windows/BSD/armv6/armv7/riscv64), --self-check on native + QEMU arches, Vitest + coverage, govulncheck, pnpm audit, gosec, CodeQL, multi-arch Docker + container self-check, Lighthouse, Playwright, generate check
codeql.ymlpush / PR / weekly / manualCodeQL for Go and JavaScript/TypeScript
release.ymlv* tags / manualMulti-arch binaries + GitHub Release (SBOM + NOTICE), multi-arch image to GHCR (linux/amd64, arm64). Draft -> attach assets -> publish for immutable releases.
nightly.ymlschedule / manualUnique nightly-* prerelease tags (never moves a tag) + GHCR :nightly
pages.ymlpush (docs/web) / manualDocs + offline demo -> GitHub Pages at https://athenaeum.quad4.io

Default GITHUB_TOKEN permissions are read-only. Jobs elevate only what they need (security-events, packages, pages, contents / attestations for releases). Dependabot keeps Actions, Go modules, and web/ npm deps updated weekly.

Immutable releases

This repo enables GitHub immutable releases. After a release is published, its assets and Git tag cannot change. Release and nightly workflows always create a draft, upload every asset, then publish. Do not force-move v* tags or rebuild a published tag. Cut a new version instead. Verify with gh release verify <tag> when needed.