Skip to content

Commit cb058c2

Browse files
authored
Merge pull request #66 from open-platform-model/add-adr-system
docs: add ADR template and workflow instructions
2 parents 9c4b0d0 + 068af99 commit cb058c2

19 files changed

Lines changed: 887 additions & 180 deletions

AGENTS.md

Lines changed: 1 addition & 179 deletions
Original file line numberDiff line numberDiff line change
@@ -1,179 +1 @@
1-
# AGENTS.md - OPM CLI repository guide
2-
3-
## Purpose
4-
5-
This repository contains the OPM CLI, the command-line interface for Open
6-
Platform Model workflows. Its purpose is to let users build, validate,
7-
render, deploy, and inspect portable application releases defined with CUE,
8-
with a strong focus on type safety, clear command behavior, and Kubernetes-
9-
oriented workflows.
10-
11-
Primary stack: `cobra`, CUE Go SDK, Kubernetes `client-go`, `charmbracelet/log`, `testify`.
12-
13-
This file is for coding agents working in `cli/`.
14-
15-
## Repository Rules
16-
17-
- Keep changes small and independently verifiable; `CONSTITUTION.md` explicitly prefers tiny batches.
18-
- Prefer updating existing packages over introducing new abstractions unless duplication or coupling justifies it.
19-
20-
## Entrypoint
21-
22-
Read these documents when entering `cli/`:
23-
24-
- `CONSTITUTION.md` - repository principles and change-shaping constraints. Read `CONSTITUTION.md` for the full list of design principles.
25-
- `AGENTS.md` - repository-specific implementation guidance, commands, and package map.
26-
- `README.md` - product purpose, command groups, and user-facing workflows.
27-
- `docs/STYLE.md` - documentation prose style rules for this repo.
28-
29-
## Repository Layout
30-
31-
- `cmd/opm/` - CLI entrypoint and root command wiring.
32-
- `internal/cmd/` - Cobra command implementations.
33-
- `internal/cmdutil/` - shared flags, annotations, and command-facing helpers.
34-
- `internal/config/` - config resolution, schema validation, defaults.
35-
- `internal/kubernetes/` - cluster operations, status, apply, delete, events.
36-
- `internal/output/` - terminal formatting, log output, tables, manifests.
37-
- `internal/releasefile/` - release file detection and loading.
38-
- `internal/workflow/` - shared render/apply/query orchestration.
39-
- `pkg/loader/` - CUE loading for modules, providers, and releases.
40-
- `pkg/render/` - render pipeline logic.
41-
- `pkg/errors/` - shared structured errors; alias this import as `oerrors`.
42-
- `tests/integration/` - integration programs run with `go run`.
43-
- `tests/e2e/` - end-to-end Go tests.
44-
45-
## Environment Notes
46-
47-
- Go version in `go.mod`: `1.25.0`.
48-
- Integration and some CUE workflows rely on registry configuration.
49-
- Useful defaults during local development:
50-
51-
```bash
52-
export OPM_REGISTRY='opmodel.dev=localhost:5000+insecure,registry.cue.works'
53-
export CUE_REGISTRY='opmodel.dev=localhost:5000+insecure,registry.cue.works'
54-
```
55-
56-
## Build And Dev Commands
57-
58-
### Core commands
59-
60-
- `task build` - build `./bin/opm` from `./cmd/opm` with version ldflags.
61-
- `task build:all` - cross-compile for Linux, macOS, and Windows.
62-
- `task install` - install the CLI with version ldflags into `$GOPATH/bin`.
63-
- `task clean` - remove `bin/`, `coverage.out`, and `coverage.html`.
64-
- `task generate` - run `go generate ./...`.
65-
66-
### Formatting and static analysis
67-
68-
- `task fmt` - run `go fmt ./...` and `goimports -w .`.
69-
- `task vet` - run `go vet ./...`.
70-
- `task lint` - run `golangci-lint run ./...`.
71-
- `task lint:fix` - run `golangci-lint run --fix ./...`.
72-
- `task tidy` - run `go mod tidy`.
73-
- `task check` - run `fmt`, `vet`, `lint`, and all tests.
74-
75-
### Tests
76-
77-
- `task test` - run unit, integration, and e2e suites.
78-
- `task test:unit` - run `go test ./internal/...` and `go test ./pkg/...`.
79-
- `task test:integration` - run integration programs; requires a live kind cluster.
80-
- `task test:e2e` - run `go test ./tests/e2e/... -v`.
81-
- `task test:verbose` - run `go test -v ./...`.
82-
- `task test:coverage` - run `go test -coverprofile=coverage.out ./...` then generate `coverage.html`.
83-
84-
### Running one test
85-
86-
- Preferred repo task: `task test:run TEST=TestName`.
87-
- Exact implementation: `go test -v ./... -run "TestName"`.
88-
- Narrow to one package when possible for speed, for example:
89-
- `go test ./internal/config -run TestLoad -v`
90-
- `go test ./pkg/render -run TestFinalize -v`
91-
- For a single subtest, use the full regexp name accepted by `go test -run`.
92-
93-
### Integration cluster helpers
94-
95-
- `task cluster:create` - create local `kind` cluster `opm-dev`.
96-
- `task cluster:status` - check whether the cluster is running.
97-
- `task cluster:delete` - remove the local cluster.
98-
- `task cluster:recreate` - recreate the cluster from scratch.
99-
- `task test:integration` checks for context `kind-opm-dev` before it runs.
100-
101-
## Coding Standards
102-
103-
### General
104-
105-
- Follow `gofmt` and `goimports`; do not hand-format imports.
106-
- Keep command packages thin; orchestration belongs in `internal/workflow` or focused internal/pkg packages.
107-
- Prefer explicit behavior over magic inference; `CONSTITUTION.md` favors clear inputs and early validation.
108-
- Preserve cross-platform behavior; avoid hardcoded Unix-only paths or shell assumptions.
109-
110-
### Imports
111-
112-
- Group imports in standard Go order: stdlib, third-party, internal project imports.
113-
- Use blank lines between groups exactly as `goimports` produces them.
114-
- Alias `github.com/opmodel/cli/pkg/errors` as `oerrors` when imported.
115-
- Avoid unnecessary aliases for other packages unless there is a collision or a strong clarity reason.
116-
117-
### Types and APIs
118-
119-
- Prefer concrete structs as return values; accept interfaces at boundaries when they improve testability.
120-
- Avoid `interface{}` / `any` unless the API genuinely requires open-ended data.
121-
- Keep config, flags, and render inputs strongly typed.
122-
- Propagate `context.Context` through APIs that perform I/O, Kubernetes calls, or longer workflows.
123-
- This repo uses fresh CUE contexts per command/workflow rather than sharing one global mutable context.
124-
125-
### Naming
126-
127-
- Exported identifiers use Go's standard PascalCase; unexported identifiers use camelCase.
128-
- Use descriptive names tied to the domain: `ReleaseSelectorFlags`, `ResolveModulePath`, `BootstrapRegistry`.
129-
- Boolean helpers should read naturally, for example `HasWarnings` or `configHasProviders`.
130-
- Error sentinel names should follow Go conventions; the linter enables `errname` and revive naming rules.
131-
- Keep package names short, lowercase, and responsibility-focused.
132-
133-
### Error handling
134-
135-
- Validate early and fail before execution when flags, config, or inputs are invalid.
136-
- Wrap errors with context using `%w`, for example `fmt.Errorf("loading module: %w", err)`.
137-
- Prefer actionable user-facing errors with hints over raw internal failures.
138-
- Reuse structured error types in `pkg/errors` where appropriate, especially `DetailError` and validation helpers.
139-
- Commands should use `RunE` and return errors rather than printing-and-exiting inline.
140-
- Preserve sentinel errors with wrapping so callers can use `errors.Is` / `errors.As`.
141-
142-
### Control flow and package boundaries
143-
144-
- Commands parse flags and delegate; they should not hold core business logic.
145-
- `internal/` packages may depend on `pkg/`; `pkg/` must stay reusable and command-agnostic.
146-
- Keep output formatting separate from data generation.
147-
- Prefer small functions with clear responsibilities over large multipurpose helpers.
148-
149-
### Tests
150-
151-
- Prefer table-driven tests when covering multiple scenarios.
152-
- Use `require` for setup and fatal preconditions; use `assert` for non-fatal expectations.
153-
- Use `t.Helper()` in test helpers.
154-
- Prefer `t.TempDir()` over manual fixture directories when practical.
155-
- Name tests `TestXxx` with behavior-oriented suffixes, matching existing patterns like `TestRenderFromReleaseFile_NilConfig`.
156-
157-
## Lint Configuration Highlights
158-
159-
- `golangci-lint` runs in readonly module download mode.
160-
- Important enabled linters include `errorlint`, `errname`, `gocritic`, `gocyclo`, `gosec`, `revive`, `staticcheck`, and `tparallel`.
161-
- `nolint` comments must be specific and include an explanation.
162-
- `gocyclo` threshold is 15; refactor large branches before complexity grows.
163-
- Tests have some relaxed exclusions for `dupl`, `errcheck`, `goconst`, and `gosec`.
164-
- `examples/`, `experiments/`, `third_party/`, and `builtin/` are excluded from lint/format scopes.
165-
166-
## Documentation And Output Conventions
167-
168-
- Favor ASCII-safe output in docs, examples, and terminal-oriented text.
169-
- For box-drawing tables or diagrams, use `[x]` / `[ ]` instead of Unicode checkmarks.
170-
- When documenting CLI behavior, emphasize what happened and how to fix failures.
171-
- Follow SemVer and Conventional Commits for user-visible changes and commit messages.
172-
173-
## Agent Checklist
174-
175-
- Read the touched package and nearby tests before editing.
176-
- Run targeted tests first, then broader checks if the change warrants it.
177-
- If you changed formatting-sensitive files, run `task fmt`.
178-
- If you changed behavior, run the smallest relevant `go test` command plus any affected task.
179-
- Before finishing substantial work, prefer `task lint` and the relevant test suite.
1+
@CLAUDE.md

