diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 392c21ef..d21f24e8 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -306,13 +306,22 @@ This list lives here, in the repository, where a tool can check it. A scope MUST NOT be a file name or a class name: those move; the zone they inhabit does not. `fix(core):`, never `fix(ErrorCode.cs):`. -The scope is optional here because the two published packages -(`FirstClassErrors` and `FirstClassErrors.Testing`) share a single tag-driven -version: the scope carries no versioning weight, only readability. What does not -belong to a component takes **no** scope — repository infrastructure (the +The scope is load-bearing for the release record. The tooling partitions commits +into **release trains** by scope — `tools/trains.sh` is the single source of +truth — and each train publishes independently: `lib` (scopes `core`, `analyzers`, +`testing`, `binder` → `FirstClassErrors`, `FirstClassErrors.Testing` and +`FirstClassErrors.RequestBinder`), `cli` (scopes `cli`, `gendoc` → the `fce` tool) +and `dum` (scope `dummies` → `Dummies`). A commit's scope decides which train's +release notes and changelog it lands in; see +[Adding a release train](doc/handwritten/for-maintainers/AddingAReleaseTrain.en.md). + +Because of that, a user-facing change **must** carry a scope: an unscoped `feat:` +or `fix:` matches no train and is **silently dropped from every release note and +changelog**, so the change would vanish from the release record. Only what +genuinely belongs to no component stays unscoped — repository infrastructure (the solution, `Directory.Build.props`, the workflows, `.gitignore`, `CLAUDE.md`), -repository-wide documentation, ADRs, and the `FirstClassErrors.Usage` samples: -`ci: …`, `docs: …`. +repository-wide documentation, ADRs, and the `FirstClassErrors.Usage` samples — +and those use non-version-driving types anyway: `ci: …`, `docs: …`, `chore: …`. When one atomic change crosses several components, the commit MUST carry all their scopes, comma-separated with no space and ordered alphabetically. The @@ -521,11 +530,11 @@ guide. It applies from its adoption on, to every commit created after. Prior history is not rewritten. -Enforcement stands today at pull-request review, which refuses a non-conforming -message and lets the author correct it before the merge. The repository will -lock the rule in turn: a `commit-msg` hook that refuses the message at write -time, doubled with a CI check, since a local hook can be bypassed. Merge -commits, generated by GitHub, are exempt. +Enforcement is layered. A `commit-msg` hook (versioned under `.githooks/`, enabled +once per clone) refuses a non-conforming message at write time, and — because a +local hook can be bypassed — a CI check re-runs the same validation on every pull +request, so a bypassed hook is still caught before the merge. Merge commits, +generated by GitHub, are exempt. ### Credits diff --git a/doc/handwritten/for-users/ArbitraryTestValues.fr.md b/doc/handwritten/for-users/ArbitraryTestValues.fr.md index f34fd2ea..e5b707a3 100644 --- a/doc/handwritten/for-users/ArbitraryTestValues.fr.md +++ b/doc/handwritten/for-users/ArbitraryTestValues.fr.md @@ -124,7 +124,7 @@ Avant de recourir à une valeur arbitraire, vérifiez que : ---
-← Tests d’erreur déterministes · ↑ Table des matières · Générer et publier le catalogue → +← Tests d’erreur déterministes · ↑ Table des matières · Générer et publier le catalogue →
--- diff --git a/doc/handwritten/for-users/ArchitectureOfTheDocumentationPipeline.fr.md b/doc/handwritten/for-users/ArchitectureOfTheDocumentationPipeline.fr.md index 65d939ec..ebc657c6 100644 --- a/doc/handwritten/for-users/ArchitectureOfTheDocumentationPipeline.fr.md +++ b/doc/handwritten/for-users/ArchitectureOfTheDocumentationPipeline.fr.md @@ -184,7 +184,7 @@ Le code reste la source de vérité ; le pipeline rend cette connaissance transp ---
-← Versionnage du catalogue · ↑ Table des matières · Référence de l’extraction et de la découverte des projets → +← Versionnage du catalogue · ↑ Table des matières · Référence de l’extraction et de la découverte des projets →
--- \ No newline at end of file diff --git a/doc/handwritten/for-users/BestPractices.fr.md b/doc/handwritten/for-users/BestPractices.fr.md index 8eac3948..2f2bccd0 100644 --- a/doc/handwritten/for-users/BestPractices.fr.md +++ b/doc/handwritten/for-users/BestPractices.fr.md @@ -111,7 +111,7 @@ Avant de merger une modification liée aux erreurs, vérifiez que : ---
-← Cas d’usage · ↑ Table des matières · Guide des tests → +← Cas d’usage · ↑ Table des matières · Guide des tests →
--- \ No newline at end of file diff --git a/doc/handwritten/for-users/CONTRIBUTING.fr.md b/doc/handwritten/for-users/CONTRIBUTING.fr.md index 815b62bc..694a778a 100644 --- a/doc/handwritten/for-users/CONTRIBUTING.fr.md +++ b/doc/handwritten/for-users/CONTRIBUTING.fr.md @@ -308,7 +308,9 @@ l’un des suivants : |---|---| | `core` | `FirstClassErrors` — la bibliothèque d’exécution (`Error`, `Outcome`, `ErrorCode`, `ErrorContextKey`, …) | | `analyzers` | `FirstClassErrors.Analyzers` — les analyzers Roslyn et leurs diagnostics `FCExxx` | +| `binder` | `FirstClassErrors.RequestBinder` — le request binder pour la frontière de l’adaptateur primaire | | `cli` | `FirstClassErrors.Cli` — l’outil en ligne de commande | +| `dummies` | `Dummies` — le générateur autonome de valeurs de test arbitraires | | `gendoc` | `FirstClassErrors.GenDoc` et son worker — le générateur de documentation | | `testing` | `FirstClassErrors.Testing` — le package de support aux tests | @@ -316,13 +318,22 @@ Cette liste vit ici, dans le dépôt, là où un outil peut la vérifier. Un sco être un nom de fichier ni un nom de classe : ceux-ci bougent ; la zone qu’ils habitent, non. `fix(core):`, jamais `fix(ErrorCode.cs):`. -Le scope est optionnel ici parce que les deux packages publiés (`FirstClassErrors` et -`FirstClassErrors.Testing`) partagent une seule version pilotée par tag : le scope ne porte -aucun poids de versioning, seulement de la lisibilité. Ce qui n’appartient pas à un -composant ne prend **aucun** scope — l’infrastructure du dépôt (la solution, -`Directory.Build.props`, les workflows, `.gitignore`, `CLAUDE.md`), la documentation à -l’échelle du dépôt, les ADR, et les exemples de `FirstClassErrors.Usage` : `ci: …`, -`docs: …`. +Le scope porte le dossier de release. L’outillage répartit les commits en **trains de +release** selon le scope — `tools/trains.sh` est la source de vérité unique — et chaque train +publie indépendamment : `lib` (scopes `core`, `analyzers`, `testing`, `binder` → +`FirstClassErrors`, `FirstClassErrors.Testing` et `FirstClassErrors.RequestBinder`), `cli` +(scopes `cli`, `gendoc` → l’outil `fce`) et `dum` (scope `dummies` → `Dummies`). Le scope +d’un commit décide dans les release notes et le changelog de quel train il atterrit ; voir +[Ajouter un train de release](../for-maintainers/AddingAReleaseTrain.fr.md). + +À cause de cela, un changement visible par l’utilisateur **doit** porter un scope : un `feat:` +ou `fix:` sans scope ne correspond à aucun train et est **silencieusement écarté de toutes les +release notes et de tous les changelogs**, de sorte que le changement disparaîtrait du dossier +de release. Seul ce qui n’appartient réellement à aucun composant reste sans scope — +l’infrastructure du dépôt (la solution, `Directory.Build.props`, les workflows, `.gitignore`, +`CLAUDE.md`), la documentation à l’échelle du dépôt, les ADR, et les exemples de +`FirstClassErrors.Usage` — et ceux-ci emploient de toute façon des types qui ne pilotent pas +la version : `ci: …`, `docs: …`, `chore: …`. Lorsqu’un changement atomique traverse plusieurs composants, le commit DOIT porter tous leurs scopes, séparés par des virgules sans espace et classés par ordre alphabétique. @@ -524,11 +535,11 @@ un ADR sous `doc/handwritten/for-maintainers/adr/`, ou une mise à jour de ce gu Il s’applique à partir de son adoption, à chaque commit créé après. L’historique antérieur n’est pas réécrit. -L’application repose aujourd’hui sur la relecture de pull request, qui refuse un message non -conforme et laisse l’auteur le corriger avant le merge. Le dépôt verrouillera la règle à son -tour : un hook `commit-msg` qui refuse le message à l’écriture, doublé d’une vérification CI, -puisqu’un hook local peut être contourné. Les commits de merge, générés par GitHub, en sont -exemptés. +L’application est en couches. Un hook `commit-msg` (versionné sous `.githooks/`, activé une +fois par clone) refuse un message non conforme à l’écriture, et — parce qu’un hook local peut +être contourné — une vérification CI rejoue la même validation sur chaque pull request, de +sorte qu’un hook contourné est tout de même rattrapé avant le merge. Les commits de merge, +générés par GitHub, en sont exemptés. ### Crédits diff --git a/doc/handwritten/for-users/CatalogVersioning.fr.md b/doc/handwritten/for-users/CatalogVersioning.fr.md index 1442673c..5fb41862 100644 --- a/doc/handwritten/for-users/CatalogVersioning.fr.md +++ b/doc/handwritten/for-users/CatalogVersioning.fr.md @@ -163,7 +163,7 @@ Un renommage reste cassant, car les consommateurs connaissent l'ancien code. Lor ---
-← CI/CD et intégration opérationnelle · ↑ Table des matières · Référence des commandes → +← CI/CD et intégration opérationnelle · ↑ Table des matières · Référence des commandes →
--- diff --git a/doc/handwritten/for-users/CatalogVersioningCI.fr.md b/doc/handwritten/for-users/CatalogVersioningCI.fr.md index d8d4c1ae..80b33018 100644 --- a/doc/handwritten/for-users/CatalogVersioningCI.fr.md +++ b/doc/handwritten/for-users/CatalogVersioningCI.fr.md @@ -214,7 +214,7 @@ Cette forme peut servir à produire des notes de version du contrat d'erreurs ou ---
-← Référence des commandes · ↑ Table des matières · Architecture du pipeline de documentation → +← Référence des commandes · ↑ Table des matières · Architecture du pipeline de documentation →
--- diff --git a/doc/handwritten/for-users/CatalogVersioningReference.fr.md b/doc/handwritten/for-users/CatalogVersioningReference.fr.md index 2d979485..1e8f4ea9 100644 --- a/doc/handwritten/for-users/CatalogVersioningReference.fr.md +++ b/doc/handwritten/for-users/CatalogVersioningReference.fr.md @@ -147,7 +147,7 @@ Les commandes `catalog update` et `catalog diff` acceptent notamment : ---
-← Guide du versionnage · ↑ Table des matières · Intégration CI/CD → +← Guide du versionnage · ↑ Table des matières · Intégration CI/CD →
--- \ No newline at end of file diff --git a/doc/handwritten/for-users/DeterministicTesting.en.md b/doc/handwritten/for-users/DeterministicTesting.en.md index e7f68a5a..e96d2c8e 100644 --- a/doc/handwritten/for-users/DeterministicTesting.en.md +++ b/doc/handwritten/for-users/DeterministicTesting.en.md @@ -160,7 +160,7 @@ public void A_missing_order_error_is_fully_deterministic() { ## Arbitrary occurrence data -When a test needs `OccurredAt` and `InstanceId` to be stable but does not assert their exact values, freeze them to an *arbitrary* value with `Clock.UseAny()` and `InstanceIds.UseAny()` rather than `UseFixed`; both take an optional seed for reproducibility. They belong to the broader `Any` factory for values a test does not assert on — see [Arbitrary Test Values](ArbitraryTestValues.en.md). +When a test needs `OccurredAt` and `InstanceId` to be stable but does not assert their exact values, freeze them to an *arbitrary* value with `Clock.UseAny()` and `InstanceIds.UseAny()` rather than `UseFixed`; both are parameterless, and a test that needs those arbitrary values to be reproducible wraps its body in `Dummies.Any.Reproducibly(...)`. They belong to the broader `Any` factory for values a test does not assert on — see [Arbitrary Test Values](ArbitraryTestValues.en.md). ## Scope and parallel tests diff --git a/doc/handwritten/for-users/DeterministicTesting.fr.md b/doc/handwritten/for-users/DeterministicTesting.fr.md index c43f78bf..6db8ad6d 100644 --- a/doc/handwritten/for-users/DeterministicTesting.fr.md +++ b/doc/handwritten/for-users/DeterministicTesting.fr.md @@ -160,7 +160,7 @@ public void Une_erreur_de_commande_absente_est_totalement_deterministe() { ## Données d’occurrence arbitraires -Lorsqu’un test a besoin que `OccurredAt` et `InstanceId` soient stables sans asserter leurs valeurs exactes, figez-les sur une valeur *arbitraire* avec `Clock.UseAny()` et `InstanceIds.UseAny()` plutôt que `UseFixed` ; les deux acceptent une graine optionnelle pour la reproductibilité. Ils appartiennent à la factory `Any`, plus large, dédiée aux valeurs qu’un test n’assertit pas — voir [Valeurs de test arbitraires](ArbitraryTestValues.fr.md). +Lorsqu’un test a besoin que `OccurredAt` et `InstanceId` soient stables sans asserter leurs valeurs exactes, figez-les sur une valeur *arbitraire* avec `Clock.UseAny()` et `InstanceIds.UseAny()` plutôt que `UseFixed` ; les deux sont sans paramètre, et un test qui a besoin que ces valeurs arbitraires soient reproductibles enveloppe son corps dans `Dummies.Any.Reproducibly(...)`. Ils appartiennent à la factory `Any`, plus large, dédiée aux valeurs qu’un test n’assertit pas — voir [Valeurs de test arbitraires](ArbitraryTestValues.fr.md). ## Portée et tests parallèles @@ -203,7 +203,7 @@ Avant d’approuver un test déterministe, vérifiez que : ---
-← Tester les outcomes et les erreurs · ↑ Table des matières · Valeurs de test arbitraires → +← Tester les outcomes et les erreurs · ↑ Table des matières · Valeurs de test arbitraires →
--- \ No newline at end of file diff --git a/doc/handwritten/for-users/DocumentationExtractionReference.fr.md b/doc/handwritten/for-users/DocumentationExtractionReference.fr.md index d7690882..cf3e2353 100644 --- a/doc/handwritten/for-users/DocumentationExtractionReference.fr.md +++ b/doc/handwritten/for-users/DocumentationExtractionReference.fr.md @@ -280,7 +280,7 @@ Lorsque des erreurs attendues manquent, parcourez le pipeline dans l’ordre — ---
-← Architecture du pipeline de documentation · ↑ Table des matières · Écrire son propre renderer → +← Architecture du pipeline de documentation · ↑ Table des matières · Écrire son propre renderer →
--- \ No newline at end of file diff --git a/doc/handwritten/for-users/ErrorContext.fr.md b/doc/handwritten/for-users/ErrorContext.fr.md index b4722490..67883276 100644 --- a/doc/handwritten/for-users/ErrorContext.fr.md +++ b/doc/handwritten/for-users/ErrorContext.fr.md @@ -173,7 +173,7 @@ Si la réponse est oui aux six questions, c’est une excellente candidate. ---
-← Concepts fondamentaux · ↑ Table des matières · Guide d’écriture des erreurs → +← Concepts fondamentaux · ↑ Table des matières · Guide d’écriture des erreurs →
--- \ No newline at end of file diff --git a/doc/handwritten/for-users/FAQ.fr.md b/doc/handwritten/for-users/FAQ.fr.md index 1c5000c6..94cd0b26 100644 --- a/doc/handwritten/for-users/FAQ.fr.md +++ b/doc/handwritten/for-users/FAQ.fr.md @@ -130,7 +130,7 @@ Voir [Taxonomie et composition des erreurs](ErrorTaxonomy.fr.md). ---
-← Internationalisation · ↑ Table des matières +← Internationalisation · ↑ Table des matières
--- diff --git a/doc/handwritten/for-users/Internationalisation.fr.md b/doc/handwritten/for-users/Internationalisation.fr.md index 3ec7e429..775e6e17 100644 --- a/doc/handwritten/for-users/Internationalisation.fr.md +++ b/doc/handwritten/for-users/Internationalisation.fr.md @@ -250,7 +250,7 @@ Avant de publier des catalogues localisés, vérifiez que : ---
-← Écrire son propre renderer · ↑ Table des matières · FAQ → +← Écrire son propre renderer · ↑ Table des matières · FAQ →
--- \ No newline at end of file diff --git a/doc/handwritten/for-users/LoggingIntegration.fr.md b/doc/handwritten/for-users/LoggingIntegration.fr.md index f9603397..89449aa9 100644 --- a/doc/handwritten/for-users/LoggingIntegration.fr.md +++ b/doc/handwritten/for-users/LoggingIntegration.fr.md @@ -265,7 +265,7 @@ Avant d’approuver une intégration de logging, vérifiez que : ---
-← Générer et publier le catalogue · ↑ Table des matières · Versionnage du catalogue → +← Générer et publier le catalogue · ↑ Table des matières · Versionnage du catalogue →
--- \ No newline at end of file diff --git a/doc/handwritten/for-users/OperationalIntegration.fr.md b/doc/handwritten/for-users/OperationalIntegration.fr.md index 9457dae8..8c0fe001 100644 --- a/doc/handwritten/for-users/OperationalIntegration.fr.md +++ b/doc/handwritten/for-users/OperationalIntegration.fr.md @@ -239,7 +239,7 @@ Avant d’approuver un pipeline de livraison du catalogue, vérifiez que : ---
-← Valeurs de test arbitraires · ↑ Table des matières · Intégrer FirstClassErrors au logging structuré → +← Valeurs de test arbitraires · ↑ Table des matières · Intégrer FirstClassErrors au logging structuré →
--- \ No newline at end of file diff --git a/doc/handwritten/for-users/OutcomeGuide.fr.md b/doc/handwritten/for-users/OutcomeGuide.fr.md index 4701452d..a358ccfd 100644 --- a/doc/handwritten/for-users/OutcomeGuide.fr.md +++ b/doc/handwritten/for-users/OutcomeGuide.fr.md @@ -293,7 +293,7 @@ Avant de valider un flux `Outcome`, vérifiez que : ---
-← Patterns d’utilisation · ↑ Table des matières · Bonnes pratiques → +← Patterns d’utilisation · ↑ Table des matières · Bonnes pratiques →
--- \ No newline at end of file diff --git a/doc/handwritten/for-users/Testing.fr.md b/doc/handwritten/for-users/Testing.fr.md index 5e7a0f53..8c66056c 100644 --- a/doc/handwritten/for-users/Testing.fr.md +++ b/doc/handwritten/for-users/Testing.fr.md @@ -166,7 +166,7 @@ Avant d’approuver un test d’erreur, vérifiez que : ---
-← Bonnes pratiques · ↑ Table des matières · Tests d’erreur déterministes → +← Bonnes pratiques · ↑ Table des matières · Tests d’erreur déterministes →
--- \ No newline at end of file diff --git a/doc/handwritten/for-users/UsagePatterns.fr.md b/doc/handwritten/for-users/UsagePatterns.fr.md index 7fe2133e..42e8f221 100644 --- a/doc/handwritten/for-users/UsagePatterns.fr.md +++ b/doc/handwritten/for-users/UsagePatterns.fr.md @@ -199,7 +199,7 @@ Choisissez le contrat à partir de la première liste, le type d’erreur à par ---
-← Guide d’écriture des erreurs · ↑ Table des matières · Composer avec Outcome → +← Guide d’écriture des erreurs · ↑ Table des matières · Composer avec Outcome →
--- \ No newline at end of file diff --git a/doc/handwritten/for-users/WhenNotToUseFirstClassErrors.fr.md b/doc/handwritten/for-users/WhenNotToUseFirstClassErrors.fr.md index fa2419cd..86182e6e 100644 --- a/doc/handwritten/for-users/WhenNotToUseFirstClassErrors.fr.md +++ b/doc/handwritten/for-users/WhenNotToUseFirstClassErrors.fr.md @@ -73,7 +73,7 @@ L’objectif de cette bibliothèque n’est pas de rendre toutes les exceptions ---
-← Principes de conception · ↑ Table des matières · Concepts clés → +← Principes de conception · ↑ Table des matières · Concepts clés →
--- \ No newline at end of file diff --git a/doc/handwritten/for-users/WritingACustomRenderer.fr.md b/doc/handwritten/for-users/WritingACustomRenderer.fr.md index bc40ecbb..3b008160 100644 --- a/doc/handwritten/for-users/WritingACustomRenderer.fr.md +++ b/doc/handwritten/for-users/WritingACustomRenderer.fr.md @@ -307,7 +307,7 @@ Avant de publier un renderer, vérifiez que : ---
-← Référence de l’extraction et de la découverte des projets · ↑ Table des matières · Internationalisation → +← Référence de l’extraction et de la découverte des projets · ↑ Table des matières · Internationalisation →
--- \ No newline at end of file diff --git a/doc/handwritten/for-users/WritingErrorMessages.fr.md b/doc/handwritten/for-users/WritingErrorMessages.fr.md index 063b75a4..95c482af 100644 --- a/doc/handwritten/for-users/WritingErrorMessages.fr.md +++ b/doc/handwritten/for-users/WritingErrorMessages.fr.md @@ -212,7 +212,7 @@ Pour le titre, la description, la règle, les diagnostics et les exemples stable ---
-← Écrire la documentation d’une erreur · ↑ Table des matières · Cas d’usage → +← Écrire la documentation d’une erreur · ↑ Table des matières · Cas d’usage →
--- \ No newline at end of file diff --git a/doc/handwritten/for-users/WritingErrorsGuide.fr.md b/doc/handwritten/for-users/WritingErrorsGuide.fr.md index 5821dbe7..4ccf675c 100644 --- a/doc/handwritten/for-users/WritingErrorsGuide.fr.md +++ b/doc/handwritten/for-users/WritingErrorsGuide.fr.md @@ -218,7 +218,7 @@ Pour choisir les textes publics et internes portés à l’exécution, continuez ---
-← Guide du contexte d’erreur · ↑ Table des matières · Écrire les messages d’une erreur → +← Guide du contexte d’erreur · ↑ Table des matières · Écrire les messages d’une erreur →
--- \ No newline at end of file