Skip to content

Check the Prose Gate for Vocabulary Instead of Counting Its Lines - #3474

Merged
ptr727 merged 3 commits into
developfrom
prose-gate-vocab-check
Oct 25, 2026
Merged

ptr727 merged 3 commits into
developfrom
prose-gate-vocab-check

Conversation

@ptr727

@ptr727 ptr727 commented Oct 25, 2026

Copy link
Copy Markdown
Owner

Summary

Replaces the line ceiling on .github/actions/prose-gate/prose_lint.py with a check aimed at what the ceiling stood for, per the maintainer's decision on #3441. The ceiling's own docstring said vocabulary and exemptions live in prose-gate.json, and a line count could not tell that defect from parser logic, so each lexer fix moved the ceiling or compacted unrelated code to fit.

TestVocabularyLivesInTheData in tests/test_prose_lint.py now fails where the script holds either of these:

  • A string equal to a banned spelling, as prose_lint.british_spellings generates them, or to an entry of an exemption list. Stem and ending fragments and the US forms are not entries, since they are ordinary words a lexer may spell. Neither are service_accounts, names like root an identifier can use.
  • A collection literal of more than five words, counted through nested literals and reported once at the outermost. A word is letters alone, with inner spaces, hyphens, and apostrophes allowed, so flags, paths, and environment variable names are not words. GIT_LOCATION therefore settles without an exemption by name. A mapping's key counts only beside a value holding words, so RULE_TABLE's dispatch keys do not.

Each shape has a case on a constructed script, and the real script holds none.

Verification

  • Full unit suite, python -m unittest discover -s tests with tests/requirements.txt: 2947 tests, OK, 7 skipped.
  • ruff format and check, mypy: clean. prose_lint.py --diff against the merge base, with and without --check sentence-length: clean.
  • On a copy of the real script with "judgement", a six-word nested tuple, and a hub_hosted path appended, the check reports all three. Renaming GIT_LOCATION reports nothing, since its entries are not words.
  • Three local adversarial passes, at the frontier tier. The first found stem fragments and US forms read as entries, nested literals uncounted, flags counted as words, and an overclaiming docstring, each fixed. The second found two cases that proved nothing, both fixed. The third found nothing.

Declined local findings

  • Path and directive lists are not counted toward the cap (introduced). Paths and directive names are also the script's own logic, its argv and the file names it reads, so counting them false-fires the way counting flags did. An exact copy of an existing entry is still caught by equality.
  • Counting stops at a frozenset(...) call (introduced). Counting through calls false-fires on RULE_TABLE, the gate's own dispatch idiom, whose hyphenated word keys sit over frozenset groups.

Pre-existing findings, not filed

  • .github/actions/prose-gate/prose_lint.py TERMINATOR: an abbreviation list (e.g, i.e, vs, etc) sits inside a regex, a shape no literal check reads (pre-existing).
  • A word list written as one string split at runtime, "a b c".split(), reads as one constant and is not counted (pre-existing, no instance in the script).

🤖 Generated with Claude Code

ptr727 and others added 3 commits October 25, 2026 10:25
The size ceiling on prose_lint.py stood for the rule that vocabulary and
exemptions live in prose-gate.json, but a line count could not tell that
defect from parser logic, so each lexer fix moved the ceiling or compacted
unrelated code to fit. The test now fails where the script holds a
collection literal of more than five words, or a string equal to an entry
of the data file's spelling or exemption lists. GIT_LOCATION is exempt by
name, being the variables git locates a repository by rather than prose.

Closes #3441

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The spelling entries come from british_spellings, so stem fragments and
US forms no longer read as copied vocabulary, and service accounts are
left out as names an identifier can use. A word is letters alone, so
flags and environment variable names are not words and GIT_LOCATION
needs no exemption by name. A literal counts the words its nested
literals hold, reported once at the outermost.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
A literal nested inside another one past the cap is now reported once,
and the dispatch-table case uses letter keys, so each proves the shape
it names.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Copilot AI lite review requested due to automatic review settings October 25, 2026 17:39
@ptr727

ptr727 commented Oct 25, 2026

Copy link
Copy Markdown
Owner Author

A recorded local strict-review pass covers head 9d631289859dd57826c5f183e88a38564f0d58da, the content this pull request carries at that commit against develop, and it recorded 0 findings.

@coderabbitai

coderabbitai Bot commented Oct 25, 2026

Copy link
Copy Markdown

