Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
26 commits
Select commit Hold shift + click to select a range
4ad7fc3
Add v0.2 design spec
ccf Sep 14, 2026
7b9be13
Revise v0.2 spec after three-lens review
ccf Sep 14, 2026
0c83a65
Revise v0.2 spec after scoped re-review (revision 3)
ccf Sep 14, 2026
88caaac
Add v0.2 implementation plan
ccf Sep 14, 2026
244c0de
Revise v0.2 plan after worktree dry run; sync spec
ccf Sep 14, 2026
7c52691
Normalize apostrophe look-alikes between letters before scanning
ccf Sep 14, 2026
61bb874
Add repetition block: maximal repeated phrases with content-word floor
ccf Sep 14, 2026
1eab919
Add grammar block: trailing participial clauses and container-noun ph…
ccf Sep 14, 2026
a24b072
Add nominalization hits and disclaimer-opener check
ccf Sep 14, 2026
32cda98
Add sentence-length tail keys and four summary lines
ccf Sep 14, 2026
1c652b5
Add report fixtures with sensitivity, specificity, and pinned fairnes…
ccf Sep 14, 2026
c10514e
Rebuild human_plain.txt with mechanical extraction only, no sentence …
ccf Sep 14, 2026
67496c8
Add SOURCES.md citation registry and key-resolution test
ccf Sep 14, 2026
7fad810
Add grammar and repetition tells to surface-tells; date-stamp the wor…
ccf Sep 14, 2026
1f12ea6
Add register gate, passive and convergence guards to SKILL; fairness …
ccf Sep 14, 2026
5f2f2f0
Document v0.2: README, CHANGELOG, invariants; version 0.2.0
ccf Sep 14, 2026
783e57e
Fix scanner critical/important findings from v0.2 whole-branch review
ccf Sep 14, 2026
50fd570
Un-pin implementation-specific fixture bands; guard SOURCES.md and SK…
ccf Sep 14, 2026
2dba5b2
Fix passive/convergence wording, Vintage: invariant, and doc drift
ccf Sep 14, 2026
f94acdd
Fix two Bugbot findings on PR #6: hyphenated -ing and multi-comma ope…
ccf Sep 14, 2026
b9bcd3c
Revise A7 (segment-based guard), fix A8 en-dash ranges, A10 gram-run …
ccf Sep 14, 2026
0897393
Extend spec's post-review amendments with A6, revised A7, A8, A10
ccf Sep 14, 2026
8227e57
Prune IRREGULAR_PAST homographs from the A7 finite-verb veto
ccf Sep 14, 2026
7ef1e4f
Prune six more IRREGULAR_PAST homographs; fix a coincidental -ed match
ccf Sep 14, 2026
ad9642d
Fix prep-led intermediate segments that hide a real clause (A13)
ccf Sep 14, 2026
359cbd3
Keep subordinator-led intermediate segments opener-internal (A14)
ccf Sep 14, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions .claude-plugin/marketplace.json
Original file line number Diff line number Diff line change
Expand Up @@ -7,14 +7,14 @@
},
"metadata": {
"description": "Remove AI tells from prose. Skill + /humanize command grounded in StoryScope (arXiv 2604.03136).",
"version": "0.1.2"
"version": "0.2.0"
},
"plugins": [
{
"name": "humanize",
"description": "Audit prose for AI tells and rewrite it to read as natural human writing, grounded in StoryScope's measured human-vs-AI feature gaps",
"source": "./plugins/humanize",
"version": "0.1.2",
"version": "0.2.0",
"author": { "name": "ccf" },
"license": "MIT",
"keywords": ["writing", "prose", "editing", "ai-detection", "storyscope", "humanize"],
Expand Down
19 changes: 14 additions & 5 deletions .cursor/BUGBOT.md
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
# Bugbot review guide — humanize

This repo is a Claude Code plugin that audits prose for AI tells and rewrites
it. Design spec: `docs/design/2026-09-13-humanize-plugin-design.md`.
it. Design spec: `docs/design/2026-09-13-humanize-plugin-design.md` and
`docs/design/2026-09-14-humanize-v0.2-design.md`.

## Invariants to enforce

Expand All @@ -10,13 +11,19 @@ it. Design spec: `docs/design/2026-09-13-humanize-plugin-design.md`.
or 3.10+ syntax (match statements, `X | Y` in runtime positions, PEP 604 in
non-annotation code).
- Nothing under `tests/` or `plugins/**/scripts/` makes network or LLM calls.
- Every base-rate number in `plugins/humanize/skills/humanize/references/*.md`
must trace to `data/storyscope_feature_gaps.csv`. If a PR changes a number,
check the CSV row.
- A `Base rate:` line in `plugins/humanize/skills/humanize/references/*.md`
must trace to a row in `data/storyscope_feature_gaps.csv` (or a future CSV
documented in `data/README.md`; none added in v0.2). If a PR changes a
number, check the CSV row. Any other number must sit on a `Scan:`, `Rule
of thumb:`, or `Vintage:` line carrying an inline `[author-year]` key that
resolves in `references/SOURCES.md` (`tests/test_manifests.py` enforces
this); flag a human/AI rate sourced from a model-vs-model comparison.
- Reference-doc entries use the exact five-line shape: `### name` /
`Looks like:` / `Base rate:` (or `Scan:`) / `Why it reads as AI:` /
`Fix: <removal | addition | rebalance> — …`, plus a sixth `Outside fiction:`
line on every entry in style-tells.md.
line on every entry in style-tells.md. Optional `Rule of thumb:` and
`Vintage:` lines may follow. `rebalance` also covers register-dependent
features fixed by proportion, not deletion (nominalization).
- `SKILL.md` body stays under ~150 lines.
- The skill and README never claim output is "undetectable", passes
a detector, or is "certified human".
Expand All @@ -29,6 +36,8 @@ it. Design spec: `docs/design/2026-09-13-humanize-plugin-design.md`.
- Division by zero and empty input in every rate/statistic helper.
- Test assertions that encode the implementation's current output rather than
the intended behavior.
- A number on a `Why it reads as AI:` line, or a `[key]` absent from
`SOURCES.md` (grep `\[[a-z-]*-[0-9]\{4\}\]`).

## Do not review

Expand Down
29 changes: 28 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,32 @@ All notable changes to this project are documented here. The format follows

## [Unreleased]

## [0.2.0] - 2026-09-14

### Added
- Repetition block: verbatim phrase and whole-sentence repeat detection,
capped at a 60-token phrase length.
- Grammar block: participial-tail and container-noun detection; nominalization
hits.
- Disclaimer-opener detection and sentence-tail keys in the scan output.
- Four new `--text` summary lines; five new surface tells.
- Principle 8: register and proficiency are not tells.
- `references/SOURCES.md`, the citation registry for non-StoryScope numbers.
- Report fixtures with sensitivity, specificity, direction, and pinned
fairness gates.
- `SKILL.md` line-budget test.

### Changed
- `SKILL.md`: register gate, passive guard, and convergence check.
- Provenance invariant now allows cited non-StoryScope numbers on `Scan:`,
`Rule of thumb:`, and `Vintage:` lines.
- Apostrophe normalization changes `words`, `wordlist.rate`, and every per-1k
rate on text containing look-alike apostrophe glyphs (they now tokenize as
one word).

### Fixed
- Apostrophe look-alike glyphs between letters.

## [0.1.2] - 2026-09-14

### Added
Expand Down Expand Up @@ -61,7 +87,8 @@ Initial release (#1).
CI (pre-commit, pytest on Python 3.9 and 3.13, `claude plugin validate
--strict`), and a Bugbot review guide.

[Unreleased]: https://github.com/ccf/humanize/compare/v0.1.2...HEAD
[Unreleased]: https://github.com/ccf/humanize/compare/v0.2.0...HEAD
[0.2.0]: https://github.com/ccf/humanize/compare/v0.1.2...v0.2.0
[0.1.2]: https://github.com/ccf/humanize/compare/v0.1.1...v0.1.2
[0.1.1]: https://github.com/ccf/humanize/compare/v0.1.0...v0.1.1
[0.1.0]: https://github.com/ccf/humanize/releases/tag/v0.1.0
18 changes: 15 additions & 3 deletions CLAUDE.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ StoryScope (arXiv 2604.03136). Spec and plan: `docs/design/`. Changelog: `CHANGE

```
uv sync # first time
uv run pytest -q # 53 tests, must be warning-free
uv run pytest -q # 100 tests, must be warning-free
uv run ruff format <files> && uv run ruff check --fix <files>
claude plugin validate --strict .
uv run python plugins/humanize/skills/humanize/scripts/surface_scan.py --text <file>
Expand All @@ -24,12 +24,24 @@ Never run bare `ruff format .` — ruff 0.16 formats Python fences inside
- Regex literals contain curly quotes and dashes (’ “ ” — –). Copy them exactly;
dropping one splits a raw string into several literals and breaks matching.
Use heredocs for `python -c` probes — inline quoting mangles them.
- Every base rate in `references/*.md` traces to a row in
`data/storyscope_feature_gaps.csv`. Do not type numbers from memory.
- A `Base rate:` line traces to a row in `data/storyscope_feature_gaps.csv`
(or a future CSV documented in `data/README.md`; none added in v0.2). Any
other number in `references/*.md` sits on a `Scan:`, `Rule of thumb:`, or
`Vintage:` line with an inline `[author-year]` key that resolves in
`references/SOURCES.md` (`tests/test_manifests.py` enforces it);
model-vs-model sources never appear as a human/AI rate. Do not type numbers
from memory.
- Reference entries are exactly: `### name` / `Looks like:` / `Base rate:` (or
`Scan:`) / `Why it reads as AI:` / `Fix: <removal | addition | rebalance> — …`;
`style-tells.md` adds `Outside fiction:`. Fix tag follows direction: `removal`
when AI shows more, `addition` when humans show more, `rebalance` for scales.
Optional lines: `Rule of thumb:`, `Vintage:`. `rebalance` also covers
register-dependent features where the fix is proportion, not deletion
(nominalization).
- New scanner blocks (`repetition`, `grammar`, `nominalization`,
`discourse.disclaimer_opener`, `sentence_len` tails) are counts and quotable
hits; `nominalization` has no rate by design. Directional keys are gated on
`tests/fixtures/`; reported-only keys are never thresholded.
- The skill and README never say output is "undetectable", passes a detector, or
is "certified human".
- `SKILL.md` stays under ~150 lines. `/humanize` is the skill itself — do not add
Expand Down
38 changes: 24 additions & 14 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,13 +6,16 @@ flattening the author's voice.

It is grounded in [StoryScope](https://github.com/jenna-russell/storyscope)
(Russell, Rajendhran, Pham, Iyyer, Wieting, *StoryScope: Investigating
idiosyncrasies in AI fiction*, [arXiv:2604.03136](https://arxiv.org/abs/2604.03136)),
which measured 304 narrative and stylistic features on 61,575 stories and found
that AI writing converges on shared defaults while human writing disperses.
This plugin turns the 77 features with the largest human-vs-AI gaps into an
audit checklist, adds the surface-level tells StoryScope deliberately excluded,
and pairs both with a dependency-free scanner for the numbers a model can't
eyeball.
idiosyncrasies in AI fiction*,
[arXiv:2604.03136](https://arxiv.org/abs/2604.03136)), which measured 304
narrative and stylistic features on 61,575 stories and found that AI writing
converges on shared defaults while human writing disperses. This plugin turns
the 77 features with the largest human-vs-AI gaps into an audit checklist,
adds the surface-level tells StoryScope deliberately excluded, and pairs both
with a dependency-free scanner for the numbers a model can't eyeball. v0.2
adds a grammar and repetition layer from register and reader-perception
studies (Reinhart et al. 2025; Jakesch et al. 2023; Herbold et al. 2023 and
others); every cited number resolves in `references/SOURCES.md`.

## Install

Expand Down Expand Up @@ -90,6 +93,9 @@ Rewrite (excerpt):
choice, and the report says so.
- **Numbers are evidence, not verdicts.** This is a writing tool. It never
claims text is undetectable or "certified human".
- **Register and proficiency are not tells.** Formal, plain-language,
technical, and second-language prose share the measured AI profile; the
plugin measures it and never infers authorship from it.

## What's inside

Expand All @@ -103,8 +109,11 @@ plugins/humanize/
style-tells.md 20 StoryScope style features with base rates
narrative-tells.md 57 StoryScope narrative features (fiction only)
model-fingerprints.md Claude / GPT / Gemini / DeepSeek / Kimi tendencies
scripts/surface_scan.py stdlib-only metrics: burstiness, punctuation,
tricolons, not-but, wordlists, closers
SOURCES.md citation registry (not loaded at runtime)
scripts/surface_scan.py stdlib-only metrics: burstiness and sentence tails, punctuation,
tricolons, not-but, wordlists, closers, repeated phrases,
participial tails, container nouns, nominalization hits,
disclaimer opener
data/ StoryScope taxonomy + computed feature gaps
tools/gen_tell_scaffold.py regenerate reference scaffolds from the data
tests/ pytest; no network, no LLM calls
Expand All @@ -128,8 +137,9 @@ compare.

## Credit and license

MIT. StoryScope code and data are MIT-licensed; base rates in the reference
docs are computed from their released `storyscope_features.parquet` (see
`data/README.md`). They were measured on fiction and are used here as evidence,
not verdicts. The AI fiction test fixture is from StoryScope's released
dev split; the human fiction fixture is public domain.
MIT. StoryScope code and data are MIT-licensed; `Base rate:` lines are
computed from their released `storyscope_features.parquet` (see
`data/README.md`); every other cited number carries an `[author-year]` key
resolved in `references/SOURCES.md`. Base rates were measured on fiction and
are used here as evidence, not verdicts. The AI fiction test fixture is from
StoryScope's released dev split; the human fiction fixture is public domain.
Loading
Loading