Skip to content

docs(ai): document the repository's Go conventions as a generated skill - #200

Merged
sourcehawk merged 1 commit into
mainfrom
docs/how-we-write-go
Aug 25, 2026
Merged

docs(ai): document the repository's Go conventions as a generated skill#200
sourcehawk merged 1 commit into
mainfrom
docs/how-we-write-go

Conversation

@sourcehawk

Copy link
Copy Markdown
Owner

Description

The repository tells a contributor what to change and what to document, but never how the Go itself
should read: how much a godoc owes a caller, when an inline comment earns its line, where a long call
breaks, which file a new function belongs in. That knowledge lived in reviewers' heads, so every
contributor rediscovered it and every review spent time on it. This adds .ai/how-we-write-go.md as
the written source of those conventions and generates it into a how-we-write-go skill alongside the
existing AI instruction files. It is documentation only: no Go source changes, and nothing here is
enforced by a linter, so the conventions bind by being read rather than by failing CI.

Changes

  • New .ai/how-we-write-go.md: 18 sections covering doc comments, inline comments, whitespace rhythm,
    line breaking, code bloat, layering and side effects, typed string constants, error wrapping,
    naming, context propagation, interface design, panic vs error, where code lives, and order within a
    file. Ported from the camunda-operator skill of the same name.
  • Rewritten for this repository rather than copied. Line breaking now describes the 120-character soft
    limit and the break-after-paren shape pkg/ already uses, because nothing in make fmt reflows Go
    (gofmt and goimports leave line breaks alone) and there is no golines here. The controller
    layering section became builder/resource/mutator/component, with the rule that mutators, editors,
    gates and status handlers stay free of I/O so golden tests keep running without a cluster. "Where to
    put code" became pkg/ as public API against internal/, plus the file roles a primitive package
    always has. Examples are grounded on real symbols: concepts.ConvergingOperation, concepts.Alive,
    component.OperatorCRD embedding client.Object, NewPolicyRulesEditor's panic.
  • Operator-specific sections of the original are dropped: label conventions, controller events vs
    logs, the status-condition model, reconcile requeue patterns, and CRD kubebuilder/CEL validation.
    This is a framework, not an operator.
  • ai-instructions-gen now also writes .claude/skills/how-we-write-go/SKILL.md, and .ai/base.md
    gained a "House Go style" subsection so CLAUDE.md, .junie/guidelines.md and
    .github/copilot-instructions.md all point at the tracked source. Junie and Copilot cannot read
    .claude/skills/, and .claude/* is gitignored here, so the tracked file has to be the one they
    are sent to.

Related

  • The conventions are documentation, not enforcement. If any of them are worth making mechanical
    (a line-length linter, an import-boundary check between pkg/ and internal/), that is a separate
    change.

Testing

make ai-instructions runs clean and the generated SKILL.md is byte-identical to .ai/how-we-write-go.md;
prettier reports both unchanged on a second pass, so the source is already at its formatted fixed point
and the frontmatter description stays on a single line rather than folding across lines.

Every claim the guide makes about this repository was checked against the source rather than carried
over from the original. Line-length behaviour was measured across pkg/, internal/ and cmd/; the
primitive file-role claim was verified against all 21 primitive packages; and four examples that did
not match the real API were corrected: Component.Reconcile's signature, concepts.Alive's method
name (ConvergingStatus, not AliveStatus), the NewComponentBuilder call shape, and mutator
methods returning nothing.

No Go source changed, so make all behaviour is unaffected by this diff.

The repository states what to change and what to document, but never how the
Go itself should read: how much a godoc owes a caller, when an inline comment
earns its line, where a long call breaks, which file a new function belongs in.
Reviewers carried that in their heads and every contributor rediscovered it.

Add .ai/how-we-write-go.md as the source of those conventions, ported from the
camunda-operator skill of the same name and rewritten around this repository:
the 120-character soft limit and break-after-paren shape that pkg/ already uses
(nothing in `make fmt` reflows Go), the builder/resource/mutator/component
layering and the rule that mutators, editors, gates and status handlers stay
free of I/O, pkg/ as public API against internal/, and the fixed file roles of a
primitive package. The operator-side sections of the original are dropped: this
is a framework, not an operator.

Generate it into .claude/skills/how-we-write-go/SKILL.md from ai-instructions-gen,
and point CLAUDE.md, .junie/guidelines.md and the Copilot instructions at the
tracked source, since neither Junie nor Copilot reads .claude/skills.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01AkugYZxCwKb17i8gfFj4tR
Copilot AI lite review requested due to automatic review settings August 25, 2026 23:51
@sourcehawk
sourcehawk merged commit a822a90 into main Aug 25, 2026
8 checks passed
@sourcehawk
sourcehawk deleted the docs/how-we-write-go branch August 25, 2026 23:53

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟡 Changes recommended

There are a couple of concrete accuracy/consistency issues in the new guide and generation flow (notably make all/examples and make fmt wording, plus deterministic generation ordering for the new .claude/skills copy).

Once you've addressed the issues Copilot identified, you can request another Copilot review.

Pull request overview

This PR adds a repository-specific “house Go style” guide (.ai/how-we-write-go.md) and wires it into the existing AI-instructions generation flow so contributors (and AI tooling) have a single, tracked source of Go writing conventions for this framework.

Changes:

  • Add .ai/how-we-write-go.md describing GoDoc, inline comments, formatting/line breaks, layering, naming, errors, and file organization conventions.
  • Update AI instruction entrypoints (.ai/base.md, generated .github/copilot-instructions.md) to point contributors at the new guide.
  • Extend make ai-instructions-gen to generate a Claude skill file at .claude/skills/how-we-write-go/SKILL.md.
File summaries
File Description
Makefile Adds .ai/how-we-write-go.md to AI generation; copies it into .claude/skills/how-we-write-go/SKILL.md.
.github/copilot-instructions.md Adds a “House Go style” section referencing .ai/how-we-write-go.md.
.ai/how-we-write-go.md New Go conventions guide intended to be the canonical “house style” source.
.ai/base.md Adds the “House Go style” subsection so generated instruction entrypoints link to the guide.
Review details

Suppressed comments (1)

Makefile:66

  • ai-instructions currently relies on prerequisite ordering (ai-instructions-gen fmt-md). With the new .claude/skills/.../SKILL.md copy, this can leave the generated skill out of sync if fmt-md rewrites .ai/how-we-write-go.md after it was copied (and Make may also run prerequisites in parallel under -j). Consider making ai-instructions a recipe that formats first, generates, then formats again so the outputs are deterministic and the copied skill stays byte-identical to the source.
AI_GO := .ai/how-we-write-go.md

.PHONY: ai-instructions
ai-instructions: ai-instructions-gen fmt-md

  • Files reviewed: 4/4 changed files
  • Comments generated: 2
  • Review effort level: Lite

💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

Comment thread .ai/how-we-write-go.md
Comment on lines +200 to +202
Nothing in `make fmt` reflows Go source: `gofmt` and `goimports` normalise indentation and imports, and leave your line
breaks exactly where you put them. The soft limit is 120 characters, the same width prettier applies to Markdown here,
and holding it is your job rather than a tool's.
Comment thread .ai/how-we-write-go.md
Comment on lines +657 to +658
**Every public change lands with its example.** `examples/` is compiled and run by `make all`, and each directory
demonstrates one concept. A new capability that no example exercises is a capability nobody will find.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants