From da640f3dcd2d8b4dce83a680a729cfbe794b3672 Mon Sep 17 00:00:00 2001 From: Alex Clarke Date: Fri, 21 Aug 2026 14:02:39 -0600 Subject: [PATCH] feat: created a new comment-discipline skill for the built in sisyphus suite --- assets/agents/coder/graph.yaml | 15 +++++-- assets/agents/sisyphus/config.yaml | 4 +- assets/skills/code-review/SKILL.md | 1 + assets/skills/comment-discipline/SKILL.md | 51 +++++++++++++++++++++++ 4 files changed, 66 insertions(+), 5 deletions(-) create mode 100644 assets/skills/comment-discipline/SKILL.md diff --git a/assets/agents/coder/graph.yaml b/assets/agents/coder/graph.yaml index a70d317..2ca905c 100644 --- a/assets/agents/coder/graph.yaml +++ b/assets/agents/coder/graph.yaml @@ -15,6 +15,7 @@ skills_enabled: true enabled_skills: - ai-slop-remover - code-review + - comment-discipline - git-master - frontend-ui-ux - verification-gates @@ -167,6 +168,7 @@ nodes: enabled_skills: - ai-slop-remover - code-review + - comment-discipline - git-master - frontend-ui-ux - verification-gates @@ -177,9 +179,10 @@ nodes: ## Skills Use `skill__list` to see what's available, then `skill__load` the ones - that fit the work: `ai-slop-remover` always, `frontend-ui-ux` when - touching UI, `git-master` when touching history, `verification-gates` - to remember what evidence is required. Unload when a phase ends. + that fit the work: `ai-slop-remover` and `comment-discipline` always, + `frontend-ui-ux` when touching UI, `git-master` when touching history, + `verification-gates` to remember what evidence is required. Unload when + a phase ends. ## Writing code @@ -212,7 +215,11 @@ nodes: Before writing ANY file: 1. Find a similar existing file (grep, then read). 2. Match its style: imports, naming, structure, error handling. - 3. Follow the same patterns exactly. Do not invent new ones. + 3. While reading it, note the repo's comment register per + `comment-discipline` (self-documenting / api-documented / + comment-heavy) and write comments to match. When the signal is + weak, write NO comment. + 4. Follow the same patterns exactly. Do not invent new ones. ## Fix loop diff --git a/assets/agents/sisyphus/config.yaml b/assets/agents/sisyphus/config.yaml index 7ea6f6a..625806e 100644 --- a/assets/agents/sisyphus/config.yaml +++ b/assets/agents/sisyphus/config.yaml @@ -1,6 +1,6 @@ name: sisyphus description: OpenCode-style orchestrator - classifies intent, delegates to specialists, tracks progress with todos, enforces OMO-grade verification discipline -version: 3.3.0 +version: 3.4.0 agent_session: temp auto_continue: true @@ -26,6 +26,7 @@ skills_enabled: true enabled_skills: - ai-slop-remover - code-review + - comment-discipline - git-master - frontend-ui-ux - delegation-protocol @@ -384,6 +385,7 @@ instructions: | When you write or modify files yourself (rather than delegating to coder): + - **Calibrate comments before writing.** Load `comment-discipline` and note the repo's comment register (self-documenting / api-documented / comment-heavy) from the sibling files you read; write comments to match. When the signal is weak, write NO comment. - **For editing an existing file**, prefer `fs_patch`. It's a surgical edit that preserves unchanged content. Send only the diff hunks for the lines you want to change; do not re-send the whole file. This is faster, cheaper, and dramatically less prone to accidental data loss than a full rewrite. - **For writing a NEW file or doing a COMPLETE rewrite**, use `fs_write`. Use it only when most of the content is changing or the file doesn't exist yet. - **NEVER write files via `execute_command`.** Do not use: diff --git a/assets/skills/code-review/SKILL.md b/assets/skills/code-review/SKILL.md index a052903..9634685 100644 --- a/assets/skills/code-review/SKILL.md +++ b/assets/skills/code-review/SKILL.md @@ -88,6 +88,7 @@ A diff review is a review of THE CHANGE, not the whole file: - Are names accurate? `get_user` that mutates is a lie; rename or split. - Could a competent reader understand this without comments? +- Do NEW comments match the repo's comment register? You already read neighboring files for conventions — compare against them. Flag BOTH directions: narrated/restating comments in a repo that uses self-documenting code (each one is a finding, cite the line), AND missing doc comments on new public items in a repo that documents its public API. Comments explaining non-obvious *why* (decisions, workarounds, invariants) are warranted in every repo; comments captioning *what* the code plainly does are warranted in none. - Is there a simpler way to express the same logic? - Is the function doing one thing, or several things glued together? diff --git a/assets/skills/comment-discipline/SKILL.md b/assets/skills/comment-discipline/SKILL.md new file mode 100644 index 0000000..b14107d --- /dev/null +++ b/assets/skills/comment-discipline/SKILL.md @@ -0,0 +1,51 @@ +--- +description: Calibrate comment density and style to the repository's existing conventions before writing code. Detects the repo's comment register (self-documenting / api-documented / comment-heavy) from the sibling files you already read for pattern matching, or from a declared policy in workspace instructions, then dictates when a comment is warranted. Default when signal is weak - write NO comment. Complements ai-slop-remover (which bans comments that restate code in every register). +--- +You are about to write or modify code. LLMs systematically over-comment — narrating every block, restating signatures, banner-ing sections — and that default is wrong in most repositories. Before writing, determine the repo's **comment register** and match it, exactly the way you already match imports, naming, and error handling. + +## Step 0: Check for a declared policy first + +Detection is a heuristic; a repo owner's declaration is ground truth. Before sampling files, check the workspace instructions already in your context (`COYOTE.md` / `AGENTS.md` / `CLAUDE.md`) for a stated comment policy (e.g. a "Comments" or "Style" section). If one exists, obey it and skip detection entirely. + +## Step 1: Detect the register (during reads you already do) + +Pattern-matching discipline already requires you to find and read 2-3 similar existing files before writing. While reading them, observe: + +1. **Density** — roughly what fraction of lines are comments? Near-zero, sparse (~1 per function or less), or pervasive (most blocks narrated)? +2. **Types present** — doc comments on public items (`///`, `/** */`, docstrings)? Inline "why" comments? Section banners (`// ===== Handlers =====`)? Commented-out code (a smell, not a convention — never imitate it)? +3. **What the comments say** — do they explain *why* (decisions, workarounds, invariants, links to issues) or narrate *what* (restating the code)? A repo whose comments are all "why" is self-documenting even if density is nonzero. +4. **Config signals** — these force the answer regardless of sampled style: `#![warn(missing_docs)]` or `#![deny(missing_docs)]` in Rust, eslint `jsdoc`/`require-jsdoc` rules, pylint/pydocstyle docstring checkers, a lint config banning TODO without a ticket. Lint-enforced conventions are mandatory. +5. **TODO/FIXME conventions** — bare `TODO:`, or `TODO(name):`, or ticket-linked `TODO(#123):`? Match the observed form if you must leave one. + +Sample from the SAME language and module you're editing — a repo can have a chatty Python test suite and a silent Rust core. The nearest siblings win. + +## Step 2: Classify into a register + +| Register | You observed | Your rule when writing | +|---|---|---| +| **self-documenting** | Near-zero density; the comments that exist explain decisions, temp fixes, or non-obvious behavior | Comment ONLY for: why a non-obvious approach was chosen, documented workarounds/temp fixes (with issue link if the repo does that), safety/concurrency invariants, regex or math explanations. Everything else: make the code clearer instead | +| **api-documented** | Doc comments on public functions/types/modules; sparse or no inline comments | Write doc comments on every NEW public item, matching the repo's doc style (sections, examples, link syntax). Inline comments still follow self-documenting rules | +| **comment-heavy** | Pervasive narration, section banners, per-block comments | Match it. Comment your work the way the siblings do — same placement, same tone, same banner style. Under-commenting here is a convention violation just like over-commenting elsewhere | + +Mixed signals (e.g. doc comments everywhere + narrated private code) → combine rows: doc comments mandatory AND inline narration matched. + +## Step 3: The tiebreak + +**When the signal is weak or files disagree: write NO comment.** Your untrained default is comment-heavy, so the correction must push the other way. A missing comment is a one-line review nit; a hundred useless comments are a cleanup task. If you genuinely cannot tell and the comment feels important, it is usually a sign the code should be restructured until the comment is unnecessary. + +## Invariants that do NOT bend with register + +1. **Never restate the code.** `// increment the counter` above `counter += 1` is slop in EVERY register — comment-heavy repos narrate intent and sections, they don't caption individual lines the reader can read. (This is `ai-slop-remover`'s rule; it applies unconditionally.) +2. **Always keep the genuinely necessary comment**, even in the sparsest repo: non-obvious algorithm choices (with the reference), regex explanations, safety invariants (`unsafe` justifications, lock ordering), intentional deviations from the obvious approach, and workarounds for upstream bugs (with the link). +3. **Never leave commented-out code**, regardless of what the repo tolerates. +4. **Never delete or rewrite EXISTING comments** that don't match the register you detected — that's out-of-scope churn. Register calibration governs comments YOU write. +5. **Lint-enforced doc requirements win** over any sampled style and over the tiebreak. + +## Anti-patterns + +- Narrating your implementation (`// First we parse the config, then...`) in a repo whose functions are bare. +- Skipping doc comments on a new public API because nearby private code has none — publics and privates often follow different rules; compare against other PUBLIC items. +- Writing doc comments that restate the signature (`/// Gets the user. Returns the user.`) to satisfy an api-documented register — the register demands docs, not filler; say what the caller can't infer. +- Section banners in a repo that has none. +- Imitating the single chattiest file in an otherwise silent repo — classify from the majority of your samples, not the outlier. +- Treating this skill as license to argue with a declared policy: COYOTE.md says comment-heavy → you write comments, even if you find them redundant.