CLAUDE.md

Lines changed: 198 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1,198 @@
1-
@AGENTS.md
1+
# OPM CLI repository guide
2+
3+
## Purpose
4+
5+
OPM CLI — command-line interface for Open Platform Model workflows. Build, validate, render, deploy, inspect portable app releases defined with CUE. Focus: type safety, clear command behavior, Kubernetes-oriented workflows.
6+
7+
Stack: `cobra`, CUE Go SDK, Kubernetes `client-go`, `charmbracelet/log`, `testify`.
8+
9+
For coding agents working in `cli/`.
10+
11+
## Repository Rules
12+
13+
- Small, independently verifiable changes; `CONSTITUTION.md` prefers tiny batches.
14+
- Update existing packages over new abstractions unless duplication/coupling justifies it.
15+
16+
## Entrypoint
17+
18+
Read when entering `cli/`:
19+
20+
- `CONSTITUTION.md` - repo principles + change-shaping constraints.
21+
- `CLAUDE.md` - implementation guidance, commands, package map.
22+
- `README.md` - product purpose, command groups, user workflows.
23+
- `docs/STYLE.md` - doc prose style rules.
24+
25+
## Repository Layout
26+
27+
- `adr/` - Architecture Decision Records
28+
- `cmd/opm/` - CLI entrypoint + root command wiring.
29+
- `internal/cmd/` - Cobra command implementations.
30+
- `internal/cmdutil/` - shared flags, annotations, command-facing helpers.
31+
- `internal/config/` - config resolution, schema validation, defaults.
32+
- `internal/kubernetes/` - cluster ops, status, apply, delete, events.
33+
- `internal/output/` - terminal formatting, log output, tables, manifests.
34+
- `internal/releasefile/` - release file detection + loading.
35+
- `internal/workflow/` - shared render/apply/query orchestration.
36+
- `pkg/loader/` - CUE loading for modules, providers, releases.
37+
- `pkg/render/` - render pipeline logic.
38+
- `pkg/errors/` - shared structured errors; alias as `oerrors`.
39+
- `tests/integration/` - integration programs via `go run`.
40+
- `tests/e2e/` - end-to-end Go tests.
41+
42+
## Architecture Decision Records
43+
44+
ADRs capture significant technical decisions with context + consequences.
45+
46+
- Location: `adr/`
47+
- Template: `adr/TEMPLATE.md`
48+
- Naming: `NNN-kebab-case-title.md` (three-digit, zero-padded)
49+
50+
### Creating a new ADR
51+
52+
1. Copy `adr/TEMPLATE.md` to `adr/NNN-title.md` with next available number.
53+
2. Set status to `Proposed`.
54+
3. Fill Context, Decision, Consequences.
55+
4. Update status to `Accepted` once agreed.
56+
57+
### Updating an ADR
58+
59+
- Never delete — update status instead.
60+
- Retire: set status `Deprecated`.
61+
- Replace: set status `Superseded by ADR-NNN`, create new ADR.
62+
- One decision per ADR.
63+
64+
## Environment Notes
65+
66+
- Go version in `go.mod`: `1.25.0`.
67+
- Integration + CUE workflows need registry config.
68+
- Local dev defaults:
69+
70+
```bash
71+
export OPM_REGISTRY='opmodel.dev=localhost:5000+insecure,registry.cue.works'
72+
export CUE_REGISTRY='opmodel.dev=localhost:5000+insecure,registry.cue.works'
73+
```
74+
75+
## Build And Dev Commands
76+
77+
### Core commands
78+
79+
- `task build` - build `./bin/opm` from `./cmd/opm` with version ldflags.
80+
- `task build:all` - cross-compile for Linux, macOS, Windows.
81+
- `task install` - install CLI with version ldflags into `$GOPATH/bin`.
82+
- `task clean` - remove `bin/`, `coverage.out`, `coverage.html`.
83+
- `task generate` - run `go generate ./...`.
84+
85+
### Formatting and static analysis
86+
87+
- `task fmt` - run `go fmt ./...` and `goimports -w .`.
88+
- `task vet` - run `go vet ./...`.
89+
- `task lint` - run `golangci-lint run ./...`.
90+
- `task lint:fix` - run `golangci-lint run --fix ./...`.
91+
- `task tidy` - run `go mod tidy`.
92+
- `task check` - run `fmt`, `vet`, `lint`, all tests.
93+
94+
### Tests
95+
96+
- `task test` - run unit, integration, e2e suites.
97+
- `task test:unit` - run `go test ./internal/...` and `go test ./pkg/...`.
98+
- `task test:integration` - run integration programs; needs live kind cluster.
99+
- `task test:e2e` - run `go test ./tests/e2e/... -v`.
100+
- `task test:verbose` - run `go test -v ./...`.
101+
- `task test:coverage` - run `go test -coverprofile=coverage.out ./...` then generate `coverage.html`.
102+
103+
### Running one test
104+
105+
- Preferred: `task test:run TEST=TestName`.
106+
- Direct: `go test -v ./... -run "TestName"`.
107+
- Narrow to one package for speed:
108+
- `go test ./internal/config -run TestLoad -v`
109+
- `go test ./pkg/render -run TestFinalize -v`
110+
- Single subtest: use full regexp name via `go test -run`.
111+
112+
### Integration cluster helpers
113+
114+
- `task cluster:create` - create local `kind` cluster `opm-dev`.
115+
- `task cluster:status` - check cluster running.
116+
- `task cluster:delete` - remove local cluster.
117+
- `task cluster:recreate` - recreate cluster from scratch.
118+
- `task test:integration` checks for context `kind-opm-dev` before running.
119+
120+
## Coding Standards
121+
122+
### General
123+
124+
- Follow `gofmt` and `goimports`; no hand-formatting imports.
125+
- Keep command packages thin; orchestration in `internal/workflow` or focused internal/pkg packages.
126+
- Explicit behavior over magic inference; `CONSTITUTION.md` favors clear inputs + early validation.
127+
- Preserve cross-platform behavior; no hardcoded Unix-only paths or shell assumptions.
128+
129+
### Imports
130+
131+
- Standard Go order: stdlib, third-party, internal project imports.
132+
- Blank lines between groups as `goimports` produces.
133+
- Alias `github.com/opmodel/cli/pkg/errors` as `oerrors`.
134+
- No unnecessary aliases unless collision or strong clarity reason.
135+
136+
### Types and APIs
137+
138+
- Concrete structs as return values; interfaces at boundaries for testability.
139+
- No `interface{}` / `any` unless API genuinely needs open-ended data.
140+
- Config, flags, render inputs: strongly typed.
141+
- Propagate `context.Context` through I/O, Kubernetes calls, longer workflows.
142+
- Fresh CUE contexts per command/workflow, not one global mutable context.
143+
144+
### Naming
145+
146+
- Exported: PascalCase; unexported: camelCase.
147+
- Descriptive domain names: `ReleaseSelectorFlags`, `ResolveModulePath`, `BootstrapRegistry`.
148+
- Booleans read naturally: `HasWarnings`, `configHasProviders`.
149+
- Error sentinels follow Go conventions; linter enables `errname` + revive naming rules.
150+
- Package names: short, lowercase, responsibility-focused.
151+
152+
### Error handling
153+
154+
- Validate early, fail before execution on invalid flags/config/inputs.
155+
- Wrap errors with context via `%w`: `fmt.Errorf("loading module: %w", err)`.
156+
- Actionable user-facing errors with hints over raw internal failures.
157+
- Reuse `pkg/errors` types, especially `DetailError` + validation helpers.
158+
- Commands use `RunE`, return errors — no print-and-exit inline.
159+
- Preserve sentinel errors via wrapping for `errors.Is` / `errors.As`.
160+
161+
### Control flow and package boundaries
162+
163+
- Commands parse flags + delegate; no core business logic.
164+
- `internal/` depends on `pkg/`; `pkg/` stays reusable + command-agnostic.
165+
- Output formatting separate from data generation.
166+
- Small focused functions over large multipurpose helpers.
167+
168+
### Tests
169+
170+
- Table-driven tests for multiple scenarios.
171+
- `require` for setup/fatal preconditions; `assert` for non-fatal expectations.
172+
- `t.Helper()` in test helpers.
173+
- `t.TempDir()` over manual fixture dirs when practical.
174+
- Name `TestXxx` with behavior suffixes, e.g. `TestRenderFromReleaseFile_NilConfig`.
175+
176+
## Lint Configuration Highlights
177+
178+
- `golangci-lint` runs in readonly module download mode.
179+
- Key linters: `errorlint`, `errname`, `gocritic`, `gocyclo`, `gosec`, `revive`, `staticcheck`, `tparallel`.
180+
- `nolint` comments must be specific with explanation.
181+
- `gocyclo` threshold: 15; refactor before complexity grows.
182+
- Tests relax `dupl`, `errcheck`, `goconst`, `gosec`.
183+
- `examples/`, `experiments/`, `third_party/`, `builtin/` excluded from lint/format.
184+
185+
## Documentation And Output Conventions
186+
187+
- ASCII-safe output in docs, examples, terminal text.
188+
- Box-drawing: `[x]` / `[ ]` not Unicode checkmarks.
189+
- CLI docs: emphasize what happened + how to fix failures.
190+
- Follow SemVer + Conventional Commits for user-visible changes.
191+
192+
## Agent Checklist
193+
194+
- Read touched package + nearby tests before editing.
195+
- Run targeted tests first, broader checks if warranted.
196+
- Changed formatting files → run `task fmt`.
197+
- Changed behavior → run smallest relevant `go test` + affected task.
198+
- Before finishing substantial work → `task lint` + relevant test suite.

0 commit comments

Comments
 (0)