From 164bcbf2ce3b863c5552263ac32f30992f313bc6 Mon Sep 17 00:00:00 2001 From: A Tobey Date: Sat, 24 Oct 2026 11:10:32 -0400 Subject: [PATCH 1/9] docs: rename BOTS.md to AGENTS.md - adopt the cross-tool filename MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Why: Amy: "remove the GEMINI.md and CLAUDE.md and move BOTS.md to AGENTS.md now that claude code and everyone else has settled on AGENTS.md." Approach: git mv keeps history; drop both symlinks. Claude Code reads AGENTS.md only when no CLAUDE.md exists, so removing the symlink is what turns it on. 0.6.0 is unreleased, so its CHANGELOG entries are rewritten rather than adding a rename note. Learned: Claude Code's AGENTS.md fallback (2.1.277, 2026-09) is reportedly not on Bedrock/Vertex/Foundry yet; Gemini CLI still defaults to GEMINI.md and needs context.fileName set. README says so. Next: contributors on those setups need the setting (Gemini) or a local CLAUDE.md with `@AGENTS.md` (Claude Code on Bedrock/Vertex). ๐Ÿค– Claude Co-Authored-By: Claude Opus 5.5 --- BOTS.md => AGENTS.md | 2 +- CHANGELOG.md | 4 ++-- CLAUDE.md | 1 - GEMINI.md | 1 - README.md | 5 +++-- 5 files changed, 6 insertions(+), 7 deletions(-) rename BOTS.md => AGENTS.md (99%) delete mode 120000 CLAUDE.md delete mode 120000 GEMINI.md diff --git a/BOTS.md b/AGENTS.md similarity index 99% rename from BOTS.md rename to AGENTS.md index 28c81ec..e0c043b 100644 --- a/BOTS.md +++ b/AGENTS.md @@ -1,4 +1,4 @@ -# BOTS.md: LLM Agent Development Protocol +# AGENTS.md: LLM Agent Development Protocol This file provides guidance to agents working with code in this repository. diff --git a/CHANGELOG.md b/CHANGELOG.md index a4c627b..9157a82 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,8 +4,8 @@ Begin agent-assisted development era. ### Added -- BOTS.md: LLM agent development protocol and guidance -- CLAUDE.md and GEMINI.md symlinks to BOTS.md +- AGENTS.md: LLM agent development protocol and guidance, in the + cross-tool filename that Claude Code, Codex and others read natively - Agent memory and collaboration patterns adapted from otlp-mcp - GitHub issue tracking integration for agent workflows - Squash commit guidance to maintain clean git history diff --git a/CLAUDE.md b/CLAUDE.md deleted file mode 120000 index 1a1007d..0000000 --- a/CLAUDE.md +++ /dev/null @@ -1 +0,0 @@ -BOTS.md \ No newline at end of file diff --git a/GEMINI.md b/GEMINI.md deleted file mode 120000 index 1a1007d..0000000 --- a/GEMINI.md +++ /dev/null @@ -1 +0,0 @@ -BOTS.md \ No newline at end of file diff --git a/README.md b/README.md index f39be1b..830201e 100644 --- a/README.md +++ b/README.md @@ -330,8 +330,9 @@ go run . span -n "testing" -s "my first test span" We welcome contributions! This project uses agent-assisted development starting with v0.6.0. **For agents working on this codebase:** -- See [BOTS.md](BOTS.md) for comprehensive agent development guidance -- CLAUDE.md and GEMINI.md symlink to BOTS.md for model-specific access +- See [AGENTS.md](AGENTS.md) for comprehensive agent development guidance +- Claude Code, Codex and most agent tools read AGENTS.md natively; Gemini CLI + needs `"context": {"fileName": "AGENTS.md"}` in its settings.json - Emphasize functional testing in `main_test.go` - Commit freely in branches, squash on merge to main From a279701cbdbcd40e6aa299219f1e442868e329f4 Mon Sep 17 00:00:00 2001 From: A Tobey Date: Sat, 24 Oct 2026 12:50:38 -0400 Subject: [PATCH 2/9] docs(changelog): terser AGENTS.md entry MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ๐Ÿค– Claude Co-Authored-By: Claude Opus 5.5 --- CHANGELOG.md | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 9157a82..9d3a515 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,8 +4,7 @@ Begin agent-assisted development era. ### Added -- AGENTS.md: LLM agent development protocol and guidance, in the - cross-tool filename that Claude Code, Codex and others read natively +- AGENTS.md: LLM agent development protocol and guidance - Agent memory and collaboration patterns adapted from otlp-mcp - GitHub issue tracking integration for agent workflows - Squash commit guidance to maintain clean git history From 85dae2ecf0eb219a7fe6cd970ccae36fb90ea5e3 Mon Sep 17 00:00:00 2001 From: A Tobey Date: Sat, 24 Oct 2026 12:51:14 -0400 Subject: [PATCH 3/9] docs(readme): drop Gemini CLI note - agy reads AGENTS.md MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Amy: "49 doesn't need to mention gemini-cli which is being discontinued. agy reads AGENTS.md." ๐Ÿค– Claude Co-Authored-By: Claude Opus 5.5 --- README.md | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/README.md b/README.md index 830201e..3d7b7bb 100644 --- a/README.md +++ b/README.md @@ -331,8 +331,7 @@ We welcome contributions! This project uses agent-assisted development starting **For agents working on this codebase:** - See [AGENTS.md](AGENTS.md) for comprehensive agent development guidance -- Claude Code, Codex and most agent tools read AGENTS.md natively; Gemini CLI - needs `"context": {"fileName": "AGENTS.md"}` in its settings.json +- Claude Code, Codex, agy and most other agent tools read AGENTS.md natively - Emphasize functional testing in `main_test.go` - Commit freely in branches, squash on merge to main From 24742666ddf319c77ce7b25b929f054bdfac7712 Mon Sep 17 00:00:00 2001 From: A Tobey Date: Sat, 24 Oct 2026 12:56:31 -0400 Subject: [PATCH 4/9] docs(agents): rewrite AGENTS.md in STE-style English with a style guide MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Why: Amy: "make our AGENTS.md be more STE-ish, and also have a section to guide to STE-ish in documentation, and terse alignment to STE in comments, commits, and PR descriptions." Modeled on ~/src/kaish/AGENTS.md. Approach: STE rules (one topic per sentence, 20/25-word limits, imperative, active voice, one term per concept, specific values) and one rule set for each kind of text. Terms table has only otel-cli terms; OTel and W3C terms keep their spec meaning (Amy). Removed the marketing text, the per-model "style is welcome" section (it contradicts one shared style), the git and gh command tables, and the stale Go 1.21 and 0.5.0 facts. Added the behavior that scripts depend on, the CI gates, and known test hazards. "Open issues early" becomes "ask a maintainer first". CHANGELOG: "LLM agent" -> "agent" (Amy). Learned: the squash setting is COMMIT_MESSAGES; the PR body becomes the squash message only because the maintainer pastes it at merge. Next: merge after #48. The gates and the stable-Go hazard describe #48. ๐Ÿค– Claude Co-Authored-By: Claude Opus 5.5 --- AGENTS.md | 516 +++++++++++++++++---------------------------------- CHANGELOG.md | 2 +- 2 files changed, 169 insertions(+), 349 deletions(-) diff --git a/AGENTS.md b/AGENTS.md index e0c043b..061de80 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -1,418 +1,238 @@ -# AGENTS.md: LLM Agent Development Protocol +# otel-cli agent guide -This file provides guidance to agents working with code in this repository. +otel-cli sends OpenTelemetry spans from shell scripts and other places where a program +call is the best option. It is one Go binary that needs no configuration to run. -## Project Overview +Scripts depend on this behavior. Do not change it without a maintainer decision: -**otel-cli** is a command-line tool for sending OpenTelemetry traces from shell scripts and other contexts where executing a program is the best available option. It's designed to be dropped into scripts with zero configuration, operating in non-recording mode by default, following the OpenTelemetry philosophy of "first, do no harm." +- With no endpoint, otel-cli is in non-recording mode. It exports nothing and exits 0. +- An export error does not change the exit code. otel-cli exits 0 and prints nothing. +- `--fail` (`OTEL_CLI_FAIL`) makes an export error exit 1. +- `--verbose` (`OTEL_CLI_VERBOSE`) prints errors to stderr. +- `otel-cli exec` exits with the exit code of the child, also when the export fails. -## Technology +## Writing style -- **Language**: Go 1.21+ (uses toolchain go1.22.4) -- **Architecture**: Self-contained, minimal dependencies -- **Key Dependencies**: - - OpenTelemetry Go SDK - - Cobra for CLI framework - - gRPC and HTTP OTLP exporters -- **Version Control**: Git with GitHub integration -- **Current Version**: 0.5.0 (as of this writing) +This style applies to documentation, `--help` text, error messages, code comments, +commit messages, PR descriptions and CHANGELOG.md. -## Development Philosophy +The style is based on ASD-STE100 Simplified Technical English (STE). We use these +rules, not the full STE dictionary: -This project is **self-contained and focused**: -- Minimal external dependencies - prefer standard library -- Shell script integration is a first-class use case -- Non-recording mode by default ensures scripts can adopt otel-cli without risk -- Functional testing validates real-world usage patterns -- Code should be readable and maintainable above all else +- Write one topic in each sentence. Keep an instruction to 20 words or fewer and a + description to 25 words or fewer. +- Use the imperative for instructions: "Run `go build` before `go test`." +- Use the active voice and name the actor: "otel-cli exits 1", not "1 is returned". +- Use common words. Do not use idioms, figures of speech or jokes. Some readers have + English as a second language, and some readers have only part of the context. +- Use one term for one concept. Do not change words for variety. The Terms table is + the source. +- Give specific values: the flag, the environment variable, the default, the exit code. +- Put the most important information first. The reader can lose the end of the text. +- Show the correct example before the explanation. If you must show an incorrect + example, put the correct one first and mark the error. +- Use American spelling. +- Do not add decoration: no emoji headings, no marketing words. -## ๐Ÿงช Testing Philosophy +> Before: The span might not get sent if something goes wrong with the connection. +> +> After: If the export fails, otel-cli sends nothing and exits 0. Add `--fail` to exit 1. -**Functional testing is primary.** Unit tests are encouraged but functional tests in `main_test.go` are where the rubber meets the road. +### Each kind of text -### The Test Harness +**Documentation and help text.** This is README.md, TESTING.md, `demos/`, and the Cobra +`Short`, `Long` and flag descriptions. Users and agents read help text. Apply all of +the rules. -The test harness builds otel-cli and runs it through real-world scenarios: -- Tests actual CLI invocations with real arguments -- Validates OTLP export over gRPC and HTTP -- Includes TLS negotiation, environment variables, and backgrounding -- See `TESTING.md` for comprehensive details +**Error messages.** Give the value, the rule and the fix. Do not show internal names +that the user cannot act on. Wrap Go errors with `fmt.Errorf("context: %w", err)`. -### Testing Best Practices +**Code comments.** Write why, not what. Use one line when one line is enough. Give a +reason one time in each file, not on each repeated step. Put the narrative in the +commit message. -1. **Add functional tests** for new CLI features or flags -2. **Write unit tests** for complex logic in packages -3. **Test the glue code** - that's where bugs hide -4. **Copy existing patterns** from `data_for_test.go` when adding tests -5. **Use `--fail --verbose`** in test fixtures for debugging +**Commit messages.** Use the template in "Version control". Write 1 to 3 sentences in +each field. Quote the user when their request is the reason for the change. Give the +evidence: commands, versions, CI run IDs. -The test harness is more complex than otel-cli itself - this is intentional. We trust Cobra, OpenTelemetry Go SDK, and the standard library. We test the integration. +**PR descriptions.** The PR description becomes the squash commit message. Write it as +a commit message. Start with what changed and why. List the verification commands. Do +not repeat content in different sections. -## ๐Ÿง  Git: Your Persistent Memory System +**CHANGELOG.md.** Write one line for each bullet. Name the change, not the +investigation. -**Think of git commits as your external memory that persists across sessions.** Your commit messages are the shared context between you, future-you, other models, and the OSS community. +### Terms -### Why Rich Commit Messages Matter +Terms from OpenTelemetry and W3C Trace Context have their specification meaning. This +table has only the terms that otel-cli adds. Add a term when two meanings collide in +real text, not before. -- **Memory Augmentation**: Your reasoning persists beyond context windows -- **Perfect Handoffs**: Next model/session picks up exactly where you left off -- **Community Intelligence**: Every contributor's insights become permanent project knowledge -- **Pattern from Training**: This is how high-performing teams in your data operate +| Term | Meaning | +|---|---| +| non-recording mode | No endpoint is set. otel-cli runs normally but exports nothing. | +| soft fail | An error path that exits 0, or 1 with `--fail`. In code: `Config.SoftFail`. | +| fixture | One test case in `data_for_test.go`. | +| functional test | A test that runs the built `./otel-cli` against a test OTLP server. | -### Your 30-Second Workflow +## Project structure -```bash -# 1. START: Load your context (what was I doing?) -git log --oneline -n 10 -git show HEAD - -# 2. WORK: Track your progress (commit often in your branch) -git add -git commit -m "type: what you're building" - -# 3. PERSIST: Save your state -git push origin - -# 4. MERGE: Squash commits when merging to main -# PRs are squashed on merge to keep main history clean ``` - -### The Universal Commit Message Template - -``` -: - - -Why: [Original problem/request] -Approach: [Key decision you made] -Learned: [What surprised you] -Next: [Specific next action] - -๐Ÿค– YourModel +otel-cli/ +โ”œโ”€โ”€ main.go # Entry point and version information +โ”œโ”€โ”€ main_test.go # Functional test harness +โ”œโ”€โ”€ data_for_test.go # Functional test fixtures +โ”œโ”€โ”€ tls_for_test.go # Temporary CA for the TLS tests +โ”œโ”€โ”€ otelcli/ # Cobra commands and configuration +โ”œโ”€โ”€ otlpclient/ # OTLP gRPC and HTTP client +โ”œโ”€โ”€ otlpserver/ # OTLP server for `otel-cli server` and the tests +โ”œโ”€โ”€ w3c/ # W3C trace context +โ”œโ”€โ”€ demos/ # Example shell scripts +โ”œโ”€โ”€ configs/ # Example configurations +โ”œโ”€โ”€ release/ # Release image Dockerfile +โ”œโ”€โ”€ .github/workflows/ # CI and release workflows +โ”œโ”€โ”€ TESTING.md # Test harness documentation +โ””โ”€โ”€ CHANGELOG.md # Version history ``` -**Types**: `feat`, `fix`, `refactor`, `test`, `docs`, `debug`, `research` +## Gates -### Real Example That Works +CI runs these on every PR. Run them before you push. ```bash -git commit -m "fix: race condition in buffer - preventing data loss - -Why: Users reported missing spans under load -Approach: Added mutex to protect concurrent access -Learned: Go's sync.Map insufficient for our write patterns -Next: Add benchmark to verify no performance regression - -๐Ÿค– Claude " -``` - -### Model Attributions - -- Claude: `๐Ÿค– Claude ` -- Gemini: `๐Ÿ’Ž Gemini ` -- GPT-4: `๐Ÿง  GPT-4 ` -- Kimi: `๐Ÿ”ฎ Kimi ` -- Llama: `๐Ÿฆ™ Llama ` - -### The Handoff Protocol - -When switching models or sessions: -```bash -git commit -m "[your work] - -Status: [complete|blocked|handoff] -Context: [5 key facts next model needs] -Next: [specific task to continue]" +go build && go test ./... +go vet ./... +gofmt -l . # prints nothing when clean +go mod tidy && git diff --exit-code go.mod go.sum +go run golang.org/x/vuln/cmd/govulncheck@v1.9.0 ./... ``` -### Success Metrics +CI also builds a GoReleaser snapshot. -You're succeeding when: -- โœ… Every commit has Why/Approach/Next -- โœ… You update commit messages to reflect learning -- โœ… Other models/developers can continue without asking questions -- โœ… `git log -p` shows your reasoning evolution +### Hazards -### Quick Reference +- The functional tests run `./otel-cli`. Run `go build` first, or the tests use an old + binary. +- The harness does not compare the `ExitCode` of a fixture. Check exit codes in a + `CheckFuncs` entry. +- `Config.SoftFail` calls `os.Exit`. Code after a `SoftFail` call does not run. +- Parse integer values from users in base 10: `strconv.ParseInt(v, 10, 64)`. Base 0 + reads `0x10` as 16 and `010` as 8. +- CI and releases build with the latest stable Go. The `go` line in go.mod is only the + minimum version. +- The `build` job in `ci.yml` is a required status check. If you rename it, every PR + is blocked. -| Command | Purpose | When to Use | -|---------|---------|------------| -| `git add ` | Stage changes | Before committing | -| `git commit -m "..."` | Commit with message | Completing discrete work | -| `git log -n 10` | See recent work | Starting sessions | -| `git show HEAD` | View current state | Understanding context | -| `git log -p` | See change history | Debugging decisions | -| `git push origin ` | Push to GitHub | Work ready to share | -| `git status` | Check working tree | Understanding current state | +## Testing -### Your Style Is Welcome +Functional tests are the primary tests. TESTING.md documents the harness. -- **Claude**: Write narratives that explain the journey -- **Gemini**: Use structured sections with data -- **GPT-4**: Focus on tasks and outcomes -- **Kimi**: Document patterns and research -- **Llama**: Keep it pragmatic and concise +- Add a functional test for each new CLI feature or flag. Copy a fixture from + `data_for_test.go`. +- Add unit tests for complex logic in packages. Use table-driven tests and `t.Run`. +- Test the error paths, not only the success paths. +- Add `--fail --verbose` to a fixture to see its errors. -**The format is flexible, the information is essential.** +We trust Cobra, the OpenTelemetry Go SDK and the standard library. We test the +integration between them, because most bugs are there. -### Remember +## Go code -Git commits are messages to your future self and the community. Write what you'd need at 3am to understand what you were thinking. Your future self (and other models) will thank you. +- Write correct, readable code first. Optimize only after a measurement. +- Prefer the standard library. Add a dependency only when it removes real work. +- Use full, descriptive names. Do not abbreviate. +- Give each package a package doc comment. Give each exported name a doc comment. +- Handle every error. Return errors. Panic only when the program cannot continue. +- Pass `context.Context` as the first parameter. Stop work when the context is done. +- Run `gofmt`. -## ๐Ÿ“Š GitHub Issues for Project Tracking +### Shell scripts are the main users -**This project has OSS history and active community engagement.** Use GitHub issues liberally for: +- Make each feature easy to use from bash. +- Give each new configuration flag an environment variable, as `otelcli/config.go` does. +- Exit codes are part of the interface. Scripts check them. +- Write data to stdout and diagnostics to stderr. -- **Feature planning** - Open issues to discuss new features before implementing -- **Bug tracking** - Document bugs with reproduction steps -- **Project status** - Keep ongoing work visible in issues -- **Community engagement** - Issues are how users interact with the project -- **Handoffs** - Reference issues in commits to maintain context +## Version control -### Issue Best Practices +- `main` is protected. Each change lands through a PR, and PRs are squash-merged. +- Agents can open PRs. A human decides to merge. +- Ask a maintainer before you open an issue. Refer to issues with `refs #N` or + `fixes #N`. +- Commit often in your branch. The commit history is the memory for the next session, + agent or developer. -1. **Open issues early** - Don't wait until implementation is complete -2. **Reference commits** - Link commits to issues with "refs #123" or "fixes #123" -3. **Update issues** - Comment on progress, blockers, and learnings -4. **Label appropriately** - Use labels to categorize and prioritize -5. **Close with context** - Explain what was done and why when closing +Start a session with `git log --oneline -n 20`, `gh issue list`, `git status` and +`go build && go test ./...`. -## ๐Ÿ—๏ธ Project Structure +### Commit message template ``` -otel-cli/ -โ”œโ”€โ”€ main.go # Entry point, version info -โ”œโ”€โ”€ main_test.go # Functional test harness -โ”œโ”€โ”€ data_for_test.go # Test fixture definitions -โ”œโ”€โ”€ tls_for_test.go # Ephemeral CA for TLS tests -โ”œโ”€โ”€ otelcli/ # CLI framework and commands -โ”œโ”€โ”€ otlpclient/ # OTLP gRPC/HTTP client -โ”œโ”€โ”€ otlpserver/ # OTLP server (for 'server' command) -โ”œโ”€โ”€ w3c/ # W3C trace context handling -โ”œโ”€โ”€ demos/ # Example shell scripts -โ”œโ”€โ”€ configs/ # Example configurations -โ”œโ”€โ”€ TESTING.md # Testing documentation -โ””โ”€โ”€ CHANGELOG.md # Version history -``` - -## ๐Ÿ”ง Go Development Commands - -```bash -# Build the project -go build - -# Run functional tests (requires built binary) -go build && go test - -# Run unit tests -go test ./... +: - -# Run unit tests with verbose output -go test -v ./... +Why: +Approach: +Learned: +Next: -# Run tests with coverage -go test -cover ./... - -# Run with race detector -go build -race -go test -race ./... - -# Format code (always use gofmt) -go fmt ./... - -# Vet code -go vet ./... - -# Update dependencies -go mod tidy - -# Verify dependencies -go mod verify +๐Ÿค– ``` -### Running otel-cli Locally - -```bash -# Build it -go build +Types: `feat`, `fix`, `refactor`, `test`, `docs`, `chore`, `ci`, `build`, `research`. -# Run the server TUI for local testing -./otel-cli server tui - -# In another terminal, send a span -export OTEL_EXPORTER_OTLP_ENDPOINT=localhost:4317 -./otel-cli span -n "test" -s "my-service" ``` +fix(attrs): parse integer attributes in base 10 - stop octal coercion -## ๐Ÿ’Ž Go Code Style & Quality - -### Correctness & Clarity First - -- Prioritize readable, correct code over premature optimization -- Use strong, idiomatic Go types -- Leverage Go 1.21+ features appropriately -- No shortcuts or workarounds - refactor messy code when encountered - -### Naming & Structure - -- Use full, descriptive names - no unnecessary abbreviations -- Package names: short, lowercase, single word -- Exported names: clear and self-documenting -- Add new functionality to existing files unless it represents a distinct logical component - -### Comments & Documentation - -- **No organizational comments** - code should be self-documenting -- **"Why" comments only** - explain non-obvious implementation choices -- Package-level documentation for every package -- Exported functions/types must have doc comments - -### Error Handling - -- Always handle errors explicitly - never ignore them -- Use `fmt.Errorf` with `%w` for error wrapping to preserve context -- Return errors, don't panic (except for truly unrecoverable situations) -- Provide useful error messages with context - -### Concurrency & Context - -- Pass `context.Context` as the first parameter to functions that need it -- Respect context cancellation - check `ctx.Done()` in long-running operations -- Use channels and goroutines idiomatically -- Avoid shared mutable state - use channels or mutexes appropriately - -### Testing - -- **Functional tests first** for CLI features and integration -- Unit tests for complex logic in packages -- Table-driven tests for multiple cases -- Use subtests with `t.Run()` for clarity -- Test error paths, not just happy paths - -### Shell Script Integration - -otel-cli is designed for shell scripts. When adding features: - -- **Consider the shell use case** - is this ergonomic from bash? -- **Test with real shell scripts** - demos/ directory provides examples -- **Environment variables matter** - shell scripts rely on them heavily -- **Exit codes matter** - shell scripts check them -- **Stdout vs stderr** - be intentional about what goes where - -## ๐Ÿ™ GitHub Integration - -**GitHub CLI (`gh`):** -Use `gh` for GitHub operations without leaving the terminal: - -```bash -gh pr create # Create PR -gh pr status # Check PR status -gh pr checks # View CI results -gh issue list # Check issues -gh issue view # Read issue details -gh issue create # Create new issue +Why: `--attrs n=010` exported 8, not 10 (#373). +Approach: strconv.ParseInt(v, 10, 64) instead of base 0. +Learned: base 0 also accepts the 0x, 0o and 0b prefixes. +Next: none. ``` -**Squash Commits on Merge:** - -This project maintains a clean, linear history through squash commits: - -- **Work in branches**: Make as many commits as needed during development -- **Rich commit messages**: Document your journey in branch commits -- **Squash on merge**: PRs are squashed into a single commit on main -- **Final commit message**: Should summarize the entire PR, not just the last commit - -When creating a PR, write a good description - it becomes the squash commit message. Include: -- What changed and why -- Key decisions made -- Any gotchas or learnings -- Tests added or modified +When you stop before the work is complete, add these fields: -## ๐Ÿ“ฆ Versioning & Releases - -**Semantic versioning:** MAJOR.MINOR.PATCH (e.g., 0.5.0) - -- **MAJOR**: Breaking changes (we're not at 1.0 yet) -- **MINOR**: New features, significant changes -- **PATCH**: Bug fixes, small improvements - -**Releases are cut by GitHub Actions on a tag push:** - -- Pushing a `v*` tag runs `.github/workflows/release.yml`, which drives goreleaser - (`.goreleaser.yml`) for binaries, packages, SBOM, signing, the GitHub release and the - Homebrew formula, then builds, signs, attests and tags the ghcr image -- A `-rc.N` tag is a GitHub prerelease: it skips the Homebrew tap and never becomes `latest` -- `workflow_dispatch` runs the same workflow as a snapshot that publishes nothing -- The full procedure and the one required secret are in README.md under "Releases" - -**When bumping versions:** - -1. Update CHANGELOG.md with changes and merge that to main first -2. Tag the release off main: `git tag v0.X.Y && git push origin v0.X.Y` -3. Watch the `release` workflow; nothing else is manual - -## ๐ŸŽฏ When Working on otel-cli - -### Starting a Session - -1. `git log --oneline -n 20` - What's been happening? -2. `gh issue list` - What's being tracked? -3. `git status` - What's the current state? -4. `go build && go test` - Does everything work? - -### Making Changes - -1. **Open/reference an issue** - Keep work visible -2. **Write tests first** - Especially functional tests -3. **Make it work** - Get it functionally correct -4. **Make it right** - Clean up, refactor, document -5. **Commit with context** - Rich commit messages - -### Completing Work - -1. **All tests pass** - `go build && go test && go test ./...` -2. **Code formatted** - `go fmt ./...` -3. **Commit with attribution** - Use the template above (multiple commits OK in branch) -4. **Push and create PR** - Reference the issue with good description -5. **Update issue** - Mark as complete or pending review -6. **Squash on merge** - PRs are squashed to keep main history clean +``` +Status: complete | blocked | handoff +Context: +Next: +``` -## ๐Ÿค Cross-Model Collaboration +### Model attribution -Git's power is in context preservation across sessions, agents, and developers. +Credit each model that wrote or reviewed the change, with one line for each model: -**Picking up someone else's work:** +- Claude: `๐Ÿค– Claude ` +- Gemini: `๐Ÿ’Ž Gemini ` +- GPT: `๐Ÿง  GPT ` +- Kimi: `๐Ÿ”ฎ Kimi ` +- Llama: `๐Ÿฆ™ Llama ` -1. Find their commit: `git log --oneline -n 20` -2. Read their message: `git show ` -3. See the changes: `git show -p` -4. Continue their work with your own commits +## Releases -**Avoiding duplicate work:** +otel-cli uses semantic versioning. Before 1.0, a minor release can break compatibility. -- Always check `git log -n 20` before starting something new -- Search commit messages: `git log --grep="keyword"` -- Check GitHub issues: `gh issue list` +A `v*` tag push runs `.github/workflows/release.yml`. GoReleaser (`.goreleaser.yml`) +makes the binaries, packages, SBOM, signatures, GitHub release and Homebrew formula. +The workflow then builds, signs, attests and tags the ghcr.io image. -## Remember +- A `-rc.N` tag makes a GitHub prerelease. It does not update the Homebrew tap or + `latest`. +- A `workflow_dispatch` run is a snapshot. It publishes nothing. -**Git commits are permanent project knowledge.** They are: +To release: -- Context for future sessions and developers -- Documentation of architectural decisions -- Reasoning traces that survive indefinitely -- Messages to your future self and the community +1. Update CHANGELOG.md and merge it to main. +2. Tag main: `git tag v0.X.Y && git push origin v0.X.Y`. +3. Watch the `release` workflow. -**Your commit message quality directly impacts the next agent's and next developer's ability to succeed.** Write for them. +README.md, "Releases" has the full procedure and the required secret. ## Attribution -- Built by A. Tobey while at Equinix (primarily on the Metal team) -- Forked and maintained by A. Tobey (@tobert) since 2025 -- Agent-assisted development begins with v0.6.0 -- All commits should use appropriate agent attribution (see section above) +- A. Tobey wrote otel-cli at Equinix, mostly on the Metal team. +- A. Tobey (@tobert) forked it and maintains it since 2025. +- Agent-assisted development starts with v0.6.0. ## License -Apache License 2.0 - Copyright (c) 2025 A. Tobey - -See LICENSE file for full details. +Apache License 2.0. Copyright (c) 2025 A. Tobey. See LICENSE. diff --git a/CHANGELOG.md b/CHANGELOG.md index 9d3a515..6164739 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,7 +4,7 @@ Begin agent-assisted development era. ### Added -- AGENTS.md: LLM agent development protocol and guidance +- AGENTS.md: agent development protocol and guidance - Agent memory and collaboration patterns adapted from otlp-mcp - GitHub issue tracking integration for agent workflows - Squash commit guidance to maintain clean git history From e2c468f5be643368665ae128bdb76215a1dd3bdb Mon Sep 17 00:00:00 2001 From: A Tobey Date: Sat, 24 Oct 2026 12:56:48 -0400 Subject: [PATCH 5/9] docs(agents): drop the list of model attributions MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Amy: "let's drop the list of models in the attribution section" ๐Ÿค– Claude Co-Authored-By: Claude Opus 5.5 --- AGENTS.md | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) diff --git a/AGENTS.md b/AGENTS.md index 061de80..5e819ad 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -199,13 +199,7 @@ Next: ### Model attribution -Credit each model that wrote or reviewed the change, with one line for each model: - -- Claude: `๐Ÿค– Claude ` -- Gemini: `๐Ÿ’Ž Gemini ` -- GPT: `๐Ÿง  GPT ` -- Kimi: `๐Ÿ”ฎ Kimi ` -- Llama: `๐Ÿฆ™ Llama ` +Credit each model that wrote or reviewed the change, with one line for each model. ## Releases From c6e686629d235ec59a4aec12f04c0497d30f2237 Mon Sep 17 00:00:00 2001 From: A Tobey Date: Sat, 24 Oct 2026 13:00:11 -0400 Subject: [PATCH 6/9] docs(agents): name STE without the standard number MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Amy: "can we simple say 'The style is inspired by Simplified Technical English.'" ๐Ÿค– Claude Co-Authored-By: Claude Opus 5.5 --- AGENTS.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/AGENTS.md b/AGENTS.md index 5e819ad..5259741 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -16,8 +16,8 @@ Scripts depend on this behavior. Do not change it without a maintainer decision: This style applies to documentation, `--help` text, error messages, code comments, commit messages, PR descriptions and CHANGELOG.md. -The style is based on ASD-STE100 Simplified Technical English (STE). We use these -rules, not the full STE dictionary: +The style is inspired by Simplified Technical English (STE). We use these rules, not +the full STE dictionary: - Write one topic in each sentence. Keep an instruction to 20 words or fewer and a description to 25 words or fewer. From c279236b967b766523769890092add1a021c1097 Mon Sep 17 00:00:00 2001 From: A Tobey Date: Sat, 24 Oct 2026 13:06:17 -0400 Subject: [PATCH 7/9] docs(agents): apply kaibo review - exec exit-code precedence, test hazards MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Why: Amy asked for a kaibo deepseek review of AGENTS.md. Approach: verified each finding against the code before applying it. - exec: a nonzero child exit code has priority over --fail (otelcli/config.go:381-390). Stated in the behavior list and Terms. - Hazards: Expect.ExitCode is set by 9 fixtures and never compared (checkProcess, main_test.go:201); PATH in a fixture stops the run; -short skips IsLongTest; Diag.ExecExitCode must be set before SoftFail. - Testing: name `otel-cli status` as the debugging tool. - Env var rule matches the code: one-invocation flags like --start have none. - STE fixes: two figures of speech, a 21-word instruction, a repeated sentence, a duplicate Next: field in the handoff block. - Copyright line matches LICENSE (Equinix Metal 2020, A. Tobey 2025). Learned: the --fail exit-1 contract has no test; the fixtures that set ExitCode: 1 look like assertions but check nothing. Next: Amy's call on a test-gap fix. ๐Ÿ” Reviewed-by: DeepSeek (kaibo, deepseek cast) ๐Ÿค– Claude Co-Authored-By: Claude Opus 5.5 --- AGENTS.md | 40 +++++++++++++++++++++++++--------------- 1 file changed, 25 insertions(+), 15 deletions(-) diff --git a/AGENTS.md b/AGENTS.md index 5259741..bf260e1 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -10,6 +10,7 @@ Scripts depend on this behavior. Do not change it without a maintainer decision: - `--fail` (`OTEL_CLI_FAIL`) makes an export error exit 1. - `--verbose` (`OTEL_CLI_VERBOSE`) prints errors to stderr. - `otel-cli exec` exits with the exit code of the child, also when the export fails. + A nonzero child exit code has priority over `--fail`. ## Writing style @@ -55,8 +56,8 @@ commit message. each field. Quote the user when their request is the reason for the change. Give the evidence: commands, versions, CI run IDs. -**PR descriptions.** The PR description becomes the squash commit message. Write it as -a commit message. Start with what changed and why. List the verification commands. Do +**PR descriptions.** The PR description becomes the squash commit message. Start with +what changed and why. List the verification commands. Do not repeat content in different sections. **CHANGELOG.md.** Write one line for each bullet. Name the change, not the @@ -65,13 +66,13 @@ investigation. ### Terms Terms from OpenTelemetry and W3C Trace Context have their specification meaning. This -table has only the terms that otel-cli adds. Add a term when two meanings collide in -real text, not before. +table has only the terms that otel-cli adds. Add a term when real text uses one word +for two concepts. Do not add terms in advance. | Term | Meaning | |---|---| | non-recording mode | No endpoint is set. otel-cli runs normally but exports nothing. | -| soft fail | An error path that exits 0, or 1 with `--fail`. In code: `Config.SoftFail`. | +| soft fail | An error path. otel-cli exits 0, or 1 with `--fail`. A nonzero `exec` child exit code has priority. In code: `Config.SoftFail`. | | fixture | One test case in `data_for_test.go`. | | functional test | A test that runs the built `./otel-cli` against a test OTLP server. | @@ -79,7 +80,7 @@ real text, not before. ``` otel-cli/ -โ”œโ”€โ”€ main.go # Entry point and version information +โ”œโ”€โ”€ main.go # Entry point and version variables โ”œโ”€โ”€ main_test.go # Functional test harness โ”œโ”€โ”€ data_for_test.go # Functional test fixtures โ”œโ”€โ”€ tls_for_test.go # Temporary CA for the TLS tests @@ -90,6 +91,8 @@ otel-cli/ โ”œโ”€โ”€ demos/ # Example shell scripts โ”œโ”€โ”€ configs/ # Example configurations โ”œโ”€โ”€ release/ # Release image Dockerfile +โ”œโ”€โ”€ Dockerfile # Local development image +โ”œโ”€โ”€ .goreleaser.yml # Release build configuration โ”œโ”€โ”€ .github/workflows/ # CI and release workflows โ”œโ”€โ”€ TESTING.md # Test harness documentation โ””โ”€โ”€ CHANGELOG.md # Version history @@ -113,9 +116,13 @@ CI also builds a GoReleaser snapshot. - The functional tests run `./otel-cli`. Run `go build` first, or the tests use an old binary. -- The harness does not compare the `ExitCode` of a fixture. Check exit codes in a - `CheckFuncs` entry. +- The harness ignores `Expect.ExitCode`. Fixtures set it, but it tests nothing. Check + exit codes in a `CheckFuncs` entry. +- A fixture must not set `PATH`. The harness stops the run. +- `go test -short ./...` skips the fixtures that set `IsLongTest`. - `Config.SoftFail` calls `os.Exit`. Code after a `SoftFail` call does not run. +- `exec` keeps the child exit code in `Diag.ExecExitCode`. Set it before any + `SoftFail` call, or the exit code is lost. - Parse integer values from users in base 10: `strconv.ParseInt(v, 10, 64)`. Base 0 reads `0x10` as 16 and `010` as 8. - CI and releases build with the latest stable Go. The `go` line in go.mod is only the @@ -132,6 +139,8 @@ Functional tests are the primary tests. TESTING.md documents the harness. - Add unit tests for complex logic in packages. Use table-driven tests and `t.Run`. - Test the error paths, not only the success paths. - Add `--fail --verbose` to a fixture to see its errors. +- Run `otel-cli status` to see the configuration, environment and diagnostics. The + harness reads its output. We trust Cobra, the OpenTelemetry Go SDK and the standard library. We test the integration between them, because most bugs are there. @@ -149,7 +158,8 @@ integration between them, because most bugs are there. ### Shell scripts are the main users - Make each feature easy to use from bash. -- Give each new configuration flag an environment variable, as `otelcli/config.go` does. +- Give a new flag an environment variable when scripts set it for many commands. Flags + for one invocation, such as `--start`, do not need one. - Exit codes are part of the interface. Scripts check them. - Write data to stdout and diagnostics to stderr. @@ -159,11 +169,11 @@ integration between them, because most bugs are there. - Agents can open PRs. A human decides to merge. - Ask a maintainer before you open an issue. Refer to issues with `refs #N` or `fixes #N`. -- Commit often in your branch. The commit history is the memory for the next session, - agent or developer. +- Commit often in your branch. The next session reads the commit history to learn what + changed and why. -Start a session with `git log --oneline -n 20`, `gh issue list`, `git status` and -`go build && go test ./...`. +Start each session with `git status`, `git log --oneline -n 20` and `gh issue list`. +Then run `go build && go test ./...`. ### Commit message template @@ -194,7 +204,6 @@ When you stop before the work is complete, add these fields: ``` Status: complete | blocked | handoff Context: -Next: ``` ### Model attribution @@ -229,4 +238,5 @@ README.md, "Releases" has the full procedure and the required secret. ## License -Apache License 2.0. Copyright (c) 2025 A. Tobey. See LICENSE. +Apache License 2.0. Copyright 2020 Packet Host, Inc. / Equinix Metal and 2025 A. Tobey. +See LICENSE. From 5f1b441eb6c30a22e5dbbdc66253622c845d676c Mon Sep 17 00:00:00 2001 From: A Tobey Date: Sat, 24 Oct 2026 13:25:35 -0400 Subject: [PATCH 8/9] docs(agents): drop the Expect.ExitCode hazard - #50 makes it checked MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ๐Ÿค– Claude Co-Authored-By: Claude Opus 5.5 --- AGENTS.md | 2 -- 1 file changed, 2 deletions(-) diff --git a/AGENTS.md b/AGENTS.md index bf260e1..ccb72e0 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -116,8 +116,6 @@ CI also builds a GoReleaser snapshot. - The functional tests run `./otel-cli`. Run `go build` first, or the tests use an old binary. -- The harness ignores `Expect.ExitCode`. Fixtures set it, but it tests nothing. Check - exit codes in a `CheckFuncs` entry. - A fixture must not set `PATH`. The harness stops the run. - `go test -short ./...` skips the fixtures that set `IsLongTest`. - `Config.SoftFail` calls `os.Exit`. Code after a `SoftFail` call does not run. From 063bb82f985b97910b2d8e0cb6558aaebf2038ea Mon Sep 17 00:00:00 2001 From: A Tobey Date: Sat, 24 Oct 2026 13:40:09 -0400 Subject: [PATCH 9/9] docs(readme): drop the agent tools line MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Amy: "drop line 334 in pr49" ๐Ÿค– Claude Co-Authored-By: Claude Opus 5.5 --- README.md | 1 - 1 file changed, 1 deletion(-) diff --git a/README.md b/README.md index 3d7b7bb..91aab48 100644 --- a/README.md +++ b/README.md @@ -331,7 +331,6 @@ We welcome contributions! This project uses agent-assisted development starting **For agents working on this codebase:** - See [AGENTS.md](AGENTS.md) for comprehensive agent development guidance -- Claude Code, Codex, agy and most other agent tools read AGENTS.md natively - Emphasize functional testing in `main_test.go` - Commit freely in branches, squash on merge to main