X-Git-Url: https://git.giacomolli.uk/onechat/blobdiff_plain/b64d7548bd9f61921bdc650228642e77c73b0777..0979625154094df73577d6e2be2d0e9a0a87306c:/.agents/skills/go-code/SKILL.md?ds=sidebyside diff --git a/.agents/skills/go-code/SKILL.md b/.agents/skills/go-code/SKILL.md index 71ff6c9..374c2e9 100644 --- a/.agents/skills/go-code/SKILL.md +++ b/.agents/skills/go-code/SKILL.md @@ -19,13 +19,20 @@ description: Go style rules. Use before you write or review Go code. integration with the name of that feature. Start the names of its files with the same name. Keep a name generic only when more than one feature uses it. -- Use unexported names. In the `main` package, an exported name has no - effect. -- Write all the letters of an initialism in one case. -- Put entry points first, then each struct's methods as a group, then - standalone utility functions. Do not put a utility function between - the methods of one type. -- In each group, order functions by first use in the file. +- Write type names with a capital letter, so that a variable can have + the name of its type. Write all other package-level names in lower + case. +- Write all the letters of an initialism in one case. `revive` checks + common initialisms. +- Order declarations as imports, constants, variables, types, + constructors, methods, then standalone helpers. Types include structs, + interfaces, and aliases. Put all types before any constructor or + method, also when a file holds more than one type. The Tests section + gives the exception for files with tests. +- Keep each type's methods in one group. Do not put a helper between + them. Order functions by first use within their declaration group, not + across groups. Entry points do not go before types or constructors + merely because they are entry points. ## Entry point and context @@ -38,20 +45,53 @@ description: Go style rules. Use before you write or review Go code. Call `defer cancel()` immediately after you create the context. - Reuse `ctx` when a child context replaces its parent. Use a different name only when both contexts stay in use. Return `ctx.Err()` directly. +- Derive each context from the context of the caller. When work must + finish even after the caller is cancelled, such as a final write, use + `context.WithoutCancel` of the caller's context. Use + `context.Background()` only where no caller context exists: in `run`, + and in methods that follow `io.Closer`. +- Name a duration that limits one operation after that operation, and + end the name with `Timeout`, so that the name says what it limits + without its comment. Define it in the file that applies it, not in the + file of another type. ## Errors -- Handle every returned error. +- Handle every returned error, including an error assigned to `_`. Never + use a blank assignment to hide an unchecked error from a linter. + Handle meaningful errors. When the user approves an intentional + discard, call the operation with an explicit `// nolint: errcheck` + directive and a comment that gives the reason, not a blank assignment. + The `check` skill gives the approval rule. - Reuse an existing `err` for later operations in the same scope. Use a different variable only to keep or join errors. - Use `errors.Is` and `errors.As` to examine errors. Do not compare an error directly with a sentinel, because errors can be wrapped. + `errorlint` checks comparisons and type assertions on errors. - When a function has more than one error path, wrap each returned error with the context of its operation. A function with one error path can - return the error directly. + return the error directly. `wrapcheck` checks package and interface + calls, with the exceptions in `.golangci.yml`. Review local calls and + the number of error paths by hand. - When deferred cleanup can fail, use a named `err` result and join the cleanup error with `errors.Join`. +## Logs + +- Log with the `*slog.Logger` of the part (`daemonLogger`). The handler + formats the line; do not format values into the message. +- Write the message as a short event in plain words, such as "receive + failed" or "subagent done". Do not explain what it means or what the + user must do. +- Put names, IDs, counts, and durations in attributes, with short keys + (`name`, `id`, `after`, `retry`). Put the cause in `err`; the handler + writes it last. +- Use info for normal events, warn for a failure that is retried or + loses nothing, and error for a failure that loses data or stops a + part. +- Never log secrets, tokens, message text, or phone numbers. Redact IDs + as the existing code does. + ## Style - Keep function signatures on one line. Write function bodies on more @@ -64,10 +104,14 @@ description: Go style rules. Use before you write or review Go code. table-driven test. A small type of two fields that acts as one value, such as a key or a coordinate pair, can use a positional literal on one line. -- Put an empty line between logical blocks, also after multiline - declarations, assignments, literals, and calls. Keep an operation with - its immediate error or result check. Keep a short declaration with its - immediate use. +- Put an empty line between logical blocks and after multiline + declarations, assignments, literals, and calls. The only exception + after a multiline construct is its immediate error check. Separate a + multiline literal from a following loop, even when the loop uses that + literal. Keep a single-line declaration with its immediate use, and an + operation with its immediate error check. This does not waive the + separator after a multiline construct. `wsl_v5` and `nlreturn` check + only part of this rule. Review the other boundaries by hand. - Use GNU-style command flags: two dashes for long flags, such as `--cwd`, and one dash only for one-letter flags, such as `-h`. - Prefer the Go standard library. Prefer Go over cgo. @@ -85,11 +129,26 @@ description: Go style rules. Use before you write or review Go code. - Add tests for meaningful behavior. Do not add tests that only repeat implementation details. -- Use `testify/require` for assertions. +- Use `testify/require` for assertions. `testifylint` checks the + assertion forms. - Name a table-driven case slice `testCases` and its range variable `tc`. A subtest name describes the behavior, not a generic outcome or input. -- In a test file, put constants immediately after the imports, then the - tests, then supporting types, methods, and helpers. +- Each file with tests must have the name of its owning production file + with `_test` before `.go`: `memory_test.go` tests `memory.go`. Move + scenario and integration tests into their owner's test file. Do not + add an empty production file to make a test filename valid. Only + `_helper_test.go` files are exempt from this pairing rule. +- In an ordinary `_test.go` file, order declarations as imports, + constants, variables, tests, supporting types, constructors, methods, + then helpers. This tests-first order is the exception to the + production order. Put all supporting types before their constructors + and methods. +- A `_helper_test.go` file has no tests. Order its declarations as + imports, constants, variables, types, constructors, methods, then + helpers, as in a production file. +- Keep a helper that only one test file uses in that file. Put a helper + that more than one test file uses in a file without tests. Name that + file for what it holds, and end the name with `_helper_test.go`. - Supply valid required dependencies in tests. Do not make a dependency optional only to make a test simpler.