0.0.3-alpha.5
This commit is contained in:
90
deltas/0.0.3/alpha.5.md
Normal file
90
deltas/0.0.3/alpha.5.md
Normal file
@@ -0,0 +1,90 @@
|
|||||||
|
<!-- file: deltas/0.0.3/alpha.5.md -->
|
||||||
|
<!-- version: 1 -->
|
||||||
|
|
||||||
|
# Delta 0.0.3-alpha.5 — audit des headers Markdown
|
||||||
|
|
||||||
|
## Baseline et version
|
||||||
|
|
||||||
|
Baseline : `0.0.3-alpha.4`, avec `history/0.0.3/alpha.4.md` appliqué et committé. Ce delta MUST NOT être appliqué avant ce commit.
|
||||||
|
|
||||||
|
Version avant application :
|
||||||
|
|
||||||
|
```text
|
||||||
|
0.0.3-alpha.4
|
||||||
|
```
|
||||||
|
|
||||||
|
Version après application :
|
||||||
|
|
||||||
|
```text
|
||||||
|
0.0.3-alpha.5
|
||||||
|
```
|
||||||
|
|
||||||
|
## Objet
|
||||||
|
|
||||||
|
Extraire le contrôle des headers Markdown répété en Python inline dans les gates précédentes. `scripts/audit_markdown_headers.py` vérifie une seule propriété documentaire : les deux premières lignes de chaque fichier choisi doivent déclarer son chemin relatif canonique et une révision interne positive. Le script accepte des chemins explicites depuis la racine du projet, lit sans modifier, produit des erreurs déterministes avec chemin et ligne et distingue violation de sélection invalide.
|
||||||
|
|
||||||
|
`docs/rules/300-DOCUMENTATION.md` possède la convention pour le corpus Markdown de PGR. La matrice inscrit l'audit mécanique séparément de la revue des rôles documentaires, de l'audit des tableaux et de celui des liens. Une révision positive ne démontre pas qu'elle a été incrémentée à bon escient : cela reste une décision de revue.
|
||||||
|
|
||||||
|
## Scope
|
||||||
|
|
||||||
|
REPLACE :
|
||||||
|
|
||||||
|
```text
|
||||||
|
VERSION
|
||||||
|
docs/rules/300-DOCUMENTATION.md
|
||||||
|
docs/validation/001-VALIDATION_MATRIX.md
|
||||||
|
```
|
||||||
|
|
||||||
|
ADD :
|
||||||
|
|
||||||
|
```text
|
||||||
|
scripts/audit_markdown_headers.py
|
||||||
|
tests/test_markdown_headers.py
|
||||||
|
deltas/0.0.3/alpha.5.md
|
||||||
|
```
|
||||||
|
|
||||||
|
DELETE : aucun.
|
||||||
|
|
||||||
|
L'archive livre uniquement ces fichiers complets. Aucun history `alpha.5`, réécriture historique, nouveau profil de langage ou autre audit Markdown n'est inclus.
|
||||||
|
|
||||||
|
## Validation opérateur
|
||||||
|
|
||||||
|
Après application sur le commit `alpha.4`, depuis la racine du dépôt :
|
||||||
|
|
||||||
|
```bash
|
||||||
|
test "$(cat VERSION)" = '0.0.3-alpha.5'
|
||||||
|
git cat-file -e HEAD:history/0.0.3/alpha.4.md
|
||||||
|
test -f history/0.0.3/alpha.4.md
|
||||||
|
test -f deltas/0.0.3/alpha.5.md
|
||||||
|
test ! -e history/0.0.3/alpha.5.md
|
||||||
|
|
||||||
|
grep -Fx '<!-- version: 2 -->' docs/rules/300-DOCUMENTATION.md
|
||||||
|
grep -Fx '<!-- version: 8 -->' docs/validation/001-VALIDATION_MATRIX.md
|
||||||
|
|
||||||
|
python3 -B -m unittest discover -s tests -p test_markdown_headers.py -v
|
||||||
|
python3 -B scripts/audit_markdown_headers.py \
|
||||||
|
README.md RULES.md ROADMAP.md CHANGELOG.md docs deltas history prompts
|
||||||
|
python3 -B scripts/audit_markdown_tables.py \
|
||||||
|
README.md RULES.md ROADMAP.md CHANGELOG.md docs deltas history prompts
|
||||||
|
python3 -B scripts/audit_markdown_links.py \
|
||||||
|
README.md RULES.md ROADMAP.md CHANGELOG.md docs deltas history prompts
|
||||||
|
|
||||||
|
git diff --check
|
||||||
|
git add VERSION docs/rules/300-DOCUMENTATION.md \
|
||||||
|
docs/validation/001-VALIDATION_MATRIX.md scripts/audit_markdown_headers.py \
|
||||||
|
tests/test_markdown_headers.py deltas/0.0.3/alpha.5.md
|
||||||
|
git diff --cached --check
|
||||||
|
git status --short
|
||||||
|
```
|
||||||
|
|
||||||
|
Scope attendu avant ajout du history : trois `REPLACE` et trois `ADD`, sans toucher à un delta ou history antérieur. Vérifier que le nouveau script reste monotâche, traite les headers faux et les chemins absents, et ne remplace ni la revue des documents ni les deux autres audits Markdown.
|
||||||
|
|
||||||
|
## Transition
|
||||||
|
|
||||||
|
### PASS
|
||||||
|
|
||||||
|
Produire séparément `history/0.0.3/alpha.5.md` avec les preuves réellement observées, l'appliquer et committer avant la tranche `alpha.6`, consacrée à la décision conditionnelle sur le template de workflow.
|
||||||
|
|
||||||
|
### FAIL
|
||||||
|
|
||||||
|
Enregistrer la défaillance et corriger ce scope dans `alpha.5.fix.1`, sauf REPLAN explicitement justifié.
|
||||||
@@ -1,5 +1,5 @@
|
|||||||
<!-- file: docs/rules/300-DOCUMENTATION.md -->
|
<!-- file: docs/rules/300-DOCUMENTATION.md -->
|
||||||
<!-- version: 1 -->
|
<!-- version: 2 -->
|
||||||
|
|
||||||
# Documentation rules
|
# Documentation rules
|
||||||
|
|
||||||
@@ -165,6 +165,8 @@ La syntaxe de commentaire dépend du format. Pour Markdown :
|
|||||||
<!-- version: 1 -->
|
<!-- version: 1 -->
|
||||||
```
|
```
|
||||||
|
|
||||||
|
Dans le dépôt PGR, `README.md`, `RULES.md`, `ROADMAP.md`, `CHANGELOG.md` et les fichiers Markdown gouvernés sous `docs/`, `deltas/`, `history/` et `prompts/` MUST placer ces deux commentaires sur leurs deux premières lignes. Le `file` MUST être le chemin relatif depuis la racine du dépôt et `version` MUST être un entier positif sans zéro initial. `scripts/audit_markdown_headers.py` contrôle mécaniquement ces deux champs pour les chemins explicitement sélectionnés. Ce contrôle ne juge ni le contenu du document, ni si le numéro de révision a réellement été incrémenté lors d'un changement.
|
||||||
|
|
||||||
`file` identifie le chemin relatif canonique du fichier.
|
`file` identifie le chemin relatif canonique du fichier.
|
||||||
|
|
||||||
`version` est une révision interne du fichier. Elle est indépendante de `VERSION`, de SemVer produit, des versions de protocole, de schema ou de package.
|
`version` est une révision interne du fichier. Elle est indépendante de `VERSION`, de SemVer produit, des versions de protocole, de schema ou de package.
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
<!-- file: docs/validation/001-VALIDATION_MATRIX.md -->
|
<!-- file: docs/validation/001-VALIDATION_MATRIX.md -->
|
||||||
<!-- version: 7 -->
|
<!-- version: 8 -->
|
||||||
|
|
||||||
# Matrice de validation PGR
|
# Matrice de validation PGR
|
||||||
|
|
||||||
@@ -14,11 +14,12 @@ Les catégories et règles de sélection sont définies dans [`../rules/400-VALI
|
|||||||
## Contrôles actifs
|
## Contrôles actifs
|
||||||
|
|
||||||
| ID | Catégorie | Commande / contrôle | Prérequis | Trigger | Phase | Coût | Acteur |
|
| ID | Catégorie | Commande / contrôle | Prérequis | Trigger | Phase | Coût | Acteur |
|
||||||
|--------------------|-----------|--------------------------------------------------------------------------------------|------------------------|---------------------------------|----------------------|--------|-----------------|
|
|---------------------|-----------|--------------------------------------------------------------------------------------|------------------------|---------------------------------|----------------------|--------|-----------------|
|
||||||
| `PGR-GIT-001` | `CHECK` | `git diff --check` ou `git diff --cached --check` selon l'état de l'index | Git | toute modification suivie | alpha/beta/RC/stable | faible | opérateur |
|
| `PGR-GIT-001` | `CHECK` | `git diff --check` ou `git diff --cached --check` selon l'état de l'index | Git | toute modification suivie | alpha/beta/RC/stable | faible | opérateur |
|
||||||
| `PGR-VERSION-001` | `CHECK` | comparer `VERSION` à la version attendue par le delta courant | fichier `VERSION` | changement de tranche/version | alpha/beta/RC/stable | faible | opérateur |
|
| `PGR-VERSION-001` | `CHECK` | comparer `VERSION` à la version attendue par le delta courant | fichier `VERSION` | changement de tranche/version | alpha/beta/RC/stable | faible | opérateur |
|
||||||
| `PGR-LAYOUT-001` | `AUDIT` | comparer les fichiers ajoutés/remplacés/supprimés au scope déclaré du delta | scope du delta | changement de structure | alpha/beta/RC/stable | faible | opérateur/revue |
|
| `PGR-LAYOUT-001` | `AUDIT` | comparer les fichiers ajoutés/remplacés/supprimés au scope déclaré du delta | scope du delta | changement de structure | alpha/beta/RC/stable | faible | opérateur/revue |
|
||||||
| `PGR-DOC-001` | `AUDIT` | vérifier headers `file/version`, chemins et responsabilités des documents touchés | fichiers documentaires | modification documentaire | alpha/beta/RC/stable | faible | opérateur/revue |
|
| `PGR-DOC-001` | `AUDIT` | vérifier chemins, rôles et responsabilités des documents touchés | fichiers documentaires | modification documentaire | alpha/beta/RC/stable | faible | opérateur/revue |
|
||||||
|
| `PGR-MD-HEADER-001` | `AUDIT` | `python3 -B scripts/audit_markdown_headers.py <paths...>` | Python 3 | Markdown gouverné modifié | alpha/beta/RC/stable | faible | opérateur/CI |
|
||||||
| `PGR-MD-TABLE-001` | `AUDIT` | `python3 -B scripts/audit_markdown_tables.py <paths...>` | Python 3 | table Markdown ajoutée/modifiée | alpha/beta/RC/stable | faible | opérateur/CI |
|
| `PGR-MD-TABLE-001` | `AUDIT` | `python3 -B scripts/audit_markdown_tables.py <paths...>` | Python 3 | table Markdown ajoutée/modifiée | alpha/beta/RC/stable | faible | opérateur/CI |
|
||||||
| `PGR-NAV-001` | `AUDIT` | `python3 -B scripts/audit_markdown_links.py <paths...>` | Python 3 | navigation ou réconciliation | beta/RC/stable | faible | opérateur/CI |
|
| `PGR-NAV-001` | `AUDIT` | `python3 -B scripts/audit_markdown_links.py <paths...>` | Python 3 | navigation ou réconciliation | beta/RC/stable | faible | opérateur/CI |
|
||||||
| `PGR-SCOPE-001` | `AUDIT` | vérifier que les documents vivants pointent vers les propriétaires normatifs actuels | documents vivants | réconciliation de phase | beta/RC/stable | faible | revue |
|
| `PGR-SCOPE-001` | `AUDIT` | vérifier que les documents vivants pointent vers les propriétaires normatifs actuels | documents vivants | réconciliation de phase | beta/RC/stable | faible | revue |
|
||||||
@@ -28,6 +29,8 @@ Un contrôle manuel peut rester dans la matrice lorsqu'aucun audit automatisé f
|
|||||||
|
|
||||||
`PGR-MD-TABLE-001` reste volontairement monotâche : il contrôle uniquement la structure et l'alignement source des tableaux Markdown.
|
`PGR-MD-TABLE-001` reste volontairement monotâche : il contrôle uniquement la structure et l'alignement source des tableaux Markdown.
|
||||||
|
|
||||||
|
`PGR-MD-HEADER-001` contrôle seulement les deux premières lignes des fichiers Markdown sélectionnés : chemin relatif depuis la racine et révision interne positive. La revue `PGR-DOC-001` reste responsable du rôle documentaire et de la pertinence réelle d'un incrément de révision.
|
||||||
|
|
||||||
`PGR-NAV-001` est automatisé séparément par `audit_markdown_links.py`. Il vérifie uniquement l'existence des cibles de liens Markdown locaux inline, sans contrôler les anchors, les headers, les responsabilités documentaires ou la forme des tableaux.
|
`PGR-NAV-001` est automatisé séparément par `audit_markdown_links.py`. Il vérifie uniquement l'existence des cibles de liens Markdown locaux inline, sans contrôler les anchors, les headers, les responsabilités documentaires ou la forme des tableaux.
|
||||||
|
|
||||||
PGR préfère plusieurs audits simples avec une responsabilité identifiable à un script unique qui agrège des règles indépendantes.
|
PGR préfère plusieurs audits simples avec une responsabilité identifiable à un script unique qui agrège des règles indépendantes.
|
||||||
|
|||||||
41
history/0.0.3/alpha.5.md
Normal file
41
history/0.0.3/alpha.5.md
Normal file
@@ -0,0 +1,41 @@
|
|||||||
|
<!-- file: history/0.0.3/alpha.5.md -->
|
||||||
|
<!-- version: 1 -->
|
||||||
|
|
||||||
|
# History 0.0.3-alpha.5 — audit des headers Markdown
|
||||||
|
|
||||||
|
## Statut
|
||||||
|
|
||||||
|
PASS
|
||||||
|
|
||||||
|
La gate de `alpha.5` exécutée par l'opérateur le `2026-09-24` a validé le script monotâche des headers Markdown, ses cas positifs et négatifs, et les audits documentaires de PGR.
|
||||||
|
|
||||||
|
## Baseline et version
|
||||||
|
|
||||||
|
L'opérateur a confirmé `VERSION = 0.0.3-alpha.5`, la présence dans `HEAD` de `history/0.0.3/alpha.4.md` par `git cat-file -e`, l'existence du delta `alpha.5` et l'absence du history courant avant sa livraison. Les révisions internes attendues de `docs/rules/300-DOCUMENTATION.md` et de la matrice sont respectivement `2` et `8`.
|
||||||
|
|
||||||
|
## Validation opérateur observée
|
||||||
|
|
||||||
|
`python3 -B -m unittest discover -s tests -p test_markdown_headers.py -v` a exécuté `6` tests, tous `ok`, avec résultat final `OK`. Les audits ont affiché :
|
||||||
|
|
||||||
|
```text
|
||||||
|
Markdown header audit: clean (88 file(s))
|
||||||
|
Markdown table audit: clean (3 table(s), 88 file(s))
|
||||||
|
Markdown link audit: clean (67 local link(s), 88 file(s))
|
||||||
|
```
|
||||||
|
|
||||||
|
`git diff --check` et `git diff --cached --check` n'ont affiché aucun diagnostic. Après ajout des fichiers du delta, le statut indexé transmis est exactement :
|
||||||
|
|
||||||
|
```text
|
||||||
|
M VERSION
|
||||||
|
A deltas/0.0.3/alpha.5.md
|
||||||
|
M docs/rules/300-DOCUMENTATION.md
|
||||||
|
M docs/validation/001-VALIDATION_MATRIX.md
|
||||||
|
A scripts/audit_markdown_headers.py
|
||||||
|
A tests/test_markdown_headers.py
|
||||||
|
```
|
||||||
|
|
||||||
|
Le collage du terminal intercale un fragment d'une commande `git status --short` dans la sortie d'un test. Les six cas, le résumé `OK` et les résultats finaux des trois audits restent lisibles ; aucun échec n'est signalé.
|
||||||
|
|
||||||
|
## Transition
|
||||||
|
|
||||||
|
Appliquer ce history puis committer `alpha.5` avant le delta `alpha.6`. Le commit futur n'est pas attesté par la transcription fournie. La suite prévue consiste à décider, après comparaison des prompts existants, si une courte spécification de prompt manuel améliore réellement la clôture stable.
|
||||||
96
scripts/audit_markdown_headers.py
Normal file
96
scripts/audit_markdown_headers.py
Normal file
@@ -0,0 +1,96 @@
|
|||||||
|
#!/usr/bin/env python3
|
||||||
|
# file: scripts/audit_markdown_headers.py
|
||||||
|
# version: 1
|
||||||
|
|
||||||
|
"""Validate path and positive revision in selected Markdown file headers."""
|
||||||
|
|
||||||
|
from __future__ import annotations
|
||||||
|
|
||||||
|
import argparse
|
||||||
|
import pathlib
|
||||||
|
import re
|
||||||
|
import sys
|
||||||
|
|
||||||
|
_IGNORED_DIRECTORIES = frozenset({".git", ".idea", ".venv", "__pycache__", "dist", "node_modules", "target"})
|
||||||
|
_VERSION = re.compile(r"<!-- version: [1-9][0-9]* -->")
|
||||||
|
|
||||||
|
|
||||||
|
def _selected_files(raw_paths: list[str], root: pathlib.Path) -> tuple[list[pathlib.Path], list[str]]:
|
||||||
|
files: set[pathlib.Path] = set()
|
||||||
|
errors: list[str] = []
|
||||||
|
|
||||||
|
for raw_path in raw_paths:
|
||||||
|
path = pathlib.Path(raw_path)
|
||||||
|
if path.is_dir() or path.is_file():
|
||||||
|
if not path.resolve().is_relative_to(root):
|
||||||
|
errors.append(f"Markdown header audit: path outside project root: {path}")
|
||||||
|
continue
|
||||||
|
if path.is_dir():
|
||||||
|
candidates = (
|
||||||
|
candidate
|
||||||
|
for candidate in path.rglob("*.md")
|
||||||
|
if candidate.is_file() and not any(part in _IGNORED_DIRECTORIES for part in candidate.parts)
|
||||||
|
)
|
||||||
|
elif path.is_file() and path.suffix.lower() == ".md":
|
||||||
|
candidates = iter((path,))
|
||||||
|
else:
|
||||||
|
errors.append(f"Markdown header audit: unsupported or missing path: {path}")
|
||||||
|
continue
|
||||||
|
|
||||||
|
for candidate in candidates:
|
||||||
|
canonical = candidate.resolve()
|
||||||
|
if not canonical.is_relative_to(root):
|
||||||
|
errors.append(f"Markdown header audit: path outside project root: {candidate}")
|
||||||
|
else:
|
||||||
|
files.add(canonical)
|
||||||
|
|
||||||
|
return sorted(files), errors
|
||||||
|
|
||||||
|
|
||||||
|
def _audit_file(path: pathlib.Path, root: pathlib.Path) -> list[str]:
|
||||||
|
relative = path.relative_to(root).as_posix()
|
||||||
|
lines = path.read_text(encoding="utf-8").splitlines()
|
||||||
|
errors: list[str] = []
|
||||||
|
expected_file = f"<!-- file: {relative} -->"
|
||||||
|
|
||||||
|
if not lines or lines[0] != expected_file:
|
||||||
|
errors.append(f"{relative}:1: expected `{expected_file}`")
|
||||||
|
if len(lines) < 2 or _VERSION.fullmatch(lines[1]) is None:
|
||||||
|
errors.append(f"{relative}:2: expected positive `<!-- version: N -->`")
|
||||||
|
return errors
|
||||||
|
|
||||||
|
|
||||||
|
def main() -> int:
|
||||||
|
"""Run the read-only Markdown header audit from the project root."""
|
||||||
|
|
||||||
|
parser = argparse.ArgumentParser(description=__doc__)
|
||||||
|
parser.add_argument("paths", nargs="+", help="Markdown files or directories to audit")
|
||||||
|
args = parser.parse_args()
|
||||||
|
|
||||||
|
root = pathlib.Path.cwd().resolve()
|
||||||
|
files, selection_errors = _selected_files(args.paths, root)
|
||||||
|
if selection_errors or not files:
|
||||||
|
for error in selection_errors or ["Markdown header audit: no Markdown files selected"]:
|
||||||
|
print(error, file=sys.stderr)
|
||||||
|
return 2
|
||||||
|
|
||||||
|
errors: list[str] = []
|
||||||
|
for path in files:
|
||||||
|
try:
|
||||||
|
errors.extend(_audit_file(path, root))
|
||||||
|
except (OSError, UnicodeError) as error:
|
||||||
|
print(f"Markdown header audit: cannot read {path}: {error}", file=sys.stderr)
|
||||||
|
return 2
|
||||||
|
|
||||||
|
for error in errors:
|
||||||
|
print(error, file=sys.stderr)
|
||||||
|
if errors:
|
||||||
|
print(f"Markdown header audit: {len(errors)} error(s) across {len(files)} file(s)", file=sys.stderr)
|
||||||
|
return 1
|
||||||
|
|
||||||
|
print(f"Markdown header audit: clean ({len(files)} file(s))")
|
||||||
|
return 0
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
raise SystemExit(main())
|
||||||
76
tests/test_markdown_headers.py
Normal file
76
tests/test_markdown_headers.py
Normal file
@@ -0,0 +1,76 @@
|
|||||||
|
# file: tests/test_markdown_headers.py
|
||||||
|
# version: 1
|
||||||
|
|
||||||
|
"""Exercise the Markdown header audit's real file and CLI contracts."""
|
||||||
|
|
||||||
|
from __future__ import annotations
|
||||||
|
|
||||||
|
import pathlib
|
||||||
|
import subprocess
|
||||||
|
import sys
|
||||||
|
import tempfile
|
||||||
|
import unittest
|
||||||
|
|
||||||
|
_SCRIPT = pathlib.Path(__file__).resolve().parents[1] / "scripts/audit_markdown_headers.py"
|
||||||
|
|
||||||
|
|
||||||
|
class MarkdownHeaderAuditTests(unittest.TestCase):
|
||||||
|
def setUp(self) -> None:
|
||||||
|
temporary = tempfile.TemporaryDirectory(prefix="pgr-headers-")
|
||||||
|
self.addCleanup(temporary.cleanup)
|
||||||
|
self.root = pathlib.Path(temporary.name)
|
||||||
|
|
||||||
|
def source(self, name: str, contents: str) -> pathlib.Path:
|
||||||
|
path = self.root / name
|
||||||
|
path.parent.mkdir(parents=True, exist_ok=True)
|
||||||
|
path.write_text(contents, encoding="utf-8")
|
||||||
|
return path
|
||||||
|
|
||||||
|
def run_audit(self, *paths: str) -> subprocess.CompletedProcess[str]:
|
||||||
|
return subprocess.run(
|
||||||
|
[sys.executable, "-B", str(_SCRIPT), *paths],
|
||||||
|
cwd=self.root, capture_output=True, text=True, check=False,
|
||||||
|
)
|
||||||
|
|
||||||
|
def test_valid_root_and_nested_files_are_deduplicated(self) -> None:
|
||||||
|
self.source("README.md", "<!-- file: README.md -->\n<!-- version: 1 -->\n")
|
||||||
|
self.source("docs/page.md", "<!-- file: docs/page.md -->\n<!-- version: 27 -->\n")
|
||||||
|
result = self.run_audit("README.md", "docs", "docs/page.md")
|
||||||
|
self.assertEqual(result.returncode, 0, result.stderr)
|
||||||
|
self.assertIn("clean (2 file(s))", result.stdout)
|
||||||
|
|
||||||
|
def test_wrong_path_and_nonpositive_revision_report_both_lines(self) -> None:
|
||||||
|
self.source("docs/page.md", "<!-- file: docs/other.md -->\n<!-- version: 0 -->\n")
|
||||||
|
result = self.run_audit("docs/page.md")
|
||||||
|
self.assertEqual(result.returncode, 1)
|
||||||
|
self.assertIn("docs/page.md:1:", result.stderr)
|
||||||
|
self.assertIn("docs/page.md:2:", result.stderr)
|
||||||
|
self.assertIn("2 error(s)", result.stderr)
|
||||||
|
|
||||||
|
def test_leading_zero_revision_is_rejected(self) -> None:
|
||||||
|
self.source("README.md", "<!-- file: README.md -->\n<!-- version: 01 -->\n")
|
||||||
|
result = self.run_audit("README.md")
|
||||||
|
self.assertEqual(result.returncode, 1)
|
||||||
|
self.assertIn("README.md:2:", result.stderr)
|
||||||
|
|
||||||
|
def test_missing_path_is_a_selection_error(self) -> None:
|
||||||
|
result = self.run_audit("missing.md")
|
||||||
|
self.assertEqual(result.returncode, 2)
|
||||||
|
self.assertIn("unsupported or missing path", result.stderr)
|
||||||
|
|
||||||
|
def test_empty_directory_is_a_selection_error(self) -> None:
|
||||||
|
(self.root / "docs").mkdir()
|
||||||
|
result = self.run_audit("docs")
|
||||||
|
self.assertEqual(result.returncode, 2)
|
||||||
|
self.assertIn("no Markdown files selected", result.stderr)
|
||||||
|
|
||||||
|
def test_generated_directory_is_skipped(self) -> None:
|
||||||
|
self.source("docs/visible.md", "<!-- file: docs/visible.md -->\n<!-- version: 1 -->\n")
|
||||||
|
self.source("docs/target/skip.md", "incorrect\n")
|
||||||
|
result = self.run_audit("docs")
|
||||||
|
self.assertEqual(result.returncode, 0, result.stderr)
|
||||||
|
self.assertIn("clean (1 file(s))", result.stdout)
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
unittest.main()
|
||||||
Reference in New Issue
Block a user