diff --git a/Cargo.toml b/Cargo.toml index 3c29488..99eb583 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,5 +1,5 @@ # file: Cargo.toml -# version: 27 +# version: 28 [workspace] resolver = "3" @@ -16,7 +16,7 @@ members = [ ] [workspace.package] -version = "0.0.2-beta.1.fix.1" +version = "0.0.2-beta.1.fix.2" edition = "2024" publish = false repository = "https://git.sasedev.com/Sasedev/sasedev-knowledge" diff --git a/VERSION b/VERSION index 62d32e5..b9576b8 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -0.0.2-beta.1.fix.1 +0.0.2-beta.1.fix.2 diff --git a/deltas/0.0.2/beta.1.fix.2.md b/deltas/0.0.2/beta.1.fix.2.md new file mode 100644 index 0000000..8c1fc4f --- /dev/null +++ b/deltas/0.0.2/beta.1.fix.2.md @@ -0,0 +1,161 @@ + + + +# Delta 0.0.2-beta.1.fix.2 — correction finale de la gate beta + +## Base requise + +État `0.0.2-beta.1.fix.1` committé et poussé après application du history : + +```text +history/0.0.2/beta.1.fix.1.md = FAIL +``` + +La version devient : + +```text +0.0.2-beta.1.fix.2 +``` + +## Cause + +`beta.1.fix.1` acquiert toutes les preuves runtime manquantes, y compris les trois smokes HTTP, mais sa gate contient deux défauts propres au livrable de validation : + +- l'audit Python de stabilisation utilise une chaîne délimitée par apostrophes contenant `n'est`, produisant `SyntaxError: unterminated string literal` ; +- `docs/validation/001-VALIDATION_MATRIX.md` se termine par une ligne vide supplémentaire, ce que `git diff --check` puis `git diff --cached --check` rejettent comme `new blank line at EOF`. + +Le script d'hygiène texte de `fix.1` vérifie seulement `endswith(b'\n')` et ne détecte donc pas le suffixe invalide `b'\n\n'`. + +## Objet du fix + +Le fix n'introduit aucune fonctionnalité et ne rejoue pas mécaniquement les preuves runtime déjà acquises sur un arbre produit inchangé. Il : + +- corrige le quoting de l'audit Python ; +- normalise tous ses fichiers remplacés à exactement un LF terminal ; +- rend durable la règle d'un unique LF terminal chez `400-VALIDATION` ; +- étend l'audit d'hygiène pour rejeter `\n\n` à EOF ; +- interdit dans les gates destinées au shell interactif les modifications persistantes `set -e`, `set -u` et `set -o pipefail` ; +- conserve comme preuves cumulatives les résultats `PASS` de `beta.1.fix.1` pour Cargo/Clippy/tests, Web et smokes HTTP. + +## Scope + +Fichiers remplacés : + +```text +VERSION +Cargo.toml +docs/rules/400-VALIDATION.md +docs/plans/002-V0_0_2_GIT_SYNC_PLAN.md +docs/validation/001-VALIDATION_MATRIX.md +``` + +Fichier ajouté : + +```text +deltas/0.0.2/beta.1.fix.2.md +``` + +Aucun fichier sous `crates/` ou `Web/` n'est remplacé. Aucun package, dépendance, contrat métier, comportement Git ou future release n'est ajouté. + +## Gate opérateur + +Exécuter les commandes ci-dessous directement dans le shell interactif. La gate ne modifie volontairement pas les options globales du shell. + +```bash +test "$(cat VERSION)" = '0.0.2-beta.1.fix.2' +grep -F 'version = "0.0.2-beta.1.fix.2"' Cargo.toml +grep -A2 '^## Statut$' history/0.0.2/beta.1.fix.1.md | grep -Fx 'FAIL' + +git diff --check + +python3 -B scripts/audit_markdown_headers.py README.md RULES.md ROADMAP.md CHANGELOG.md docs prompts deltas history +python3 -B scripts/audit_markdown_links.py README.md RULES.md ROADMAP.md CHANGELOG.md docs prompts deltas history +python3 -B scripts/audit_markdown_tables.py README.md RULES.md ROADMAP.md CHANGELOG.md docs prompts deltas history + +python3 - <<'PYGATE' +from pathlib import Path +import tomllib + +workspace = tomllib.loads(Path("Cargo.toml").read_text(encoding="utf-8")) +assert len(workspace["workspace"]["members"]) == 9 + +study = Path("docs/studies/005-V0_0_2_GIT_SYNC_RECONCILIATION.md").read_text(encoding="utf-8") +assert "Aucun prompt `0.0.3` n'est créé" in study +roadmap = Path("ROADMAP.md").read_text(encoding="utf-8") +assert "0.0.3" not in roadmap +assert not Path("prompts/003-V0_0_3_START_PROMPT.md").exists() +assert not Path("history/0.0.2/beta.1.fix.2.md").exists() + +previous = Path("history/0.0.2/beta.1.fix.1.md").read_text(encoding="utf-8") +for phrase in ( + "knowledge-pgr-server smoke PASS", + "knowledge-howtos-server smoke PASS", + "knowledge-snippets-server smoke PASS", + "cargo check --workspace", + "cargo test --workspace --all-targets --all-features", +): + assert phrase in previous, phrase + +rule400 = Path("docs/rules/400-VALIDATION.md").read_text(encoding="utf-8") +assert "exactement un unique LF" in rule400 +assert "ne doit pas modifier durablement les options du shell" in rule400 +print("Knowledge 0.0.2-beta.1.fix.2 stabilization audit: clean") +PYGATE + +python3 - <<'PYTEXT' +from pathlib import Path + +roots = [Path('README.md'), Path('RULES.md'), Path('ROADMAP.md'), Path('CHANGELOG.md'), Path('docs'), Path('prompts'), Path('deltas'), Path('history')] +paths = [] +for root in roots: + if root.is_file(): + paths.append(root) + elif root.is_dir(): + paths.extend(path for path in root.rglob('*') if path.is_file()) +for path in paths: + data = path.read_bytes() + assert b'\r' not in data, path + assert data.endswith(b'\n'), path + assert not data.endswith(b'\n\n'), path + text = data.decode('utf-8') + for number, line in enumerate(text.splitlines(), start=1): + assert line == line.rstrip(' \t'), (path, number) +print(f'Knowledge beta.1.fix.2 text hygiene: clean ({len(paths)} file(s))') +PYTEXT + +test -f Cargo.lock +git check-ignore -q Cargo.lock +if git ls-files --error-unmatch Cargo.lock >/dev/null 2>&1; then + echo 'Cargo.lock must remain untracked for Knowledge' >&2 + exit 1 +fi + +test -z "$(git diff --name-only -- crates Web)" +test ! -e crates/knowledge-forge-gitea-lib +test ! -e crates/knowledge-store-postgres-lib + +git add -A +git diff --cached --check +git status --short +``` + +## Résultat attendu + +Le `PASS` doit notamment afficher : + +```text +Knowledge 0.0.2-beta.1.fix.2 stabilization audit: clean +Knowledge beta.1.fix.2 text hygiene: clean (... file(s)) +``` + +Aucune commande Cargo, npm ou smoke n'est répétée dans ce fix documentaire : leurs preuves `PASS` sont conservées dans le history `beta.1.fix.1`, et le contrôle de scope prouve l'absence de diff sous `crates/` et `Web/`. + +## Transition + +`PASS` ferme la stabilisation beta et autorise uniquement : + +```text +0.0.2-rc.1 +``` + +Le history `beta.1.fix.2` est produit seulement après réception de la gate opérateur complète. diff --git a/docs/plans/002-V0_0_2_GIT_SYNC_PLAN.md b/docs/plans/002-V0_0_2_GIT_SYNC_PLAN.md index 66f3a98..5d862eb 100644 --- a/docs/plans/002-V0_0_2_GIT_SYNC_PLAN.md +++ b/docs/plans/002-V0_0_2_GIT_SYNC_PLAN.md @@ -1,5 +1,5 @@ - + # Plan 0.0.2 — Git générique et synchronisation de lecture @@ -28,7 +28,7 @@ PGR publish report pgr-0.1.3-publish.001-report.md = PASS Le passage de PGR `v0.1.1` à `v0.1.3` est traité comme adoption d'un projet existant via `230-ADOPTION`. Les artefacts historiques de `0.0.1` ne sont pas réécrits. `v0.1.3` constitue une provenance d'adoption, pas une dépendance normative vivante : les futurs démarrages Knowledge doivent partir des règles locales et ne consultent PGR que lorsqu'une nouvelle adoption est explicitement engagée. -`0.0.2-alpha.1` est `FAIL` pour défaut de structure du présent plan malgré des contrôles techniques propres. `alpha.1.fix.1` a corrigé uniquement ce cadrage documentaire et sa gate opérateur est `PASS`. `alpha.2` a été fermée par `alpha.2.fix.2` `PASS`. `alpha.3` a été fermée par `alpha.3.fix.1` `PASS`. `alpha.4` a été fermée par `alpha.4.fix.1` `PASS`, terminant l'adoption PGR comme migration ponctuelle. `alpha.5` est `PASS` et ferme le scope fonctionnel alpha avec `knowledge-app-lib` et le cas d'usage partagé `Changed` / `Unchanged`. `beta.1` est `PARTIAL` : la réconciliation, les audits Rust/Git et la baseline Web passent, mais la gate générée a omis les smokes HTTP requis pendant la stabilisation. `beta.1.fix.1` est la tranche courante et rejoue la stabilisation complète sans changement fonctionnel. +`0.0.2-alpha.1` est `FAIL` pour défaut de structure du présent plan malgré des contrôles techniques propres. `alpha.1.fix.1` a corrigé uniquement ce cadrage documentaire et sa gate opérateur est `PASS`. `alpha.2` a été fermée par `alpha.2.fix.2` `PASS`. `alpha.3` a été fermée par `alpha.3.fix.1` `PASS`. `alpha.4` a été fermée par `alpha.4.fix.1` `PASS`, terminant l'adoption PGR comme migration ponctuelle. `alpha.5` est `PASS` et ferme le scope fonctionnel alpha avec `knowledge-app-lib` et le cas d'usage partagé `Changed` / `Unchanged`. `beta.1` est `PARTIAL` : la réconciliation, les audits Rust/Git et la baseline Web passent, mais la gate générée a omis les smokes HTTP requis pendant la stabilisation. `beta.1.fix.1` est `FAIL` : les smokes HTTP sont désormais acquis, mais un `SyntaxError` dans l'audit de stabilisation et une ligne vide supplémentaire à EOF font échouer la gate. `beta.1.fix.2` est la tranche courante et corrige uniquement ces défauts de validation. ## Mission @@ -238,7 +238,7 @@ Statut opérateur : **PARTIAL**. La tranche n'ajoute aucune grande fonctionnalité. La réconciliation documentaire, les audits Rust/Git, la baseline Web, le manifest Vite et la revue d'horizon passent. La gate générée a toutefois omis les trois smokes HTTP alors que la stratégie de validation du présent plan les exige pendant la stabilisation. -`beta.1.fix.1` corrige uniquement ce contrat de validation, rend explicite chez l'owner local `400-VALIDATION` qu'un smoke de stabilisation planifié reste obligatoire même sans diff runtime, puis rejoue la gate complète avec les trois launchers. Aucun code produit, contrat métier, package ou scope fonctionnel n'est modifié. +`beta.1.fix.1` corrige le contrat de smoke et acquiert effectivement les trois smokes HTTP, mais reste `FAIL` parce que son audit Python de stabilisation contient une chaîne mal quotée et que `001-VALIDATION_MATRIX.md` introduit une ligne vide supplémentaire à EOF. `beta.1.fix.2` corrige uniquement ces deux défauts de gate, rend durable la règle d'un unique LF terminal et retire les modifications persistantes d'options shell des gates interactives. Aucun code produit, contrat métier, package ou scope fonctionnel n'est modifié. La réconciliation doit : @@ -313,7 +313,7 @@ Un REPLAN modifie le présent plan de manière explicite ; il ne doit pas être ## Revue d'horizon -État courant : **réalisée dans `0.0.2-beta.1`; contenu acquis, clôture beta en attente du smoke `beta.1.fix.1`**. +État courant : **réalisée dans `0.0.2-beta.1`; contenu et smokes runtime acquis, clôture beta en attente de la gate propre `beta.1.fix.2`**. Résultat : aucune version postérieure à `0.0.2` n'est réservée. Les domaines futurs restent non numérotés parce qu'aucune mission suivante ne possède encore un scope et un ordre suffisamment décidés. diff --git a/docs/rules/400-VALIDATION.md b/docs/rules/400-VALIDATION.md index 0d15f27..40d4454 100644 --- a/docs/rules/400-VALIDATION.md +++ b/docs/rules/400-VALIDATION.md @@ -1,5 +1,5 @@ - + # Validation locale Knowledge @@ -97,6 +97,8 @@ cargo fmt --all Les audits Markdown ou autres contrôles documentaires peuvent être exécutés avant ou après le formatage Rust puisqu'ils ne portent pas sur les sources Rust. +Une gate fournie pour exécution dans le shell interactif de l'opérateur ne doit pas modifier durablement les options du shell avec `set -e`, `set -u`, `set -o pipefail` ou une combinaison équivalente. La gate doit laisser chaque commande produire son résultat observable sans risquer de terminer la session terminal de l'opérateur. + Pour une tranche Web, les preuves npm/typecheck/build sont ajoutées lorsque `Web/` ou son contrat d'intégration est touché. Une tranche documentaire ou Rust sans diff Web ne rejoue pas automatiquement le frontend. Une phase de stabilisation globale explicitement prévue par le plan (`beta`, `rc` ou clôture stable) peut imposer une preuve de non-régression runtime même sans diff direct sous `Web/` ou dans les launchers. Lorsqu'un plan exige un smoke de stabilisation, cette preuve est obligatoire et ne peut pas être omise au motif que le code runtime n'a pas changé dans la tranche. @@ -107,4 +109,15 @@ Un warning provenant d'une dépendance tierce n'est pas automatiquement un `FAIL ## Traçabilité +## Hygiène des fichiers texte + +Les fichiers texte gouvernés doivent utiliser LF et se terminer par exactement un unique LF. Un suffixe `\n\n` est une ligne vide supplémentaire à EOF et doit être rejeté par la validation lorsqu'il est introduit par la tranche. + +La validation d'hygiène doit donc distinguer : + +```text +...dernière ligne\n valide +...dernière ligne\n\n invalide +``` + Chaque delta liste sa gate exécutable et la matrice conserve le contrat durable. Le history enregistre les résultats réellement observés ; il ne résume pas une prévalidation comme si elle avait été exécutée par l'opérateur. diff --git a/docs/validation/001-VALIDATION_MATRIX.md b/docs/validation/001-VALIDATION_MATRIX.md index b34a8f2..fd83d9a 100644 --- a/docs/validation/001-VALIDATION_MATRIX.md +++ b/docs/validation/001-VALIDATION_MATRIX.md @@ -1,5 +1,5 @@ - + # Matrice de validation Knowledge @@ -778,5 +778,22 @@ Le fix de clôture beta doit prouver : - `Cargo.lock` présent localement, ignoré et non suivi ; - hygiène texte et `git diff --cached --check` propres. -Le `PASS` de `beta.1.fix.1` ferme la stabilisation beta et autorise uniquement `0.0.2-rc.1`. Un résultat incomplet ou en échec produit son history réel et interdit la RC. +`beta.1.fix.1` est `FAIL` malgré les smokes HTTP `PASS` : son audit Python de stabilisation échoue sur un quoting invalide et `git diff --cached --check` détecte une ligne vide supplémentaire à EOF. La transition autorisée est uniquement `beta.1.fix.2`. +## Gate de `0.0.2-beta.1.fix.2` + +Le fix de clôture beta doit prouver : + +- `VERSION = 0.0.2-beta.1.fix.2` et version workspace identique ; +- history `history/0.0.2/beta.1.fix.1.md` présent avec statut `FAIL` et committé avant application ; +- aucun diff sous `crates/` ou `Web/` ; +- aucune nouvelle fonctionnalité, package Cargo/npm, dépendance ou contrat runtime ; +- audit Python de stabilisation corrigé et exécutable, sans chaîne littérale mal quotée ; +- fichiers texte gouvernés terminés par exactement un LF, sans ligne vide supplémentaire à EOF ; +- audits Markdown locaux propres ; +- preuves runtime acquises en `beta.1.fix.1` conservées dans son history : Cargo/Clippy/tests, baseline Web et trois smokes HTTP `PASS` ; +- `Cargo.lock` présent localement, ignoré et non suivi ; +- `git diff --check` puis `git diff --cached --check` propres ; +- gate interactive ne modifiant pas le shell opérateur avec `set -euo pipefail`. + +Le `PASS` de `beta.1.fix.2`, combiné aux preuves runtime `PASS` conservées dans `history/0.0.2/beta.1.fix.1.md`, ferme la stabilisation beta et autorise uniquement `0.0.2-rc.1`. diff --git a/history/0.0.2/beta.1.fix.2.md b/history/0.0.2/beta.1.fix.2.md new file mode 100644 index 0000000..75ccce1 --- /dev/null +++ b/history/0.0.2/beta.1.fix.2.md @@ -0,0 +1,132 @@ + + + +# History 0.0.2-beta.1.fix.2 — fermeture propre de la stabilisation beta + +## Statut + +PASS + +La gate opérateur de `0.0.2-beta.1.fix.2` exécutée le `2026-09-29` passe intégralement. Le fix corrige uniquement les défauts de validation de `beta.1.fix.1` : quoting Python, fin de fichier à exactement un LF et discipline du shell interactif. + +Aucun code produit, contrat métier, package Cargo/npm ou comportement runtime n'est modifié. + +## Baseline opérateur + +`beta.1.fix.1` a été historisé, committé et poussé avant application de ce fix : + +```text +commit 4b51098 +message 0.0.2-beta.1.fix.1 +branch master +push origin/master PASS +status clean après push +``` + +La gate démarre avec : + +```text +VERSION 0.0.2-beta.1.fix.2 +Cargo workspace version 0.0.2-beta.1.fix.2 +history/0.0.2/beta.1.fix.1.md FAIL +``` + +## Diff et documentation + +Les contrôles suivants passent : + +```text +git diff --check PASS +Markdown header audit clean (91 file(s)) +Markdown link audit clean (72 local link(s), 91 file(s)) +Markdown table audit clean (4 table(s), 91 file(s)) +``` + +## Audit de stabilisation corrigé + +Le bloc `PYGATE` s'exécute sans erreur et confirme : + +```text +workspace Cargo 9 membres +aucun prompt 0.0.3 PASS +aucun history beta.1.fix.2 anticipé PASS +preuves runtime beta.1.fix.1 présentes PASS +règle unique LF locale PASS +règle shell interactif locale PASS +Knowledge 0.0.2-beta.1.fix.2 stabilization audit: clean +``` + +Le quoting Python contenant `n'est` est donc corrigé. + +## Hygiène texte et EOF + +L'audit renforcé vérifie pour les `91` fichiers texte gouvernés : + +```text +CR absent PASS +au moins un LF terminal PASS +pas de suffixe LF LF PASS +aucun espace/tab terminal par ligne PASS +``` + +Résultat : + +```text +Knowledge beta.1.fix.2 text hygiene: clean (91 file(s)) +``` + +La propriété « exactement un unique LF » est désormais effectivement prouvée. + +## Frontières + +Les contrôles suivants passent : + +```text +Cargo.lock présent localement PASS +Cargo.lock ignoré PASS +Cargo.lock non suivi PASS +aucun diff sous crates/ ou Web/ PASS +aucune crate forge Gitea PASS +aucun store PostgreSQL PASS +``` + +Après staging : + +```text +git diff --cached --check PASS +``` + +Le statut final contient exactement les fichiers documentaires/gate prévus par `beta.1.fix.2`. + +## Preuves cumulatives de stabilisation + +`beta.1.fix.1` conserve les preuves runtime acquises sur le même arbre produit : + +```text +cargo check --workspace PASS +cargo clippy --workspace --all-targets --all-features PASS +cargo test --workspace --all-targets --all-features PASS +npm ci / typecheck / build PASS +knowledge-pgr-server smoke PASS +knowledge-howtos-server smoke PASS +knowledge-snippets-server smoke PASS +``` + +`beta.1.fix.2` ne les rejoue pas parce qu'il ne modifie aucun fichier produit ; il ferme uniquement les défauts de la gate. + +## Décision + +`0.0.2-beta.1.fix.2` est `PASS`. + +La stabilisation beta est fermée. La transition autorisée est uniquement : + +```text +appliquer ce history +-> git add / diff --cached --check / status +-> commit exact "0.0.2-beta.1.fix.2" +-> push origin master +-> vérifier le workspace propre +-> appliquer seulement ensuite 0.0.2-rc.1 +``` + +`rc.1` doit geler le scope et rejouer la gate complète de release candidate sans nouvelle fonctionnalité.