| Dimension | Shared | Only in A | Only in B | Overlap |
|---|---|---|---|---|
| Sections | 0 | 1 | 15 | 0% |
| Commands | 3 | 0 | 11 | 21% |
| Section tags | 1 | 0 | 8 | 11% |
What each file covers
Sections
0 shared · 1 only in A · 15 only in B- − Go Standards
- + AGENTS.md
- + Project Overview
- + Repository Structure
- + Setup Commands
- + Build binary
- + Run all tests (main module)
- + Lambda (separate module under lambda/): build, package, test
- + Check Go formatting (includes lambda/)
- + Lint (optional; requires golangci-lint)
- + Code Style
- + Testing
- + CI
- + Documentation and AI Context (Mandatory)
- + PR Guidance
- + References
Commands
3 shared · 0 only in A · 11 only in B- + make build
- + make test-all
- + make lambda.build
- + make lambda.zip
- + make lambda.test
- + go.mod
- + gh issue create
- + go test ./...
- + make e2e
- + go.*
- + git commit --amend -s --no-edit
- make check-fmt
- git commit -s
- make lint
Section tags
1 shared · 0 only in A · 8 only in B- + setup
- + build
- + test
- + code-style
- + architecture
- + testing-strategy
- + git-pr
- + docs
- lint-format
Line diff
devopsfactory-io/neptune · .cursor/rules/go-standards.mdc
@@ −1 @@
1---
2description: Go style and conventions for Neptune
3globs: "**/*.go"
4alwaysApply: false
5---
6
7# Go Standards
8
9- **Format**: Use `gofmt -s`. Run `make check-fmt` before committing. Use `git commit -s` for DCO sign-off (see [CONTRIBUTING.md](CONTRIBUTING.md)).
10- **Lint**: Follow `.golangci.yml`; do not introduce new linter violations. Run `make lint` when available.
11- **Packages**: Code in `internal/` must not be imported from outside this module.
12- **Errors**: Always handle errors; add context with `fmt.Errorf("...: %w", err)` where useful.
13- **Tests**: Place `*_test.go` in the same package as the code. Use table-driven tests when testing multiple cases.
14- **Exports**: Public functions and types must have doc comments starting with the name (e.g. `// NewClient creates ...`).
15
devopsfactory-io/neptune · AGENTS.md
@@ +1 @@
1# AGENTS.md
2
3Guidance for AI coding agents working on the Neptune project.
4
5---
6
7## Project Overview
8
9**Neptune** is a Terraform and OpenTofu pull request automation tool inspired by [Atlantis](https://github.com/runatlantis/atlantis). It runs plan/apply (Terraform or OpenTofu) on pull requests using the [Terramate](https://github.com/terramate-io/terramate) Go SDK for change detection and run order. When a step has `once` false or unset (default), Neptune runs the step’s command in each changed stack (Terramate SDK or local stacks; no Terramate CLI needed when using Terramate); object storage (GCS or S3) is used for stack locking, and GitHub for PR requirements and comments.
10
11**Main capabilities**: Load config from `.neptune.yaml` and env; in CI (non-E2E), config is loaded from the repository’s default branch via git (fallback to PR branch) so PR authors cannot change workflow steps; check PR requirements (approved, mergeable, undiverged, rebased); lock stacks in object storage (GCS, AWS S3, or S3-compatible e.g. MinIO); run workflow steps (per-stack by default, or once in root when `once: true`); for stacks_management: local, **neptune stacks** provides list (--changed) and create, with **--format** (json, yaml, text, formatted; default formatted); when using discovery, run order can be set via **depends_on** in each **stack.hcl** (path-only; relative paths and directory-of-stacks supported); post results as PR comments. Optional `repository.automerge: true` enables PR auto-merge after a successful apply (GitHub GraphQL). Log level is configurable via `log_level` (config), `NEPTUNE_LOG_LEVEL`, or the global **--log-level** CLI flag (DEBUG, INFO, ERROR).
12
13**Language**: Go (see `go.mod`).
14
15---
16
17## Repository Structure
18
19- **`main.go`** – Entry point; version/commit/date via ldflags.
20- **`cmd/`** – CLI (Cobra): `root.go` (global **--log-level** flag), `version.go`, `command.go`, `unlock.go`, `stacks.go` (stacks list, create; **--format** json|yaml|text|formatted, default formatted; **neptune stacks create** supports optional **--depends-on** comma-separated paths). **neptune stacks list** and **neptune stacks create** are for local use and do not require `GITHUB_TOKEN` or other CI env vars (unlike **neptune command** and **neptune unlock**).
21- **`internal/config`** – Load env + YAML, validate `.neptune.yaml` (including optional `log_level`, `stacks_management`, root-level `local_stacks`).
22- **`internal/domain`** – Config, lock, run, and GitHub domain structs (WorkflowStep uses `once`; RepositoryConfig has `StacksManagement`, `LocalStacks`).
23- **`internal/log`** – Structured logging (DEBUG, INFO, ERROR) via `log/slog`; level from `NEPTUNE_LOG_LEVEL` or config `log_level`.
24- **`internal/stacks`** – Stacks provider interface (terramate, local); list/changed stacks for locking and runner.
25- **`internal/lock`** – Lock interface: gets stack list from stacks provider, object-storage lock files (GCS, S3).
26- **`internal/run`** – Execute workflow phase steps (shell).
27- **`internal/github`** – GitHub API client, PR requirements (approved, mergeable, undiverged), commit statuses (GetHeadSHA, CreateCommitStatus) for **neptune plan** / **neptune apply**; GraphQL EnablePullRequestAutoMerge when `repository.automerge` is true.
28- **`internal/git`** – Rebased check; DefaultBranch (git CLI), ShowFileFromRef, FetchBranch for loading config from default branch.
29- **`internal/notifications/github`** – Format and post PR comments.
30- **`examples/`** – Infra examples (S3/GCS backend, automerge, Terramate stacks, Terragrunt).
31- **`scripts/`** – Maintainer scripts (if any).
32- **`e2e/`** – End-to-end tests: three Terramate stacks (null_resource/local_file), MinIO via Docker Compose, and `scripts/run-terramate.sh` that runs Neptune plan/apply with `NEPTUNE_E2E=1` (skips GitHub; see [e2e/README.md](e2e/README.md)).
33- **`lambda/`** – AWS Lambda handler for Neptune GitHub App webhooks (verify signature, parse `pull_request`—including `labeled` when the added label is `NEPTUNE_PR_LABEL`—and `issue_comment`, trigger `repository_dispatch`; optional `NEPTUNE_PR_LABEL` gates on PR label). See [lambda/README.md](lambda/README.md).
34- **`lambda/cloudformation/`** – CloudFormation template to deploy the Lambda (Function URL, IAM, Secrets Manager). See [lambda/README.md](lambda/README.md#deploy-with-cloudformation).
35- **`Makefile`**, **`.golangci.yml`**, **`.goreleaser.yml`**, **`.github/workflows/`** – Build, test, lint, release.
36- **`.claude/agents/` (migrated to hub)** – Agent definitions have been moved to the [code-agent-hub](https://github.com/devopsfactory-io/code-agent-hub) at `.claude/agents/neptune/`. Agents include: documentation-maintainer, em, go-developer, iac-developer, issue-reviewer, issue-writer, platform-engineering, pr-reviewer, qa, security.
37- **`.claude/commands/`** – Claude slash commands: `/feature`, `/bug` (invoke the issue-writer workflow to create issues from the repo’s issue templates; the draft is validated by issue-reviewer before `gh issue create`).
38- **Root community docs**: [CODE_OF_CONDUCT.md](CODE_OF_CONDUCT.md), [SECURITY.md](SECURITY.md), [GOVERNANCE.md](GOVERNANCE.md), [MAINTAINERS.md](MAINTAINERS.md), [ROADMAP.md](ROADMAP.md), [LICENSE](LICENSE).
39
40---
41
42## Setup Commands
43
44```bash
45# Build binary
46make build
47
48# Run all tests (main module)
49make test-all
50
51# Lambda (separate module under lambda/): build, package, test
52make lambda.build
53make lambda.zip
54make lambda.test
55
56# Check Go formatting (includes lambda/)
57make check-fmt
58
59# Lint (optional; requires golangci-lint)
60make lint
61```
62
63Use Go version from `go.mod`. No other prerequisites for building or testing the Go CLI. CI runs `make test-all`, `make lambda.test`, and `make check-fmt`.
64
65---
66
67## Code Style
68
69- **Format**: Use `gofmt -s`; run `make check-fmt` before committing.
70- **Linting**: `.golangci.yml` is authoritative; do not introduce new linter violations.
71- **Packages**: Code under `internal/` must not be imported from outside this module.
72- **Errors**: Return errors with context (e.g. `fmt.Errorf("...: %w", err)`); avoid naked returns.
73- **Exports**: Public functions and types should have doc comments starting with the name.
74
75---
76
77## Testing
78
79- **Run**: `go test ./...` or `make test-all`.
80- **Location**: Place `*_test.go` next to the code under test (same package).
81- **Coverage**: Existing tests cover `internal/config`, `internal/git`, `internal/github`, `internal/run`, `internal/notifications/github`; add tests for new behavior and keep coverage for touched code.
82- **No external services**: Unit tests should not require live GitHub or GCS; mock or stub as needed.
83- **E2E**: Run `make e2e` or `./e2e/scripts/run-terramate.sh` (requires Docker, Terraform). Uses MinIO and `NEPTUNE_E2E=1` to skip GitHub. For **stacks_management: local**, run `./e2e/scripts/run-local-stacks-files.sh` or `./e2e/scripts/run-local-declared-stacks.sh`. E2E config uses steps with default `once: false` (Neptune runs commands per stack).
84- **Automerge**: E2E and integration tests in this repo do not exercise the automerge feature. A separate repository (e.g. a fork or copy of [examples/](examples/)) can be used to test automerge end-to-end (e.g. open a PR with changes in two stacks, comment `@neptbot apply`, then verify the apply comment and that the PR is set to auto-merge after checks pass).
85
86---
87
88## CI
89
90- **`.github/workflows/test.yml`** – On push to `main`/`release-*` and on PRs; path filter for Go files; runs `make test-all` and `make check-fmt`.
91- **`.github/workflows/e2e.yml`** – On push/PR when e2e-related paths change; runs `./e2e/scripts/run-terramate.sh` with MinIO (Docker Compose). See [e2e/README.md](e2e/README.md).
92- **`.github/workflows/integration.yml`** – On PRs when integration-relevant paths change; runs Neptune plan/apply on the same PR with real GitHub (requirements check, PR comments, commit statuses) and MinIO for locks. Needs `statuses: write` for commit status API. See [e2e/README.md](e2e/README.md#integration-tests).
93- **`.github/workflows/cross-repo-test.yml`** – On PRs (non-draft) to `main`/`release-*` when core paths change (`e2e/**`, `cmd/**`, `internal/**`, `lambda/**`, `go.*`); runs cross-repo integration tests against the external `neptune-tests` repository. Creates dynamic Terramate stacks on a throwaway branch in `neptune-tests`, opens a test PR with a `neptune-ref` marker, waits for neptbot to execute the full plan/apply webhook flow (up to 10 minutes each), verifies commit statuses (`neptune plan`, `neptune apply`), checks automerge state, and cleans up the branch and PR. Uses the `neptune-ci` GitHub App (secrets: `NEPTUNE_CI_APP_ID`, `NEPTUNE_CI_PRIVATE_KEY`) for cross-repo operations. Runs in parallel with `e2e.yml` and `integration.yml`.
94- **`.github/workflows/lint.yml`** – On PRs; path filter for Go; runs golangci-lint.
95- **`.github/workflows/labeler.yml`** – On pull_request (opened, synchronize, reopened); runs [actions/labeler](https://github.com/actions/labeler) with [.github/labeler.yml](.github/labeler.yml). Path-based: neptune, dependencies, documentation. Head-branch (branch name): `feat*`→feature, `enhance*`→enhancement, `fix*` (not fix*dep*)→bug, branch containing `!`→breaking-change, `ci*`→github-actions, `(deps)`→dependencies. See CONTRIBUTING.md for contributor-facing branch naming.
96- **`.github/workflows/label-old-prs.yml`** – workflow_dispatch; applies the labeler to existing PRs (inputs: state e.g. merged/closed/all, limit). Use to backfill labels on old or merged PRs (Actions → "Label old PRs" → Run workflow). Because the labeler does not receive branch context on workflow_dispatch, a separate step applies the same rules as `.github/labeler.yml` to both head branch and PR title (e.g. `feat*`→feature if either branch or title matches), then the labeler runs for path-based labels.
97- **`.github/workflows/release.yml`** – On push of tags `v*.*.*` (and workflow_dispatch); runs GoReleaser to create GitHub Release with neptune binaries (archives e.g. `neptune_linux_amd64.tar.gz` and raw binaries e.g. `neptune_linux_amd64`), Lambda zip (`neptune-webhook.zip`) and raw binary `neptune-webhook_linux_amd64` (Lambda binary is `neptune-webhook`; zip contains it), checksums, and release notes. The release body is generated by **GitHub** (GoReleaser uses `changelog.use: github-native`) and categorized using [.github/release.yml](.github/release.yml) and PR labels (Breaking Changes, Features, Bug fixes, Documentation, Dependency updates, Other work). Release footer includes Full Changelog link.
98- **Renovate** – Dependency-update PRs (Go modules and GitHub Actions) are opened by [Renovate](https://docs.renovatebot.com/) from [.github/renovate.json5](.github/renovate.json5). To enable Renovate, install the [Renovate GitHub App](https://github.com/apps/renovate) and select the repo. Do not remove or override this config without reason.
99
100Semantic versioning: use tags like `v0.2.0`. GoReleaser injects version/commit/date into the binary via ldflags.
101
102**Changelog and breaking changes**: The release body is generated by GitHub (github-native) and categorized by [.github/release.yml](.github/release.yml) and **PR labels**. For breaking changes to appear under "Breaking Changes", apply the `breaking-change` label to the PR before merge. The commit subject convention (`!:`) is still recommended for semver (e.g. `feat!: remove deprecated flag`) but does not drive release-note sections; labels do.
103
104---
105
106## Documentation and AI Context (Mandatory)
107
108After any change that affects behavior, APIs, config, or CI:
109
1101. **Delegate**: Delegate documentation updates to the **documentation-maintainer** agent (defined in the hub at `.claude/agents/neptune/documentation-maintainer/`) so it runs the full maintain-documentation checklist (README, docs/, examples/, AGENTS.md, CLAUDE.md, .claude/commands, .claude/skills).
1112. **Do not edit plan files** (e.g. `neptune_go_rewrite*.plan.md` or `ai_agent_config*.plan.md`) unless the user explicitly asks.
112
113When in doubt, update. See `CLAUDE.md` (Documentation rule, always applies) and the **maintain-documentation** skill (`.claude/skills/maintain-documentation/`); the agent holds the detailed checklist.
114
115---
116
117## PR Guidance
118
119Before submitting:
120
1211. **Commits must be signed off (DCO).** Use `git commit -s` when creating commits. Do not add a `Made-with: Cursor` (or similar) trailer to commit messages. If you already committed without sign-off, run `git commit --amend -s --no-edit` then force-push. See [CONTRIBUTING.md](CONTRIBUTING.md) and `CLAUDE.md` (DCO rule).
1222. Run `make test-all` and `make check-fmt`.
1233. Ensure no new linter errors (`make lint` if available).
1244. If behavior or setup changed, delegate to the **documentation-maintainer** subagent.
1255. **Branch naming**: Branch names matching [.github/labeler.yml](.github/labeler.yml) (e.g. `feat/...`, `fix/...`, `enhance/...`, `(deps)/...`, `ci/...`, or branch containing `!` for breaking) get PR labels applied automatically, which drive release-note categories. See [CONTRIBUTING.md](CONTRIBUTING.md#branch-naming-and-pr-labels).
126
127PR titles may follow a conventional style (e.g. `feat(cmd): ...`, `fix(lock): ...`, `docs: ...`) but this is not enforced.
128
129---
130
131## References
132
133- **Contributing (human)**: [CONTRIBUTING.md](CONTRIBUTING.md) – main entry for contributors; [CODE_OF_CONDUCT.md](CODE_OF_CONDUCT.md), [SECURITY.md](SECURITY.md); issue and PR templates in [.github/ISSUE_TEMPLATE/](.github/ISSUE_TEMPLATE/) and [.github/pull_request_template.md](.github/pull_request_template.md).
134- **Governance**: [GOVERNANCE.md](GOVERNANCE.md), [MAINTAINERS.md](MAINTAINERS.md), [ROADMAP.md](ROADMAP.md).
135- **Claude project rules**: `CLAUDE.md` – mandatory rules (DCO, Go standards, CI/release, config schema) embedded as project instructions.
136- **Claude commands**: `.claude/commands/` – slash commands (e.g. `/feature`, `/bug`) that trigger the issue-writer workflow. Drafts are validated by issue-reviewer before creation.
137- **Claude skills**: `.claude/skills/` – workflows for documentation maintenance, releases, testing, and open-pull-request (open a PR from current changes via gh CLI).
138- **Getting started**: [docs/getting-started-terramate.md](docs/getting-started-terramate.md) and [docs/getting-started-local-stacks.md](docs/getting-started-local-stacks.md) – onboarding with GitHub Actions and neptbot (Terramate or local stacks).
139- **Neptune config**: [docs/configuration.md](docs/configuration.md) and [.neptune.example.yaml](.neptune.example.yaml) for `.neptune.yaml` schema; [docs/object-storage.md](docs/object-storage.md) for backend env vars.
140- **Why Neptune / workflow comparison**: [docs/workflow-comparison.md](docs/workflow-comparison.md) – comparison of normal Terraform + GitHub Actions, Neptune, and Atlantis; use when explaining rationale for apply-before-merge.
141
@@ −1 +1 @@
1+# AGENTS.md
2+
3+Guidance for AI coding agents working on the Neptune project.
4+
15 ---
2−description: Go style and conventions for Neptune
3−globs: "**/*.go"
4−alwaysApply: false
6+
7+## Project Overview
8+
9+**Neptune** is a Terraform and OpenTofu pull request automation tool inspired by [Atlantis](https://github.com/runatlantis/atlantis). It runs plan/apply (Terraform or OpenTofu) on pull requests using the [Terramate](https://github.com/terramate-io/terramate) Go SDK for change detection and run order. When a step has `once` false or unset (default), Neptune runs the step’s command in each changed stack (Terramate SDK or local stacks; no Terramate CLI needed when using Terramate); object storage (GCS or S3) is used for stack locking, and GitHub for PR requirements and comments.
10+
11+**Main capabilities**: Load config from `.neptune.yaml` and env; in CI (non-E2E), config is loaded from the repository’s default branch via git (fallback to PR branch) so PR authors cannot change workflow steps; check PR requirements (approved, mergeable, undiverged, rebased); lock stacks in object storage (GCS, AWS S3, or S3-compatible e.g. MinIO); run workflow steps (per-stack by default, or once in root when `once: true`); for stacks_management: local, **neptune stacks** provides list (--changed) and create, with **--format** (json, yaml, text, formatted; default formatted); when using discovery, run order can be set via **depends_on** in each **stack.hcl** (path-only; relative paths and directory-of-stacks supported); post results as PR comments. Optional `repository.automerge: true` enables PR auto-merge after a successful apply (GitHub GraphQL). Log level is configurable via `log_level` (config), `NEPTUNE_LOG_LEVEL`, or the global **--log-level** CLI flag (DEBUG, INFO, ERROR).
12+
13+**Language**: Go (see `go.mod`).
14+
515 ---
616
7−# Go Standards
17+## Repository Structure
818
9−- **Format**: Use `gofmt -s`. Run `make check-fmt` before committing. Use `git commit -s` for DCO sign-off (see [CONTRIBUTING.md](CONTRIBUTING.md)).
10−- **Lint**: Follow `.golangci.yml`; do not introduce new linter violations. Run `make lint` when available.
11−- **Packages**: Code in `internal/` must not be imported from outside this module.
12−- **Errors**: Always handle errors; add context with `fmt.Errorf("...: %w", err)` where useful.
13−- **Tests**: Place `*_test.go` in the same package as the code. Use table-driven tests when testing multiple cases.
14−- **Exports**: Public functions and types must have doc comments starting with the name (e.g. `// NewClient creates ...`).
19+- **`main.go`** – Entry point; version/commit/date via ldflags.
20+- **`cmd/`** – CLI (Cobra): `root.go` (global **--log-level** flag), `version.go`, `command.go`, `unlock.go`, `stacks.go` (stacks list, create; **--format** json|yaml|text|formatted, default formatted; **neptune stacks create** supports optional **--depends-on** comma-separated paths). **neptune stacks list** and **neptune stacks create** are for local use and do not require `GITHUB_TOKEN` or other CI env vars (unlike **neptune command** and **neptune unlock**).
21+- **`internal/config`** – Load env + YAML, validate `.neptune.yaml` (including optional `log_level`, `stacks_management`, root-level `local_stacks`).
22+- **`internal/domain`** – Config, lock, run, and GitHub domain structs (WorkflowStep uses `once`; RepositoryConfig has `StacksManagement`, `LocalStacks`).
23+- **`internal/log`** – Structured logging (DEBUG, INFO, ERROR) via `log/slog`; level from `NEPTUNE_LOG_LEVEL` or config `log_level`.
24+- **`internal/stacks`** – Stacks provider interface (terramate, local); list/changed stacks for locking and runner.
25+- **`internal/lock`** – Lock interface: gets stack list from stacks provider, object-storage lock files (GCS, S3).
26+- **`internal/run`** – Execute workflow phase steps (shell).
27+- **`internal/github`** – GitHub API client, PR requirements (approved, mergeable, undiverged), commit statuses (GetHeadSHA, CreateCommitStatus) for **neptune plan** / **neptune apply**; GraphQL EnablePullRequestAutoMerge when `repository.automerge` is true.
28+- **`internal/git`** – Rebased check; DefaultBranch (git CLI), ShowFileFromRef, FetchBranch for loading config from default branch.
29+- **`internal/notifications/github`** – Format and post PR comments.
30+- **`examples/`** – Infra examples (S3/GCS backend, automerge, Terramate stacks, Terragrunt).
31+- **`scripts/`** – Maintainer scripts (if any).
32+- **`e2e/`** – End-to-end tests: three Terramate stacks (null_resource/local_file), MinIO via Docker Compose, and `scripts/run-terramate.sh` that runs Neptune plan/apply with `NEPTUNE_E2E=1` (skips GitHub; see [e2e/README.md](e2e/README.md)).
33+- **`lambda/`** – AWS Lambda handler for Neptune GitHub App webhooks (verify signature, parse `pull_request`—including `labeled` when the added label is `NEPTUNE_PR_LABEL`—and `issue_comment`, trigger `repository_dispatch`; optional `NEPTUNE_PR_LABEL` gates on PR label). See [lambda/README.md](lambda/README.md).
34+- **`lambda/cloudformation/`** – CloudFormation template to deploy the Lambda (Function URL, IAM, Secrets Manager). See [lambda/README.md](lambda/README.md#deploy-with-cloudformation).
35+- **`Makefile`**, **`.golangci.yml`**, **`.goreleaser.yml`**, **`.github/workflows/`** – Build, test, lint, release.
36+- **`.claude/agents/` (migrated to hub)** – Agent definitions have been moved to the [code-agent-hub](https://github.com/devopsfactory-io/code-agent-hub) at `.claude/agents/neptune/`. Agents include: documentation-maintainer, em, go-developer, iac-developer, issue-reviewer, issue-writer, platform-engineering, pr-reviewer, qa, security.
37+- **`.claude/commands/`** – Claude slash commands: `/feature`, `/bug` (invoke the issue-writer workflow to create issues from the repo’s issue templates; the draft is validated by issue-reviewer before `gh issue create`).
38+- **Root community docs**: [CODE_OF_CONDUCT.md](CODE_OF_CONDUCT.md), [SECURITY.md](SECURITY.md), [GOVERNANCE.md](GOVERNANCE.md), [MAINTAINERS.md](MAINTAINERS.md), [ROADMAP.md](ROADMAP.md), [LICENSE](LICENSE).
39+
40+---
41+
42+## Setup Commands
43+
44+```bash
45+# Build binary
46+make build
47+
48+# Run all tests (main module)
49+make test-all
50+
51+# Lambda (separate module under lambda/): build, package, test
52+make lambda.build
53+make lambda.zip
54+make lambda.test
55+
56+# Check Go formatting (includes lambda/)
57+make check-fmt
58+
59+# Lint (optional; requires golangci-lint)
60+make lint
61+```
62+
63+Use Go version from `go.mod`. No other prerequisites for building or testing the Go CLI. CI runs `make test-all`, `make lambda.test`, and `make check-fmt`.
64+
65+---
66+
67+## Code Style
68+
69+- **Format**: Use `gofmt -s`; run `make check-fmt` before committing.
70+- **Linting**: `.golangci.yml` is authoritative; do not introduce new linter violations.
71+- **Packages**: Code under `internal/` must not be imported from outside this module.
72+- **Errors**: Return errors with context (e.g. `fmt.Errorf("...: %w", err)`); avoid naked returns.
73+- **Exports**: Public functions and types should have doc comments starting with the name.
74+
75+---
76+
77+## Testing
78+
79+- **Run**: `go test ./...` or `make test-all`.
80+- **Location**: Place `*_test.go` next to the code under test (same package).
81+- **Coverage**: Existing tests cover `internal/config`, `internal/git`, `internal/github`, `internal/run`, `internal/notifications/github`; add tests for new behavior and keep coverage for touched code.
82+- **No external services**: Unit tests should not require live GitHub or GCS; mock or stub as needed.
83+- **E2E**: Run `make e2e` or `./e2e/scripts/run-terramate.sh` (requires Docker, Terraform). Uses MinIO and `NEPTUNE_E2E=1` to skip GitHub. For **stacks_management: local**, run `./e2e/scripts/run-local-stacks-files.sh` or `./e2e/scripts/run-local-declared-stacks.sh`. E2E config uses steps with default `once: false` (Neptune runs commands per stack).
84+- **Automerge**: E2E and integration tests in this repo do not exercise the automerge feature. A separate repository (e.g. a fork or copy of [examples/](examples/)) can be used to test automerge end-to-end (e.g. open a PR with changes in two stacks, comment `@neptbot apply`, then verify the apply comment and that the PR is set to auto-merge after checks pass).
85+
86+---
87+
88+## CI
89+
90+- **`.github/workflows/test.yml`** – On push to `main`/`release-*` and on PRs; path filter for Go files; runs `make test-all` and `make check-fmt`.
91+- **`.github/workflows/e2e.yml`** – On push/PR when e2e-related paths change; runs `./e2e/scripts/run-terramate.sh` with MinIO (Docker Compose). See [e2e/README.md](e2e/README.md).
92+- **`.github/workflows/integration.yml`** – On PRs when integration-relevant paths change; runs Neptune plan/apply on the same PR with real GitHub (requirements check, PR comments, commit statuses) and MinIO for locks. Needs `statuses: write` for commit status API. See [e2e/README.md](e2e/README.md#integration-tests).
93+- **`.github/workflows/cross-repo-test.yml`** – On PRs (non-draft) to `main`/`release-*` when core paths change (`e2e/**`, `cmd/**`, `internal/**`, `lambda/**`, `go.*`); runs cross-repo integration tests against the external `neptune-tests` repository. Creates dynamic Terramate stacks on a throwaway branch in `neptune-tests`, opens a test PR with a `neptune-ref` marker, waits for neptbot to execute the full plan/apply webhook flow (up to 10 minutes each), verifies commit statuses (`neptune plan`, `neptune apply`), checks automerge state, and cleans up the branch and PR. Uses the `neptune-ci` GitHub App (secrets: `NEPTUNE_CI_APP_ID`, `NEPTUNE_CI_PRIVATE_KEY`) for cross-repo operations. Runs in parallel with `e2e.yml` and `integration.yml`.
94+- **`.github/workflows/lint.yml`** – On PRs; path filter for Go; runs golangci-lint.
95+- **`.github/workflows/labeler.yml`** – On pull_request (opened, synchronize, reopened); runs [actions/labeler](https://github.com/actions/labeler) with [.github/labeler.yml](.github/labeler.yml). Path-based: neptune, dependencies, documentation. Head-branch (branch name): `feat*`→feature, `enhance*`→enhancement, `fix*` (not fix*dep*)→bug, branch containing `!`→breaking-change, `ci*`→github-actions, `(deps)`→dependencies. See CONTRIBUTING.md for contributor-facing branch naming.
96+- **`.github/workflows/label-old-prs.yml`** – workflow_dispatch; applies the labeler to existing PRs (inputs: state e.g. merged/closed/all, limit). Use to backfill labels on old or merged PRs (Actions → "Label old PRs" → Run workflow). Because the labeler does not receive branch context on workflow_dispatch, a separate step applies the same rules as `.github/labeler.yml` to both head branch and PR title (e.g. `feat*`→feature if either branch or title matches), then the labeler runs for path-based labels.
97+- **`.github/workflows/release.yml`** – On push of tags `v*.*.*` (and workflow_dispatch); runs GoReleaser to create GitHub Release with neptune binaries (archives e.g. `neptune_linux_amd64.tar.gz` and raw binaries e.g. `neptune_linux_amd64`), Lambda zip (`neptune-webhook.zip`) and raw binary `neptune-webhook_linux_amd64` (Lambda binary is `neptune-webhook`; zip contains it), checksums, and release notes. The release body is generated by **GitHub** (GoReleaser uses `changelog.use: github-native`) and categorized using [.github/release.yml](.github/release.yml) and PR labels (Breaking Changes, Features, Bug fixes, Documentation, Dependency updates, Other work). Release footer includes Full Changelog link.
98+- **Renovate** – Dependency-update PRs (Go modules and GitHub Actions) are opened by [Renovate](https://docs.renovatebot.com/) from [.github/renovate.json5](.github/renovate.json5). To enable Renovate, install the [Renovate GitHub App](https://github.com/apps/renovate) and select the repo. Do not remove or override this config without reason.
99+
100+Semantic versioning: use tags like `v0.2.0`. GoReleaser injects version/commit/date into the binary via ldflags.
101+
102+**Changelog and breaking changes**: The release body is generated by GitHub (github-native) and categorized by [.github/release.yml](.github/release.yml) and **PR labels**. For breaking changes to appear under "Breaking Changes", apply the `breaking-change` label to the PR before merge. The commit subject convention (`!:`) is still recommended for semver (e.g. `feat!: remove deprecated flag`) but does not drive release-note sections; labels do.
103+
104+---
105+
106+## Documentation and AI Context (Mandatory)
107+
108+After any change that affects behavior, APIs, config, or CI:
109+
110+1. **Delegate**: Delegate documentation updates to the **documentation-maintainer** agent (defined in the hub at `.claude/agents/neptune/documentation-maintainer/`) so it runs the full maintain-documentation checklist (README, docs/, examples/, AGENTS.md, CLAUDE.md, .claude/commands, .claude/skills).
111+2. **Do not edit plan files** (e.g. `neptune_go_rewrite*.plan.md` or `ai_agent_config*.plan.md`) unless the user explicitly asks.
112+
113+When in doubt, update. See `CLAUDE.md` (Documentation rule, always applies) and the **maintain-documentation** skill (`.claude/skills/maintain-documentation/`); the agent holds the detailed checklist.
114+
115+---
116+
117+## PR Guidance
118+
119+Before submitting:
120+
121+1. **Commits must be signed off (DCO).** Use `git commit -s` when creating commits. Do not add a `Made-with: Cursor` (or similar) trailer to commit messages. If you already committed without sign-off, run `git commit --amend -s --no-edit` then force-push. See [CONTRIBUTING.md](CONTRIBUTING.md) and `CLAUDE.md` (DCO rule).
122+2. Run `make test-all` and `make check-fmt`.
123+3. Ensure no new linter errors (`make lint` if available).
124+4. If behavior or setup changed, delegate to the **documentation-maintainer** subagent.
125+5. **Branch naming**: Branch names matching [.github/labeler.yml](.github/labeler.yml) (e.g. `feat/...`, `fix/...`, `enhance/...`, `(deps)/...`, `ci/...`, or branch containing `!` for breaking) get PR labels applied automatically, which drive release-note categories. See [CONTRIBUTING.md](CONTRIBUTING.md#branch-naming-and-pr-labels).
126+
127+PR titles may follow a conventional style (e.g. `feat(cmd): ...`, `fix(lock): ...`, `docs: ...`) but this is not enforced.
128+
129+---
130+
131+## References
132+
133+- **Contributing (human)**: [CONTRIBUTING.md](CONTRIBUTING.md) – main entry for contributors; [CODE_OF_CONDUCT.md](CODE_OF_CONDUCT.md), [SECURITY.md](SECURITY.md); issue and PR templates in [.github/ISSUE_TEMPLATE/](.github/ISSUE_TEMPLATE/) and [.github/pull_request_template.md](.github/pull_request_template.md).
134+- **Governance**: [GOVERNANCE.md](GOVERNANCE.md), [MAINTAINERS.md](MAINTAINERS.md), [ROADMAP.md](ROADMAP.md).
135+- **Claude project rules**: `CLAUDE.md` – mandatory rules (DCO, Go standards, CI/release, config schema) embedded as project instructions.
136+- **Claude commands**: `.claude/commands/` – slash commands (e.g. `/feature`, `/bug`) that trigger the issue-writer workflow. Drafts are validated by issue-reviewer before creation.
137+- **Claude skills**: `.claude/skills/` – workflows for documentation maintenance, releases, testing, and open-pull-request (open a PR from current changes via gh CLI).
138+- **Getting started**: [docs/getting-started-terramate.md](docs/getting-started-terramate.md) and [docs/getting-started-local-stacks.md](docs/getting-started-local-stacks.md) – onboarding with GitHub Actions and neptbot (Terramate or local stacks).
139+- **Neptune config**: [docs/configuration.md](docs/configuration.md) and [.neptune.example.yaml](.neptune.example.yaml) for `.neptune.yaml` schema; [docs/object-storage.md](docs/object-storage.md) for backend env vars.
140+- **Why Neptune / workflow comparison**: [docs/workflow-comparison.md](docs/workflow-comparison.md) – comparison of normal Terraform + GitHub Actions, Neptune, and Atlantis; use when explaining rationale for apply-before-merge.
15141