Important

  • 🔍 Trigger review

This repository does not receive automatic reviews because it has fewer than 10 stars.

Run configuration
  • Autofix · Keep fixing CodeRabbit findings and required CI, and resolving merge conflicts

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟢 Approval recommended

The reviewed changes have no unresolved findings, and all approval-readiness assessments support approval.

No open issues 🎉

What changed in this PR

This pull request replaces the brittle line-count ceiling for prose_lint.py with AST-based checks that keep vocabulary and exemption data in prose-gate.json.

Changes:

  • Detects copied data-file entries and oversized word-based collection literals.
  • Handles nested collections, mapping keys, flags, paths, directive names, and service-account names.
  • Removes the obsolete production-script line-count assertion.
File Description
tests/​test_prose_lint.py Adds vocabulary-detection helpers and comprehensive tests, and removes the obsolete line ceiling test.

Review effort: Lite

@codecov

codecov Bot commented Oct 25, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 80.98%. Comparing base (412ce42) to head (9d63128).

Additional details and impacted files
@@           Coverage Diff            @@
##           develop    #3474   +/-   ##
========================================
  Coverage    80.98%   80.98%           
========================================
  Files           25       25           
  Lines         8895     8895           
========================================
  Hits          7204     7204           
  Misses        1691     1691           
Flag Coverage Δ
python-3.13 80.98% <ø> (ø)

Flags with carried forward coverage won't be shown. Click here to find out more.

☔ View full report in Codecov by Harness.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

@ptr727
ptr727 merged commit aa85f74 into develop Oct 25, 2026
14 checks passed
@ptr727
ptr727 deleted the prose-gate-vocab-check branch October 25, 2026 17:51
ptr727 added a commit that referenced this pull request Oct 25, 2026
## Summary

Answers the finding promotion
[#3476](#3476) raised on
the vocabulary check
[#3474](#3474) added to
`tests/test_prose_lint.py`.

- **The `is_word` docstring** said "letters alone", while its pattern
joins letter runs with single spaces, hyphens, or apostrophes. It now
says that. It also names which paths and environment variable names are
not words, those with a separator or an underscore, since an all-letter
name such as `HOME` is one. The test covering them is renamed to match.
- **A word tuple keying a mapping beside a value holding no words was
never reported** (class sweep, found by the local pass). The mapping
does not count such a key, yet marked it nested, so the key literal was
skipped as well. Only a key the mapping counts is nested now, and the
docstring says a literal reports at the outermost literal that counts
it. One case proves each half: `KEYED` reports at the tuple, and
`COUNTED` reports once, at the mapping.

## Verification

- `tests/test_prose_lint.py`: 629 tests, OK. ruff format and check,
mypy: clean. `prose_lint.py --diff` against the merge base, with and
without `--check sentence-length`: clean.
- Three local adversarial passes at the frontier tier. The first found
the remaining environment-name overclaim and the skipped key, the second
two unproven halves and two wording gaps, each fixed. The third found
nothing.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

---------

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
ptr727 added a commit that referenced this pull request Oct 25, 2026
…3476)

## Summary

Promotes the pull requests merged into develop since release 2.0.1178.

- [#3474](#3474): replaces
the prose gate's line ceiling with a test that fails where
`prose_lint.py` holds a banned spelling, an exemption entry, or a
collection literal of more than five words.
- [#3477](#3477): answers
this promotion's review. The `is_word` docstring now says what its
pattern accepts, and a word tuple keying a mapping beside a wordless
value is reported.
- [#3478](#3478): answers
this promotion's second review round, a case proving paths with a `/` or
`\` separator are not words.

Closes #3441

## Constituent coverage

Each change this promotion carries had coverage on its own pull request
into develop, at its merged head:

| Pull request | Merged head | Coverage |
| --- | --- | --- |
| [#3474](#3474) |
`9d631289` | attested local pass at the merged head, base `develop`, and
a Copilot table on the merged head naming exactly its one changed file,
no open findings |
| [#3477](#3477) |
`0999fc81` | attested local pass at the merged head, base `develop`, and
a Copilot table on the merged head naming exactly its one changed file,
no open findings |
| [#3478](#3478) |
`93ba9d90` | attested local pass at the merged head, base `develop`, and
a Copilot table on the merged head naming exactly its one changed file,
no open findings |

🤖 Generated with [Claude Code](https://claude.com/claude-code)
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.

2 participants