From 6c1f834172a41f3ea500b723386df61734682624 Mon Sep 17 00:00:00 2001 From: Sebastian Iancu Date: Thu, 1 Oct 2026 14:35:52 +0200 Subject: [PATCH] docs: drop the README Status column and align docs with sibling plugins README.md: - Remove the Status column; every row said "shipped". - Group Components rows by kind (skills, agent, hooks, config, rule) and move the dev scripts to Development. - Fix stale facts: hooks-test.sh covers all three hooks, and the validator has three plugin-specific invariants (the Google tie-break sentence was missing). Link docs/testing.md for their definitions. - Match the docs-editing README conventions: label punctuation, the audience sentence, the Claude Code install line. docs/: - testing.md gains a "What scripts/validate.py checks" subsection covering the structural checks and the three invariants, and stops claiming the validator requires an agent `tools:` key (it rejects `allowed-tools:` only). CI installs Python 3; it does not pin it. - install.md: the Cursor-only rule differs between hosts; line edits. - testing.md, versioning.md and authoring.md drop ~100-column hard wraps for one line per paragraph, like install.md and the sibling plugins. authoring.md drops "command" from its title, and the Google-internal exclusions render as their own paragraph. Co-Authored-By: Claude Opus 5.5 --- CHANGELOG.md | 15 +++++ README.md | 74 +++++++++++----------- docs/authoring.md | 154 ++++++++++++--------------------------------- docs/install.md | 20 +++--- docs/testing.md | 72 ++++++++++----------- docs/versioning.md | 39 ++++-------- 6 files changed, 145 insertions(+), 229 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 37824bd..5f0f91d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -9,6 +9,21 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/), ### Changed - Docs: `README.md` follows the shared Cadasto plugin layout (badge row, requirements, table of contents, features); each `docs/` page opens with a paragraph naming its reader. - Docs: `docs/versioning.md` release steps include updating the README version badge. +- Docs: `README.md` drops the Status column from Components and groups its rows by kind. +- Docs: `README.md` moves the dev scripts from Components to Development. +- Docs: `docs/testing.md` lists what `scripts/validate.py` checks in its own subsection, including the three plugin-specific invariants. +- Docs: `docs/testing.md` gives the `/go-lint-setup` triggering test an expected result. +- Docs: `docs/testing.md`, `docs/versioning.md`, and `docs/authoring.md` use one line per paragraph, like `docs/install.md`. +- Docs: `docs/authoring.md` drops "command" from its title; `docs/authoring.md` and `docs/versioning.md` call slash commands skills. + +### Fixed +- Docs: `README.md` counts three plugin-specific validator invariants, adding the Google tie-break sentence. +- Docs: `README.md` says `scripts/hooks-test.sh` tests all three hook scripts. +- Docs: `docs/install.md` names the Cursor-only rule among host differences. +- Docs: `docs/testing.md` says to load a working copy with `--plugin-dir`, not install it. +- Docs: `docs/testing.md` says CI installs Python 3 rather than pinning it. +- Docs: `docs/testing.md` says the validator rejects an agent's `allowed-tools:`, not that it requires `tools:`. +- Docs: `docs/authoring.md` renders the Google-internal exclusions as their own paragraph, not as part of the *Best Practices* bullet. ## [0.6.0] - 2026-09-09 diff --git a/README.md b/README.md index 6978071..6a69ee5 100644 --- a/README.md +++ b/README.md @@ -6,11 +6,11 @@ [![Cursor](https://img.shields.io/badge/Cursor-plugin-000?logo=cursor&logoColor=white)](https://cursor.com) [![Keep a Changelog](https://img.shields.io/badge/Keep%20a%20Changelog-1.1.0-E05735)](CHANGELOG.md) -An AI plugin by **Cadasto B.V.** that teaches AI coding assistants idiomatic Go coding standards: formatting, naming, error handling, concurrency, testing, and project layout. It adds skills, an agent, and three hooks (session-start, format-on-save, skill-nudge) for **[Claude Code](https://docs.claude.com/en/docs/claude-code/overview)** and **[Cursor](https://cursor.com)** from one shared component set, plus a Cursor rule. +An AI plugin by **Cadasto B.V.** that teaches AI coding assistants idiomatic Go coding standards: formatting, naming, error handling, concurrency, testing, and project layout. It is for anyone who has an assistant write or review Go. It adds seven skills, a report-only review agent, and three hooks (session-start, format-on-save, skill-nudge) for **[Claude Code](https://docs.claude.com/en/docs/claude-code/overview)** and **[Cursor](https://cursor.com)** from one shared component set, plus a Cursor rule. -The plugin owns the judgement layer of Go standards. Formatting, vetting and linting stay with the deterministic tools (`gofmt`/`gofumpt`, `go vet`, `staticcheck`, `golangci-lint`, `go test -race`): each skill names the tool that enforces a rule and cites the source a judgement rule comes from, and the `go-reviewer` agent reports what those tools miss. It covers Go only and carries no business rules. +The plugin owns the judgement layer of Go standards. Formatting, vetting, and linting stay with the deterministic tools (`gofmt`/`gofumpt`, `go vet`, `staticcheck`, `golangci-lint`, `go test -race`): each skill names the tool that enforces a rule and cites the source a judgement rule comes from, and the `go-reviewer` agent reports what those tools miss. It covers Go only and carries no business rules. -**Requirements.** A Claude Code or Cursor host. The plugin is pure Markdown + JSON, with no build step and no MCP server, and it installs without a Go toolchain. Its hooks and enforcement guidance expect **Go 1.26.4+** (Go 1.27 supported; its additions are flagged as hints) plus `gofmt`, `gofumpt`, `goimports`, and `gopls` on the host `PATH`, and golangci-lint v2 (v2.13.0 or newer on Go 1.27) for full-tree linting. See [Host toolchain (minimal requirements)](docs/install.md#host-toolchain-minimal-requirements) for what each tool drives and copy-paste install commands. +**Requirements.** A Claude Code or Cursor host. The plugin is pure Markdown + JSON, with no build step and no MCP server, and it installs without a Go toolchain. Its hooks and enforcement guidance expect **Go 1.26.4+** (Go 1.27 supported; its additions are flagged as hints) with `gofmt`, `gofumpt`, `goimports`, and `gopls` on the host `PATH`, and golangci-lint v2 (v2.13.0 or newer on Go 1.27) for full-tree linting. See [Host toolchain (minimal requirements)](docs/install.md#host-toolchain-minimal-requirements) for what each tool drives and copy-paste install commands. ## Table of contents @@ -24,17 +24,17 @@ The plugin owns the judgement layer of Go standards. Formatting, vetting and lin ## Features -- **Routing:** the auto-invoked `go-coding` router sends each Go topic to the enforcing tool, then to the focused skill that owns it. -- **Focused standards:** `go-errors`, `go-concurrency`, `go-testing`, `go-idioms`, and `go-layout` load on use, with each rule cited and framed around the linter that enforces it. -- **Linter setup:** `/go-lint-setup` scaffolds, adopts, or debugs a golangci-lint v2 config, based on the shipped `references/golangci.v2.yml`. -- **Review:** the report-only `go-reviewer` agent returns severity-ranked findings for what linters miss. -- **Format on save:** a hook runs `gofumpt -w` (or `gofmt -w -s`) on each edited `*.go` file. -- **Skill nudges:** after a `*.go` edit, a hook names one matching skill, once per skill per session. -- **Cursor parity:** Cursor gets the same skills, agent, and hooks, plus `rules/go-context.mdc` mirroring the router. +- **Routing**: you ask about a Go topic; the auto-invoked `go-coding` router names the tool that enforces it and the focused skill that owns it. +- **Focused standards**: `go-errors`, `go-concurrency`, `go-testing`, `go-idioms`, and `go-layout` load on use, with each rule cited and framed around the linter that enforces it. +- **Linter setup**: `/go-lint-setup` scaffolds the reference golangci-lint v2 config (`references/golangci.v2.yml`), or adopts or debugs the one a repo already has. +- **Review**: the report-only `go-reviewer` agent returns severity-ranked findings for what linters miss. +- **Format on save**: a hook runs `gofumpt -w` (or `gofmt -w -s`) on each edited `*.go` file. +- **Skill nudges**: after a `*.go` edit, a hook names one matching skill, once per skill per session. +- **Cursor parity**: Cursor gets the same skills, agent, and hooks, plus `rules/go-context.mdc` mirroring the router. ## Installation -**Claude Code**: from the Cadasto marketplace: +**Claude Code**, from the Cadasto marketplace: ```text /plugin marketplace add Cadasto/plugin-marketplace @@ -43,59 +43,55 @@ The plugin owns the judgement layer of Go standards. Formatting, vetting and lin Or load a local working copy for a single session: `claude --plugin-dir /path/to/go-coding-plugin`. -**Cursor**: add this repository as a plugin (Settings → Plugins, from a Git URL or a local path). The repo includes a Cursor manifest at [`.cursor-plugin/plugin.json`](.cursor-plugin/plugin.json); skills, agents, and hook scripts are shared with the Claude plugin. +**Cursor**: add this repository as a plugin (Settings → Plugins, from a Git URL or a local path). The repo includes a Cursor manifest at [`.cursor-plugin/plugin.json`](.cursor-plugin/plugin.json); skills, agents, references, and hook scripts are shared with the Claude plugin. See [docs/install.md](docs/install.md) for marketplace, local-development, update, and Cursor install details. ## Components -| Component | Status | Purpose | -|-----------|--------|---------| -| Skill `go-coding` | shipped | Auto-invoked router: sends each Go topic to the enforcing tool and the focused skill below; recommends `gopls-lsp`. | -| Session-start hook | shipped | Detects a Go workspace (`go.mod`/`*.go`) and prints one standards line; dual-host. | -| Format-on-save hook | shipped | After each `Write`/`Edit` of a `*.go` file, runs `gofumpt -w` (or `gofmt -w -s`) on it; dual-host, host-only, silent no-op if no formatter is installed. | -| Skill-nudge hook | shipped | After each `Write`/`Edit` of a `*.go` file, names ONE matching go-coding skill for that edit, once per skill per session; dual-host: delivered as a hook `systemMessage` under Claude Code, a plain line under Cursor. | -| Skills `go-errors`, `go-concurrency`, `go-testing`, `go-idioms`, `go-layout` | shipped | Load-on-use standards, each rule cited and framed around the enforcing linter (`modernize`, `errorlint`, `-race`, …). `go-layout` also owns naming, doc comments, and exported-API shape. | -| Agent `go-reviewer` | shipped | Report-only, context-isolated Go reviewer for what linters miss; severity-ranked findings, no sub-agent dispatch. Its grant excludes `Write`/`Edit` but includes `Bash` to run the linters, so no-edit is a contract it keeps rather than a sandbox that enforces it. | -| Skill `/go-lint-setup` (user-invoked) | shipped | Slash-command skill: scaffolds, adopts, or debugs the golangci-lint v2 config in a repo. | -| Lint config `references/golangci.v2.yml` | shipped | Reference golangci-lint v2 config (`modernize` + stack linters). | -| Cursor rule `go-context.mdc` | shipped | `**/*.go`-scoped guidance mirroring the router for Cursor. | -| Scripts `scripts/hooks-test.sh`, `scripts/usage-report.py` | shipped | Dev tooling, not part of the installed component surface: a bash test harness for the hooks, and a stdlib-only adoption-report generator over local session transcripts. | - -Guidance is grounded in [Effective Go](https://go.dev/doc/effective_go), [Go Code Review Comments](https://go.dev/wiki/CodeReviewComments), the [Google Go Style Guide](https://google.github.io/styleguide/go/) (its *Guide*, *Style Decisions*, and *Best Practices*), the [Uber Go Style Guide](https://github.com/uber-go/guide), and the standard toolchain (`gofmt`/`gofumpt`, `go vet`, `staticcheck`, `golangci-lint`, `go test -race`). +| Component | Purpose | +|-----------|---------| +| Skill `go-coding` | Auto-invoked router: sends each Go topic to the enforcing tool and the focused skill that owns it; recommends the official `gopls-lsp` plugin. | +| Skills `go-errors`, `go-concurrency`, `go-testing`, `go-idioms`, `go-layout` | Load-on-use standards, each rule cited and framed around the enforcing linter (`modernize`, `errorlint`, `-race`, …). `go-layout` also owns naming, doc comments, and exported-API shape. | +| Skill `/go-lint-setup` | User-invoked: scaffolds, adopts, or debugs the golangci-lint v2 config in a repo. Never overwrites an existing config unprompted. | +| Agent `go-reviewer` | Report-only, context-isolated Go reviewer for what linters miss. Returns severity-ranked findings and dispatches no sub-agents. Its tool grant excludes `Write` and `Edit` but includes `Bash` to run the linters, so report-only is a contract it keeps rather than a sandbox that enforces it. | +| Session-start hook | Detects a Go workspace (`go.mod` or `*.go`) and prints one standards line; dual-host. | +| Format-on-save hook | After each `Write`/`Edit` of a `*.go` file, runs `gofumpt -w` (or `gofmt -w -s`) on that file, on the host; dual-host. A silent no-op when no formatter is installed. | +| Skill-nudge hook | After each `Write`/`Edit` of a `*.go` file, names one matching go-coding skill, once per skill per session; dual-host. Arrives as a hook `systemMessage` under Claude Code and as a plain line under Cursor. | +| Lint config `references/golangci.v2.yml` | Reference golangci-lint v2 config (`modernize` plus the stack linters). | +| Cursor rule `go-context.mdc` | `**/*.go`-scoped guidance mirroring the router for Cursor. | + +The guidance draws on [Effective Go](https://go.dev/doc/effective_go), [Go Code Review Comments](https://go.dev/wiki/CodeReviewComments), the [Google Go Style Guide](https://google.github.io/styleguide/go/) (its *Guide*, *Style Decisions*, and *Best Practices*), the [Uber Go Style Guide](https://github.com/uber-go/guide), and the standard toolchain (`gofmt`/`gofumpt`, `go vet`, `staticcheck`, `golangci-lint`, `go test -race`). ## Using with subagent orchestrators -Subagents do not inherit the parent session's skills. A plan runner that dispatches implementers -and reviewers must say so in every brief: +Subagents do not inherit the parent session's skills. A plan runner that dispatches implementers and reviewers must tell them, in every brief, to load the skills: -- **Implementer brief:** "Before writing code, invoke the Skill tool with `go-coding:go-coding`, then - the focused skills matching your diff (see its *Route, then load* table). Run `golangci-lint run` - on every touched package before committing." -- **Reviewer brief:** "Before reading the diff, load `go-coding:go-coding` plus `go-errors`, - `go-testing` and the skills the diff calls for; cite the rule a finding rests on. Do not dispatch - `go-reviewer`: you are the review seat." +- **Implementer brief**: "Before writing code, invoke the Skill tool with `go-coding:go-coding`, then the focused skills matching your diff (see its *Route, then load* table). Run `golangci-lint run` on every touched package before committing." +- **Reviewer brief**: "Before reading the diff, load `go-coding:go-coding` plus `go-errors`, `go-testing` and the skills the diff calls for; cite the rule a finding rests on. Do not dispatch `go-reviewer`: you are the review seat." -Use `go-reviewer` directly when no such seat exists (an ad-hoc "review this file" request). +Use `go-reviewer` directly when no such seat exists, as with an ad-hoc "review this file" request. ## Development The plugin has no build step. Validate locally: ```bash -./scripts/validate.sh # manifests, parity, paths, frontmatter, hooks, doc inventories, linters, fixers -./scripts/hooks-test.sh # bash tests for hooks/session-start.sh + hooks/skill-nudge.sh +./scripts/validate.sh # manifests, parity, paths, frontmatter, hooks, doc inventories, linters, fixers, tie-break +./scripts/hooks-test.sh # bash tests for the three hook scripts claude plugin validate . # manifest + component structure ``` -Beyond the shared structural checks, the validator enforces two invariants specific to this plugin. The first is **advice equals tooling**: every linter a component teaches must be reachable from the reference config. The second applies when a Go toolchain at the floor minor is on `PATH`: the `go-idioms` **Fixer** column is verified against `go tool fix help`, so a renamed or retired fixer fails the build rather than shipping as advice. +Beyond the structural checks, the validator enforces three invariants specific to this plugin: advice equals tooling, the `go-idioms` Fixer column, and the Google tie-break sentence. [What `scripts/validate.py` checks](docs/testing.md#what-scriptsvalidatepy-checks) in docs/testing.md defines each one and the drift it guards against. + +`scripts/usage-report.py` measures how often the skills and the `go-reviewer` agent load, from local Claude Code session transcripts; see [Measuring adoption](docs/testing.md#measuring-adoption). ## Documentation - [docs/install.md](docs/install.md): install on both hosts, and the Go toolchain each hook expects - [docs/testing.md](docs/testing.md): validate and dogfood - [docs/versioning.md](docs/versioning.md): SemVer policy and release steps -- [docs/authoring.md](docs/authoring.md): skill, command, agent, and rule authoring conventions +- [docs/authoring.md](docs/authoring.md): skill, agent, and rule authoring conventions See [AGENTS.md](AGENTS.md) for contributor conventions. diff --git a/docs/authoring.md b/docs/authoring.md index c12c7a5..8a4f7fd 100644 --- a/docs/authoring.md +++ b/docs/authoring.md @@ -1,59 +1,33 @@ -# Skill, command, agent, and rule authoring conventions +# Skill, agent, and rule authoring conventions -This page is for contributors adding or changing a skill, command, agent, or Cursor rule, and for -anyone refreshing the skills against current Go practice. It expands on the *how* behind -[AGENTS.md](../AGENTS.md), which stays authoritative, and it holds the source registry a refresh -re-reads. The shipped components are the reference examples. +This page is for contributors adding or changing a skill (including a slash-command skill), agent, or Cursor rule, and for anyone refreshing the skills against current Go practice. It expands on the *how* behind [AGENTS.md](../AGENTS.md), which stays authoritative, and it holds the source registry a refresh re-reads. The shipped components are the reference examples. ## Naming and layout -- **Components are kebab-case** and namespaced `:` (for example - `go-coding:go-errors`); don't repeat the plugin's words in a component name. A component's - frontmatter `name` MUST equal its directory (skills) or filename stem (agents); - `scripts/validate.py` enforces this. -- `skills//SKILL.md` (includes user-invoked slash commands) · `agents/.md` · - `rules/.mdc`. Shared reference material (for example `references/golangci.v2.yml`) lives in - top-level `references/`. The legacy `commands/.md` layout is not used. +- **Components are kebab-case** and namespaced `:` (for example `go-coding:go-errors`); don't repeat the plugin's words in a component name. A component's frontmatter `name` MUST equal its directory (skills) or filename stem (agents); `scripts/validate.py` enforces this. +- `skills//SKILL.md` (includes user-invoked slash commands) · `agents/.md` · `rules/.mdc`. Shared reference material (for example `references/golangci.v2.yml`) lives in top-level `references/`. The legacy `commands/.md` layout is not used. ## Skill, agent, or rule -- **Skill (auto-invoked)**: a load-on-use procedure or router. Only its `description` is always-on, - so keep that lean (the instruction budget is finite). The `go-coding` router + the `go-*` - standards skills are the model. -- **Skill (user-invoked / slash command)**: a thin one-shot `skills//SKILL.md` that also - carries `argument-hint` + `allowed-tools`; use `$ARGUMENTS` in the body. Invoked as `/`. See - `/go-lint-setup`. (The legacy `commands/` folder is not used.) -- **Agent**: a context-isolated specialist. Use **`tools:`** (a YAML block list), **never** - `allowed-tools:`, because in an agent that key is silently ignored and the agent inherits *all* tools. - See `go-reviewer` (report-only, no sub-agent dispatch). -- **Cursor rule**: a Cursor-only `.mdc` with `description` / `globs` / `alwaysApply` that mirrors a - skill for the Cursor host. See `rules/go-context.mdc`. +- **Skill (auto-invoked)**: a load-on-use procedure or router. Only its `description` is always-on, so keep that lean (the instruction budget is finite). The `go-coding` router + the `go-*` standards skills are the model. +- **Skill (user-invoked / slash command)**: a thin one-shot `skills//SKILL.md` that also carries `argument-hint` + `allowed-tools`; use `$ARGUMENTS` in the body. Invoked as `/`. See `/go-lint-setup`. (The legacy `commands/` folder is not used.) +- **Agent**: a context-isolated specialist. Use **`tools:`** (a YAML block list), **never** `allowed-tools:`, because in an agent that key is silently ignored and the agent inherits *all* tools. See `go-reviewer` (report-only, no sub-agent dispatch). +- **Cursor rule**: a Cursor-only `.mdc` with `description` / `globs` / `alwaysApply` that mirrors a skill for the Cursor host. See `rules/go-context.mdc`. ## The `description` (the trigger) -For skills the `description` is always-on metadata: keep it lean (~50–75 words) and in the third person: -*what + scope*, 3–5 representative triggers ("This skill should be used when…"), and a short -"Not for …" anti-trigger. For commands it's the one-line palette entry; pair it with `argument-hint`. +For skills the `description` is always-on metadata, so keep it lean (~50–75 words) and in the third person. Give *what + scope*, 3–5 representative triggers ("This skill should be used when…"), and a short "Not for …" anti-trigger. For a slash-command skill it is also the one-line palette entry; pair it with `argument-hint`. -**YAML gotcha:** a `description` value with an unquoted `: ` (colon-space), for example writing -`version: "2"` inline, makes a real YAML parser read it as a nested mapping, so the component loads -with *empty* metadata (every field silently dropped). `claude plugin validate` catches this, and -`scripts/validate.py` guards against it too. Reword or quote the value. +**YAML gotcha:** a `description` value with an unquoted `: ` (colon-space), for example writing `version: "2"` inline, makes a real YAML parser read it as a nested mapping, so the component loads with *empty* metadata (every field silently dropped). `claude plugin validate` catches this, and `scripts/validate.py` guards against it too. Reword or quote the value. ## Body -- **Deterministic beats prose.** Point at the tool that enforces a rule (`gofmt`/`gofumpt`, - `go vet`, a `golangci-lint` linter, `modernize`, `go test -race`) rather than re-deriving it. - Ground every judgment rule in a cited source (Effective Go, Go Code Review Comments, the Google or - Uber style guide, a `go.dev/blog` post, `pkg.go.dev`); do not invent rules. -- Imperative voice; explain *why* a rule matters rather than relying on bare MUST/NEVER. Keep skill - bodies focused: the always-on cost is the `description`, and the body loads on use. +- **Deterministic beats prose.** Point at the tool that enforces a rule (`gofmt`/`gofumpt`, `go vet`, a `golangci-lint` linter, `modernize`, `go test -race`) rather than re-deriving it. Ground every judgment rule in a cited source (Effective Go, Go Code Review Comments, the Google or Uber style guide, a `go.dev/blog` post, `pkg.go.dev`); do not invent rules. +- Imperative voice; explain *why* a rule matters rather than relying on bare MUST/NEVER. Keep skill bodies focused: the always-on cost is the `description`, and the body loads on use. ## Refreshing the standards baseline (source registry) -When asked to *refresh the skills against current Go practice*, re-read these sources in this order -and update the affected skill bodies. Do not refresh from memory, and do not add a rule without a -citation. Everything the skills assert should be traceable to one of these. +When asked to *refresh the skills against current Go practice*, re-read these sources in this order and update the affected skill bodies. Do not refresh from memory, and do not add a rule without a citation. Everything the skills assert should be traceable to one of these. **Tier 1: normative, always check first** @@ -68,42 +42,23 @@ citation. Everything the skills assert should be traceable to one of these. **Tier 2: style guides (attribute when a rule comes from one, and name the document)** -- Google Go Style Guide: three documents of different weight, ranked by Google itself; a citation - names which one: - - the *Guide* (), **normative and canonical**: the five ordered readability principles - (clarity, simplicity, concision, maintainability, consistency) and, under simplicity, *least mechanism*. This is - the tie-break order the router, the Cursor rule and the reviewer use, as one identical sentence in - all three, checked by `scripts/validate.py`. - - *Style Decisions* (), **normative, not canonical**: the reviewer rulebook for naming, - commentary, imports, errors, language, common libraries, useful test failures. The main Google - source for skill rules. - - *Best Practices* (), **advisory**: patterns with trade-offs (test doubles, option structs, - error structure, shadowing, table-test literals). - Google-internal guidance is not adopted: flag conventions, Google's own logging library and - verbosity levels, protocol-buffer stubs, and CLI library choices. +- Google Go Style Guide: three documents of different weight, ranked by Google itself; a citation names which one: + - the *Guide* (), **normative and canonical**: the five ordered readability principles (clarity, simplicity, concision, maintainability, consistency) and, under simplicity, *least mechanism*. This is the tie-break order the router, the Cursor rule and the reviewer use, as one identical sentence in all three, checked by `scripts/validate.py`. + - *Style Decisions* (), **normative, not canonical**: the reviewer rulebook for naming, commentary, imports, errors, language, common libraries, useful test failures. The main Google source for skill rules. + - *Best Practices* (), **advisory**: patterns with trade-offs (test doubles, option structs, error structure, shadowing, table-test literals). + + Google-internal guidance is not adopted: flag conventions, Google's own logging library and verbosity levels, protocol-buffer stubs, and CLI library choices. - Uber Go Style Guide: **Tier 3: the enforcing tools (this is what keeps "advice == tooling" true)** -- **`go tool fix help` on the floor-version toolchain**: the authority for which fixers `go fix` - actually ships (the plain rows in the `go-idioms` **Fixer** column). The `go fix` blog post: - -- `modernize` per-fixer docs: . - These track x/tools **tip**, which is usually ahead of the toolchain, so they are the source for **†** rows and - never evidence that a fixer ships in `go fix` -- golangci-lint docs: · v1→v2 migration: - · changelog (for the CI pin): - -- `go.dev/blog` for feature-specific posts (`synctest`, `testing-b-loop`, `slog`, `range-functions`, - `examples`) -- **Linter rule catalogues**: when a skill says a tool catches something, the rule id or name comes - from here, not from memory: `go vet` analyzers ; staticcheck checks - ; revive rules ; errorlint - ; gofumpt rules ; - the golangci-lint linters index - -**Revision record**: the mutable sources, as last read. A refresh diffs each against its recorded -revision first, so it reads what changed rather than everything, then updates this table. +- **`go tool fix help` on the floor-version toolchain**: the authority for which fixers `go fix` actually ships (the plain rows in the `go-idioms` **Fixer** column). The `go fix` blog post: +- `modernize` per-fixer docs: . These track x/tools **tip**, which is usually ahead of the toolchain, so they are the source for **†** rows and never evidence that a fixer ships in `go fix` +- golangci-lint docs: · v1→v2 migration: · changelog (for the CI pin): +- `go.dev/blog` for feature-specific posts (`synctest`, `testing-b-loop`, `slog`, `range-functions`, `examples`) +- **Linter rule catalogues**: when a skill says a tool catches something, the rule id or name comes from here, not from memory: `go vet` analyzers ; staticcheck checks ; revive rules ; errorlint ; gofumpt rules ; the golangci-lint linters index + +**Revision record**: the mutable sources, as last read. A refresh diffs each against its recorded revision first, so it reads what changed rather than everything, then updates this table. | Source | Revision read | Checked | |---|---|---| @@ -115,53 +70,24 @@ revision first, so it reads what changed rather than everything, then updates th **Procedure** -1. Confirm the current *released* Go version (release history); a draft `go1.NN` page is not a - baseline. Guidance for an unreleased version goes in as one *italic, explicitly labelled* - sentence (`*Go 1.NN (draft, expected …)*`), never as a rule. - **The baseline is a hard floor** (currently **Go 1.26.4+**; Go 1.27 is supported too, with its - additions flagged as hints rather than folded into the floor): recommend the modern form flat, with - no "on 1.NN+ modules prefer…" hedging and no fallback branch for older toolchains. Keep the - version annotation (`Since`, "(Go 1.24)"): that is provenance, and it tells a reader on an older - module what a bump would buy. When the floor moves, delete the guidance below it. -2. Diff each `go-*` skill against Tier 1 for the baseline and the two prior versions. The common - miss is a stdlib API that landed *after* a skill was written (`errors.AsType`, `t.ArtifactDir`). +1. Confirm the current *released* Go version (release history); a draft `go1.NN` page is not a baseline. Guidance for an unreleased version goes in as one *italic, explicitly labelled* sentence (`*Go 1.NN (draft, expected …)*`), never as a rule. + + **The baseline is a hard floor** (currently **Go 1.26.4+**; Go 1.27 is supported too, with its additions flagged as hints rather than folded into the floor): recommend the modern form flat, with no "on 1.NN+ modules prefer…" hedging and no fallback branch for older toolchains. Keep the version annotation (`Since`, "(Go 1.24)"): that is provenance, and it tells a reader on an older module what a bump would buy. When the floor moves, delete the guidance below it. +2. Diff each `go-*` skill against Tier 1 for the baseline and the two prior versions. The common miss is a stdlib API that landed *after* a skill was written (`errors.AsType`, `t.ArtifactDir`). 3. Verify every version gate in `pkg.go.dev`'s "added in" annotation before writing a `Since` cell. -4. Re-check the Tier 3 tool names: a renamed or dropped fixer/linter turns a rule into a wrong - command (`waitgroup` → `waitgroupgo`). - **Run the tool, don't read about it:** when a floor-version toolchain is available, - `go tool fix help` settles fixer names in one command, whereas pkg.go.dev's modernize page tracks - x/tools tip, which is usually ahead of what `go fix` ships; same idea for linters - (`golangci-lint help linters` on the pinned build). `scripts/validate.py` enforces both - halves: every linter taught in components must be enabled in `references/golangci.v2.yml`, - and, when a floor-minor Go toolchain is on PATH (CI's matrix installs both `1.26.x` and - `1.27.x`; locally it soft-skips with a note), the `go-idioms` Fixer column is verified against - `go tool fix help`: plain names must be registered, † names must not be. An analyzer a skill - teaches as *opt-in* (`shadow` in `go-idioms`) is the deliberate exception to the first half: it - is taught together with the config line that switches it on, and is not added to the reference - config at a refresh. The floor minor lives in `GO_FLOOR_MINOR` in the script and in the - workflow's matrix floor entry (`1.26.x`); move all three (docs baseline included) together. - **Never hardcode a tool version in a component.** A named `golangci-lint` release rots within - weeks and nobody remembers why it was chosen; the skills carry the *pin policy* (pin exactly, one - source of truth, automated bump PR) plus the changelog URL, and let the consuming repo own the - number. The same goes for `gopls`/`gofumpt` versions outside `docs/install.md`. -5. Keep the two copies of the reference lint config in sync: `references/golangci.v2.yml` and the - scaffold block in `go-lint-setup`. -6. Run `python3 scripts/validate.py --check-links`: every cited URL must still resolve; a moved - page is fixed in the same refresh. -7. Update the **Revision record** above, then record the refresh in **CHANGELOG.md** under - `## [Unreleased]`. +4. Re-check the Tier 3 tool names: a renamed or dropped fixer/linter turns a rule into a wrong command (`waitgroup` → `waitgroupgo`). + + **Run the tool, don't read about it:** when a floor-version toolchain is available, `go tool fix help` settles fixer names in one command, whereas pkg.go.dev's modernize page tracks x/tools tip, which is usually ahead of what `go fix` ships; same idea for linters (`golangci-lint help linters` on the pinned build). `scripts/validate.py` enforces both halves: every linter taught in components must be enabled in `references/golangci.v2.yml`, and, when a floor-minor Go toolchain is on PATH (CI's matrix installs both `1.26.x` and `1.27.x`; locally it soft-skips with a note), the `go-idioms` Fixer column is verified against `go tool fix help`: plain names must be registered, † names must not be. An analyzer a skill teaches as *opt-in* (`shadow` in `go-idioms`) is the deliberate exception to the first half: it is taught together with the config line that switches it on, and is not added to the reference config at a refresh. The floor minor lives in `GO_FLOOR_MINOR` in the script and in the workflow's matrix floor entry (`1.26.x`); move all three (docs baseline included) together. + + **Never hardcode a tool version in a component.** A named `golangci-lint` release rots within weeks and nobody remembers why it was chosen; the skills carry the *pin policy* (pin exactly, one source of truth, automated bump PR) plus the changelog URL, and let the consuming repo own the number. The same goes for `gopls`/`gofumpt` versions outside `docs/install.md`. +5. Keep the two copies of the reference lint config in sync: `references/golangci.v2.yml` and the scaffold block in `go-lint-setup`. +6. Run `python3 scripts/validate.py --check-links`: every cited URL must still resolve; a moved page is fixed in the same refresh. +7. Update the **Revision record** above, then record the refresh in **CHANGELOG.md** under `## [Unreleased]`. ## Dual-host parity -Skills, commands, and agents are shared by both hosts. The **Cursor** manifest -(`.cursor-plugin/plugin.json`) must declare each component path, plus a `.mdc` mirror wherever a -Cursor rule is wanted; **Claude** discovers the default folders automatically. Keep the two -manifests' `name`/`version`/`description`/`author` identical (`scripts/validate.py` checks parity), -and the Cursor hook command **workspace-relative** (`bash hooks/session-start.sh`), never -`${CLAUDE_PLUGIN_ROOT}`. +Skills (slash-command skills included) and agents are shared by both hosts. The **Cursor** manifest (`.cursor-plugin/plugin.json`) must declare each component path, plus a `.mdc` mirror wherever a Cursor rule is wanted; **Claude** discovers the default folders automatically. Keep the two manifests' `name`/`version`/`description`/`author` identical (`scripts/validate.py` checks parity), and the Cursor hook command **workspace-relative** (`bash hooks/session-start.sh`), never `${CLAUDE_PLUGIN_ROOT}`. ## Before committing -Run `./scripts/validate.sh` and `claude plugin validate .`, then test triggering locally; see -[testing.md](testing.md). When adding or renaming a component, sync **AGENTS.md**, **README.md**, -and **CHANGELOG.md** in lockstep. +Run `./scripts/validate.sh` and `claude plugin validate .`, then test triggering locally; see [testing.md](testing.md). When adding or renaming a component, sync **AGENTS.md**, **README.md**, and **CHANGELOG.md** in lockstep. diff --git a/docs/install.md b/docs/install.md index c3625e3..3f76c3c 100644 --- a/docs/install.md +++ b/docs/install.md @@ -1,6 +1,6 @@ # Installing the Go Coding Plugin -This page is for anyone installing, updating, or dogfooding the plugin: the Claude Code marketplace install, a local working copy for development, Cursor, and the Go toolchain the hooks expect on the host. The plugin is distributed for both [Claude Code](https://docs.claude.com/en/docs/claude-code/plugins) (`.claude-plugin/`) and [Cursor](https://cursor.com/docs/plugins) (`.cursor-plugin/`). Skill, agent, and rule content is shared; only the manifest and hook layer differ. The plugin is pure Markdown + JSON, so there is no build step and **no MCP server** to wire up. +This page is for anyone installing, updating, or dogfooding the plugin: the Claude Code marketplace install, a local working copy for development, Cursor, and the Go toolchain the hooks expect on the host. The plugin is distributed for both [Claude Code](https://docs.claude.com/en/docs/claude-code/plugins) (`.claude-plugin/`) and [Cursor](https://cursor.com/docs/plugins) (`.cursor-plugin/`). Both hosts share the skill, agent, and reference content; only the manifests, the hook configs, and the Cursor-only rule in `rules/` differ. The plugin is pure Markdown + JSON, so there is no build step and **no MCP server** to wire up. ## Claude Code @@ -19,15 +19,15 @@ The marketplace name is `cadasto`, so the plugin is addressed as `go-coding@cada claude --plugin-dir /path/to/go-coding-plugin ``` -`--plugin-dir` loads the plugin from disk for **that session only**. It does not persist, which makes it the right tool for dogfooding an unreleased working copy. It is repeatable (`--plugin-dir A --plugin-dir B`) and also accepts a `.zip`. +`--plugin-dir` loads the plugin from disk for **that session only**, which makes it the right tool for dogfooding an unreleased working copy. It is repeatable (`--plugin-dir A --plugin-dir B`) and also accepts a `.zip`. -Claude Code has **no `plugin add` subcommand**. `claude plugin install` resolves names from a configured marketplace, not filesystem paths, and `claude plugin marketplace add ` expects a marketplace manifest (`.claude-plugin/marketplace.json`), which a single-plugin repository like this one does not have. For a persistent install, go through the marketplace above. +Claude Code has **no `plugin add` subcommand**. `claude plugin install` resolves names from a configured marketplace, not filesystem paths, and `claude plugin marketplace add ` expects a marketplace manifest (`.claude-plugin/marketplace.json`), which a single-plugin repository like this one does not have. For a persistent install, use the marketplace. ### Inspect / update ```bash -claude plugin validate . # manifest + component structure -claude plugin details go-coding # component inventory + projected token cost +claude plugin validate . # manifest + component structure +claude plugin details go-coding # component inventory + projected token cost ``` ```text @@ -35,7 +35,7 @@ claude plugin details go-coding # component inventory + projected token cost /plugin update go-coding ``` -A session restart is required for an update to take effect. +Restart the session for an update to take effect. ## Cursor @@ -43,7 +43,7 @@ Add this repository as a plugin (Cursor **Settings → Plugins**, via Git URL or ## Host toolchain (minimal requirements) -Installing the plugin itself needs no Go toolchain, because the plugin is pure Markdown + JSON. Its **enforcement** layer only delivers value when the standard Go tools are on the host `PATH`: the `format-on-save` hook shells out to a formatter, the golangci-lint v2 reference config lists `gofumpt`/`goimports` as formatters, and the recommended official `gopls-lsp` plugin (`@claude-plugins-official`) drives `gopls`. The plugin targets **Go 1.26.4+** + golangci-lint v2 as a hard floor: it carries no fallback guidance for 1.25 or older modules. +Installing the plugin itself needs no Go toolchain, because the plugin is pure Markdown + JSON. Its **enforcement** layer only delivers value when the standard Go tools are on the host `PATH`: the `format-on-save` hook shells out to a formatter, the golangci-lint v2 reference config lists `gofumpt`/`goimports` as formatters, and the recommended official `gopls-lsp` plugin (`@claude-plugins-official`) drives `gopls`. The plugin targets **Go 1.26.4+** and golangci-lint v2 as a hard floor: it carries no fallback guidance for 1.25 or older modules. At minimum the host should provide: @@ -97,7 +97,7 @@ These are **host-only** dev tools; the plugin still works without them (the form The plugin ships three host-agnostic hooks (Claude `hooks/hooks.json`, Cursor `hooks/cursor-hooks.json`): - **`session-start.sh`**: on session start, detects a Go workspace (`go.mod`/`*.go`) and prints one standards line. -- **`format-on-save.sh`**: after each edit of a `*.go` file (Claude `PostToolUse` on `Write`/`Edit`; Cursor `afterFileEdit`), runs **`gofumpt -w`** on that file, or **`gofmt -w -s`** when `gofumpt` is not installed. It is **host-only** (no container round-trip), **edits the file in place**, and is a **silent no-op** when no Go formatter is on `PATH`, so install `gofmt` (ships with Go) or `gofumpt` to benefit. It never blocks an edit. This is per-file formatting only; run `golangci-lint` and your tests via CI/`make` for full-tree checks. -- **`skill-nudge.sh`**: after each edit of a `*.go` file (same trigger as `format-on-save.sh`), names ONE matching go-coding skill for that edit (a `_test.go` file → `go-testing`; goroutine/channel/`sync`/`atomic`/`errgroup` content → `go-concurrency`; `fmt.Errorf`/`errors.*` → `go-errors`), once per skill per session. Delivered as a hook `systemMessage` under Claude Code (reaches the model's context on exit 0) or a plain line under Cursor. It never blocks an edit. +- **`format-on-save.sh`**: after each edit of a `*.go` file (Claude `PostToolUse` on `Write`/`Edit`; Cursor `afterFileEdit`), runs **`gofumpt -w`** on that file, or **`gofmt -w -s`** when `gofumpt` is not installed. It is **host-only** (no container round-trip), **edits the file in place**, and is a **silent no-op** when no Go formatter is on `PATH`, so it needs Go (which ships `gofmt`) or `gofumpt` on the host. It never blocks an edit. This is per-file formatting only; run `golangci-lint` and your tests via CI/`make` for full-tree checks. +- **`skill-nudge.sh`**: after each edit of a `*.go` file (same trigger as `format-on-save.sh`), names one matching go-coding skill for that edit (a `_test.go` file → `go-testing`; goroutine/channel/`sync`/`atomic`/`errgroup` content → `go-concurrency`; `fmt.Errorf`/`errors.*` → `go-errors`), once per skill per session. Delivered as a hook `systemMessage` under Claude Code (reaches the model's context on exit 0) or a plain line under Cursor. It never blocks an edit. -> The Cursor wiring targets the `afterFileEdit` event; if your Cursor version exposes a different post-edit event or payload shape, adjust `hooks/cursor-hooks.json` and the path-extraction in `format-on-save.sh` accordingly. +> The Cursor wiring targets the `afterFileEdit` event; if your Cursor version exposes a different post-edit event or payload shape, adjust `hooks/cursor-hooks.json` and the path extraction in `format-on-save.sh` to match. diff --git a/docs/testing.md b/docs/testing.md index b540793..4b06f1c 100644 --- a/docs/testing.md +++ b/docs/testing.md @@ -1,68 +1,62 @@ # Testing and validation -This page is for contributors checking a change before a pull request or a release: what each -validator checks, how to exercise the components by hand, and how to measure skill adoption. -The repository is pure content (JSON manifests and Markdown components) with no build step or -package manager, so testing means validating structure, then installing locally and exercising -the components. +This page is for contributors checking a change before a pull request or a release: what each validator checks, how to exercise the components by hand, and how to measure skill adoption. The repository is pure content (JSON manifests and Markdown components) with no build step or package manager, so testing means validating structure, then loading a working copy and exercising the components. ## Validation -- **Manifest / component validation**: `./scripts/validate.sh` checks both `plugin.json` manifests, dual-host parity (name/version/description/author agree), declared component paths, kebab-case names, hook-config JSON, hook parity (the same `hooks/*.sh` wired for the equivalent event on both hosts, each existing and executable, none left unwired), doc component inventories (every shipped skill, agent and hook named where the docs claim to list them), and SKILL.md / agent / command frontmatter (including `name` == directory/filename, and that agents declare `tools:` not `allowed-tools:`). The wrapper runs `scripts/validate.py`; if Python 3 isn't installed it prints a warning and skips (exit 0) rather than failing. Install `python3` for the full local check, or rely on `claude plugin validate .` and CI. CI pins Python and calls `python3 scripts/validate.py` directly, so the deep check can never silently skip there. +- **Manifest / component validation**: `./scripts/validate.sh`, a wrapper around `scripts/validate.py`; see [What `scripts/validate.py` checks](#what-scriptsvalidatepy-checks). Without Python 3 the wrapper prints a warning and exits 0 instead of failing; install `python3` for the full local check, or rely on `claude plugin validate .` and CI. CI installs Python 3 and calls `python3 scripts/validate.py` directly, so the full check never silently skips there. - **Validator self-test**: `python3 scripts/validate.py --selftest` (also run by CI) rebuilds each structural check's failure case in a temporary tree and requires the check to catch it, so a check that has quietly stopped checking cannot pass as green. It also exercises the link checker's fetch policy (HEAD then GET, one retry on a transport error or an HTTP 429/503, a 404 reported as broken) against a local HTTP server, with no network access. - **Link check**: with `python3 scripts/validate.py --check-links`, every URL cited in skills, agents, rules, and docs must resolve. Needs the network, so it is its own switch; CI runs it weekly and on pull requests that touch those files, the checker itself, or its workflow (`.github/workflows/links.yml`). - **Hook tests**: `./scripts/hooks-test.sh` (also run by CI on every PR) runs bash tests for all three hook scripts (`hooks/session-start.sh`, `hooks/format-on-save.sh`, `hooks/skill-nudge.sh`), including a can-fail self-test block that proves the negative-case helpers actually fail on bad input. - **Official validator**: `claude plugin validate .` checks the manifest and component structure (no extra dependencies). - **Structural review**: run the `plugin-dev:plugin-validator` agent after creating or modifying components. -- **Skill quality review**: run the `plugin-dev:skill-reviewer` agent for description-triggering quality, progressive disclosure, content structure. -- **Token cost**: `claude plugin details go-coding` shows the inventory and projected token cost; keep skill/command metadata lean. +- **Skill quality review**: run the `plugin-dev:skill-reviewer` agent for how well each description triggers, progressive disclosure, and content structure. +- **Token cost**: `claude plugin details go-coding` shows the inventory and projected token cost; keep skill metadata lean. + +### What `scripts/validate.py` checks + +Structural checks: + +- Both manifests parse as JSON and carry the required fields, with a lowercase `name` of alphanumerics, hyphens, and periods, and they agree on `name`, `version`, `description`, and `author` (dual-host parity). +- Every component path a manifest declares exists inside the plugin directory, and skill, agent, command, and rule names are kebab-case. +- Hook-config JSON is valid, and hook parity holds: the same `hooks/*.sh` is wired for the equivalent event on both hosts, each wired script exists and is executable, and none is left unwired. +- SKILL.md, agent, and command frontmatter carries the required keys, with `name` equal to the directory or filename stem. **An agent that declares `allowed-tools:` fails**: the key is ignored, so the agent would inherit every tool. +- `rules/*.mdc` frontmatter carries a `description`, and no frontmatter value contains an unquoted `: ` or ` #`, which a YAML parser would read as a nested mapping or a comment, silently dropping the metadata. +- Doc component inventories: every shipped skill, agent, and hook is named in the docs that list them (`README.md`, `AGENTS.md`, and this page; `docs/install.md` for the hooks only). + +Three invariants specific to this plugin: + +- **Advice equals tooling**: every linter a component teaches (through `--enable-only=…` or "the `` linter") must be enabled in `references/golangci.v2.yml`, so no skill tells an agent to rely on a linter the reference config does not ship. +- **Fixer column**: when a Go toolchain at the floor minor (`GO_FLOOR_MINOR`) is on `PATH`, the `go-idioms` **Fixer** column is verified against `go tool fix help`: plain names must be registered, † names must not be, so a renamed or retired fixer fails the build instead of shipping as advice. Locally it soft-skips without that toolchain; CI installs it. +- **Tie-break sentence**: the Google readability tie-break sentence, which ranks clarity first and consistency last (`TIE_BREAK_SENTENCE` in the script holds the exact text), must appear verbatim in each of the `go-coding` router, `rules/go-context.mdc`, and `go-reviewer`. ## Local triggering tests -Install from your working copy (see [install.md](install.md)), then exercise each component: +Load your working copy with `--plugin-dir` (see [install.md](install.md)), then exercise each component: - **Session-start hook**: open a repo with a `go.mod`/`*.go`; one Go-standards line should print at session start (and nothing in a non-Go repo). - **`go-coding` router**: ask for a Go review or idiom help; it should route to the enforcing tool and the focused skill. - **Standards skills**: a topic prompt should engage the matching skill (for example error wrapping → `go-errors`, a flaky time-based test → `go-testing`/`go-concurrency`, linter setup → `go-lint-setup`). - **Format-on-save hook**: save a deliberately mis-formatted `*.go` file; `format-on-save.sh` should reformat that one file in place (`gofumpt -w`, or `gofmt -w -s` when `gofumpt` is absent) and say nothing when neither is installed. -- **Skill-nudge hook**: edit a `_test.go` file; the nudge should name `go-coding:go-testing` (as a systemMessage under Claude Code, a plain line under Cursor) and, critically, the model should ACT on it (load the skill), not merely have the line appear in the transcript. A second edit to a `_test.go` file in the same session should be silent (once per skill per session), and so should an edit that does not itself touch the topic: a doc-comment fix in a file that defines a sentinel elsewhere must not claim the edit touches an error path. +- **Skill-nudge hook**: edit a `_test.go` file; the nudge should name `go-coding:go-testing` (as a `systemMessage` under Claude Code, a plain line under Cursor), and the model should **act** on it by loading the skill; the line appearing in the transcript is not enough. A second edit to a `_test.go` file in the same session should be silent (once per skill per session), and so should an edit that does not itself touch the topic: a doc-comment fix in a file that defines a sentinel elsewhere must not claim the edit touches an error path. - **`go-reviewer` agent**: ask for a Go code review; it returns severity-ranked findings and does not spawn sub-agents. -- **Slash command (skill)**: `/go-lint-setup`. +- **`/go-lint-setup`**: run it in a Go repo without a golangci-lint config and confirm it writes the reference v2 config; run it in a repo that already has one and confirm it does not overwrite it unprompted. - **Cursor rule**: in Cursor, open a `.go` file and confirm `go-context.mdc` attaches. -After editing content, reinstall (or restart the session) to pick up changes. +After editing content, restart the session (or reload the plugin in Cursor) to pick up changes. ## Measuring adoption -The layout and concurrency skills, and the router's dispatch behaviour, were shaped by -a usage analysis of local Claude Code session transcripts. `scripts/usage-report.py` -(stdlib-only) reproduces that measurement so adoption stays checkable over time: +The layout and concurrency skills, and the router's dispatch behaviour, were shaped by a usage analysis of local Claude Code session transcripts. `scripts/usage-report.py` (stdlib-only) reproduces that measurement so adoption stays checkable over time: ```bash python3 scripts/usage-report.py --since YYYY-MM-DD --out report.md ``` -Run with no arguments to scan `~/.claude/projects` from the beginning and print the -report to stdout; `--since` narrows to a start date, `--out` writes the report to a -file instead. `--help` repeats the counting rules. - -**Counted:** a `Skill` tool invocation whose `skill` input starts with `go-coding:`; a -`Task`/`Agent` tool invocation with `subagent_type` `go-coding:go-reviewer`; a user -`` invocation naming a go-coding skill. Events are split into main-session, -subagent, and user-invoked, per month. The report renders two tables: "Per skill / agent" -counts every event (so a skill loaded three times in one session counts three times), and -"Sessions with >=1 event, per skill / agent" counts distinct sessions instead, so a skill -loaded three times in one session counts once there. The 50% target below is read off the -sessions table: (sessions loading a given focused skill) / (sessions loading -`go-coding:go-coding`). - -**Not counted:** the SessionStart banner line, or skill-body text echoed back inside -tool results: only structured tool invocations and explicit slash-command text count. -Nor is Cursor: the script reads Claude Code transcripts (`~/.claude/projects`) only, so -the numbers describe adoption on one of the two hosts. - -**Target:** the focused standards skills (`go-errors`, `go-testing`, `go-idioms`, -`go-lint-setup`, `go-layout`, `go-concurrency`) should load on at least 50% of sessions -where the `go-coding` router itself loads, and `go-layout` / `go-concurrency` -specifically should show non-zero counts in any period where the corresponding work -(project layout/API design, or goroutines/channels/context) is actually touched. +Run with no arguments to scan `~/.claude/projects` from the beginning and print the report to stdout; `--since` narrows to a start date, `--out` writes the report to a file instead. `--help` repeats the counting rules. + +**Counted:** a `Skill` tool invocation whose `skill` input starts with `go-coding:`; a `Task`/`Agent` tool invocation with `subagent_type` `go-coding:go-reviewer`; a user `` invocation naming a go-coding skill. Events are split into main-session, subagent, and user-invoked, per month. The report renders two tables: "Per skill / agent" counts every event (so a skill loaded three times in one session counts three times), and "Sessions with >=1 event, per skill / agent" counts distinct sessions instead, so a skill loaded three times in one session counts once there. The 50% target below is read off the sessions table: (sessions loading a given focused skill) / (sessions loading `go-coding:go-coding`). + +**Not counted:** the SessionStart banner line, or skill-body text echoed back inside tool results: only structured tool invocations and explicit slash-command text count. Nor is Cursor: the script reads Claude Code transcripts (`~/.claude/projects`) only, so the numbers describe adoption on one of the two hosts. + +**Target:** the focused standards skills (`go-errors`, `go-testing`, `go-idioms`, `go-lint-setup`, `go-layout`, `go-concurrency`) should load on at least 50% of sessions where the `go-coding` router itself loads, and `go-layout` / `go-concurrency` specifically should show non-zero counts in any period where the corresponding work (project layout/API design, or goroutines/channels/context) is actually touched. diff --git a/docs/versioning.md b/docs/versioning.md index 8c5d311..f7f57cf 100644 --- a/docs/versioning.md +++ b/docs/versioning.md @@ -1,31 +1,22 @@ # Versioning and releases -This page is for maintainers cutting a release: how to choose the version bump, the release -steps, and how a release reaches users through the Cadasto marketplace. The plugin uses -[Semantic Versioning](https://semver.org), adapted to skill, command, agent, and rule content: +This page is for maintainers cutting a release: how to choose the version bump, the release steps, and how a release reaches users through the Cadasto marketplace. The plugin uses [Semantic Versioning](https://semver.org), adapted to skill, agent, and rule content: | Bump | When | |------|------| -| **Major** | A skill/command/agent/rule is removed or renamed, or its behaviour/scope changes incompatibly | +| **Major** | A skill (slash commands included), agent, or rule is removed or renamed, or its behaviour/scope changes incompatibly | | **Minor** | A new component is added, or an existing one's coverage meaningfully expands | | **Patch** | Typos, clarifications, reference/source fixes; no behaviour change | -While on the `0.x` line, treat the plugin as pre-stable: a breaking change may still ship in a minor -bump. +While on the `0.x` line, treat the plugin as pre-stable: a breaking change may still ship in a minor bump. ## Release steps -1. Bump `version` in **both** manifests (they must agree): `.claude-plugin/plugin.json` and - `.cursor-plugin/plugin.json`. Keep `description` and `author` identical across both; - `scripts/validate.py` enforces this parity. +1. Bump `version` in **both** manifests (they must agree): `.claude-plugin/plugin.json` and `.cursor-plugin/plugin.json`. Keep `description` and `author` identical across both; `scripts/validate.py` enforces this parity. 2. Run `./scripts/validate.sh`, `./scripts/hooks-test.sh`, and `claude plugin validate .`. -3. **Dogfood:** load the working copy (`claude --plugin-dir /path/to/go-coding-plugin`) and - exercise the components against a real Go change on **both** hosts; see [testing.md](testing.md). -4. Fold the accumulated `## [Unreleased]` notes into a dated `## [X.Y.Z] - YYYY-MM-DD` section in - [CHANGELOG.md](../CHANGELOG.md) (Keep a Changelog: groups in order Added, Changed, Deprecated, - Removed, Fixed, Security; see [AGENTS.md](../AGENTS.md#changelog-style)). -5. Sync the docs surface (AGENTS.md, README.md) with what shipped, and the component list in the - session-start hook's banner (`hooks/session-start.sh`). +3. **Dogfood:** load the working copy (`claude --plugin-dir /path/to/go-coding-plugin`) and exercise the components against a real Go change on **both** hosts; see [testing.md](testing.md). +4. Fold the accumulated `## [Unreleased]` notes into a dated `## [X.Y.Z] - YYYY-MM-DD` section in [CHANGELOG.md](../CHANGELOG.md) (Keep a Changelog: groups in order Added, Changed, Deprecated, Removed, Fixed, Security; see [AGENTS.md](../AGENTS.md#changelog-style)). +5. Sync the docs surface (AGENTS.md, README.md) with what shipped, and the component list in the session-start hook's banner (`hooks/session-start.sh`). 6. Update the version badge in [README.md](../README.md) to `X.Y.Z`. 7. Commit (`chore(release): vX.Y.Z`) and tag: `git tag -a vX.Y.Z -m "go-coding-plugin vX.Y.Z"`. 8. Push commits and the tag: `git push origin main --follow-tags`. @@ -37,20 +28,14 @@ This plugin has **no companion MCP server**, so there is no server-compatibility ## Marketplace -This plugin is listed in the [Cadasto marketplace](https://github.com/Cadasto/plugin-marketplace) -as `go-coding@cadasto`. The catalog **pins every entry to a release tag**, so tagging and pushing a -release here does not ship it: users see nothing until the marketplace entry moves. +This plugin is listed in the [Cadasto marketplace](https://github.com/Cadasto/plugin-marketplace) as `go-coding@cadasto`. The catalog **pins every entry to a release tag**, so tagging and pushing a release here does not ship it: users see nothing until the marketplace entry moves. After step 8, update the entry in `Cadasto/plugin-marketplace`: -1. Bump that entry's `version` to `X.Y.Z` and `source.ref` to `vX.Y.Z` together (validation there - rejects a mismatch). -2. Bump the catalog's own `metadata.version`: a plugin minor/major is a catalog **minor**, a plugin - patch is a catalog **patch**. -3. Add a dated `## [X.Y.Z] - YYYY-MM-DD` section in the catalog `CHANGELOG.md`, then run - `python3 scripts/validate.py --fix`. +1. Bump that entry's `version` to `X.Y.Z` and `source.ref` to `vX.Y.Z` together (validation there rejects a mismatch). +2. Bump the catalog's own `metadata.version`: a plugin minor/major is a catalog **minor**, a plugin patch is a catalog **patch**. +3. Add a dated `## [X.Y.Z] - YYYY-MM-DD` section in the catalog `CHANGELOG.md`, then run `python3 scripts/validate.py --fix`. See the catalog's [docs/versioning.md](https://github.com/Cadasto/plugin-marketplace/blob/main/docs/versioning.md). -The catalog copies `description`, `version`, and `keywords` verbatim from `.claude-plugin/plugin.json`, -so update the entry whenever any of those change, not only on a release. +The catalog copies `description`, `version`, and `keywords` verbatim from `.claude-plugin/plugin.json`, so update the entry whenever any of those change, not only on a release.