Repository navigation
Conversation
… minefield On 2026-09-09 four consecutive Ringer checks failed CORRECT worker output in one evening. Two never executed at all: a \" sequence reached Ruby as "unterminated string; expected a closing delimiter" after passing through JSON escaping, shell quoting and Ruby string parsing. One aborted on a banned string that appeared in the explanatory comment the brief had *demanded* the worker write. One asserted on a notes.md belonging to a different task. The check is the product — the skill says so — and it is the one artifact in the loop that nothing checks. This removes the class: comments stripped by file type (ERB <%# %> first, the exact shape that failed), literal matching so nothing needs escaping, and failures that report the real count and line number instead of a bare abort. Red/green tested against all four real cases, including proving --raw still fails the file that comment-stripping passes. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
First-write bug, caught by running the tool rather than trusting it. DOTALL was applied to every comment pattern, so the LINE form ^\s*#.*$ swallowed the whole file from its first comment: a 5979-byte Ruby controller stripped to 175 bytes, and every --contains after that reported a false absence. Only ERB was exercised before shipping, and ERB uses a block comment, so the broken path never ran. Comment patterns now carry their own spans-newlines flag; tested across .rb, .erb and .js, including that a comment-only string is still stripped and that --raw still fails the file comment-stripping passes. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Six subprocess tests, because the thing under test IS the CLI contract — a check invokes it from a shell and reads its exit code. Covers contains/absent, comment-stripping (the originating bug: a worker's own explanatory comment tripping a banned-string grep) and its --raw opt-out, exact counts, ordering, a failure message that names the pattern, and a missing file failing rather than passing vacuously. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Why
A Ringer check lives inside a JSON string, inside a shell command. Every hand-written
ruby -e '...'orpython3 -c '...'assertion therefore passes through JSON escaping, then shell quoting, then the target language's string parser, before its regex is even compiled.On one day I lost four consecutive checks to that stack — and in every case the check was wrong, not the work:
\"sequences that reached Ruby as a syntax error, or as a literal that could never match;notes.mdbelonging to a different task entirely.A wall of red from broken checks reads as a broken system rather than a careful one, and it teaches workers to bend correct code until the grep goes quiet.
What this adds
scripts/assert-file, a small stdlib-only helper so that class of bug cannot be written again — no nested quoting, comments stripped by file type, and a non-zero exit that says which assertion failed and what it actually saw.--strip-commentsis on by default (--rawopts out), which is the fix for the first failure above: a brief that asks a worker to justify itself in a comment shouldn't hand the check a false positive. Patterns are literal by default;--regexwhen you mean it.--labelprefixes the failure message so a multi-assertion check says which one broke.Tests
tests/test_assert_file.py, six tests, each running the real script as a subprocess — the thing under test is the command-line contract, and asserting on an imported function would prove something no check exercises.Covers contains/absent on one file, comment-stripping plus its
--rawopt-out, exact counts, ordering (--beforecatches order, not mere presence), a failure message that names the pattern it could not find, and — the one that matters most for check honesty — a missing file failing rather than passing vacuously.Full suite green on this branch: 261 passed.
🤖 Generated with Claude Code