Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions plugins/cozystack/.claude-plugin/plugin.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"name": "cozystack",
"version": "1.16.0",
"description": "Cozystack platform skills bundle. Start with cozystack:wizard — it begins with a free-form 'tell me about your setup and goal' question, parses hints, then asks Talos / Ubuntu / Existing, builds a chain, and dispatches downstream skills via a cluster config directory the operator picks (every artifact lives there: inventory.yml, kubeconfig, .state.yaml, cozystack-platform-package.yaml — operator manages git on their own; optional sops opt-in encrypts secret files in-tree). Skills, invoked as cozystack:<name>: wizard (orchestrator + 3-route dispatcher + Phase 4.5 active research + auto-dispatches debug on any failed_at), talos-bootstrap (Talos node prep via talm — Talos-1.12-aware maintenance probe, NAT-provider cert-SAN guardrail before first talm apply, multidoc machine-config with per-node VIP-link IPv4 stubs, etcd bootstrap, kubeconfig fetch, cozystack-tuned shape verification with Phase 11.5 auto-upgrade), talos-reset (cloud-provider terminate+relaunch helper for OCI/AWS/GCP/Hetzner when nodes are unrecoverable from inside; preserves block volumes + secondary VNICs + NSG memberships), ubuntu-bootstrap (wraps cozystack/ansible-cozystack — OS prep + k3s install in one go), cluster-install (Cozystack on a ready cluster — node-readiness, ZFS pool provisioning via privileged DaemonSet on Talos with hostNetwork, extractedprism for kube-apiserver HA, OCI-tag-normalized cozy-installer chart, Platform Package, inline tenants/root ingress patch + LINSTOR pool registration during watch loop with combined HRs-Ready + pools-registered gate, Phase 8.6 default StorageClasses for v1.3.x, Phase 9.1 end-to-end reachability probe), debug (investigate a stuck or broken install — gathers symptoms, classifies operator error / config drift / upstream bug / not-yet-supported, applies fixes or workarounds, drafts upstream issues on approval; never opens PRs or files silently), cluster-upgrade (v1.x patch/minor upgrade with release-notes analysis), package-deploy (dev-loop deploy of a single package with ExternalArtifact support), package-bump (single-package version bump with changelog adaptation), external-app-create (scaffold a new external-apps package), dev-ui-bootstrap (bootstrap a UI dev sandbox — Playwright + Vite dev server for cozystack-ui pointed at a chosen kubeconfig; worktree, @playwright/test, Chromium, playwright.config.ts, dev:e2e / test:e2e scripts, kubectl proxy + Vite on a free port), comment-audit (audit a diff's code comments for design-doc prose — rationale, product motivation, before/after narrative, incident retelling — and report cuts, keeps and arguments duplicated across sites; reports only, modifies nothing), comment-trim (apply the cuts — delete the prose, keep every comment that documents a real mechanism, then prove mechanically with the bundled comments-only.py that no code moved; leaves the result in the working tree, does not commit or push). comment-audit and comment-trim are repository-agnostic and usable on any codebase. All skills match the operator's natural language detected from conversation context — code identifiers, commands, file paths, and GitHub-public text stay canonical. All skills follow the same gate-and-confirm discipline: read-only lookups run freely; any mutation needs explicit per-step approval.",
"version": "1.17.0",
"description": "Cozystack platform skills bundle. Start with cozystack:wizard — it begins with a free-form 'tell me about your setup and goal' question, parses hints, then asks Talos / Ubuntu / Existing, builds a chain, and dispatches downstream skills via a cluster config directory the operator picks (every artifact lives there: inventory.yml, kubeconfig, .state.yaml, cozystack-platform-package.yaml — operator manages git on their own; optional sops opt-in encrypts secret files in-tree). Skills, invoked as cozystack:<name>: wizard (orchestrator + 3-route dispatcher + Phase 4.5 active research + auto-dispatches debug on any failed_at), talos-bootstrap (Talos node prep via talm — Talos-1.12-aware maintenance probe, NAT-provider cert-SAN guardrail before first talm apply, multidoc machine-config with per-node VIP-link IPv4 stubs, etcd bootstrap, kubeconfig fetch, cozystack-tuned shape verification with Phase 11.5 auto-upgrade), talos-reset (cloud-provider terminate+relaunch helper for OCI/AWS/GCP/Hetzner when nodes are unrecoverable from inside; preserves block volumes + secondary VNICs + NSG memberships), ubuntu-bootstrap (wraps cozystack/ansible-cozystack — OS prep + k3s install in one go), cluster-install (Cozystack on a ready cluster — node-readiness, ZFS pool provisioning via privileged DaemonSet on Talos with hostNetwork, extractedprism for kube-apiserver HA, OCI-tag-normalized cozy-installer chart, Platform Package, inline tenants/root ingress patch + LINSTOR pool registration during watch loop with combined HRs-Ready + pools-registered gate, Phase 8.6 default StorageClasses for v1.3.x, Phase 9.1 end-to-end reachability probe), debug (investigate a stuck or broken install — gathers symptoms, classifies operator error / config drift / upstream bug / not-yet-supported, applies fixes or workarounds, drafts upstream issues on approval; never opens PRs or files silently), cluster-upgrade (v1.x patch/minor upgrade with release-notes analysis), package-deploy (dev-loop deploy of a single package with ExternalArtifact support), package-bump (single-package version bump with changelog adaptation), external-app-create (scaffold a new external-apps package), dev-ui-bootstrap (bootstrap a UI dev sandbox — Playwright + Vite dev server for cozystack-ui pointed at a chosen kubeconfig; worktree, @playwright/test, Chromium, playwright.config.ts, dev:e2e / test:e2e scripts, kubectl proxy + Vite on a free port), comment-audit (audit a diff's code comments for design-doc prose — rationale, product motivation, before/after narrative, incident retelling — and report cuts, tightens, keeps and arguments duplicated across sites; reports only, modifies nothing), comment-trim (apply the cuts — delete the prose, tighten verbose-but-legitimate blocks, keep every comment that documents a real mechanism, then prove mechanically with the bundled comments-only.py that no code moved and a grep-based pointer-invariant check that no pointer sits on top of the prose it replaces; leaves the result in the working tree, does not commit or push). comment-audit and comment-trim are repository-agnostic and usable on any codebase. All skills match the operator's natural language detected from conversation context — code identifiers, commands, file paths, and GitHub-public text stay canonical. All skills follow the same gate-and-confirm discipline: read-only lookups run freely; any mutation needs explicit per-step approval.",
"author": {
"name": "Cozystack",
"url": "https://github.com/cozystack"
Expand Down
31 changes: 30 additions & 1 deletion plugins/cozystack/skills/comment-audit/SKILL.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
---
name: comment-audit
description: Audit code comments for design-doc prose — rationale, product motivation, before/after narrative, incident retelling — and report which ones to cut, which to keep, and which arguments are restated at several sites. Use this whenever reviewing a diff or PR that reads comment-heavy, whenever someone says a change has "too many comments", "excessive comments", "comment bloat", "essays in the code", or asks whether comments are justified, and as a matter of course on any PR that adds a large block of commentary to a function or package doc. Reports only; pair with `cozystack:comment-trim` to apply the cuts. Language-agnostic — works on any repository, not only Cozystack ones.
description: Audit code comments for design-doc prose — rationale, product motivation, before/after narrative, incident retelling — and report which ones to cut, which to tighten, which to keep, and which arguments are restated at several sites. Use this whenever reviewing a diff or PR that reads comment-heavy, whenever someone says a change has "too many comments", "excessive comments", "comment bloat", "essays in the code", or asks whether comments are justified, and as a matter of course on any PR that adds a large block of commentary to a function or package doc. Reports only; pair with `cozystack:comment-trim` to apply the cuts. Language-agnostic — works on any repository, not only Cozystack ones.
argument-hint: "[PR number | file | diff base] [--all] (default: lines the change added)"
---

Expand Down Expand Up @@ -36,6 +36,8 @@ A comment is design-doc prose when it argues rather than informs:

The test is not length. A twelve-line comment about a mutation hazard is fine; a three-line one about why the product wants this is not.

But length is not free either, and "it is all true" is not a defence. A doc comment is a **reference, not an explanation**: it tells a reader what they must not get wrong, in the fewest words that carry the claim. Prose that derives a conclusion — laying out the question, the wrong answer, then the right one — belongs in the design doc even when every sentence of it is correct. A block of nine true mechanism sentences where two would do is a finding, and the verdict for it is *Tighten*, not *Keep*.

## Do not judge by density

Resist computing comment-to-code ratios and comparing against neighboring files. If the file or its neighbours already carry design-doc prose, the local average is exactly the thing under review — matching it certifies the problem. Judge each comment on its own register. Ratios are at most a way to pick which file to read first, never evidence for a finding.
Expand Down Expand Up @@ -72,12 +74,34 @@ Two copies of an argument means one of them goes. Where a comment exists to stop

A paraphrase is a second copy that will drift; a pointer cannot.

**Grep finds copied phrasing. It cannot find a paraphrase, and the nearest copy is usually a paraphrase.** So follow the grep with a reading check on every substantial block: look at what is declared immediately around it — the type's field docs, the neighbouring case arms, the function signature itself — and ask whether the block re-states in prose what those already say in place. This is the highest-yield duplication in practice and grep will never show it, because the two copies share no distinctive words:

```go
// RouteLink is the ifindex the FIB would send out of.
// OwnerLink is the ifindex the address is CONFIGURED on.
...
// Two questions hide in here: the FIB answers "how would I SEND to this
// address", which says nothing about the link the address lives on...
```

The field docs already carry the distinction; the paragraph is a second copy in expository form. Keep the copy at the declaration, where a reader meets the concept, and cut the prose restatement.

## Phase 4 — Build the keep list

Every audit must name the comments that should survive. Without it the request reads as "fewer comments" and comes back as the same arguments in shorter sentences.

Build this list as you go through Phase 2 rather than as an afterthought — a keep list assembled at the end tends to be thin, because by then the reader is in cutting mode.

## Phase 5 — Sort keepers into Keep and Tighten

A two-verdict audit (cut or keep) has nowhere to put the most common defect in a comment-heavy change: a block whose claims are all legitimate and which is still three times longer than it needs to be. Every block that survives gets a second pass:

- the claim is load-bearing and the wording is already minimal → **Keep**;
- the claim is load-bearing but stated expositionally → **Tighten**, and quote the shorter form you propose, so the author is choosing between two concrete texts rather than being told to trim;
- the claim is load-bearing and a linked design doc already carries it → **Tighten to the pointer**: the comment collapses to `// see docs/<path> §"<section>"` and the explanation goes. A pointer plus the explanation it points at is two copies, not a citation.

Read each surviving block **cold** before deciding: not as the person who worked the problem out, but as someone who arrives at the file with no memory of the change. Every sentence feels load-bearing to whoever just derived it, which is why a self-audit that skips this step reliably keeps everything.

## Report format

```text
Expand All @@ -89,6 +113,11 @@ Build this list as you go through Phase 2 rather than as an afterthought — a k
- `:<line>` — "<quoted text>". <one line: which category, and what survives if anything>
...

## Tighten
**<file>**
- `:<line>` — <what the block claims, and why the claim stays>. Proposed: "<the shorter text>"
...

## Keep
[the comments that earn their place, with a phrase each on why]

Expand Down
10 changes: 8 additions & 2 deletions plugins/cozystack/skills/comment-trim/SKILL.md
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,10 @@ State the file list and the per-file claim list, then get the operator's go-ahea

A paraphrase is a second copy of the argument and will drift; a pointer cannot. Cite the real section heading so the reference survives the document being reorganized.

**A pointer replaces the argument; it never accompanies it.** Adding the citation and leaving the explanation above it is the "second copy" this rule exists to prevent — and it is an easy mistake to make, because the block now ends with something that looks like the fix. If you write a pointer, the thing it points at goes in the same edit.

**Tighten** — where the audit says the claim stays but the wording derives it. Rewrite to the shortest form that still carries the claim, and check the result the same way as a cut: the block must now *state* the constraint rather than *argue* to it. "It is all true" does not earn nine sentences where two carry the same warning.

**Keep the claim** — mechanism, aliasing and mutation hazards, ordering constraints, "why not the obvious approach", deliberate omissions that read as bugs, non-local constraints, and anything whose violation fails silently. Verbatim by default; tighten only where the wording is genuinely in the way. When in doubt about a comment in this class, keep it: a surviving mechanism note costs a reviewer three seconds, and deleting one costs the next person an afternoon.

**Deduplicate.** Where an argument appears in a package doc and again inline, one of them goes. Keep the copy at the site that constrains the code — usually the branch or call site, since that is where someone is standing when they consider changing it — and delete the distant one.
Expand All @@ -73,7 +77,7 @@ A paraphrase is a second copy of the argument and will drift; a pointer cannot.

## Phase 3 — Verify

Two checks, in order. Neither is optional — a trim whose correctness rests on having read the diff carefully is worth much less than one that has been proven.
Three checks, in order. None is optional — a trim whose correctness rests on having read the diff carefully is worth much less than one that has been proven.

1. **Comments only.** The bundled script strips comments from both sides and compares what is left, so a stray edit cannot hide in a large diff:

Expand All @@ -86,7 +90,9 @@ Two checks, in order. Neither is optional — a trim whose correctness rests on

It is string-aware — URLs inside literals, Go raw strings, rune literals and Rust lifetimes do not fool it. Exit 0 means no code moved; 1 names the files where it did; 2 means a file's language was not recognised and needs a human look. Investigate any non-zero result before reporting; the usual cause is a real accidental edit.

2. **The project's own checks** for the packages touched — build, linter, and the tests for those packages only, never the whole suite. A comment trim cannot break a test, which is exactly why a failure here means something else went wrong and must be chased rather than waved through.
2. **Pointer invariant.** For every `see docs/...` you added, confirm the explanation it replaces is gone — grep the file for a distinctive phrase from the deleted argument and expect no hit. A pointer sitting on top of the prose it cites is the failure this skill's central rule names, and it survives the comments-only check untouched.

3. **The project's own checks** for the packages touched — build, linter, and the tests for those packages only, never the whole suite. A comment trim cannot break a test, which is exactly why a failure here means something else went wrong and must be chased rather than waved through.

## Phase 4 — Report and stop

Expand Down
Loading