Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
59 changes: 59 additions & 0 deletions tests/test_navigation_quotes.py
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,65 @@ def test_labelled_summary_with_foreign_verdict_word_is_rejected(self):
report = self._report('| #1 | [r](../../reviews/r.md) — summary: continuum HOLD; finite ACCEPT |')
self.assertEqual([f[0] for f in report['failures']], ['verdict-word-not-in-source'])

def test_prefixed_source_verdict_does_not_authorize_summary(self):
for word in check_doc_quotes.VERDICT:
for prefix in ('UN', 'RE', '_', '9', 'é'):
with self.subTest(word=word, prefix=prefix):
(self.root / 'reviews' / 'r.md').write_text(prefix + word, encoding='utf-8')
report = self._report('| #1 | [r](../../reviews/r.md) — summary: ' + word + ' |')
self.assertEqual((report['checked'], report['summaries'], report['unchecked_offline']), (1, 1, 0))
self.assertEqual([f[0] for f in report['failures']], ['verdict-word-not-in-source'])
self.assertTrue(report['failures'][0][2].startswith(word + ': '))

def test_word_start_and_existing_suffix_families_remain_accepted(self):
for word in check_doc_quotes.VERDICT:
for text in (word, '(' + word + ')', '**' + word + '_SCOPED**'):
with self.subTest(word=word, text=text):
(self.root / 'reviews' / 'r.md').write_text(text, encoding='utf-8')
report = self._report('| #1 | [r](../../reviews/r.md) — summary: ' + word + '_SCOPED |')
self.assertEqual(report['failures'], [])
self.assertEqual(report['checked'], 1)

def test_prefixed_summary_is_not_an_unprefixed_verdict_claim(self):
(self.root / 'reviews' / 'r.md').write_text('No tracked verdict.', encoding='utf-8')
for word in check_doc_quotes.VERDICT:
with self.subTest(word=word):
report = self._report('| #1 | [r](../../reviews/r.md) — summary: UN' + word + ' |')
self.assertEqual(report['failures'], [])
self.assertEqual(report['summaries'], 1)

def test_standalone_verdict_after_prefixed_word_is_found(self):
for word in check_doc_quotes.VERDICT:
with self.subTest(word=word):
(self.root / 'reviews' / 'r.md').write_text('UN' + word + '; ' + word, encoding='utf-8')
report = self._report('| #1 | [r](../../reviews/r.md) — summary: ' + word + ' |')
self.assertEqual(report['failures'], [])

def test_cli_preserves_positive_and_rejects_prefixed_source(self):
import json
import subprocess

doc = self.root / 'docs' / 'nested' / 'a.md'
flags = ['-B'] + (['-O'] if sys.flags.optimize else []) + ['-S']
for word in check_doc_quotes.VERDICT:
for prefix, expected in (('', 0), ('UN', 1)):
with self.subTest(word=word, prefix=prefix):
(self.root / 'reviews' / 'r.md').write_text(prefix + word, encoding='utf-8')
doc.write_text(HEADER + '| #1 | [r](../../reviews/r.md) — summary: ' + word + ' |\n', encoding='utf-8')
result = subprocess.run(
[sys.executable, *flags, str(ROOT / 'tools' / 'check_doc_quotes.py'),
str(doc), '--root', self.tmp, '--require-online'],
capture_output=True, check=False, timeout=15)
self.assertEqual(result.returncode, expected)
self.assertEqual(result.stderr, b'')
report = json.loads(result.stdout)
self.assertIs(report['passed'], expected == 0)
self.assertTrue(report['require_online'])
actual = report['documents'][str(doc)]
self.assertEqual((actual['checked'], actual['summaries'], actual['unchecked_offline']), (1, 1, 0))
self.assertEqual([f[0] for f in actual['failures']],
['verdict-word-not-in-source'] if expected else [])

def test_passage_without_preceding_link_is_rejected(self):
report = self._report('| #1 | “Verdict: ACCEPT” — [r](../../reviews/r.md) |')
self.assertEqual([f[0] for f in report['failures']], ['no-source-link'])
Expand Down
7 changes: 5 additions & 2 deletions tools/check_doc_quotes.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,9 @@
``--github`` (token read from ``GITHUB_TOKEN``); without it the passage is reported as
``unchecked_offline`` and does not fail the check;
* a ``summary:`` passage must not use a verdict word (ACCEPT, AMEND, HOLD, CONFIRMED,
VERIFIED, REJECT) that the linked record does not use, under the same offline rule;
VERIFIED, REJECT) that the linked record does not use, under the same offline rule.
The same leading word boundary applies to both texts; suffix forms remain allowed.
This lexical check does not establish semantic agreement or resolve negation;
* a passage with no preceding link in its segment fails (``no-source-link``).

Header and separator rows are skipped. Exit status 0 only when no checked passage fails;
Expand Down Expand Up @@ -177,7 +179,8 @@ def check_document(doc_path, root, github=False, token=None):
report['failures'].append(['not-verbatim', source, prefix])
else:
for word in VERDICT:
if re.search(r'\b' + word, passage) and word not in body:
pattern = r'\b' + word
if re.search(pattern, passage) and not re.search(pattern, body):
report['failures'].append(['verdict-word-not-in-source', source, word + ': ' + prefix])
return report

Expand Down
Loading