Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .claude/commands/tidy-history.md
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ If something is flagged, show me a plan as a table — for each commit:
keep / squash-into / reword-to / drop / reorder — plus the resulting
`git log --oneline`, every rewritten header conforming to CONTRIBUTING.md
(`<type>[(scope)][!]: <imperative, lowercase, no trailing period, ≤72 chars>`,
scope from `core, analyzers, binder, cli, dummies, gendoc, testing`). Then **ask
scope from `core, analyzers, binder, cli, justdummies, gendoc, testing`). Then **ask
me to approve.** Run no history-rewriting command before I say go.

## 4 — Rewrite (only after I approve, only while the branch is yours alone)
Expand Down
2 changes: 1 addition & 1 deletion .github/dependabot-autofix-prompt.md
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,7 @@ The header must match `<type>[(<scope>[,<scope>...])][!]: <lowercase description

- **type**: one of `feat, fix, build, chore, ci, docs, perf, refactor, revert,
style, test`. Dependabot uses `build` (NuGet) or `ci` (GitHub Actions).
- **scope** (optional): one of `core, analyzers, binder, cli, dummies, gendoc,
- **scope** (optional): one of `core, analyzers, binder, cli, justdummies, gendoc,
testing`. A dependency bump has no natural scope — **omit it**. `deps` is **not**
a valid scope here.
- **description**: imperative, lowercase first letter, no trailing period; whole
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/changelog.yml
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ name: Draft changelog
# before merging. The trains version independently and keep separate changelogs:
# lib -> CHANGELOG.md (FirstClassErrors + FirstClassErrors.Testing + FirstClassErrors.RequestBinder)
# cli -> FirstClassErrors.Cli/CHANGELOG.md (the fce .NET tool)
# dum -> Dummies/CHANGELOG.md (the standalone Dummies library)
# dum -> JustDummies/CHANGELOG.md (the standalone JustDummies library)
on:
workflow_dispatch:
inputs:
Expand Down
8 changes: 4 additions & 4 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -98,9 +98,9 @@ jobs:
# Only these library test projects carry the net472 leg (EnableNet472Floor adds it): the tooling test
# projects (Roslyn / GenDoc / Cli) stay net10-only by design, and RequestBinder.UnitTests stays net10-only
# because its fixtures bind DateOnly, a .NET 6+ type absent from net472. RequestBinder is still floored here
# through its property tests, and Dummies through its own contract suite (Dummies.UnitTests), running on the
# through its property tests, and JustDummies through its own contract suite (JustDummies.UnitTests), running on the
# netstandard2.0 asset .NET Framework consumers load — its net8-only tests are conditioned out (issue #215).
# Dummies.Xunit is floored the same way: it ships netstandard2.0, so a .NET Framework consumer loads that
# JustDummies.Xunit is floored the same way: it ships netstandard2.0, so a .NET Framework consumer loads that
# asset, and its adapter suite must prove it works there and not only on net10.
# A per-project loop (not a solution-wide -f net472, which would force the TFM onto the net10-only projects
# and fail) keeps the net472 scope exactly these five.
Expand All @@ -112,8 +112,8 @@ jobs:
FirstClassErrors.UnitTests \
FirstClassErrors.PropertyTests \
FirstClassErrors.RequestBinder.PropertyTests \
Dummies.UnitTests \
Dummies.Xunit.UnitTests ; do
JustDummies.UnitTests \
JustDummies.Xunit.UnitTests ; do
echo "::group::$proj (net472)"
dotnet test "$proj/$proj.csproj" -c Release -f net472 -p:EnableNet472Floor=true \
--logger "console;verbosity=normal"
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/dependabot-autofix.yml
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ on:
- sonar
- analyzers
- commit-lint
- dummies
- justdummies
- dependency-review
- codeql
types:
Expand Down
34 changes: 17 additions & 17 deletions .github/workflows/dummies.yml → .github/workflows/justdummies.yml
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
name: dummies
name: justdummies

on:
push:
Expand All @@ -11,7 +11,7 @@ on:

