Skip to content

Commit 94a9ed3

Browse files
chore: add conv and o11y guidance to golang skill (Vibe Kanban) (#1589)
## Summary - Added a **Conversion utilities** section to the golang skill documenting the `server/internal/conv` package (`Ptr`, `PtrEmpty`, `PtrValOr`, `Default`, pgtype converters, `Ternary`) with an emphasis on using these existing helpers instead of reimplementing them inline. - Added an **Observability** section documenting `o11y.LogDefer` and `o11y.NoLogDefer` with exact function signatures, usage guidance, and real-world examples (file closes, transaction rollbacks, HTTP response body closes). - Includes a rule that bare `defer resource.Close()` calls should be avoided in favour of these wrappers for proper error traceability. ## Why Agents frequently reimplement pointer helpers, pgtype conversions, and deferred cleanup patterns inline instead of using the existing `conv` and `o11y` packages. Adding explicit guidance to the golang skill ensures these packages are discovered and used consistently across the codebase. ## Test plan - [x] Verify the skill file renders correctly and examples are accurate - [x] Confirm function signatures match the actual `conv` and `o11y` package implementations This PR was written using [Vibe Kanban](https://vibekanban.com) Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
1 parent b28db7d commit 94a9ed3

File tree

1 file changed

+75
-0
lines changed

1 file changed

+75
-0
lines changed

.agents/skills/golang/SKILL.md

Lines changed: 75 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -217,6 +217,81 @@ This is great because:
217217

218218
</good-example>
219219

220+
## Conversion utilities (`server/internal/conv`)
221+
222+
Use the `conv` package for common type conversions instead of writing inline helpers. Key functions:
223+
224+
- `conv.Ptr(v)` — create a pointer to a literal value or return value. Use this instead of declaring a variable just to take its address.
225+
- `conv.PtrEmpty(v)` — like `Ptr` but returns `nil` when `v` is the zero value.
226+
- `conv.PtrValOr(ptr, default)` — dereference a pointer with a fallback default.
227+
- `conv.Default(val, default)` — return `val` unless it is the zero value, then return `default`.
228+
- `conv.ToPGText`, `conv.ToPGTextEmpty`, `conv.PtrToPGText`, `conv.PtrToPGTextEmpty` — convert strings to `pgtype.Text`.
229+
- `conv.FromPGText`, `conv.FromPGBool` — convert `pgtype` values to Go pointer types.
230+
- `conv.PtrToPGBool` — convert a `*bool` to `pgtype.Bool`.
231+
- `conv.Ternary(cond, trueVal, falseVal)` — inline conditional expression.
232+
233+
<important>
234+
235+
Do NOT reimplement pointer helpers, ternary expressions, or pgtype conversions inline. Always reach for `conv` first.
236+
237+
</important>
238+
239+
## Observability (`server/internal/o11y`)
240+
241+
Use the `o11y` package for deferred cleanup and error logging. Two key functions:
242+
243+
### `o11y.LogDefer`
244+
245+
```go
246+
func LogDefer(ctx context.Context, logger *slog.Logger, cb func() error) error
247+
```
248+
249+
Use `LogDefer` when a cleanup operation's error should be **logged**. Wrap cleanup calls with `defer o11y.LogDefer(...)` so failures are always visible in logs.
250+
251+
<good-example>
252+
253+
```go
254+
defer o11y.LogDefer(ctx, logger, func() error { return file.Close() })
255+
```
256+
257+
</good-example>
258+
259+
### `o11y.NoLogDefer`
260+
261+
```go
262+
func NoLogDefer(cb func() error)
263+
```
264+
265+
Use `NoLogDefer` when a cleanup operation's error can be **silently discarded** — for example, rolling back a database transaction (which is a no-op if the transaction already committed) or closing an HTTP response body.
266+
267+
<good-example>
268+
269+
```go
270+
dbtx, err := s.repo.DB().Begin(ctx)
271+
if err != nil {
272+
return nil, oops.E(oops.CodeUnexpected, err, "error accessing resource").Log(ctx, logger)
273+
}
274+
defer o11y.NoLogDefer(func() error { return dbtx.Rollback(ctx) })
275+
```
276+
277+
</good-example>
278+
279+
<good-example>
280+
281+
```go
282+
defer o11y.NoLogDefer(func() error { return resp.Body.Close() })
283+
```
284+
285+
</good-example>
286+
287+
<important>
288+
289+
- ALWAYS use `o11y.LogDefer` or `o11y.NoLogDefer` for deferred cleanup instead of bare `defer resource.Close()` calls. Bare defers silently discard errors with no traceability.
290+
- Choose `LogDefer` when the error matters for debugging (file I/O, critical resource cleanup).
291+
- Choose `NoLogDefer` when the error is expected or inconsequential (transaction rollbacks, response body closes).
292+
293+
</important>
294+
220295
## Testing
221296

222297
- When writing assertions, use `github.com/stretchr/testify/require` exclusively.

0 commit comments

Comments
 (0)