Repository navigation
Releases: benjaminjackson/sloplint
Release list
v0.9.0
sloplint 0.9.0 and the first release of the companion gem, sloplint-judge 0.1.0. Both are on rubygems: gem install sloplint sloplint-judge.
Added
sloplint check --judgeruns the rules of sloplint-judge alongside the
regex catalog and merges the notes in document order. The judge is a second
gem built from this repository (sloplint-judge.gemspec,exe/sloplint-judge)
whose rules are questions put to a System One model. sloplint loads it by
name only and exits 2 with an install hint when it is missing. A backend
failure under--judgeis exit 3 and writes no notes. Seedocs/JUDGE.md.Sloplint::Split, a paragraph and sentence splitter that keeps offsets into
the source, andEngine.context_window, the note's context drawn for any
span rather than only a regex match. Both are used by the judge.script/calibrate, which measures a judge backend against RAID and a
current-model side generated from RAID's own prompts, and reports the
pass lines fromdocs/JUDGE.md.
Fixed
--markdownopens and closes a fenced code block only at the start of a
line, at any indent, so a fence under10.or a nested bullet still
pairs. A fence quoted inside a sentence (```) used to open a
block there, and every fence after it paired wrong for the rest of the file.- The splitter also drops indented code blocks (four spaces or a tab), lines
that are one HTML tag, and YAML front matter under--markdown, so none of
them reach the judge as prose.
sloplint-judge 0.1.0
The judge is a second gem built from this repository. Its rules are questions put to a System One model (Jev, from TypeSafe) rather than regexes: does this paragraph name anything a reader could check, does this sentence tell its reader anything new. It adds sloplint check --judge and a sloplint-judge executable, needs an API key, and is the only part of sloplint that sends text off the machine. Fourteen rules in two categories; see docs/JUDGE.md.
Full notes for both gems are in CHANGELOG.md.
v0.8.1
Added
cataphoric-teaser(self-rating, warning, high confidence): the
forward-pointing tease that sells a claim as rare knowledge before making
it. "Here's what nobody tells you about hiring.", "The part most people get
wrong is the rollback." Three closed frames (a forward demonstrative, a
noun slot, a scarcity subject and a verb of telling); the bare-subject
form must reach a copula or colon, and "that's what nobody understands"
points backward and is left alone.punch-sentence(cadence, info, medium confidence): the verbless beat of
one to three words wedged between two long sentences in the middle of a
paragraph, "Not anymore." and "Simple.", whichmic-drop-closerand
bare-auxiliary-closeronly see at a paragraph's end. Two closed shapes:
a negator with up to two words after it, or one capitalised word of five
letters or more. Titles, initials and case citations before the stop are
guarded, and short clauses with a subject ("He agrees.") are not matched.
v0.8.0
[0.8.0] - 2026-09-15
Changed (breaking)
- The four old categories are gone:
rhetorical-tic,structure,puffery
andhedging. Nine new categories replace them, each named for the move
the construct makes:self-rating(the writer grades their own prose or
claim),closer(closes by restating or announcing the point),cadence
(rhythm: repetition, parallelism, the long-then-short kicker),puffery
(inflates the subject),false-correction(corrects a reading nobody
offered),false-concession(performs balance or candor and gives nothing
up),reader-address(instructs or flatters the reader),
borrowed-metaphor(an engineering term applied to an argument), and
punctuation(the mark itself). Every note,--select, and--ignorenow
use these nine names; the four old names are gone, not aliased, so a
script still passing one gets a usage error instead of a silent no-op. - The rule
ellipsis-closeris renamedbare-auxiliary-closer. Nothing
about its pattern, message, or fixtures changed, only the id. severitynow rates only what the construct costs the prose (error,
warning,info). A new field,confidence, rates how likely a match is
a false positive (high,medium,low), and alowrule replaces what
used to bedefault_on: false— it stays out of a normal run and needs
--strictor its own id named directly to turn on.sloplint rules --jsondrops thedefault_onfield and addsconfidence
andrationalefor every rule. Each note incheckoutput also gains a
confidencefield alongsideseverity.--select <category>no longer turns on that category's low-confidence
rules. Naming a category now selects only its default-on rules; to run a
low-confidence rule, pass--strictor name the rule's own id.- Every rule's severity was re-rated for what the construct costs the prose,
now that confidence carries the false-positive question on its own. The
catalog reads 11error, 56warning, 13info. Nothing shipped at
errorbefore: the eleven that do now are the ones that hurt a sentence in
any register, the puffery family (puffery-words,rich-tapestry,
vital-role,impact-noun-vague,
trailing-significance-participle), the tautology and self-ranking moves
(the-x-is-the-x,cleanest-x,most-honest-x), the fake balance
(two-things-true,none-of-this-is-to-say) andvague-attribution.
Twenty rules moved frominfotowarning, among themem-dash-overuse:
one em dash is a style choice, three in a paragraph is the tell, so the
dense form now costs more thanem-dash. Any tool that keys off severity
sees different values for the same text.
Fixed
- The test suite failed with no locale set, because
spec/plugin_spec.rb
read files without forcing UTF-8. Fixed to read as UTF-8 regardless of the
environment's locale. - The README and SPEC quoted an outdated rationale for
no-x-no-yand an
outdated sample ofsloplint checkoutput. Both are corrected and now
pinned by tests, so a future drift between the docs and the code fails the
build instead of sitting unnoticed. - SPEC's description of the
Rulemodel and of the package's file layout
had fallen out of step with the code. Both are corrected to match. --helpwas missingcountfrom its list of note keys, even though a
note already includes it for rules that tally items. Added.
Added
- A test asserting that no rule id ever matches a category name, since
--selectand--ignoreresolve a name against both and a collision
would make one shadow the other.
v0.7.0
Added
--strictruns the full catalog, including the five rules that ship off
by default. Before this, the only way to turn one on was to name it in
--select, which also turned off every other rule unless you listed
those too.--ignorestill subtracts on top of--strict, and
--selectis unchanged.ellipsis-closer(structure, info) flags the long-sentence-then-short-closer
kickermic-drop-closercatches, but built on the opposite verb shape: the
closer's verb phrase is elided down to a bare auxiliary with no object,
"The agent did." rather than a quantifier plus a full verb. No subject list
is needed — the tell is the missing verb, not the subject — so "That",
"This" and "It" are not excluded the waymic-drop-closerexcludes them.
A negative lookahead drops a closer that still holds a wh-word, since that
marks a subordinate clause with its own complement rather than an elided
one. Reusesmic-drop-closer's long-sentence prefix.actually-not-x: the adverb and a trailing "…, not X" in one clause, as in
"The disclosure actually covered two incidents, not one". Either marker
alone is ordinary technical English and neither is matched on its own; the
tell is the two of them doubled up, correcting an alternative the reader was
never offered. The narrowing is structural, not a word list: the comma in
front of "not" has to be the first comma of its clause and has to follow a
word, so a fronted setup ("Despite the name, …") and a parenthetical both
drop it. Nothing crosses a line break, so two rows of a table cannot weld
into one correction.real-x-real-y(rhetorical-tic, info) flags the same "real" used twice
attributively in one sentence, in front of two different nouns: "it can
trigger real API calls or hold real credentials". Bare "real" is an
ordinary word, so the narrowing is the repetition itself, not a noun
list. A hyphen on either side takes it out ("real-time", "non-real"), a
backreference requires the second noun to differ from the first, and a
short closed list drops the fixed senses of this register (real time,
real-world, real numbers, real user monitoring, real estate, real money).phrase-echo(rhetorical-tic, info, off by default) flags a three-word
phrase that comes back within a few hundred words, the model reusing a
phrase it has just minted. Each word must be four characters or more and
lowercase-led, and one of them six letters with nothing but letters, so "in
order to", "couldn't have been" and "New York City" never match. The window
does not cross into a list item or a table row. Off by default: a term of
art repeats because it must, and in reference prose the pattern fires on
names by the thousand per million words.trailing-restatement(structure, info, off by default) flags the tail
that says the sentence again in other words: ", which means …", ", which
is to say …", ", meaning …", and four participles that hang a result off
the sentence (", making it easier", ", allowing us to", ", giving them
more", ", leaving you with"). The connective is all a pattern can see, and the
same connective states a real consequence in careful prose, so the rule
runs only when selected.
Fixed
check's options now work without the command word:sloplint --markdown -
andsloplint --strict -scan, as the README has saidsloplint -does.
Before, the global parser rejected any option it did not own with
invalid option, socheckhad to be spelled out whenever an option
came first. An option no command knows still exits 2.--markdownnow blanks<!-- -->comment blocks along with fenced code,
inline code and URLs. Planning notes kept in comments never render, so
every rule that fired inside one was a permanent false positive.rule-of-three's message, rationale, README and SPEC entries said it
flagged three parallel comma items. The pattern requires single words in
the closing two slots, so a triad of phrases never matched; the text now
says that.
v0.6.0
The catalog grows from 50 rules to 75, and sloplint ships as a Claude Code
plugin as well as a gem.
Added
- sloplint now ships as a Claude Code plugin as well as a gem. Add the
marketplacebenjaminjackson/sloplintand installsloplint; the plugin
carries the Ruby source with it, so nothing is installed from a package
index and it works wheregem installcannot reach the network — Claude
Cowork above all. The plugin adds one skill,/sloplint:check, which runs
the scanner and reports what it returns. The skill refuses to assess prose
on its own when the scanner cannot run, because a review with no scan
behind it reads exactly like one with a scan behind it. not-by-x-but-by-y: the corrective frame on a repeated preposition, "not
by luck, but by design". The copula rules cannot see it because nothing
anchors "not" but a verb or a dash, so the anchor is the preposition, which
must repeat after "but". Ships atinfo: Thoreau and Melville write it too.
Fixed
checknow reads files and stdin as UTF-8 whatever the locale says. A
sandbox with noLANGset — Claude Cowork's, among others — leaves Ruby's
default external encoding at US-ASCII, and the first em dash in a draft then
failed the whole scan withinvalid input: invalid byte sequence in US-ASCII. Prose is the only input sloplint takes, so UTF-8 is the
assumption rather than the locale's guess. Genuinely invalid UTF-8 is still
exit 2.
Changed
-
thats-the-wholenow takesvalueandfixafter "that's the whole",
alongsidepoint,game,thing,dealandstory. The contracted
closer is the one an agent writes in technical prose ("That's the whole
value of theinfotier", "That's the whole fix"), andis-the-whole-x
sees only the uncontracted "is", so the sentence slipped both rules. The
uncontracted "That is the whole fix." moves with it, frominfounder
is-the-whole-xtowarning. The two new nouns must end the sentence or
the paragraph, or run into one of the words a closer trails off on, so
thats-the-wholeleaves "value chain", "value-add" and "fix list" alone
however the line wraps (is-the-whole-xstill reads the uncontracted
"That is the whole value chain" atinfo, as it did), and a curly
apostrophe now counts as a contraction. Both rules interpolate oneWHOLE_CLOSERS
fragment, so the lists cannot drift, and a spec walks every noun through
every form the two wrappers treat differently. Neither noun appears after
"that's the whole" in 1.55M words of public-domain prose. -
Empty or whitespace-only input
is now exit 2 withempty input: nothing to check in ..., instead of exit 0. Reporting a scan of nothing as a clean
scan is the same trap a mistyped rule id sets, and gets the same answer. The
text is tested before--markdownblanks code and URLs, so a file holding
only a fenced code block still exits 0; and only an all-empty set of sources
is an error, so one empty file among several named ones is left alone. -
The executable moved from
bin/sloplinttoexe/sloplint. claude.ai
rejects a plugin with a top-levelbin/directory, which would block
organization distribution.gem install sloplintis unaffected. -
exe/sloplintnow checksRUBY_VERSIONbefore loading anything and aborts
with an explanation, rather than raisingNoMethodErrorfromData.define.
The Ruby macOS ships at/usr/bin/rubyis 2.6 and hits this.
New rules
-
from-x-to-y-chain(rhetorical-tic, warning) flags two or more
comma-separated "from X to Y" spans in a row: "from guessing to measuring,
from hoping to knowing". Each span names two poles and nothing between
them, and stacking them sweeps across a change without describing it. Two
human shapes are skipped: the relay, where each span starts where the last
ended ("from the egg to the worm, from the worm to the fly"), and the
reduplication, where a span has the same word at both ends ("from hummock
to hummock"). Operands must open with a letter, so a list of ranges ("from
1990 to 1995, from 1997 to 2001") is not a chain. With those out it flags once in 2.4M words of pre-2022
Hacker News (a geographic sweep) and once in 1.25M words of public-domain
prose (Joyce). -
one-x-one-y(rhetorical-tic, warning) flags three or more "one X" items
in a comma chain that stands on its own: "One owner, one repository, one
weekly prune." The word does no counting; it sets a rhythm. The chain must
open a sentence or follow a colon, because after a verb ("the flat has one
bedroom, one bathroom, one balcony") the word is counting. Items are
letter-led, so an enumeration over numbers is out; the distributive "one
for you, one for me, one for the pot" is skipped at any length. Nothing in
2.4M words of pre-2022 Hacker News or 1.25M words of public-domain prose. -
everyone-nobody(structure, warning) flags the comma-spliced antithesis
on quantifier subjects: "Everyone wants the dashboard, nobody maintains
it." The
balance is what makes the diagnosis sound settled. The comma splice is
required (with "and" it is a sentence, with a period it is two), the two
subjects must differ in polarity, and the second clause must close the
sentence. Nothing in 2.4M words of pre-2022 Hacker News or 1.25M words of
public-domain prose. -
and-what-it-should(rhetorical-tic, warning) flags the elliptical tail:
"List what the assistant knows about the client, and what it should." The
second clause borrows its verb from the first and closes on a bare modal
or a negated auxiliary, so the sentence ends on a contrast it never
states. The comma, the conjunction, and the full stop right after the
modal are all required; the affirmative copula and do-verb ("and what he
does.") are complete clauses and stay out, and so does a question.
Nothing in 2.4M words of pre-2022 Hacker News or 1.25M words of
public-domain prose. -
abstract-lives-in(rhetorical-tic, info) flags an abstraction given an
address: "the craft that lives between the two desks", "its context lives
in a folder nobody else can open", "the value sits in the follow-up". The
subject list is closed and abstract, so people and dogs living and sitting
places never match, and a capitalised subject is a proper noun. "with" is
left out of the prepositions because "the decision sits with the board" is
ordinary English for who is responsible, "at" because "the value sits at
ten million" is a quantity, and "lies in" because "the problem lies in
the assumption" is where a fault is. It ships at info because the same
shape says where information literally is ("the knowledge lives in our
heads"), and a sample of pre-2022 Hacker News biased toward the
construction turns up a few of those per million words, all human. A
draft that keeps giving ideas addresses should be read as a warning. -
np-fragment-and(structure, info) flags a whole sentence made of two
noun phrases and an "and": "A named owner and a quarterly review." It is
the fix half of a model's problem-then-fix pair with the verb left out,
and its usual habitat is a bulleted list, so a list marker may open it.
Each phrase is one to three words, and no auxiliary or modal may appear,
contractions included. It ships at info because a lexical verb is
invisible to the pattern: "A car and a truck collided." has the same
shape and flags. That sentence is rare in the corpora (nothing in 2.4M
words of pre-2022 Hacker News, once in 1.25M words of public-domain
prose), but it is a sentence, so one flag is a question; a draft full of
them should be read as a warning. -
the-x-is-the-x(rhetorical-tic, warning) flags the repeated-head
equative: "the reason it holds up is the reason the other half happens",
"the problem with the tool is the problem with the team". A backreference
catches the same abstract head noun on both sides of the copula, so the
sentence equates two things while naming neither. The head list holds
only nouns that cannot name an object, since "the key to the front door
is the key on the red fob" is an identity statement; the two heads must
share a clause, so an earlier "the cost was low, but shipping is the
cost" never pairs; and the second head must be followed by a preposition,
determiner, quantifier, pronoun, plural noun or punctuation, so "the
answer key" is not a repeat. Once in 2.4M words of pre-2022 Hacker News;
nothing in 1.25M words of public-domain prose. -
same-determiner-chain(rhetorical-tic, info) is the quiet cousin of
one-x-one-y: three or more comma-separated items opening on the same
determiner or quantifier, "every file, every branch, every deploy", caught
with a backreference. The narrative possessives (my, his, her, their, its)
are left out, since "his fame, his position, his life" is every
novelist's. It ships at info because the device is one humans use on
purpose: about 8 per million words of pre-2022 Hacker News and 14 per
million
in public-domain prose. One is a question; several in a draft should be
read as a warning. -
quip-question(structure, info) flags the verbless question that opens
a pitch: "No invite?", "New to the tool?", "Still stuck?". It must start a
sentence, open on one of a short list of words, and close on the question
mark within four more words with no auxiliary or contraction, so a real
question stays out; "Need" and "Want" are left off the list because "Need
help?" is a question with its verb elided. Ships at info: about six per
million words of pre-2022 Hacker News, all of them replies asking the
same shape of a person; nothing in public-domain prose outside Joyce's
dialogue. Several in a draft should be read as a warning. -
is-the-whole-x(rhetorical-tic, info) isthats-the-wholeon any
subject: "That periodicity is the whole tell.", "Consistency is the real
test." It yi...
v0.5.0
The catalog grows from 49 rules to 50, and check becomes the default
command.
Changed
- A first argument that is not a command name is now taken as a path, so
sloplint draft.mdandsloplint -scan instead of failing with
unknown command. A mistyped command fails as a missing file, still exit 2.
New rules
-
trailing-significance-participle(structure,warning): the participle
clause hung off the end of a sentence to say what a fact means, "the sign
carries both names, showcasing the range of travellers it draws". An event
cannot showcase anything, so the claim belongs to a narrator who never
appears in the text.The verb list is closed and narrow:
highlighting,showcasing,
reinforcing,shaping,enhancing,cementing,solidifying,
embodying,fostering,facilitating,signalling. Verbs humans write
in the same position --driving,representing,reflecting,marking,
contributing,illustrating,demonstrating,emphasising,echoing,
affirming-- stay out, because they usually take a person as the subject
and a regex cannot see the subject.underscoringis left to
underscores-highlights.Two guards drop gerund lists: a preceding -ing word means the match is a
middle list item, and a following comma, "and" or "or" means it is not the
last item. "signalling to" is the physical gesture and does not flag.
v0.4.0
The catalog grows from 29 rules to 49. Every new rule was probed against
pre-2022 Hacker News comments or Project Gutenberg texts before shipping,
and each narrowing is pinned by an examples_ok fixture.
New rules
worth-saying-plainly(rhetorical-tic,warning): the self-rating
opener, "Worth saying plainly, ...". Needs all three slots -- evaluative
adjective, speech verb, manner adverb -- at a sentence or paragraph start.hold-onto-that(rhetorical-tic,warning): the sentence-initial
reader directive "Hold onto that" / "Hold on to this".cleanly(rhetorical-tic,warning): the bare manner adverb, "splits
cleanly into", "maps cleanly onto".clean-count(rhetorical-tic,warning): a number plus "clean" plus a
partition noun, "two clean buckets".cleanest-x(rhetorical-tic,warning): the superlative used to rank
one's own claim, "the cleanest framing is".clean-x(rhetorical-tic,info): "clean" in front of an idea as
praise, "a clean abstraction".earns-its-place(rhetorical-tic,warning): "earns its place" and
"earns its keep", the metaphor of a sentence or feature paying rent.does-a-lot-of-work(rhetorical-tic,warning): the remark that points
at a word and rates its load, "that qualifier does a lot of work here".failure-mode-here(rhetorical-tic,warning): "the failure mode here
is", the engineering term borrowed for an argument or a person. The
deictic "here" is the whole narrowing.thats-the-tension(rhetorical-tic,warning): the sentence-initial
closer "That's the tension." and "That's the bet:".right-up-until(rhetorical-tic,warning): "right up until it
doesn't". The intensifier is the narrowing -- the plain "until it doesn't"
is an old human idiom and stays clean.two-things-true(rhetorical-tic,warning): "two things can be true",
the concession that names neither half.notice-what-there(rhetorical-tic,warning): the self-referential
attention cue, "Notice what that argument did there", "Read that again".notice-what(rhetorical-tic,info): the bare sentence-initial
"Notice what ...", the quiet half of the pair above.none-of-this-is-to-say(rhetorical-tic,warning): the sweeping
concession that retracts an argument nobody made.if-im-being-honest(rhetorical-tic,info): the candor preamble.
Plain "to be honest" and "I'll be honest" stay clean.genuinely(rhetorical-tic,info, off by default): every
"genuinely". No allowlist separates the intensifier from the contrastive
use, so the rule runs only when named in--select, beside
rule-of-three.question-isnt(structure,info): the corrective frame in
interrogative dress, "The question isn't whether X, it's whether Y".
Requires the resolving clause.and-thats-fine(rhetorical-tic,info): the permission-granting
closer. The match must open and close a sentence.less-about-more-about(structure,info): the comparative
reframe, "It's less about X and more about Y". Both halves required.
Changed rules
sit-with-thatbroadened to any object. Two branches: the deictic object
needs no anchor, any other object needs the sentence-initial imperative.the-punchline-iswidened to take "the honest answer is" and "the honest
version is".worth-namingandworth-saying-plainlywidened together and stopped
double-flagging. Both take more verbs;worth-namingnow yields the
adverb-bearing form toworth-saying-plainly.
Docs
docs/SPEC.mdcredits Wikipedia's "Signs of AI writing" and slopwash.com's
anti-slop ruleset, next to proselint, vale and write-good.- The SPEC rule catalog had drifted ten rules behind the code. It is resynced,
andspec/rules_spec.rbnow asserts every rule id appears indocs/SPEC.md,
the same way it already asserts the README counts.
v0.3.0
[0.3.0] - 2026-08-02
- New rule
load-bearing(rhetorical-tic,warning): "load-bearing" used
as a borrowed metaphor for anything important, outside its literal
construction sense (a wall, a column, a beam). Guards on both sides —
a building noun right after it, or the predicate form ("the wall is
load-bearing") — leave the construction sense clean. - New rule
is-is(rhetorical-tic,warning): the doubled copula, "what it
is is a mistake" / "the thing is, is that...". No anchor needed -- the bare
pattern scored 0 hits across ~1.9M words of public-domain and modern prose. exactly-thereplaced by the broaderexact-exactly(rhetorical-tic,
nowinfo): flags "exact/exactly" generally, not just the fixed "exactly
the point/kind/problem/…" phrase shape, with an allowlist for the places
it's doing real work (numbers, times, same/opposite/way/etc.). Severity
drops toinfobecause a common word will still slip through on cases
the allowlist hasn't seen yet.thats-not-nothingreplaced by the broadernot-nothing
(rhetorical-tic,warning): catches the "is not nothing" litotes
regardless of subject ("Fifty basis points is not nothing"), not only
the demonstrative-subject form ("that's not nothing"). Personal-subject
litotes ("he was not nothing to her") and the "there is not nothing"
philosophy frame are allowlisted as legitimate human use.underscores-highlightsbroadened (puffery, stillinfo): "underscores
the need for", "underscored how fragile", and "underscoring the urgency"
now match, not only the fixed "underscores/highlights/emphasizes its/the/
their importance/significance" phrase. The character-noun sense
("a leading underscore", snake_case) stays excluded.
v0.2.0
is-real-and-notandworth-namingmove fromwarningtoinfo. Both
patterns match on surface form alone and can't tell the AI cadence from an
unrelated sentence that happens to share it: "is real, and/but/not" fires on
any predicate-adjective sentence regardless of what follows the conjunction
("my debt to my senses is real and constant" -- Emerson), and "worth naming"
collapses the AI meta-signpost with the plain sense of a thing worth
mentioning ("the only thing worth naming to do that" -- Emerson). Probed
against a 1.06M-word corpus (Austen, Melville, Madison, Thoreau, Emerson);
the other 19 rules still atwarningwere probed too and held up clean.puffery-words' barenestledmatched the literal verb as often as the
puffery sense -- a head nestled against a shoulder, a kitten nestled into a
blanket. It now requires a following in/among/between, the shape the
travel-brochure cliché actually takes ("nestled in the hills").- New rule
not-x-but-y(structure,info): the bare corrective "is not A
but B" with no escalation word, comma before "but" or none. Ships atinfo
because the line between a corrective and an ordinary concession is
syntactic, and a pattern can only approximate it — a concession with an
elided subject ("was not perfect but got us there") still gets through. - New rule
no-x-no-y-frag(rhetorical-tic,info): the "no X, no Y"
cadence built from sentence fragments ("No fluff. No filler.") rather than
commas.info, notwarning, because two short "no" sentences in a row is
also just writing. not-just-x-but-ynow also catches "not because A, but because B" and the
escalation wordsmerely,simply, andsolelyalongsidejust/only.
It keepswarning: the escalation word is a deliberate authorial move.- Both
not-…-but-…rules now stop at a paragraph break, so an unpunctuated
heading or list item no longer joins up with the next paragraph's "But …". no-x-no-y-fraglinks must begin a sentence, so an ordinary sentence can no
longer donate its tail to a chain ("There was no bread. No milk either." is
one sentence and one fragment, not a chain), and the link separator is
capped at two spaces so a code span blanked by--markdowncannot weld two
distant fragments together.sloplint explainno longer breaks its aligned fixture block when a fixture
contains a newline; those are escaped as\n.- Notes carry a new
contextfield: the match bracketed inside ~40 characters
of surrounding prose. Human output shows it in place of the bare match, which
told you nothing when the match was a single word or a lone em dash.excerpt
is unchanged and still the bare match. - New rule
em-dash(structure,info): flags every em dash, not just
paragraphs dense with them. em-dash-overuse(3+ em dashes in one paragraph) is nowwarning, up from
info.
v0.1.0
First public release.
- 24-rule catalog across four categories: rhetorical-tic, puffery, structure,
hedging. Seesloplint rulesorREADME.mdfor the full list. check,rules,explain,versioncommands; JSON and human-readable
output;--select/--ignoreby rule id or category;--markdownto skip
fenced code, inline code, and URLs before scanning.- Exit codes:
0clean,1notes found,2bad arguments or invalid input
(including invalid UTF-8 and unknown--select/--ignoreids). - Zero runtime dependencies; requires Ruby >= 3.3.
-v/--versionprint the version and exit 0. optparse auto-registers its
own--versionswitch on any parser that doesn't define one, and that
default printed "version unknown" to the real stdout and hard-exited,
bypassing theout:/return-a-code contract every other path honors --
caught by hand-testing the freshly built gem before this release shipped.- Rationale text (
sloplint explain) across six rules no longer narrates the
rule's own implementation -- pattern scoping, anchoring, tuning history,
corpus-driven thresholds. It states why the construct reads as AI writing
and nothing else.
Rules narrowed against a corpus of real human prose (the Federalist Papers,
Moby-Dick, Walden) before release:
not-just-x-but-yanchored on a preceding copula so it no longer flags
ordinary correlative conjunctions ("not only... but...").puffery-wordsdropped the bare adjective "profound" and narrowed "in the
heart of" to require a place object, both unguarded false-positive sources.em-dash-overuse,thats-how-x, andannounced-takeawayscoped to real
paragraphs (blank-line boundaries) instead of source lines, so hit counts
no longer swing on Markdown line-wrapping.clause-triad-thenremoved: went 0-for-40 on its own description against
the human corpus, and no reliable narrowing was found.no-x-no-y's rationale corrected to match what the pattern actually does
(fires at two items; the frequency gap between human and model prose is
the justification, not an item-count claim the pattern didn't enforce).