# Go Engineer

> Engineer a change in the Go modules (runner/ or mcp/) the house way — read the project AGENTS.md first, match the Go house style (slog, fmt.Errorf %w, stdlib table-driven tests, no new deps), honor the runner's security posture, and run the gate. Use for any code change in runner/ or mcp/ (the Go analog of the portal Elixir skills).

- Skill: `andrewdryga/go-engineer` (Agent Skill)
- Install (CLI): `npx skillmds@latest add andrewdryga/go-engineer`
- Raw SKILL.md: https://api.skillmd.com/api/skills/andrewdryga/go-engineer/raw
- Safety review: pending
- Works with: Claude Code, Claude.ai, OpenAI Codex
- Category: AI & ML
- Author: AndrewDryga (https://skillmd.com/u/andrewdryga)
- Updated: 2026-09-22
- Page: https://skillmd.com/skills/andrewdryga/go-engineer

---


# Go engineering (runner / mcp)

The Go analog of the portal skills. The rules live in the project's `AGENTS.md` —
this skill is the *order of operations*, not a copy of them.

## 1. Read the project AGENTS.md first
`runner/AGENTS.md` or `mcp/AGENTS.md`, in full. They carry the gate, the package
layout, the security posture, and the Go house style. Don't work from memory —
the conventions are specific (e.g. the runner never accepts cloud/LLM-controlled
shell code; open-ended values enter fixed shell programs only through env or
whole positional argv elements).

## 2. Wear the hats (the root manual's engineering contracts)
- **Security** especially for `runner/` — it executes commands on hosts. Any
  change to validation / admission / redaction / exec **adds or extends** a
  `*_security_test.go`. Ask: what's the abuse case?
- PM / UX / Maintainer for the rest — smallest correct change, reads clearly later.

## 3. Match the house style
- Errors are values: `fmt.Errorf("…: %w", err)`; `error` is the last return.
- `log/slog` only (runner); stderr `fatalln` is fine for the tiny `mcp` bridge.
- Tests: stdlib + table-driven (`t.Run`, `t.Helper`, `t.TempDir`) — no testify.
- Small single-purpose packages; pure types in `pkg/`, logic in `internal/`.
- A new dependency is new attack surface — justify it in one sentence or use stdlib.

## 4. Run the gate (Definition of Done)
From the repository root:

```
./run gate runner
./run gate mcp
```

Run only the gate for the module you touched. Use
`./run test <runner|mcp> [go-test-args...]` for focused feedback.
Linux-only runner behavior (Pdeathsig, `/var/log` symlinks): from the repository
root run `coop run -- go -C runner test -race -count=1 ./...`.
Show the output — never "should work". Don't pipe `go test`/`gofmt` through
`head`/`tail` (the pipe's exit code masks the tool's).

## 5. Close the loop
One focused commit (ending with its `Coop-Task: <id>` trailer) → append the
*what + why* to the task's `log.md` → `coop tasks done <id>`. Blocked?
`coop tasks block <id>` and fill its `decision.md`. The commit-gate will
gofmt-check your staged `.go`.

