Skip to content

Latest commit

 

History

History
124 lines (92 loc) · 9.83 KB

File metadata and controls

124 lines (92 loc) · 9.83 KB

AGENTS

All rules in this document are requirements — not suggestions. ALWAYS follow them.

trdl (true delivery) is an Open Source solution providing a secure channel for delivering updates from the Git repository to the end user. It uses Vault to verify operations and TUF for secure software distribution. trdl is a multi-module Go project with three components: trdl-server (a Vault plugin), trdl-client (a CLI tool), and trdl-vault (a release CLI tool).

.agents/skills holds mandatory agent skills: branch and commit conventions, PR format, code review, test verification. .claude/skills is a symlink to it, CLAUDE.md is a symlink to this file.

Highest-priority rule (MANDATORY)

  • NEVER add comments unless they document a non-obvious public API or explain genuinely non-obvious logic. NEVER add comments that restate what the code does, repeat the field/function name, describe obvious error handling, or act as section separators. When in doubt, don't comment.
  • ALWAYS use task commands for build/test/lint/format — NEVER raw go build, go test, go vet, go fmt, or golangci-lint directly.
  • ALWAYS read the matching skill in .agents/skills/ BEFORE the action it governs and follow it verbatim: git-conventions/SKILL.md before naming a branch or writing a commit message, pull-request/SKILL.md before creating or updating a PR (title, description, draft by default), rigorous-review/SKILL.md before reviewing code, test-the-tests/SKILL.md before considering a new or changed test done, agent-code-review/SKILL.md in addition to rigorous-review/SKILL.md when the diff's author is an agent or the diff touches tests. These files are the source of truth and are NOT duplicated here.
  • ALWAYS verify, don't assume — check the actual state before making changes.
  • ALWAYS start with the simplest possible solution. If it works, stop. Add complexity only when justified by a concrete, current requirement — NEVER for hypothetical future needs.
  • NEVER leave TODOs, stubs, or partial implementations.
  • ALWAYS stay within the scope of what was asked. When asked to update a plan — only update the plan, don't change code. When asked to brainstorm/discuss — only discuss, don't write code. When asked to do X — do X and nothing else. NEVER make unsolicited changes.
  • NEVER modify CHANGELOG.md, release notes, or other generated/workflow-managed files unless the user explicitly requests it.
  • When deleting a block from structured data files (YAML, JSON, TOML), ALWAYS read surrounding lines to verify adjacent content (anchors, references, unrelated entries) is preserved.
  • When removing content, ALWAYS clean up orphaned structural elements (comment separators, section headers, blank-line groups) that no longer serve a purpose.
  • When renaming a type, function, or constant, ALWAYS rename all related local variables, parameters, and error messages that reference the old name. A rename is not complete until grep for the old name returns zero hits in affected packages.

Code style

Design (MANDATORY)

The code style rules below are adapted from CODESTYLE.md. If you are asked to update code style rules, update CODESTYLE.md first, then regenerate this section to match, using ALWAYS/NEVER/MUST phrasing.

  • ALWAYS prefer stupid and simple over abstract and extendable.
  • ALWAYS prefer a bit of duplication over complex abstractions.
  • ALWAYS prefer clarity over brevity in names.
  • ALWAYS minimize interfaces, generics, embedding.
  • ALWAYS prefer fewer types. Prefer no types over few. Prefer data types over types with behavior.
  • ALWAYS prefer functions over methods. ALWAYS prefer public fields over getters/setters.
  • ALWAYS keep everything private/internal as much as possible.
  • ALWAYS validate early, validate a lot. ALWAYS keep APIs stupid and minimal.
  • NEVER prefer global state. ALWAYS prefer simplicity over micro-optimizations.
  • ALWAYS use libraries for complex things instead of reinventing the wheel.
  • NEVER add comments unless they document a non-obvious public API or explain genuinely non-obvious logic. NEVER add obvious/redundant comments, NEVER add comments restating what code does. When in doubt, don't comment.

Conventions (MANDATORY)

The code style rules below are adapted from CODESTYLE.md. If you are asked to update code style rules, update CODESTYLE.md first, then regenerate this section to match, using ALWAYS/NEVER/MUST phrasing.

  • All public functions/methods MUST accept context.Context as the first parameter.
  • All arguments of a public function are required — passing nil not allowed.
  • Optional arguments via <FunctionName>Options as the last argument. NEVER use functional options.
  • Use guard clauses and early returns to keep the happy path unindented.
  • Use samber/lo helpers in the server/ module: lo.Filter, lo.Find, lo.Map, lo.Contains, lo.Ternary, lo.ToPtr, lo.Must, etc. (not available in client/ or release/ modules).
  • Constructors: New<TypeName>[...](). No network/filesystem calls in constructors.
  • Interfaces: ALWAYS add var _ Animal = (*Dog)(nil) compile-time check.
  • Constants: avoid iota. Prefix enum constants with type name: LogLevelDebug LogLevel = "debug".
  • Errors: ALWAYS wrap with context: fmt.Errorf("read config: %w", err). Describe what is being done, not what failed. Panic on programmer errors. Prefer one-line if err := ...; err != nil.

