This file explains repo‑wide conventions and where to find scoped rules.
Precedence: the closest AGENTS.md to the files you're changing wins. Root holds global defaults only.
- Keep diffs small; add tests for new code paths.
- Use semantic commit messages following Conventional Commits style (e.g.,
feat:,fix:,docs:). - Write comprehensive commit message bodies that thoroughly describe every change introduced.
- Ask first before: adding heavy deps, running full e2e suites, or repo‑wide rewrites.
- Update
README.mdor files indocs/when you change user-facing behavior.
- Format Go code:
gofmt -w $(git ls-files '*.go') - Vet code:
go vet ./... - Run tests:
go test ./... - Full lint check:
make lint - Security check:
make security-check
- Requires a running Docker daemon (start it with
sudo systemctl start dockeron systemd hosts, orsudo service docker startotherwise) - Run the daemon with the bundled demo config:
go run . daemon --config example/ofelia.ini— serves the web UI onweb-address(default:8081, which binds all interfaces). The example config does not override it, so reach the UI athttp://127.0.0.1:8081/; pass--web-address 127.0.0.1:8081to force loopback-only binding example/ofelia.iniships working demo jobs (run-daterunsdatein alpine every 30s;local-echoruns on the host every 45s); the swarm and compose examples are commented out as they need extra infrastructure- Web UI assets live in
static/ui/and are embedded via//go:embed ui/*instatic/static.go; new files added directly understatic/ui/are picked up automatically (no registration needed). Theui/*pattern is not recursive, so a new nested subdirectory needs its own embed pattern (e.g.ui/sub/*) - After touching embedded assets, run
go build ./...to confirm the embed still resolves - Web package tests:
go test ./web/... -v -count=1(-count=1bypasses the test cache)
- Struct fields with explicit
jsontags use the tag name (e.g.,json:"lastRun"→lastRun) - Struct fields without
jsontags serialize as the Go field name (capitalized:Image,Container) - Always
grep 'json:"' web/server.gobefore writing frontend code that reads API responses apiJob.Configisjson.RawMessagefromjson.Marshal(job)— core structs lack json tags, so keys are capitalized
- ~26 CI checks: golangci-lint (140-char line limit), CodeQL, Trivy, govulncheck, mutation, unit/integration/fuzz (CodSpeed removed)
- Repo uses GitHub merge queue —
gh pr merge --delete-branchis NOT supported - Automated reviewers: github-actions (auto-approve), gemini-code-assist, Copilot (both COMMENTED — check all)
- Project
netresearch_ofeliauses Automatic Analysis — nosonar-project.properties, no sonar CI step. Config lives in project settings via API/UI; committing scanner config files risks disrupting Automatic Analysis. - Exclude a rule on a path:
POST api/settings/setwithkey=sonar.issue.ignore.multicriteria— a multi-key setting: passfieldValueswith both companion fields, e.g.--data-urlencode 'fieldValues={"ruleKey":"go:S3776","resourceKey":"**/*_test.go"}'(verify viaapi/settings/values). Issue dispositions:api/issues/do_transition— on SonarCloudacceptsupersedes the retiredwontfix; the allowed transitions per issue are listed in the issue's owntransitionsarray fromapi/issues/search. Hotspots:api/hotspots/change_status— SonarCloud only acceptsREVIEWED+SAFE/FIXED, no ACKNOWLEDGED. gocognitreproduces SonarCloudgo:S3776cognitive-complexity numbers exactly; golangci-lint here runsgocyclo(cyclomatic), which does NOT catch S3776.- Extracting a route constant named
*Token(e.g.pathAPICSRFToken) trips gosec G101 (hardcoded credentials) in the GHAS code-scanning gate — suppress with// #nosec G101 -- reason. The standalonego-check / gosecand the GHASgoseccheck are separate. - Reusable workflows pinned
@mainare intentional (own org, post-trivy-action-incident policy) — the related hotspots are accepted, not third-party actions.
- Releases trigger on
release: publishedevent viarelease-slsa.yml - Create signed tags locally, then create a GitHub release:
gh release create vX.Y.Z --title "vX.Y.Z" --notes-file notes.md --verify-tag - The Release workflow builds SLSA Level 3 provenance, container images, and binary artifacts
- Follow the narrative release notes style from previous releases (user-facing highlights first, then categorized changes)
github.com/netresearch/go-cron— maintained fork of robfig/cron with DAG engine, pause/resume, @triggered schedules- Go version tracked in
go.mod— CI reads fromgo-version-file: go.mod - Update Go version in
go.modto fix stdlib vulnerabilities (govulncheck detects these)
./cli/AGENTS.md— command-line interface and configuration./core/AGENTS.md— core business logic and scheduling./web/AGENTS.md— web interface and HTTP handlers./middlewares/AGENTS.md— notification and middleware logic./test/AGENTS.md— testing utilities and integration tests
./docs/feedback/golangci-lint-cache-cross-worktree.md— rungolangci-lint cache cleanbefore pushing if you use multiple sibling worktrees; stale cache entries from siblings get replayed as findings and block thepre-pushhook.
- Manage dependencies exclusively with Go modules.
- Do not vendor or commit downloaded modules. Avoid running
go mod vendor. - Ensure the
vendor/directory is ignored via.gitignore.
netresearch/node-vault— archived, do not create PRsnetresearch/satis-git— archived, do not create PRs
- The nearest
AGENTS.mdwins. Explicit user prompts override files.