0.0.5-alpha.3.fix.1
This commit is contained in:
164
deltas/0.0.5/alpha.3.fix.1.md
Normal file
164
deltas/0.0.5/alpha.3.fix.1.md
Normal file
@@ -0,0 +1,164 @@
|
||||
<!-- file: deltas/0.0.5/alpha.3.fix.1.md -->
|
||||
<!-- version: 1 -->
|
||||
|
||||
# Delta 0.0.5-alpha.3.fix.1 — couverture des tables dans les exemples Markdown fenced
|
||||
|
||||
## Baseline et version
|
||||
|
||||
Baseline attendue : commit opérateur de `0.0.5-alpha.3`, réalisé après application de `history/0.0.5/alpha.3.md` avec statut `FAIL`.
|
||||
|
||||
Le hash de ce commit n'est pas anticipé.
|
||||
|
||||
Version avant application :
|
||||
|
||||
```text
|
||||
0.0.5-alpha.3
|
||||
```
|
||||
|
||||
Version après application :
|
||||
|
||||
```text
|
||||
0.0.5-alpha.3.fix.1
|
||||
```
|
||||
|
||||
## Objet
|
||||
|
||||
Corriger le faux négatif découvert pendant la gate opérateur de `alpha.3` : `audit_markdown_tables.py` ignorait toutes les tables placées dans des blocs fenced, y compris les exemples explicitement `markdown` du template `004-FILE_FAMILY_CONTRACTS.md`.
|
||||
|
||||
Le fix étend uniquement le contrat de l'audit de tables. Il ne transforme pas l'audit en analyseur général des blocs de code et n'introduit aucun contenu de la tranche Rust `alpha.4`.
|
||||
|
||||
## Scope
|
||||
|
||||
REPLACE :
|
||||
|
||||
```text
|
||||
VERSION
|
||||
scripts/audit_markdown_tables.py
|
||||
docs/templates/004-FILE_FAMILY_CONTRACTS.md
|
||||
docs/validation/001-VALIDATION_MATRIX.md
|
||||
```
|
||||
|
||||
ADD :
|
||||
|
||||
```text
|
||||
tests/test_markdown_tables.py
|
||||
deltas/0.0.5/alpha.3.fix.1.md
|
||||
```
|
||||
|
||||
DELETE : aucun.
|
||||
|
||||
Le history `history/0.0.5/alpha.3.md` appartient au commit baseline du FAIL et n'est pas inclus dans l'archive du fix.
|
||||
|
||||
## Correction
|
||||
|
||||
`scripts/audit_markdown_tables.py` passe en révision interne `2`.
|
||||
|
||||
L'audit continue de contrôler les tables Markdown ordinaires. Dans un bloc fenced :
|
||||
|
||||
- une fence explicitement `markdown` est auditée ;
|
||||
- une fence explicitement `md` est auditée ;
|
||||
- une fence d'un autre langage ou sans langage reste ignorée.
|
||||
|
||||
Cette frontière évite les faux positifs sur les sorties terminal, extraits de code ou tableaux ASCII qui utilisent éventuellement des pipes sans être du Markdown à gouverner.
|
||||
|
||||
`tests/test_markdown_tables.py` verrouille quatre cas :
|
||||
|
||||
1. table ordinaire et table fenced Markdown valides toutes deux comptées ;
|
||||
2. table mal alignée dans une fence `markdown` rejetée ;
|
||||
3. alias `md` audité ;
|
||||
4. fence non Markdown conservée hors scope.
|
||||
|
||||
`docs/templates/004-FILE_FAMILY_CONTRACTS.md` passe en révision `2` et réaligne les deux tables fenced révélées par le nouvel audit.
|
||||
|
||||
`docs/validation/001-VALIDATION_MATRIX.md` passe en révision `10` et explicite la frontière de `PGR-MD-TABLE-001`.
|
||||
|
||||
## Validation opérateur
|
||||
|
||||
Après application du history `FAIL`, commit de `alpha.3`, puis application du présent delta :
|
||||
|
||||
```bash
|
||||
test "$(cat VERSION)" = '0.0.5-alpha.3.fix.1'
|
||||
test -f history/0.0.5/alpha.3.md
|
||||
test -f deltas/0.0.5/alpha.3.md
|
||||
test -f deltas/0.0.5/alpha.3.fix.1.md
|
||||
test -f tests/test_markdown_tables.py
|
||||
test ! -e history/0.0.5/alpha.3.fix.1.md
|
||||
|
||||
grep -A2 '^## Statut$' history/0.0.5/alpha.3.md | grep -Fx 'FAIL'
|
||||
grep -Fx '# version: 2' scripts/audit_markdown_tables.py
|
||||
grep -Fx '<!-- version: 2 -->' docs/templates/004-FILE_FAMILY_CONTRACTS.md
|
||||
grep -Fx '<!-- version: 10 -->' docs/validation/001-VALIDATION_MATRIX.md
|
||||
grep -Fx '# version: 1' tests/test_markdown_tables.py
|
||||
|
||||
python3 -B -m unittest discover -s tests -p 'test_markdown_tables.py' -v
|
||||
python3 -B -m unittest discover -s tests -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
|
||||
|
||||
python3 -B scripts/audit_markdown_tables.py docs/templates/004-FILE_FAMILY_CONTRACTS.md
|
||||
|
||||
python3 -B - <<'PY'
|
||||
from pathlib import Path
|
||||
import re
|
||||
|
||||
history = Path('history/0.0.5/alpha.3.md').read_text(encoding='utf-8')
|
||||
assert re.search(r'## Statut\s+FAIL\s', history)
|
||||
|
||||
script = Path('scripts/audit_markdown_tables.py').read_text(encoding='utf-8')
|
||||
assert '_MARKDOWN_FENCE_LANGUAGES = frozenset({"markdown", "md"})' in script
|
||||
assert 'audit_fenced_markdown' in script
|
||||
|
||||
template = Path('docs/templates/004-FILE_FAMILY_CONTRACTS.md').read_text(encoding='utf-8')
|
||||
assert template.count('```markdown') == 2
|
||||
|
||||
matrix = Path('docs/validation/001-VALIDATION_MATRIX.md').read_text(encoding='utf-8')
|
||||
assert 'fences explicitement `markdown` ou `md`' in matrix
|
||||
assert 'sorties terminal' in matrix
|
||||
|
||||
print('0.0.5 alpha.3.fix.1 fenced Markdown table audit: clean (regression covered, two template examples governed)')
|
||||
PY
|
||||
|
||||
git diff --check
|
||||
|
||||
git add VERSION scripts/audit_markdown_tables.py tests/test_markdown_tables.py \
|
||||
docs/templates/004-FILE_FAMILY_CONTRACTS.md \
|
||||
docs/validation/001-VALIDATION_MATRIX.md \
|
||||
deltas/0.0.5/alpha.3.fix.1.md
|
||||
|
||||
git diff --cached --check
|
||||
git status --short
|
||||
```
|
||||
|
||||
La sortie Git attendue avant ajout du history du fix est exactement :
|
||||
|
||||
```text
|
||||
M VERSION
|
||||
A deltas/0.0.5/alpha.3.fix.1.md
|
||||
M docs/templates/004-FILE_FAMILY_CONTRACTS.md
|
||||
M docs/validation/001-VALIDATION_MATRIX.md
|
||||
M scripts/audit_markdown_tables.py
|
||||
A tests/test_markdown_tables.py
|
||||
```
|
||||
|
||||
Le contrôle ciblé du template doit désormais compter ses deux exemples :
|
||||
|
||||
```text
|
||||
Markdown table audit: clean (2 table(s), 1 file(s))
|
||||
```
|
||||
|
||||
La suite Python doit compter `19` tests si aucun autre test n'est ajouté localement avant exécution.
|
||||
|
||||
## Transition
|
||||
|
||||
### PASS
|
||||
|
||||
Créer et appliquer séparément `history/0.0.5/alpha.3.fix.1.md`, committer et pousser le fix, puis reprendre le plan `0.0.5` à `alpha.4`.
|
||||
|
||||
### FAIL
|
||||
|
||||
Rester dans `0.0.5-alpha.3.fix.M`. Le scope MUST rester limité au contrat de `PGR-MD-TABLE-001` et aux tables révélées par ce contrôle tant qu'aucun défaut plus large ne justifie un REPLAN.
|
||||
6
docs/templates/004-FILE_FAMILY_CONTRACTS.md
vendored
6
docs/templates/004-FILE_FAMILY_CONTRACTS.md
vendored
@@ -1,5 +1,5 @@
|
||||
<!-- file: docs/templates/004-FILE_FAMILY_CONTRACTS.md -->
|
||||
<!-- version: 1 -->
|
||||
<!-- version: 2 -->
|
||||
|
||||
# Pattern — contrats locaux de fichiers ou familles
|
||||
|
||||
@@ -44,7 +44,7 @@ Une table Markdown convient aux registres structurés :
|
||||
|
||||
```markdown
|
||||
| Fichier ou famille | Responsabilité | Règle de modification |
|
||||
|--------------------|----------------|------------------------|
|
||||
|---------------------|------------------|----------------------------|
|
||||
| `<path-or-pattern>` | `<rôle durable>` | `<quand/comment modifier>` |
|
||||
```
|
||||
|
||||
@@ -66,7 +66,7 @@ Le registre SHOULD évoluer lorsqu'une responsabilité ou règle de modification
|
||||
|
||||
```markdown
|
||||
| Fichier ou famille | Responsabilité | Règle de modification |
|
||||
|--------------------|----------------|------------------------|
|
||||
|--------------------|---------------------------------------------------------------------------|--------------------------------------------------------------------------------------------------------------------|
|
||||
| `config/*.example` | Décrire les exemples versionnés de configuration locale. | Mettre à jour lorsqu'une option utilisateur versionnée est ajoutée ou retirée ; ne jamais y placer de secret réel. |
|
||||
| `generated/**` | Contenir les sorties reconstruisibles produites par la toolchain choisie. | Ne pas modifier manuellement ; régénérer depuis la source de vérité documentée. |
|
||||
```
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
<!-- file: docs/validation/001-VALIDATION_MATRIX.md -->
|
||||
<!-- version: 9 -->
|
||||
<!-- version: 10 -->
|
||||
|
||||
# Matrice de validation PGR
|
||||
|
||||
@@ -27,7 +27,7 @@ Les catégories et règles de sélection sont définies dans [`../rules/400-VALI
|
||||
|
||||
Un contrôle manuel peut rester dans la matrice lorsqu'aucun audit automatisé fiable n'existe encore. PGR SHOULD automatiser uniquement les propriétés stables et objectivement contrôlables.
|
||||
|
||||
`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. Il couvre les tableaux Markdown ordinaires ainsi que les exemples placés dans des fences explicitement `markdown` ou `md`. Les autres blocs fenced restent ignorés afin de ne pas interpréter comme Markdown des sorties terminal, extraits de code ou tableaux ASCII d'un autre langage.
|
||||
|
||||
`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.
|
||||
|
||||
|
||||
128
history/0.0.5/alpha.3.fix.1.md
Normal file
128
history/0.0.5/alpha.3.fix.1.md
Normal file
@@ -0,0 +1,128 @@
|
||||
<!-- file: history/0.0.5/alpha.3.fix.1.md -->
|
||||
<!-- version: 1 -->
|
||||
|
||||
# History 0.0.5-alpha.3.fix.1 — couverture des tables dans les exemples Markdown fenced
|
||||
|
||||
## Statut
|
||||
|
||||
PASS
|
||||
|
||||
La gate opérateur de `0.0.5-alpha.3.fix.1` exécutée le `2026-09-24` valide la correction de `PGR-MD-TABLE-001`. Le faux négatif constaté pendant `alpha.3` est couvert par des tests de régression, les deux tables fenced du template `004` sont désormais gouvernées par l'audit et les contrôles documentaires/Git sont propres.
|
||||
|
||||
## Baseline et version
|
||||
|
||||
La tranche part du commit opérateur de `0.0.5-alpha.3`, enregistré après application du history `FAIL`. La sortie Git fournie identifie ce commit sous la forme abrégée :
|
||||
|
||||
```text
|
||||
1b1a709 0.0.5-alpha.3
|
||||
```
|
||||
|
||||
Le push vers `origin/master` a réussi avant l'application de `alpha.3.fix.1`.
|
||||
|
||||
La version contrôlée après application du fix est :
|
||||
|
||||
```text
|
||||
0.0.5-alpha.3.fix.1
|
||||
```
|
||||
|
||||
Les artefacts suivants sont présents pendant la gate :
|
||||
|
||||
```text
|
||||
history/0.0.5/alpha.3.md
|
||||
|
||||
deltas/0.0.5/alpha.3.md
|
||||
deltas/0.0.5/alpha.3.fix.1.md
|
||||
tests/test_markdown_tables.py
|
||||
```
|
||||
|
||||
`history/0.0.5/alpha.3.fix.1.md` est absent pendant la gate, conformément au workflow.
|
||||
|
||||
## Validation opérateur observée
|
||||
|
||||
Les contrôles de statut et de révision ont réussi :
|
||||
|
||||
```text
|
||||
history/0.0.5/alpha.3.md FAIL
|
||||
scripts/audit_markdown_tables.py version 2
|
||||
docs/templates/004-FILE_FAMILY_CONTRACTS.md version 2
|
||||
docs/validation/001-VALIDATION_MATRIX.md version 10
|
||||
tests/test_markdown_tables.py version 1
|
||||
```
|
||||
|
||||
La suite ciblée du nouvel audit a exécuté `4` tests, tous réussis :
|
||||
|
||||
```text
|
||||
Ran 4 tests in 0.093s
|
||||
|
||||
OK
|
||||
```
|
||||
|
||||
Les cas couverts vérifient :
|
||||
|
||||
- le comptage conjoint d'une table ordinaire et d'une table fenced Markdown ;
|
||||
- le rejet d'une table mal alignée dans une fence `markdown` ;
|
||||
- l'audit de l'alias `md` ;
|
||||
- le maintien hors scope des fences non Markdown.
|
||||
|
||||
La suite Python globale a exécuté `19` tests, tous réussis :
|
||||
|
||||
```text
|
||||
Ran 19 tests in 0.311s
|
||||
|
||||
OK
|
||||
```
|
||||
|
||||
Les trois audits documentaires affichent :
|
||||
|
||||
```text
|
||||
Markdown header audit: clean (134 file(s))
|
||||
Markdown table audit: clean (6 table(s), 134 file(s))
|
||||
Markdown link audit: clean (127 local link(s), 134 file(s))
|
||||
```
|
||||
|
||||
Le contrôle ciblé du template affiche désormais :
|
||||
|
||||
```text
|
||||
Markdown table audit: clean (2 table(s), 1 file(s))
|
||||
```
|
||||
|
||||
Le contrôle structurel spécifique affiche :
|
||||
|
||||
```text
|
||||
0.0.5 alpha.3.fix.1 fenced Markdown table audit: clean (regression covered, two template examples governed)
|
||||
```
|
||||
|
||||
Il confirme notamment que l'audit reconnaît uniquement les fences explicites `markdown` ou `md`, que les deux exemples du template sont présents et que la matrice de validation documente l'exclusion volontaire des sorties terminal/non-Markdown.
|
||||
|
||||
`git diff --check` et `git diff --cached --check` n'ont produit aucun diagnostic.
|
||||
|
||||
Le scope Git observé avant ajout du présent history est exactement :
|
||||
|
||||
```text
|
||||
M VERSION
|
||||
A deltas/0.0.5/alpha.3.fix.1.md
|
||||
M docs/templates/004-FILE_FAMILY_CONTRACTS.md
|
||||
M docs/validation/001-VALIDATION_MATRIX.md
|
||||
M scripts/audit_markdown_tables.py
|
||||
A tests/test_markdown_tables.py
|
||||
```
|
||||
|
||||
## Résultat
|
||||
|
||||
Le défaut de `alpha.3` est corrigé sans élargir l'audit à des blocs de code qui ne sont pas explicitement du Markdown. `PGR-MD-TABLE-001` couvre maintenant les tables normales ainsi que les exemples fenced Markdown, tout en continuant d'ignorer les fences d'autres langages.
|
||||
|
||||
Aucun nouveau fix de `alpha.3` n'est requis.
|
||||
|
||||
Après la gate, une revue distincte du plan et des historiques de conception PGR a révélé un besoin de gouvernance plus large : le contrat des plans n'assigne pas encore explicitement les responsabilités de clôture/transition et PGR ne définit pas encore de revue d'horizon de roadmap. Ce besoin ne remet pas en cause le présent fix ; il justifie un REPLAN dans la tranche normale suivante.
|
||||
|
||||
## Transition
|
||||
|
||||
Appliquer le présent history puis committer et pousser `0.0.5-alpha.3.fix.1`.
|
||||
|
||||
La tranche suivante devient :
|
||||
|
||||
```text
|
||||
0.0.5-alpha.4
|
||||
```
|
||||
|
||||
avec rôle `REPLAN`. Elle doit traiter uniquement le lifecycle inter-release, le contrat de clôture/transition des plans, la revue d'horizon et les optimisations workflow directement liées. Les anciens travaux prévus à partir de `alpha.4` sont décalés sans être abandonnés.
|
||||
@@ -1,6 +1,6 @@
|
||||
#!/usr/bin/env python3
|
||||
# file: scripts/audit_markdown_tables.py
|
||||
# version: 1
|
||||
# version: 2
|
||||
|
||||
"""Validate source formatting of Markdown tables in explicitly selected paths."""
|
||||
|
||||
@@ -13,6 +13,7 @@ import sys
|
||||
|
||||
_SEPARATOR = re.compile(r"^:?-{3,}:?$")
|
||||
_IGNORED_DIRECTORIES = frozenset({".git", ".idea", ".venv", "__pycache__", "dist", "node_modules", "target"})
|
||||
_MARKDOWN_FENCE_LANGUAGES = frozenset({"markdown", "md"})
|
||||
|
||||
|
||||
def _selected_files(raw_paths: list[str]) -> tuple[list[pathlib.Path], list[str]]:
|
||||
@@ -130,11 +131,19 @@ def _validate_table(path: pathlib.Path, start_line: int, rows: list[str]) -> lis
|
||||
return errors
|
||||
|
||||
|
||||
def _fence_language(stripped: str) -> str | None:
|
||||
info = stripped[3:].strip()
|
||||
if not info:
|
||||
return None
|
||||
return info.split(None, 1)[0].lower()
|
||||
|
||||
|
||||
def _audit_file(path: pathlib.Path) -> tuple[int, list[str]]:
|
||||
lines = path.read_text(encoding="utf-8").splitlines()
|
||||
errors: list[str] = []
|
||||
tables = 0
|
||||
fence: str | None = None
|
||||
audit_fenced_markdown = False
|
||||
index = 0
|
||||
|
||||
while index < len(lines):
|
||||
@@ -143,12 +152,14 @@ def _audit_file(path: pathlib.Path) -> tuple[int, list[str]]:
|
||||
marker = stripped[:3]
|
||||
if fence is None:
|
||||
fence = marker
|
||||
audit_fenced_markdown = _fence_language(stripped) in _MARKDOWN_FENCE_LANGUAGES
|
||||
elif fence == marker:
|
||||
fence = None
|
||||
audit_fenced_markdown = False
|
||||
index += 1
|
||||
continue
|
||||
|
||||
if fence is not None:
|
||||
if fence is not None and not audit_fenced_markdown:
|
||||
index += 1
|
||||
continue
|
||||
|
||||
|
||||
90
tests/test_markdown_tables.py
Normal file
90
tests/test_markdown_tables.py
Normal file
@@ -0,0 +1,90 @@
|
||||
# file: tests/test_markdown_tables.py
|
||||
# version: 1
|
||||
|
||||
"""Exercise Markdown table detection, including explicit Markdown examples."""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
import pathlib
|
||||
import subprocess
|
||||
import sys
|
||||
import tempfile
|
||||
import unittest
|
||||
|
||||
_SCRIPT = pathlib.Path(__file__).resolve().parents[1] / "scripts/audit_markdown_tables.py"
|
||||
|
||||
|
||||
class MarkdownTableAuditTests(unittest.TestCase):
|
||||
def setUp(self) -> None:
|
||||
temporary = tempfile.TemporaryDirectory(prefix="pgr-tables-")
|
||||
self.addCleanup(temporary.cleanup)
|
||||
self.root = pathlib.Path(temporary.name)
|
||||
|
||||
def source(self, contents: str) -> pathlib.Path:
|
||||
path = self.root / "sample.md"
|
||||
path.write_text(contents, encoding="utf-8")
|
||||
return path
|
||||
|
||||
def run_audit(self) -> subprocess.CompletedProcess[str]:
|
||||
return subprocess.run(
|
||||
[sys.executable, "-B", str(_SCRIPT), "sample.md"],
|
||||
cwd=self.root, capture_output=True, text=True, check=False,
|
||||
)
|
||||
|
||||
def test_regular_and_fenced_markdown_tables_are_counted(self) -> None:
|
||||
self.source(
|
||||
"| A | BB |\n"
|
||||
"|---|----|\n"
|
||||
"| x | y |\n"
|
||||
"\n"
|
||||
"```markdown\n"
|
||||
"| C | DD |\n"
|
||||
"|---|----|\n"
|
||||
"| z | q |\n"
|
||||
"```\n"
|
||||
)
|
||||
result = self.run_audit()
|
||||
self.assertEqual(result.returncode, 0, result.stderr)
|
||||
self.assertIn("clean (2 table(s), 1 file(s))", result.stdout)
|
||||
|
||||
def test_misaligned_table_inside_markdown_fence_is_rejected(self) -> None:
|
||||
self.source(
|
||||
"```markdown\n"
|
||||
"| Fichier ou famille | Responsabilité | Règle de modification |\n"
|
||||
"|--------------------|----------------|------------------------|\n"
|
||||
"| `<path-or-pattern>` | `<rôle durable>` | `<quand/comment modifier>` |\n"
|
||||
"```\n"
|
||||
)
|
||||
result = self.run_audit()
|
||||
self.assertEqual(result.returncode, 1)
|
||||
self.assertIn("sample.md:2: column 1 is not vertically aligned", result.stderr)
|
||||
self.assertIn("column 2 is not vertically aligned", result.stderr)
|
||||
self.assertIn("column 3 is not vertically aligned", result.stderr)
|
||||
|
||||
def test_md_fence_is_audited(self) -> None:
|
||||
self.source(
|
||||
"```md\n"
|
||||
"| A | BB |\n"
|
||||
"|---|----|\n"
|
||||
"| x | y |\n"
|
||||
"```\n"
|
||||
)
|
||||
result = self.run_audit()
|
||||
self.assertEqual(result.returncode, 0, result.stderr)
|
||||
self.assertIn("clean (1 table(s), 1 file(s))", result.stdout)
|
||||
|
||||
def test_non_markdown_fence_remains_ignored(self) -> None:
|
||||
self.source(
|
||||
"```text\n"
|
||||
"| Fichier ou famille | Responsabilité |\n"
|
||||
"|--------------------|----------------|\n"
|
||||
"| x | y |\n"
|
||||
"```\n"
|
||||
)
|
||||
result = self.run_audit()
|
||||
self.assertEqual(result.returncode, 0, result.stderr)
|
||||
self.assertIn("clean (0 table(s), 1 file(s))", result.stdout)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
unittest.main()
|
||||
Reference in New Issue
Block a user