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);erroris the last return. log/slogonly (runner); stderrfatallnis fine for the tinymcpbridge.- Tests: stdlib + table-driven (
t.Run,t.Helper,t.TempDir) — no testify. - Small single-purpose packages; pure types in
pkg/, logic ininternal/. - 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.