Go standard guidelines (MANDATORY)

Follow Effective Go and Go Code Review Comments. Commonly violated rules:

  • NEVER use this/self as receiver names. Use 1-2 letter names, consistent across methods.
  • NEVER discard errors with _. Indent error flow, not happy path.
  • NEVER use dot imports.
  • NEVER use named returns or naked returns.

Code navigation (MANDATORY)

  • ALWAYS use LSP (goToDefinition, findReferences, documentSymbol, hover, goToImplementation, call hierarchy) to find definitions, usages, implementations, and callers. grep matches strings blindly: it hits comments and unrelated identifiers, and misses interface dispatch and aliased imports.
  • Use grep ONLY for literal text — config keys, error message strings, annotation names.
  • If your harness has a semantic code-search tool, prefer it over grep for intent-based questions ("how does X work"). If it does not, read the code: NEVER substitute keyword grepping for understanding.

Commands (MANDATORY)

ALWAYS use these task commands. NEVER use raw go build, go test, go fmt, go vet, or golangci-lint directly. trdl is a multi-module project — most commands are namespaced by module, and those namespaces exist only in the root Taskfile: ALWAYS run task from the repository root, never from inside server/, client/, e2e/ or release/.

Building

  • NEVER go build → ALWAYS use the appropriate build task:
    • task server:build — builds trdl-server Vault plugin (Linux only).
    • task client:build — builds trdl client CLI binary. Accepts os=... and arch=....
    • task release:build — builds trdl-vault release CLI binary. Accepts os=... and arch=....
    • task build:dev:all — builds all components for the current platform.
    • task build:dist:all — builds all components for all supported platforms.

Testing

  • NEVER go test → ALWAYS use the appropriate test task:
    • task server:test:unit — runs server unit tests (Ginkgo). Accepts paths="./...".
    • task e2e:test:e2e — runs end-to-end tests (Ginkgo). Accepts paths="./..." and focusFilter="..." / labelFilter="..." to target specific tests.

Linting and formatting

  • NEVER go vet → ALWAYS task lint. golangci-lint includes vet checks.
  • NEVER go fmt/gofmt → ALWAYS task format.
  • NEVER golangci-lint → ALWAYS task lint.
  • Module-specific linting: task server:lint, task client:lint, task release:lint, task e2e:lint.
  • Module-specific formatting: task server:format, task client:format, task release:format, task e2e:format.

Cleanup

  • task clean — remove build artifacts.

Testing (MANDATORY)

  • logboek.Context(ctx) returns the default logger ONLY for exactly context.Background(); any derived context without a bound logger panics with context is not bound with logboek logger. In a test that reaches code logging through logboek, pass context.Background() unchanged or wrap it: logboek.NewContext(ctx, logboek.DefaultLogger()).
  • Server tests use Ginkgo/Gomega. testify (assert, require) is also available in the server/ module.
  • E2E tests use Ginkgo/Gomega exclusively.
  • ALWAYS place tests alongside source files, not in a separate directory.
  • Test helpers go in helpers_test.go.
  • Test fixtures go in testdata/ subdirectory next to the tests.

PR review guidelines (MANDATORY)

  • NEVER add new external dependencies without flagging to the user first.
  • NEVER introduce breaking user-facing changes (not API changes) unless they are hidden behind a feature flag. Flag to the user first.
  • NEVER introduce changes that may compromise security. Flag to the user first.

Self-improvement (MANDATORY)

ALWAYS perform this step after completing any user request. NEVER skip it, even if the work "looks fine."

  1. Review what went wrong during execution: wasted steps, wrong assumptions, missed dependencies.
  2. If a mistake was caused by a missing rule in AGENTS.md — propose a concrete rule addition to the user.
  3. If a mistake was caused by a missing rule in OPENCODE.md — propose a concrete rule addition to the user.
  4. NEVER silently swallow lessons learned. ALWAYS surface them.

Related repositories

  • werf/common-go — Shared Go libraries used by trdl.
  • werf/common-ci — Shared CI/CD task definitions (format, lint). Referenced by root Taskfile.