# Cancel superseded runs on the same branch / PR.
concurrency:
group: dummies-${{ github.workflow }}-${{ github.ref }}
group: justdummies-${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true

# Least privilege: this workflow only checks out, packs and runs, so the token
Expand All @@ -25,24 +25,24 @@ env:
DOTNET_SKIP_FIRST_TIME_EXPERIENCE: 'true'

jobs:
# The ci workflow builds Dummies for both TFMs and runs Dummies.UnitTests on net10.0 — which resolves the
# The ci workflow builds JustDummies for both TFMs and runs JustDummies.UnitTests on net10.0 — which resolves the
# NEAREST compatible asset (net8.0). So the netstandard2.0 asset that ships in the package is compiled but
# never EXECUTED by a test. This job closes that gap: it packs the real .nupkg and consumes it from an
# isolated project (tools/dummies-check) once per consumer TFM, each forcing a different packaged asset,
# isolated project (tools/justdummies-check) once per consumer TFM, each forcing a different packaged asset,
# then proves by reflection which asset loaded and exercises the common smoke surface on it.
packaged-assets:
name: Dummies packaged-asset compatibility
name: JustDummies packaged-asset compatibility
runs-on: ubuntu-latest
# Pack (~10s) plus two short consumer runs; cap a hung run like the other workflows.
timeout-minutes: 15
env:
# Single source of truth for the throwaway package version, passed to the pack (-p:Version) and BOTH
# consume (-p:DummiesCheckVersion) steps. The run-number.attempt suffix makes every run produce a version
# consume (-p:JustDummiesCheckVersion) steps. The run-number.attempt suffix makes every run produce a version
# NuGet has never cached, so the consume steps always restore the freshly packed .nupkg instead of a
# stale copy; run_attempt (which changes on a re-run) closes the door should a ~/.nuget cache ever be
# added. DummiesCheck.csproj pins this EXACT version, and nuget.config maps the id to the local feed only,
# so it can never resolve a future stable Dummies from nuget.org.
DUMMIESCHECK_VERSION: 1.0.0-dummiescheck.${{ github.run_number }}.${{ github.run_attempt }}
# added. JustDummiesCheck.csproj pins this EXACT version, and nuget.config maps the id to the local feed only,
# so it can never resolve a future stable JustDummies from nuget.org.
JUSTDUMMIESCHECK_VERSION: 1.0.0-justdummiescheck.${{ github.run_number }}.${{ github.run_attempt }}
steps:
- name: Checkout
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7
Expand All @@ -59,23 +59,23 @@ jobs:
8.0.x
10.0.x

- name: Pack Dummies under the release SDK
- name: Pack JustDummies under the release SDK
# Pack from the repo root so the root global.json selects the .NET 10 SDK — the one release.yml packs
# with — producing the exact multi-asset artifact a consumer restores (lib/netstandard2.0 + lib/net8.0).
# GenerateSBOM is off here: the SBOM is a release-pipeline concern (release.yml), and this job only needs
# the lib/ assets. The feed and the project-local package cache are wiped first so the consume steps can
# only see this run's package — a no-op on a fresh runner, but it keeps a reused workspace idempotent.
run: |
rm -rf tools/dummies-check/local-feed tools/dummies-check/packages
dotnet pack Dummies/Dummies.csproj -c Release -p:Version="$DUMMIESCHECK_VERSION" -p:GenerateSBOM=false -o tools/dummies-check/local-feed
rm -rf tools/justdummies-check/local-feed tools/justdummies-check/packages
dotnet pack JustDummies/JustDummies.csproj -c Release -p:Version="$JUSTDUMMIESCHECK_VERSION" -p:GenerateSBOM=false -o tools/justdummies-check/local-feed

- name: Validate the net8.0 asset (net8.0 consumer)
# A net8.0 consumer resolves lib/net8.0: the modern generators (DateOnly/Int128/Half/...) must be
# PRESENT. The program self-checks and exits non-zero on any mismatch; the greps are positive proof that
# it ran AND loaded the intended asset (a program that silently no-oped would exit 0 with no banner).
working-directory: tools/dummies-check
working-directory: tools/justdummies-check
run: |
dotnet run -c Release --framework net8.0 -p:DummiesCheckVersion="$DUMMIESCHECK_VERSION" > net8.log 2>&1 || { cat net8.log; exit 1; }
dotnet run -c Release --framework net8.0 -p:JustDummiesCheckVersion="$JUSTDUMMIESCHECK_VERSION" > net8.log 2>&1 || { cat net8.log; exit 1; }
cat net8.log
grep -q 'ASSET=.NETCoreApp,Version=v8.0' net8.log
grep -q 'RESULT=PASS' net8.log
Expand All @@ -84,9 +84,9 @@ jobs:
# A net6.0 consumer resolves lib/netstandard2.0: the modern generators must be ABSENT, while the common
# surface (scalars, constraints, composition, collections, seeded reproducibility) still works. This is
# the leg the net10.0 test project can never exercise — the whole reason this workflow exists.
working-directory: tools/dummies-check
working-directory: tools/justdummies-check
run: |
dotnet run -c Release --framework net6.0 -p:DummiesCheckVersion="$DUMMIESCHECK_VERSION" > netstandard.log 2>&1 || { cat netstandard.log; exit 1; }
dotnet run -c Release --framework net6.0 -p:JustDummiesCheckVersion="$JUSTDUMMIESCHECK_VERSION" > netstandard.log 2>&1 || { cat netstandard.log; exit 1; }
cat netstandard.log
grep -q 'ASSET=.NETStandard,Version=v2.0' netstandard.log
grep -q 'RESULT=PASS' netstandard.log
Expand All @@ -97,7 +97,7 @@ jobs:
# seeded sequence — new Random(seed) keeps the legacy algorithm on modern .NET so they SHOULD agree, but
# nothing else asserts it and Random reserves the right to differ across framework versions (issue #215).
# Compare byte-for-byte; the empty-guard fails closed so a missing/renamed banner can never pass silently.
working-directory: tools/dummies-check
working-directory: tools/justdummies-check
run: |
set -euo pipefail
net8_seq="$(sed -n 's/^SEEDBATCH=//p' net8.log)"
Expand Down
4 changes: 2 additions & 2 deletions .github/workflows/release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ on:
# Publish on a train-prefixed semantic-version tag. The trains version independently:
# lib-v1.2.3 -> FirstClassErrors + FirstClassErrors.Testing + FirstClassErrors.RequestBinder
# cli-v1.2.3 -> FirstClassErrors.Cli (the fce .NET tool)
# dum-v1.2.3 -> Dummies (the standalone arbitrary-test-value library)
# dum-v1.2.3 -> JustDummies (the standalone arbitrary-test-value library)
tags:
- 'lib-v*.*.*'
- 'cli-v*.*.*'
Expand Down Expand Up @@ -190,7 +190,7 @@ jobs:
echo "ok: GenDoc's error catalog has a breaking change since $PREVIOUS_TAG, matched by the major version bump ($PREVIOUS_MAJOR -> $NEW_MAJOR)."

# Pack only the train this release targets (lib -> FirstClassErrors + .Testing + .RequestBinder;
# cli -> the fce tool; dum -> Dummies), so a lib release never republishes the CLI and vice versa.
# cli -> the fce tool; dum -> JustDummies), so a lib release never republishes the CLI and vice versa.
# The analyzer is bundled inside the main package and the GenDoc worker inside the CLI tool; the
# samples are not published.
# GenerateSBOM activates Microsoft.Sbom.Targets in each packable project: each package embeds its SPDX
Expand Down
10 changes: 5 additions & 5 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -293,9 +293,9 @@ __pycache__/
tools/floor-check/local-feed/
tools/floor-check/packages/
tools/floor-check/build.log
# Dummies packaged-asset compatibility check (tools/dummies-check): CI-generated artifacts, never committed.
# local-feed holds the packed .nupkg the dummies job produces; packages/ is the project-local NuGet
# JustDummies packaged-asset compatibility check (tools/justdummies-check): CI-generated artifacts, never committed.
# local-feed holds the packed .nupkg the justdummies job produces; packages/ is the project-local NuGet
# extraction folder (RestorePackagesPath); *.log are the job's per-asset run outputs.
tools/dummies-check/local-feed/
tools/dummies-check/packages/
tools/dummies-check/*.log
tools/justdummies-check/local-feed/
tools/justdummies-check/packages/
tools/justdummies-check/*.log
2 changes: 1 addition & 1 deletion CLAUDE.md
Original file line number Diff line number Diff line change
Expand Up @@ -94,7 +94,7 @@ The essentials, inlined so they hold even if `AGENTS.md` is not read:
* Follow `.github/pull_request_template.md` for every pull request.
* Do not open a pull request unless I explicitly ask for one.
* PR titles, descriptions, commits, and branch names must be written in English.
* Write every commit message per [`CONTRIBUTING.md`](CONTRIBUTING.md): Conventional Commits, a closed type list, the scopes `core, analyzers, binder, cli, dummies, gendoc, testing`, an imperative header within 72 characters, and `Refs: #NN` in a footer when a GitHub issue exists (issue-closing keywords belong in the PR description, not the commit).
* Write every commit message per [`CONTRIBUTING.md`](CONTRIBUTING.md): Conventional Commits, a closed type list, the scopes `core, analyzers, binder, cli, justdummies, gendoc, testing`, an imperative header within 72 characters, and `Refs: #NN` in a footer when a GitHub issue exists (issue-closing keywords belong in the PR description, not the commit).
* Write every pull request title per [`CONTRIBUTING.md`](CONTRIBUTING.md): name the whole change in English; a single-intention PR mirrors its commit header (`type(scope): description`), a multi-intention PR uses a short descriptive title, and issue references stay in the description, not the title.
* Enable the local commit-message hook once per clone with `git config core.hooksPath .githooks`; the same check runs in CI on every pull request.
* Before opening a pull request — and after pushing more commits to an open one — read the branch against a fresh `origin/main` and, if the history is messy (pending `fixup!`/`squash!`, wip/typo/"address review" commits, headers the lint rejects, one change split across non-standalone commits or two folded into one), **propose** a cleanup and rewrite only after I approve — while the branch is yours alone, with `git push --force-with-lease`, leaving the diff against `origin/main` unchanged. This repository merges with a merge commit, so a messy branch reaches `main`. Full rule in [`AGENTS.md`](AGENTS.md) ("Tidying history before a pull request"); the `/tidy-history` command runs it.
Expand Down
10 changes: 5 additions & 5 deletions CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ guidelines.
## Public API baseline

The shipping libraries — `FirstClassErrors`, `FirstClassErrors.Testing`,
`FirstClassErrors.RequestBinder` (the `lib` train) and `Dummies` (the `dum`
`FirstClassErrors.RequestBinder` (the `lib` train) and `JustDummies` (the `dum`
train) — carry a committed public-API baseline, so every change to their public
surface is a reviewed diff and an accidental breaking change (a removed overload,
a narrowed return type, a renamed member) cannot ship silently under a version
Expand All @@ -35,7 +35,7 @@ number that promises compatibility. Two guards, wired once in
surface change fails the build until the same change updates the baseline.
* **Package validation** (`EnablePackageValidation`) runs ApiCompat during
`dotnet pack`. With no baseline version set it performs the same-package
cross-target-framework check (it proves `Dummies`' net8.0 surface never drops
cross-target-framework check (it proves `JustDummies`' net8.0 surface never drops
API a netstandard2.0 consumer sees). To additionally gate against a published
version, set `PackageValidationBaselineVersion`; `0.1.0-preview.1` is the first
such baseline available for the `lib` train.
Expand All @@ -47,7 +47,7 @@ number that promises compatibility. Two guards, wired once in
* **From the CLI**: `dotnet format analyzers <project> --diagnostics RS0016`
appends the new entries to `PublicAPI.Unshipped.txt`; for a **removal**, delete
the matching line by hand.
* **Multi-target (`Dummies`)**: each framework has its own baseline under
* **Multi-target (`JustDummies`)**: each framework has its own baseline under
`PublicAPI/<tfm>/`, and `dotnet format` rewrites only one framework's file per
run — update `net8.0` and `netstandard2.0` separately when a change touches both.
* **At release**: promote the accumulated `PublicAPI.Unshipped.txt` entries into
Expand Down Expand Up @@ -299,7 +299,7 @@ When present it MUST be lowercase and MUST be one of:
| `analyzers` | `FirstClassErrors.Analyzers` — the Roslyn analyzers and their `FCExxx` diagnostics |
| `binder` | `FirstClassErrors.RequestBinder` — the request binder for the primary-adapter boundary |
| `cli` | `FirstClassErrors.Cli` — the command-line tool |
| `dummies` | `Dummies` — the standalone arbitrary-test-value generator |
| `justdummies` | `JustDummies` — the standalone arbitrary-test-value generator |
| `gendoc` | `FirstClassErrors.GenDoc` and its worker — the documentation generator |
| `testing` | `FirstClassErrors.Testing` — the test-support package |

Expand All @@ -312,7 +312,7 @@ 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
and `dum` (scope `justdummies` → `JustDummies`). 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).

Expand Down

This file was deleted.

Loading