Skip to content

ci: fail a branch that adds or changes public code with no YARD comment (spec 056, #264) - #273

Merged
plainprogrammer merged 50 commits into
mainfrom
056-yard-comment-ratchet
Nov 10, 2026
Merged

plainprogrammer merged 50 commits into
mainfrom
056-yard-comment-ratchet

Conversation

@plainprogrammer

Copy link
Copy Markdown
Owner

Closes #264.

What

bin/ci checks gets a step, "Docs: new and changed public code has a comment" (ruby script/yard/comment_ratchet.rb, directly after the YARD step), that fails a branch which adds or changes a public class, module or method with no YARD summary. It looks only at what the branch changed, never at total coverage, so untouched code is never judged and the documentation grows as code is touched.

  • It parses the judged files (app/models/, app/helpers/, app/*/concerns/, lib/, spec/support/) at the head and at the merge base with origin/main with YARD, and compares each object's text by qualified name. It reads no diff, so renames, moves and where git places a hunk don't matter.
  • It fails, never passes, when it can't see the base (no origin/main, no merge base, a shallow clone, a changed file YARD can't read). The checks job already has fetch-depth: 0.
  • Output is one line per offender (path:line: Name has no comment (added|changed)), a count, the rule's path and a line saying staleness and quality are not checked here.
  • No allowlist, baseline, skip marker, ADR, gem or change to bin/yard doc. It adds well under a second to bin/ci checks here (0.4 s).

Spec 056 (v1.2.3) supersedes spec 054's Out-of-Scope line "a rule that new code carries comments"; the supersession is recorded in both directions in docs/specs/README.md. The rule (.claude/rules/code-documentation.md), CLAUDE.md's bin/ci line and the release-and-deploy area doc are updated.

Review and evidence

  • Spec and plan: Opus reviews, two rounds each (APPROVE WITH CHANGES, nothing blocking at the end).
  • Opus code review of the implementation (APPROVE WITH CHANGES): a changed file YARD silently drops, an order-dependent two-file class verdict, symlinks and others, all fixed.
  • sdd-review Mode B (Opus): round 1 DRIFT DETECTED, round 2 SPEC-ALIGNED; recorded in docs/specs/056-yard-comment-ratchet/verification.md under ## Implementation review, with every AC mapped to its example and the known limits.
  • Local: full bin/ci green at e4bcb6ec (3121 examples, 0 failures), seeds 1 and 42424 green; with an uncommented method added to lib/collector/dev_port.rb, bin/ci checks fails at the new step naming lib/collector/dev_port.rb:22: Collector::DevPort.probe has no comment (added), and passes once reverted.

Needs a decision or a hand

  • Spec 056 v1.2.3 (PATCH, confirmed by the maintainer 2026-11-10): a method is new by qualified name across files (a move between files isn't judged); @api private on a class covers its members.
  • AC-4.2's CI half (GitHub's checks job failing on a throwaway commit) is pending: the maintainer pushes a scratch branch by hand; this PR's own passing checks run covers AC-4.3's CI time.
  • Spec 054's AC-3.7 example now boots the app in a fresh process: the new spec file loads YARD into the RSpec process, which the old in-process defined?(YARD) check forbade (verification.md, Rulings).

🤖 Generated with Claude Code

plainprogrammer and others added 30 commits November 9, 2026 18:11
…264)

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
…D, namespaces, extents)

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
… review folded in)

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
RED: 39 examples, 8 failures (edited body, removed lines, reformat,
opening edit, nested class edit, rename plus edit, comment deletion and the
two-file class), as Phase 1 knows only added.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
…ith the base (spec 056)

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
… 056)

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
…less checkout, and run as a command (spec 056)

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
…c 056)

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
…se-and-deploy area doc (spec 056)

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
…unchanged one is ignored (spec 056 AC-3.4)

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
…allback (spec 056 AC-3.4)

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
…on has a summary, in either file order (spec 056 decision 4)

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
…nitions has a summary (spec 056 decision 4)

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
…(spec 056)

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
…es (spec 056)

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
… with a namespace's api private (spec 056 decision 3)

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
…and Snapshot.build cleans up after an exception (spec 056)

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
…spec 056)

Found in the Opus code review of the implementation; YARD passes the tag down to the members it scopes under the object.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
…mary (spec 056 AC-1.4)

Red: a file that opens with a magic comment or a shebang passes the check
with an uncommented class, because the class fallback reads those lines.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
…t its summary (spec 056 AC-1.4)

The class and module reading of the raw comment lines now drops leading
shebang and magic comment lines, and so does the check of YARD's docstring,
since YARD itself keeps warn_indent and similar comments as docstring text.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
…d base (spec 056 AC-1.13)

The base's file now opens module Collector with no comment, so the example
fails if a reopened namespace is judged (checked against a scratch copy of the
script whose change rule changes every reopened namespace).

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
plainprogrammer and others added 9 commits November 10, 2026 01:02
…sibility directive exempts methods

Probed in a throwaway repository: with a free-standing @!visibility private
directive before two methods, both were judged.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
…on a namespace (PATCH)

Confirmed by the maintainer on 2026-11-10 via the coordinator. The spec now says what the approved plan's design and the code do: a method is new by qualified name across the base's scoped files (a move between files of the same class is not judged), and a class or module marked @api private covers its members. No ruling changed.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
…te on a class covers its members (spec 056 v1.2.3)

Characterization of behaviour spec 056 v1.2.3 now states and the code already
has, so there is no RED step; each example passes at once. Each was shown able
to fail by temporarily mutating script/yard/comment_ratchet.rb (restored):

- Moved method (decision 4): making `change` return :added when the base's
  item is in another file fails it (A#x reported "(added)" instead of passing,
  and "(added)" instead of "(changed)" for the edited copy).
- @api private on a class (decision 3, AC-1.10): reading the tag from the
  object's own docstring text instead of YARD's `object.tag(:api)`, which looks
  through the enclosing namespaces, fails both examples (Internal#a, Inner and
  Inner#b are judged).

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
…ith the normal line instead of crashing (spec 056 AC-3.1)

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
…c 056 AC-3.1)

The ratchet ran YARD::DocstringParser on a definition's raw comment, which executes a @!parse directive and re-parses its code into the live registry from (stdin) while the snapshot walks it, so a class whose only comment was such a directive crashed the check with Errno::ENOENT. The text before the first line starting with @ is now cut by hand: a directive is not summary text.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
…d the Mode B verdicts

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
…ocess (spec 056 loads YARD in-process)

Ruling: spec 056's in-process examples stay as they are; spec 054's AC-3.7
example checks what it means (booting the app does not load YARD) in a fresh
process, so it no longer depends on what other examples loaded.

Cause: spec/script/yard/comment_ratchet_spec.rb requires
script/yard/comment_ratchet.rb, which does `require "yard"`, so YARD is
defined in the RSpec process once that file has run. The plan assumed another
spec already did this; none does.

RED (bin/rspec spec/script/yard/comment_ratchet_spec.rb
spec/project_config_spec.rb --order defined, 91 examples, 1 failure):

  Worktree project configuration YARD (spec 054) keeps the extension and YARD
  out of the app's boot (AC-3.7)
    expected: nil
         got: "constant"

The example now runs `RAILS_ENV=test bin/rails runner "print
defined?(YARD).inspect"` and expects "nil" (about 0.8 s). With
RUBYOPT=-ryard it fails with "booting the app loaded YARD", so it still
detects a YARD loaded at boot. The Rails.autoloaders expectation is unchanged.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
…eded runs, and the AC-3.7 ruling

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
@plainprogrammer plainprogrammer self-assigned this Nov 10, 2026
plainprogrammer and others added 11 commits November 10, 2026 07:52
…tchet (spec 056)

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
…(spec 027 D4)

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
AC-4.2's CI half: scratch pull request #285 (run 42842352793) failed the
step naming lib/collector/dev_port.rb:22. AC-4.3's CI time: 0.32 s and
0.35 s on pull request #273's checks job.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
@plainprogrammer
plainprogrammer marked this pull request as ready for review November 10, 2026 15:42
@plainprogrammer
plainprogrammer merged commit 6a73cee into main Nov 10, 2026
9 checks passed
@plainprogrammer
plainprogrammer deleted the 056-yard-comment-ratchet branch November 10, 2026 15:42
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.

Check that new and changed public methods carry YARD comments

1 participant