From 377cdb030b6146a1ad49b5fe10af8d58cdcfde13 Mon Sep 17 00:00:00 2001 From: Claude Date: Fri, 31 Jul 2026 12:17:28 +0000 Subject: [PATCH] docs: record consuming JustDummies from its own repository JustDummies was extracted into Reefact/just-dummies with git filter-repo at fbf523b, preserving authors, dates, messages and the Dummies -> JustDummies rename. Nothing was removed from this repository by that extraction. ADR-0069 supersedes the colocation half of ADR-0011 and the embedding workaround ADR-0026 accepted "until JustDummies is published". It records why the cutover is gated on the first publication rather than done now -- four projects reference JustDummies and FirstClassErrors.Testing ships it, so a PackageReference to a version nobody can restore would break every build -- and it writes the cutover down step by step, in the order that keeps the build green. ADR-0011, ADR-0026, ADR-0061 and ADR-0006 stay: they record decisions this repository made, and FirstClassErrors.Testing's current shape is unreadable without them. Refs: #229 Co-Authored-By: Claude Opus 5 Claude-Session: https://claude.ai/code/session_01DYg7aYn9owaSTCShxHfdcw --- ...-justdummies-from-its-own-repository.fr.md | 127 ++++++++++++++++++ ...ume-justdummies-from-its-own-repository.md | 122 +++++++++++++++++ doc/handwritten/for-maintainers/adr/README.md | 2 + 3 files changed, 251 insertions(+) create mode 100644 doc/handwritten/for-maintainers/adr/0069-consume-justdummies-from-its-own-repository.fr.md create mode 100644 doc/handwritten/for-maintainers/adr/0069-consume-justdummies-from-its-own-repository.md diff --git a/doc/handwritten/for-maintainers/adr/0069-consume-justdummies-from-its-own-repository.fr.md b/doc/handwritten/for-maintainers/adr/0069-consume-justdummies-from-its-own-repository.fr.md new file mode 100644 index 00000000..43a5d98d --- /dev/null +++ b/doc/handwritten/for-maintainers/adr/0069-consume-justdummies-from-its-own-repository.fr.md @@ -0,0 +1,127 @@ +# ADR-0069 | Consommer JustDummies depuis son propre dépôt + +🌍 🇫🇷 Français (ce fichier) · 🇬🇧 [English](0069-consume-justdummies-from-its-own-repository.md) + +**Statut :** Proposé +**Proposé :** 2026-07-31 +**Décideurs :** Reefact +**Supersède :** [ADR-0011](0011-host-dummies-as-a-standalone-package.fr.md) (son volet colocation), ainsi que +le contournement d'embarquement accepté par [ADR-0026](0026-rebase-testing-arbitrary-values-on-dummies.fr.md) + +## Contexte + +L'[ADR-0011](0011-host-dummies-as-a-standalone-package.fr.md) décidait que JustDummies est un package +indépendant qui ne doit jamais référencer un projet FirstClassErrors, **et** qu'il vit dans ce dépôt, pour +réutiliser son infrastructure CI, packaging, release, SBOM, SourceLink et gouvernance. Il actait que la règle +de non-référence existe pour qu'« une extraction ultérieure reste mécanique plutôt qu'architecturale », et il +écartait un dépôt séparé immédiat pour des raisons de coût, non de principe. + +Cette extraction a eu lieu. Le produit — la bibliothèque, ses 28 analyseurs, son adaptateur xUnit v3, ses deux +suites de tests, sa documentation, ses ADR et son scaffolder `dum` spécifié — a été filtré hors de +l'historique de ce dépôt vers **`Reefact/just-dummies`** au +`fbf523b86acebdd34ba0bbfd437683864be3cb9c`, en préservant auteurs, dates, messages et le renommage de +`Dummies` en `JustDummies`. Rien n'a été supprimé ici. + +Ce dépôt dépend encore de JustDummies en quatre points, et l'un d'eux le **livre** : + +| Projet | Nature de la dépendance | +| --- | --- | +| `FirstClassErrors.Testing` | `ProjectReference` privé **plus** une cible de pack qui embarque `JustDummies.dll` dans son propre `lib/` | +| `FirstClassErrors.UnitTests` | `ProjectReference`, tests uniquement | +| `FirstClassErrors.RequestBinder.UnitTests` | `ProjectReference`, tests uniquement | +| `FirstClassErrors.Testing.UnitTests` | `ProjectReference`, tests uniquement | + +Tous les projets du dépôt chargent en outre les analyseurs JustDummies au build (ADR-0061). + +L'[ADR-0026](0026-rebase-testing-arbitrary-values-on-dummies.fr.md) acceptait l'embarquement comme +explicitement temporaire : JustDummies « n'est pas encore sur NuGet (ADR-0011), donc le référencer en privé et +embarquer son assembly dans ce package […] ; basculer vers un `PackageReference` NuGet une fois JustDummies +publié ». + +**JustDummies n'a jamais été publié.** Aucun tag `dum-v*` n'a jamais été poussé depuis ce dépôt, et +`Reefact/just-dummies` n'a pas publié non plus — sa politique de *trusted publishing* nuget.org n'existe pas +encore. + +## Décision + +Ce dépôt devient **consommateur** des packages `JustDummies` et de ses analyseurs publiés depuis +`Reefact/just-dummies`, et cesse d'en être la source. + +La bascule est **conditionnée à la première publication** et n'est délibérément pas exécutée par +l'extraction. Tant qu'aucun package `JustDummies` restaurable n'existe sur nuget.org, la source reste ici +telle quelle : remplacer un `ProjectReference` par un `PackageReference` vers une version que personne ne peut +restaurer casserait le build pour chaque contributeur et chaque exécution CI, sans bénéfice. + +Lorsque cette version existera, en une seule pull request : + +1. ajouter `` à `Directory.Packages.props` ; +2. remplacer les quatre `ProjectReference` vers `JustDummies` par des `PackageReference` ; +3. remplacer les `ProjectReference` vers les analyseurs — ils sont livrés dans le package de la bibliothèque + sous `analyzers/dotnet/cs`, donc un simple `PackageReference` les délivre et la plomberie + `OutputItemType="Analyzer"` disparaît ; +4. supprimer la cible `IncludeJustDummiesInPackage` et son accroche `TargetsForTfmSpecificBuildOutput` de + `FirstClassErrors.Testing.csproj`, et retirer `PrivateAssets="all"` pour que le package déclare une + dépendance `JustDummies` honnête ; +5. retirer les sept projets `JustDummies.*` de `FirstClassErrors.sln`, le train `dum` de `tools/trains.sh`, + `pack.sh` et `release.yml`, le scope `justdummies` de `tools/commit-lint/lint-commit-message.sh`, les + trois configurations `build/stryker/justdummies*.json`, et les workflows + `.github/workflows/justdummies.yml` et `justdummies-mutation.yml` ; +6. supprimer les répertoires source et `tools/justdummies-check/` en dernier, une fois que plus rien ne les + référence ; +7. exécuter le build et la suite de tests complets. + +L'ordre compte : supprimer les répertoires en premier transforme chaque autre étape en séance de débogage de +build cassé. + +## Conséquences + +### `FirstClassErrors.Testing` acquiert une vraie dépendance + +Aujourd'hui le package embarque silencieusement une copie de `JustDummies.dll` sans entrée `` : +un consommateur qui référence aussi `JustDummies` directement peut se retrouver avec deux copies à des +versions différentes, sans aucun diagnostic. Après la bascule, le package déclare sa dépendance, NuGet résout +un seul assembly, et la version devient visible et relisible. C'est l'objet du changement, pas un effet de +bord. + +### La documentation qui reste change de sujet, pas de propriétaire + +Les ADR-0011, ADR-0026 et ADR-0061 ne sont **pas** supprimés, ni l'ADR-0006. Ils actent des décisions que ce +dépôt a réellement prises, et la forme actuelle de `FirstClassErrors.Testing` est illisible sans eux. Les +ADR-0011 et ADR-0022 existent aussi dans `Reefact/just-dummies`, car ils lient les deux produits. + +`doc/handwritten/for-users/ArbitraryTestValues.{en,fr}.md` documente le package de test de ce dépôt et +mentionne JustDummies comme son moteur ; il reste, et gagne un lien vers le nouveau dépôt. + +### Les références d'issues ne fonctionnent que dans un sens + +Les messages de commit de `Reefact/just-dummies` antérieurs au 2026-07-31 citent des numéros d'issues et de +pull requests de **ce** dépôt. Rien là-bas ne peut être renuméroté : ces références se résolvent ici et +doivent continuer de se résoudre. Les issues de ce dépôt ne doivent donc pas être supprimées, seulement +fermées. + +### Jusqu'à la publication, les deux dépôts portent la source + +Cette duplication est réelle et constitue le prix de ne pas livrer un build cassé. Elle prend fin à la +première release de `JustDummies`. Le risque de divergence entre-temps est faible — ce dépôt doit traiter sa +copie comme gelée et faire atterrir les changements JustDummies dans `Reefact/just-dummies` — mais il n'est +pas nul, et c'est la raison pour laquelle la bascule ne doit pas trop attendre. + +## Alternatives considérées + +### Faire la bascule maintenant, contre une version non publiée + +Rejetée : `dotnet restore` échouerait en NU1102 pour chaque contributeur et chaque exécution CI tant qu'aucun +package n'existe. Un dépôt qui ne construit pas est pire qu'un dépôt qui porte un doublon temporaire. + +### Continuer de consommer JustDummies via un sous-module Git, ou par URL Git + +Rejetée. Les deux réintroduisent le couplage que l'extraction a supprimé, sous une forme plus difficile à +raisonner que le `ProjectReference` actuel : un sous-module épingle un commit et non une version, et ni l'un +ni l'autre n'est exprimable dans le graphe de dépendances du package publié — `FirstClassErrors.Testing` +devrait donc toujours embarquer l'assembly qu'il ne peut pas déclarer. + +### Publier JustDummies depuis ce dépôt une dernière fois, puis basculer + +Considérée parce qu'elle débloquerait la bascule immédiatement. Rejetée parce que la première version publiée +d'un package fixe l'endroit d'où il est publié : la politique de *trusted publishing*, l'URL de dépôt dans ses +métadonnées et les commits SourceLink pointeraient tous ici, et la release suivante devrait les contredire. diff --git a/doc/handwritten/for-maintainers/adr/0069-consume-justdummies-from-its-own-repository.md b/doc/handwritten/for-maintainers/adr/0069-consume-justdummies-from-its-own-repository.md new file mode 100644 index 00000000..7bf39676 --- /dev/null +++ b/doc/handwritten/for-maintainers/adr/0069-consume-justdummies-from-its-own-repository.md @@ -0,0 +1,122 @@ +# ADR-0069 | Consume JustDummies from its own repository + +🌍 🇬🇧 English (this file) · 🇫🇷 [Français](0069-consume-justdummies-from-its-own-repository.fr.md) + +**Status:** Proposed +**Proposed:** 2026-07-31 +**Decision Makers:** Reefact +**Supersedes:** [ADR-0011](0011-host-dummies-as-a-standalone-package.md) (its colocation half), and the +embedding workaround accepted by [ADR-0026](0026-rebase-testing-arbitrary-values-on-dummies.md) + +## Context + +[ADR-0011](0011-host-dummies-as-a-standalone-package.md) decided that JustDummies is an independent package +that must never reference a FirstClassErrors project, **and** that it lives in this repository, to reuse this +repository's CI, packaging, release, SBOM, SourceLink and governance infrastructure. It recorded that the +no-reference rule exists so that "a later repository extraction [stays] mechanical rather than architectural", +and it rejected an immediate separate repository on cost grounds rather than on principle. + +That extraction has now happened. The product — the library, its 28 analyzers, its xUnit v3 adapter, its two +test suites, its documentation, its ADRs and its specified `dum` scaffolder — was filtered out of this +repository's history into **`Reefact/just-dummies`** at +`fbf523b86acebdd34ba0bbfd437683864be3cb9c`, preserving authors, dates, messages and the rename from `Dummies` +to `JustDummies`. Nothing was deleted here. + +This repository still depends on JustDummies in four places, and one of them ships it: + +| Project | How it depends | +| --- | --- | +| `FirstClassErrors.Testing` | private `ProjectReference` **plus** a pack target that embeds `JustDummies.dll` inside its own `lib/` | +| `FirstClassErrors.UnitTests` | `ProjectReference`, test-only | +| `FirstClassErrors.RequestBinder.UnitTests` | `ProjectReference`, test-only | +| `FirstClassErrors.Testing.UnitTests` | `ProjectReference`, test-only | + +Every project in the repository also loads the JustDummies analyzers at build time (ADR-0061). + +[ADR-0026](0026-rebase-testing-arbitrary-values-on-dummies.md) accepted the embedding as explicitly temporary: +JustDummies "is not yet on NuGet (ADR-0011), so reference it privately and embed its assembly in this +package […]; switch to a NuGet PackageReference once JustDummies is published." + +**JustDummies has never been published.** No `dum-v*` tag was ever pushed from this repository, and +`Reefact/just-dummies` has not released either — its nuget.org trusted-publishing policy does not exist yet. + +## Decision + +This repository becomes a **consumer** of the `JustDummies` and `JustDummies.Analyzers` packages published +from `Reefact/just-dummies`, and stops being their source. + +The cutover is **gated on the first publication** and is deliberately not performed by the extraction. Until a +restorable `JustDummies` package exists on nuget.org, the source stays here exactly as it is: replacing a +`ProjectReference` with a `PackageReference` to a version nobody can restore would break the build for every +contributor and every CI run, to no benefit. + +When that version exists, in one pull request: + +1. add `` to `Directory.Packages.props`; +2. replace the four `ProjectReference`s on `JustDummies` with `PackageReference`s; +3. replace the analyzer `ProjectReference`s — the analyzers ship inside the library package under + `analyzers/dotnet/cs`, so a plain `PackageReference` delivers them and the `OutputItemType="Analyzer"` + plumbing goes away; +4. delete the `IncludeJustDummiesInPackage` target and its `TargetsForTfmSpecificBuildOutput` hook from + `FirstClassErrors.Testing.csproj`, and drop `PrivateAssets="all"` so the package declares an honest + `JustDummies` dependency; +5. remove the seven `JustDummies.*` projects from `FirstClassErrors.sln`, the `dum` train from + `tools/trains.sh`, `pack.sh` and `release.yml`, the `justdummies` scope from + `tools/commit-lint/lint-commit-message.sh`, the three `build/stryker/justdummies*.json` configurations, + and `.github/workflows/justdummies.yml` and `justdummies-mutation.yml`; +6. delete the source directories and `tools/justdummies-check/` last, once nothing references them; +7. run the full build and test suite. + +The order matters: deleting the directories first turns every other step into a broken-build debugging +session. + +## Consequences + +### `FirstClassErrors.Testing` gains a real dependency + +Today the package silently carries a copy of `JustDummies.dll` with no `` entry, so a consumer +who also references `JustDummies` directly can end up with two copies at different versions and no diagnostic. +After the cutover the package declares its dependency, NuGet resolves one assembly, and the version becomes +visible and reviewable. This is the point of the change, not a side effect. + +### The documentation that stays here changes subject, not owner + +ADR-0011, ADR-0026 and ADR-0061 are **not** deleted, and neither is ADR-0006. They record decisions this +repository genuinely made, and the reasoning behind `FirstClassErrors.Testing`'s current shape is unreadable +without them. ADR-0011 and ADR-0022 also exist in `Reefact/just-dummies`, because they bind both products. + +`doc/handwritten/for-users/ArbitraryTestValues.{en,fr}.md` documents this repository's testing package and +mentions JustDummies as its engine; it stays, and gains a link to the new repository. + +### Issue references keep working in one direction only + +Commit messages in `Reefact/just-dummies` older than 2026-07-31 cite issue and pull-request numbers of **this** +repository. Nothing there can be renumbered, so those references resolve here and must keep resolving: +this repository's issues must not be deleted, only closed. + +### Until publication, both repositories carry the source + +That duplication is real and is the cost of not shipping a broken build. It ends with the first +`JustDummies` release. Divergence risk in the interim is low — this repository should treat its copy as +frozen and land JustDummies changes in `Reefact/just-dummies` — but it is not zero, and it is the reason the +cutover should not wait long. + +## Alternatives Considered + +### Do the cutover now, against an unpublished version + +Rejected: `dotnet restore` would fail with NU1102 for every contributor and every CI run until a package +exists. A repository that cannot build is worse than one that carries a temporary duplicate. + +### Keep consuming JustDummies as a Git submodule, or by Git URL + +Rejected. Both reintroduce the coupling the extraction removed, in a form that is harder to reason about than +the current `ProjectReference`: a submodule pins a commit rather than a version, and neither is expressible in +the published package's dependency graph — so `FirstClassErrors.Testing` would still have to embed the +assembly it cannot declare. + +### Publish JustDummies from this repository one last time, then cut over + +Considered because it would unblock the cutover immediately. Rejected because the first published version of a +package fixes where it is released from: the trusted-publishing policy, the repository URL in its metadata and +the SourceLink commits would all point here, and the very next release would have to contradict them. diff --git a/doc/handwritten/for-maintainers/adr/README.md b/doc/handwritten/for-maintainers/adr/README.md index a91e6e39..fab497c7 100644 --- a/doc/handwritten/for-maintainers/adr/README.md +++ b/doc/handwritten/for-maintainers/adr/README.md @@ -269,3 +269,5 @@ Optional supporting material: | [ADR-0065](0065-carry-a-declared-constraint-as-a-value-object.md) | Carry a declared constraint as a value object, not as its rendered text | Accepted | | [ADR-0066](0066-declare-a-value-object-and-enforce-its-identity.md) | Declare a value object with an attribute, and enforce its identity by convention | Accepted | | [ADR-0067](0067-treat-the-cli-s-exit-codes-as-a-closed-published-contract.md) | Treat the CLI's exit codes as a closed, published contract | Accepted | +| [ADR-0068](https://github.com/Reefact/just-dummies/blob/main/doc/handwritten/for-maintainers/adr/0068-extract-justdummies-into-its-own-repository.md) | Extract JustDummies into its own repository *(recorded in `Reefact/just-dummies`)* | Proposed | +| [ADR-0069](0069-consume-justdummies-from-its-own-repository.md) | Consume JustDummies from its own repository | Proposed |