Conversation
Grammar/repetition scanner layer, apostrophe-glyph fix, rewrite guards, fairness principle, three new surface tells, SOURCES.md provenance, and a fixture gate for every new metric. Scope per the research review short list. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01KTKYvLEVY4mStJ3iPaB1Mh
Repetition redefined over maximal phrases with a content-word floor; apostrophe normalization after Markdown stripping, backtick excluded; container list trimmed to LAMP's 13 heads; nominalization drops deadjectival suffixes; disclaimer-opener check; register gate in SKILL; two human fixtures with sensitivity/specificity gates; grep-checkable citation keys. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01KTKYvLEVY4mStJ3iPaB1Mh
Participial-tail adverbial rule is preposition-led and verbless (the old word count suppressed the canonical tail); list rule narrowed to ", and or"; repetition maximality with no n ceiling and substring drop; rate reported-only; singularization strips one "s"; hit shapes fixed per block; SKILL budget recomputed to 148 with verbatim inserts; plain-language fixture pinned to digital.gov with fairness bands; numbers moved to Scan lines. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01KTKYvLEVY4mStJ3iPaB1Mh
Ten tasks: apostrophe fix; repetition, grammar, nominalization/disclaimer, sentence-tail scanner blocks with TDD; report fixtures with sensitivity, specificity, and pinned fairness gates; SOURCES.md registry with a key-resolution test; surface-tells, SKILL, principles, and release docs. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01KTKYvLEVY4mStJ3iPaB1Mh
Fixes found by executing the plan verbatim: E501 literals, function-word test, containment count guard, list-item participial rule, word-aware clause cap, valid summarize snippet, 624-word AI fixture, archived plain-language source with child pages, (0.0, 2.0) band rule, whole-paragraph doc anchors, SKILL budget recount, import placement, Verified lines. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01KTKYvLEVY4mStJ3iPaB1Mh
U+00B4 split words; U+02BC tokenized but missed wordlist terms. Runs after strip_markdown so backticks stay Markdown. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01KTKYvLEVY4mStJ3iPaB1Mh
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01KTKYvLEVY4mStJ3iPaB1Mh
…rases Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01KTKYvLEVY4mStJ3iPaB1Mh
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01KTKYvLEVY4mStJ3iPaB1Mh
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01KTKYvLEVY4mStJ3iPaB1Mh
…s gates Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01KTKYvLEVY4mStJ3iPaB1Mh
…exclusions Fixture content must not depend on the metric under test. Rebuilds human_plain.txt using only the stated mechanical rule (paragraphs under 8 words, list lead-ins, and boilerplate dropped) in page order, truncated at the first paragraph crossing 600 words, with no sentence-level curation. The honest fixture lands at participial_tail.count == 1, exactly at the specificity cap, so no metric report is needed. Re-pins all human_plain.txt bands in PROVENANCE.md and test_fixtures.py from the new measurements. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01KTKYvLEVY4mStJ3iPaB1Mh
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01KTKYvLEVY4mStJ3iPaB1Mh
…dlist Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01KTKYvLEVY4mStJ3iPaB1Mh
…principle SKILL.md: 150 lines. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01KTKYvLEVY4mStJ3iPaB1Mh
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01KTKYvLEVY4mStJ3iPaB1Mh
- ensure_ascii=False on every json.dumps call so --text output quotes curly characters verbatim instead of \uXXXX-escaping them (review issue 1, Critical): the same strings SKILL.md tells the model to quote in the audit table. - Cap repeated_phrases n-gram length at 60 tokens so a boundary-less "sentence" (e.g. an unpunctuated bullet list) can't drive O(L^3) work (issue 2). - Split the fronted-adverbial rule into an unconditional subordinator-led skip and a conjunctive-adverb skip, and widen PREP_SUB, clearing 9 of 11 false positives on ordinary fronted adverbials (issue 3 / T3a / T3c). - Confirm nominalization.of_frames adjacency against the raw sentence so punctuation between the words can no longer fabricate a frame that isn't literally in the text (issue 4). - Add en dash to the clause-terminator regex alongside em dash (issue 13). Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01KTKYvLEVY4mStJ3iPaB1Mh
…ILL.md - Replace the (10, 12) formal-nominalization band with a floor (>= 5): the behavior the test is for is "formal prose nominalizes, that's not a tell," and a tight band breaks on ordinary stoplist tuning (issue 6). - Widen the human_plain.txt cv band from (0.3, 0.4) to (0.28, 0.42) to match the 0.8-1.2 rule PROVENANCE.md itself documents; record the rule change and the affected values there. - Name human_plain.txt's one participial-tail hit as a known metric false positive (a gerund subject after a fronted adverbial rule (b) doesn't yet cover) in PROVENANCE.md and expected_tells.md, rather than only "genuine prose." - Make the SOURCES.md registry test split on lines starting with "## " instead of searching for the next literal heading, so body text shaped like a heading can't truncate a block early (T7). - Add a SKILL.md line-budget test (<= 150 lines): the budget is an invariant with no automated guard and the file sits exactly at it (issue 10). Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01KTKYvLEVY4mStJ3iPaB1Mh
- SKILL.md: reword the passive-recast condition to "the inferred voice or a fired tell calls for it" (the old "only when a fired tell names it" was unsatisfiable, since no tell entry mentions passives); anchor the convergence check to sentence_len.max and cv instead of an unmeasurable "narrowed vocabulary" (issues 7, 14). Still exactly 150 lines. - surface-tells.md: drop the uncited "fivefold within a year" magnitude from the Vintage line; kobak-2025's registry entry licenses the decay note only, not a figure (issue 5). - CLAUDE.md / .cursor/BUGBOT.md: add Vintage: to the permitted number-bearing lines so the shipped wordlist entry stops contradicting the invariant it's supposed to satisfy; update the test-count comment. - README.md: list disclaimer opener among the scanner's blocks (issue 11). - CHANGELOG.md: note the 60-token phrase cap, the SKILL.md line-budget test, Rule of thumb: and Vintage: in the provenance bullet, and that apostrophe normalization shifts words/wordlist.rate/per-1k rates on text with look-alike glyphs (issue 12). - Design spec: mark it "post-review amendments at the end" and append a Post-review amendments section recording every ruling above plus the measured (not illustrative) fixture figures. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01KTKYvLEVY4mStJ3iPaB1Mh
…ners
- _PARTICIPIAL_TAIL_RE gains a (?!-) lookahead so \b firing at a hyphen no
longer misreads a hyphenated compound ("cutting-edge") as a clause head
(Bugbot comment 4002402541).
- _is_fronted_adverbial now evaluates the whole prefix from sentence start
to the match, not only when the match sits at the sentence's very first
raw comma — an earlier comma inside the opener itself (city-state, dates,
thousands separators) no longer disables the adverbial check entirely
(Bugbot comment 4002402546). The prefix is segmented on its own first
comma: the resulting opener decides whether a skip is on the table at
all (subordinator / conjunctive-adverb / verbless-preposition, as
before), and whatever follows that comma is checked for a finite verb
(now including a new IRREGULAR_PAST list) to catch a complete second
clause already under way, in which case the -ing word is a genuine
trailing participial rather than the opener's gerund subject.
- PREP_SUB gains "without" per the brief's updated extension list.
Re-ran all five fixtures after A3+A6+A7 together: participial_tail.count
is unchanged (ai_report.txt 14, human_formal.txt 0, human_plain.txt 1,
ai_email.txt 0, human_email.txt 0) — both fixture gates still pass.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01KTKYvLEVY4mStJ3iPaB1Mh
…merge
- A7 REVISED: the whole-prefix finite-verb veto from the prior commit
regressed "In most quarters, revenue rises, lifting margins." from a hit
to a miss (present-tense finite verbs aren't -ed/FINITE_AUX/IRREGULAR_PAST).
_is_fronted_adverbial now splits the prefix into ", "-delimited segments:
the first segment must be opener-led per A3 (subordinator / conjunctive
adverb / preposition); every later segment must be opener-internal (one
word, e.g. "Texas", "2024", or itself preposition-led, e.g. "with 1,200
users") or the guard lifts, since a multi-word non-prepositional segment
("revenue rises", "the team grew") is a clause of its own. The verbless
finite-verb veto (now including IRREGULAR_PAST) still runs over the whole
prefix, but only for the preposition-led-first-segment branch.
- A8: en dash now terminates a clause only when followed by whitespace
(`–(?=\s)`), so a numeric range like "2023-2024" (en dash) inside a
participial tail is no longer truncated mid-range; " – then rested"
still terminates as before.
- A9 confirmed: PREP_SUB already includes "without" (added in the prior
commit, ahead of this brief update).
- A10: repeated_phrases now merges runs of overlapping cap-length (60-token)
grams sharing the same count and sentence set, collapsing sliding-window
duplicates of one verbatim repeat longer than 60 tokens into a single
representative phrase instead of counting each window separately.
- B1 REVISED: test_sources_registry_exists_with_expected_keys now splits
SOURCES.md only on the backticked key-heading form ("## `"), not any line
starting with "## ", and asserts every expected key is present before
indexing, closing both the truncation risk and the IndexError risk in the
prior fix.
Re-ran all five fixtures with A3+A6+A7(revised)+A8+A9+A10 together:
participial_tail.count unchanged (ai_report.txt 14, human_formal.txt 0,
human_plain.txt 1, ai_email.txt 0, human_email.txt 0); repetition rates on
all five fixtures also unchanged, since none contains a repeat anywhere
near the 60-token cap.
Known discrepancy, not resolved here: A10's own explicit test (two
identical 100-word sentences -> one phrase, count 2) passes exactly as
specified. Its second required test -- the A2 probe (an 8-word phrase
repeated 50 times) reporting repeated_phrase_rate < 50 -- does not pass
(measured 1012.5, down from 1637.5 before this fix, a genuine ~38%
reduction). That probe is periodic at every divisor of 8, producing a
"staircase" of same-content grams at lengths 8, 16, 24, ... each with a
different, decreasing count; A10's merge is explicitly scoped to
length-exactly-60 grams sharing the same count, so it cannot touch this
staircase, and the shortest rung alone (the 8-word unit itself, genuinely
occurring 50 times) already yields a higher rate than the threshold
regardless of merging. Reported in full in final-fix-report.md rather than
adjusting the test or inventing broader, unauthorized merge logic.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01KTKYvLEVY4mStJ3iPaB1Mh
C7 addendum: the design spec's "Post-review amendments" section, added in an earlier commit under the original C7, predated A6/A7(revised)/A8/A10 and did not record them. Appends one bullet each: - A6: the (?!-) lookahead excluding hyphenated -ing compounds as clause heads. - Revised A7: the segment-based opener guard (first segment opener-led, every later segment opener-internal or the guard lifts), IRREGULAR_PAST joining the finite-verb veto, and the two known/accepted residual false positives deferred to v0.2.x. - A8: en dash terminating a clause only when whitespace follows it. - A10: merging overlapping cap-length gram windows of one long repeat into a single phrase. CHANGELOG.md's grammar-block Added bullet is generic (no rule details), so per the brief's addendum it is left unchanged. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01KTKYvLEVY4mStJ3iPaB1Mh
A11 (Bugbot PR #6 comment 4002562248): the IRREGULAR_PAST list added for A7 included present/past homographs and common nouns/adjectives (cost, left, set, rose, read, and 36 others), so a preposition-led opener containing one of them failed the verbless test and reported a gerund subject as a trailing participial ("At low cost, shipping continued." fired on "cost"). Pruned to the 67 unambiguous past forms the brief names, adding "sought" and "caught" which the pruned list newly requires. Bugbot's companion finding (present-tense remainder after an opener, comment 4002562244) needs no new code: the revised A7 segment rule already handles it, confirmed with "In practice, this approach reduces friction, enabling teams to move faster." (still fires). Known, accepted residual issue, not tested or fixed (v0.2.x): "Under the plan costs rose, driving growth." becomes a miss now that "rose" is pruned and this sentence's opener is a single-segment prefix with no other verb. Re-ran all five fixtures: participial_tail.count unchanged (ai_report.txt 14, human_formal.txt 0, human_plain.txt 1, ai_email.txt 0, human_email.txt 0). Updated the spec's A7 post-review-amendment bullet to name the pruned list and the residual miss; CLAUDE.md test count to 97. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01KTKYvLEVY4mStJ3iPaB1Mh
A12 (re-review rounds 2-3): four more words on the A11 keep-list read as
common nouns/adjectives in ordinary openers -- felt (wool felt), thought
(on second thought), stole (fur stole), fell (one fell swoop) -- plus
borderline spent (spent grain/fuel) and led (lowercased "LED"). Removed
all six; IRREGULAR_PAST is now 61 words.
Removing "led" alone was not sufficient: _has_finite_verb's generic
`t.endswith("ed")` check independently matched "led" regardless of
IRREGULAR_PAST membership, since it makes no length distinction. Narrowed
that check to words longer than 3 characters -- no genuine English regular
past tense is 3 letters (that would require an impossible 1-letter base
verb), so this excludes "led" (and "red"/"bed"/"wed"/"fed" as a side
effect) without excluding any real regular past tense, which needs at
least a 2-letter base ("used"). Verified "In the LED aisle, shopping
continued." only stopped firing after this second fix; removing "led"
from IRREGULAR_PAST by itself left it firing.
Fallout: the A11 test's own "still fires" example, "Under the plan costs
fell, driving the decision.", relied on the now-pruned "fell" and had to
be updated to use "grew" instead -- the brief's own A12 "still fires" list
silently dropped this exact sentence for the same reason, confirming the
change is intentional, not a regression.
Test: test_irregular_past_homographs_pruned_further_round_two_and_three
-- all 4 new no-hit examples, plus a re-confirmation that "In March, the
team grew, closing the gap." still fires.
Re-ran all five fixtures: participial_tail.count unchanged (ai_report.txt
14, human_formal.txt 0, human_plain.txt 1, ai_email.txt 0, human_email.txt
0). Updated the spec's revised-A7 amendment bullet (61 words; the -ed
length fix; the three v0.2.x residual openers from re-review round 2 --
"In Austin, Travis County, hiring slowed.", "More importantly, the board
met, approving the plan.", "Meanwhile in Austin, shipping continued.");
CLAUDE.md test count to 98.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01KTKYvLEVY4mStJ3iPaB1Mh
Bugbot PR #6 comment 4002717678: in _is_fronted_adverbial, an intermediate segment starting with a PREP_SUB word was treated as opener-internal unconditionally, with no finite-verb check. So after a subordinator or conjunctive-adverb opener, a segment like "with the new vendor the team shipped faster" was swallowed as if it were mere opener-internal material (like "with 1,200 users"), and a genuine trailing participial tail was dropped: "However, with the new vendor the team shipped faster, cutting the backlog." missed its real tail. Fix: a preposition-led intermediate segment is opener-internal only when _has_finite_verb is False for it (-ed length > 3 / FINITE_AUX / IRREGULAR_PAST); if it has a finite verb, it's a clause of its own and the guard lifts, same as a non-prepositional multi-word segment already did. Single-word segments are unaffected. The first segment's own handling (subordinator / conjunctive-adverb / preposition-led-verbless) is unchanged. Known, accepted, not tested (v0.2.x general no-finite-verb rule): a present-tense clause inside a prep-led segment still misses -- "Although costs rose, in most quarters revenue rises, lifting margins." Verified by hand that this remains a miss, exactly as the brief predicts. Test: test_prep_led_intermediate_segment_with_a_finite_verb_is_a_clause -- both must-fire examples and both must-not-fire examples (the existing verbless-intermediate-segment cases, re-confirmed unaffected). Re-ran all five fixtures: participial_tail.count unchanged (ai_report.txt 14, human_formal.txt 0, human_plain.txt 1, ai_email.txt 0, human_email.txt 0). Added one clause to the spec's revised-A7 amendment bullet; CLAUDE.md test count to 99. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01KTKYvLEVY4mStJ3iPaB1Mh
There was a problem hiding this comment.
Cursor Bugbot has reviewed your changes using default effort and found 1 potential issue.
❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.
Reviewed by Cursor Bugbot for commit ad9642d. Configure here.
Bugbot PR #6 comment 4002782444: A13's finite-verb check ran on every PREP_SUB-led intermediate segment, including subordinator-led ones (after, when, once, because, although, ...). A subordinate clause always carries a verb and its comma closes it, so the following -ing word is still a gerund subject regardless of that verb -- the guard needs to stay, not lift. "However, after the audit closed, filing became routine." was firing incorrectly. Fix in the intermediate-segment loop of _is_fronted_adverbial: check SUBORDINATORS first -- a segment whose first word is a subordinator is opener-internal unconditionally, same as the first-segment rule -- then single word, then non-subordinator preposition-led-and-verbless, otherwise clause. PREP_SUB still contains words that are also subordinators (after, since, when, ...); since the SUBORDINATORS check always runs first and short-circuits with `continue`, the preposition branch is only ever reached for a genuine non-subordinator preposition, so no separate exclusion list is needed. Test: test_subordinator_led_intermediate_segment_stays_opener_internal -- both must-not-fire examples, plus a re-confirmation of A13's three must-still-fire examples to verify this fix only narrows A13's scope (stacked subordinators), not A13 itself. Also restored two em dashes in the touched docstring/comment that had been typed as ASCII "--" during editing, matching the file's existing style; curly literal count in surface_scan.py is now 19 (up from 17), not a decrease from the wave's starting 15. Re-ran all five fixtures: participial_tail.count unchanged (ai_report.txt 14, human_formal.txt 0, human_plain.txt 1, ai_email.txt 0, human_email.txt 0). Added one clause to the spec's revised-A7 amendment bullet; CLAUDE.md test count to 100. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01KTKYvLEVY4mStJ3iPaB1Mh
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.

Summary
v0.2 implements the short list from the research review (
docs/design/2026-09-14-research-review.md, PR #5): a grammar and repetition layer for the scanner, matching reference entries with a checkable citation registry, fairness guards in the skill, and fixture gates that keep the new metrics honest on human prose.Spec:
docs/design/2026-09-14-humanize-v0.2-design.md· Plan:docs/design/2026-09-14-humanize-v0.2-plan.mdScanner (
surface_scan.py, still stdlib-only, 3.9-compatible)ʼ ʹ ´ ‘ ’ ′) between letters are normalized before tokenizing, sodon’tno longer splits.repetition: maximal repeated phrases (≥4 words, ≥2 content words) across sentences, with quotable hits.grammar: trailing participial clauses (with fronted-adverbial and list-item exclusions) and abstract container-noun phrases (13 LAMP heads).nominalization: suffix hits behind a 223-word stoplist, plusof-frames. Hits only — no rate, by design (register-dependent).discourse.disclaimer_openerandsentence_lentails (pct_over_30,p90,longest_flat_run).--textsummary grows from 8 to 12 lines. Every pre-existinganalyze()key is unchanged.Knowledge
surface-tells.mdentries;Vintage:line; extended Uniform sentence length.references/SOURCES.md: 13 verified entries with[author-year]keys;tests/test_manifests.pyfails on any key inreferences/*.mdthat does not resolve.principles.md: docs: research review of academic work beyond StoryScope #5 gains the direction check; new v0.3: portable skill for Codex, Cursor, Hermes, and Claude Desktop #8 Register and proficiency are not tells.SKILL.md(exactly 150 lines): register gate in step 1, quote-hits rule in step 3, passive guard in step 5, verify-by-scan convergence check in step 6.Evaluation
ai_report.txt(AI-style),human_formal.txt(Federalist No. 10),human_plain.txt(archived plainlanguage.gov), withPROVENANCE.md.tests/test_fixtures.py: sensitivity, specificity, direction, and pinned fairness bands. 85 tests, warning-free on 3.9 and 3.13.Docs
README, CHANGELOG
0.2.0, CLAUDE.md and.cursor/BUGBOT.mdinvariants (citation rule, optional entry lines,rebalancescope), version0.2.0.Test plan
uv run pytest -q -W error→ 85 passeduv run ruff check . && uv run ruff format --check .claude plugin validate --strict .claude -p "/humanize tests/fixtures/ai_report.txt --audit-only" --plugin-dir plugins/humanize→ rows for trailing participial clause, verbatim repetition, container-noun phrase, safety disclaimer opener; no nominalization rowv0.2.0after merge🤖 Generated with Claude Code
https://claude.ai/code/session_01KTKYvLEVY4mStJ3iPaB1Mh
Note
Medium Risk
Large additive changes to regex-heavy
surface_scan.pyand audit semantics; mis-tuned participial/repetition rules could false-flag formal or plain-language human prose despite new fairness gates.Overview
v0.2.0 extends the stdlib
surface_scan.pyanalyzer with grammar and repetition signals while keeping existinganalyze()keys stable, and wires those metrics through reference docs, the skill workflow, and fixture-based regression gates.Scanner: Apostrophe look-alikes between letters are normalized before tokenization (fixes split words and wordlist misses). New output blocks cover maximal repeated phrases (150-word floor), trailing participial clauses and abstract container-noun phrases, nominalization hits/
offrames (no rate), first-paragraph disclaimer openers, and sentence-length tails (pct_over_30,p90,longest_flat_run).--textsummaries grow from 8 to 12 lines; JSON usesensure_ascii=Falsefor hit text.Knowledge & procedure:
references/SOURCES.mdplus manifest tests require every[author-year]citation in reference markdown to resolve; provenance rules now allow cited non-StoryScope numbers onScan:/Rule of thumb:/Vintage:lines. Five new surface tells, principle #8 (register/proficiency are not tells), andSKILL.mdupdates add an expository register gate, verbatim hit quoting, a passive-voice guard, and a convergence check on rewrite.Quality: New fixtures (
ai_report, Federalist excerpt, plain-language gov text) with sensitivity/specificity/direction/fairness pins intest_fixtures.py; version bumped to 0.2.0 across marketplace/plugin manifests and changelog.Reviewed by Cursor Bugbot for commit 359cbd3. Bugbot is set up for automated code reviews on this repo. Configure here.