Repository navigation
Check the Prose Gate for Vocabulary Instead of Counting Its Lines - #3474
Conversation
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>
|
A recorded local strict-review pass covers head |
|
Important
This repository does not receive automatic reviews because it has fewer than 10 stars.
|
There was a problem hiding this comment.
🟢 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 Report✅ All modified and coverable lines are covered by tests. 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
Flags with carried forward coverage won't be shown. Click here to find out more. ☔ View full report in Codecov by Harness. 🚀 New features to boost your workflow:
|
## 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>
…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)
Summary
Replaces the line ceiling on
.github/actions/prose-gate/prose_lint.pywith 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 inprose-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.TestVocabularyLivesInTheDataintests/test_prose_lint.pynow fails where the script holds either of these:prose_lint.british_spellingsgenerates 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 areservice_accounts, names likerootan identifier can use.GIT_LOCATIONtherefore settles without an exemption by name. A mapping's key counts only beside a value holding words, soRULE_TABLE's dispatch keys do not.Each shape has a case on a constructed script, and the real script holds none.
Verification
python -m unittest discover -s testswithtests/requirements.txt: 2947 tests, OK, 7 skipped.prose_lint.py --diffagainst the merge base, with and without--check sentence-length: clean."judgement", a six-word nested tuple, and ahub_hostedpath appended, the check reports all three. RenamingGIT_LOCATIONreports nothing, since its entries are not words.Declined local findings
frozenset(...)call (introduced). Counting through calls false-fires onRULE_TABLE, the gate's own dispatch idiom, whose hyphenated word keys sit overfrozensetgroups.Pre-existing findings, not filed
.github/actions/prose-gate/prose_lint.pyTERMINATOR: an abbreviation list (e.g,i.e,vs,etc) sits inside a regex, a shape no literal check reads (pre-existing)."a b c".split(), reads as one constant and is not counted (pre-existing, no instance in the script).🤖 Generated with Claude Code