Guidance for AI coding tools (Claude Code, GitHub Copilot, Cursor, Aider, Codex, etc.) working in this repo.
This is the canonical brief. GitHub Copilot reads this AGENTS.md natively; the CLAUDE.md tool-specific file points here.
Fallout — a build automation system for C#/.NET, hard-fork successor to NUKE. The build is itself a C# console app (build/_build.csproj), so any change to the framework can be dogfooded by running ./build.ps1 (Windows) or ./build.sh.
Originally NUKE by matkoch; under new maintenance as of 2026 and being renamed to Fallout. The codebase is mature, large, and has long-standing conventions — prefer matching existing patterns over introducing new ones.
Rebrand status: the structural rename has landed — namespaces (Fallout.*), package IDs, project filenames, and the global tool name (dotnet fallout) are all in place. Legacy Nuke.* lives on only as the consumer transition shims under src/Shims/. See docs/rebrand-plan.md for the locked namespace mapping.
Versioning & channels (calendar versioning, two-tier ladder — ADR-0004, channel ladder superseded by ADR-0008). The project ships on calendar versions YYYY.MINOR.PATCH (mechanically valid semver; major = year). A maturity ladder feeds the production line — GitHub Packages = test/preview; nuget.org = production:
main= the integration trunk + sole-previewchannel — default branch; both deliberate improvements/bug fixes and faster AI-assisted work land here. Per-commit-previewprereleases (2026.1.0-preview.<height>.g<commit>) to GitHub Packages only — never nuget.org. Ordinary review. (The dedicatedexperimental-alphalane was removed by ADR-0008 — it ran behindmainand carried no unique work.)release/YYYY= the production line — cut frommainon demand at the first release of the year, not preemptively (ADR-0007); until thenmain(-preview) is the most-stable line. Hardened deliberately,-rc.N→ GA, non-breaking minors/patches only after the cut, rigorous review. Tags publish to nuget.org (opt-in) + GitHub Packages + GitHub Releases.- Breaking changes are batched to the yearly major cut — they accumulate on
maingated behind[Experimental("FALLOUT0xx")](or a short-lived topic branch offmainwhen they can't be gated) and ship as next year'sYYYY+1.0.0. Mid-yearmain/production is strictly non-breaking; the production-cut review is the backstop. Version ladder:-preview<-rc< GA. - Legacy
support/v10(renamed fromrelease/v10; +hotfix/v10.x) stays on semver10.x, security/critical fixes only; retired year lines becomesupport/YYYY.release/v11is retired and its branch removed (nothing clean shipped; its work re-homed onto the 2026 line) — dead branches with no unique history are now deletable, tags are the durable release markers (ADR-0007 §6). - Opt-in unstable public APIs are marked
[Experimental("FALLOUT0xx")]and can ride any channel; promoting to stable = removing the attribute.
Active work — rebrand completion + plugin-architecture internal foundation (milestone #6), now shipping on the 2026 line. No public plugin SDK yet — that's a later major (milestone #7). Internal middleware/listener interfaces stay internal; do not expose via InternalsVisibleTo to non-test assemblies. See docs/roadmap.md and the five open RFCs (#97–#101).
- .NET SDK pinned in
global.json(currently10.0.100,rollForward: latestMinor). - Central package versions in
Directory.Packages.props— never add aVersion=to an individualPackageReference. - xUnit + FluentAssertions + Verify.Xunit for tests.
- Solution file is
fallout.slnx(new XML solution format, not.sln).
./build.ps1 # default target = Pack
./build.ps1 Compile
./build.ps1 Test
./build.ps1 GenerateTools # regenerate tool wrappers from JSON
./build.ps1 --help # list all targets and parameters
# Or via dotnet directly when iterating on a single project
dotnet build fallout.slnx
dotnet test tests/Fallout.Common.Tests/Fallout.Common.Tests.csprojDo not commit code generated by GenerateTools — generated code is regenerated manually once per release.
To restructure an existing PR's commit history into focused commits, use the /restructure-pr-commits skill.
- At PR-creation time, follow the PR-creation flow in
docs/agents/release-and-versioning.md. Every PR gets atarget/YYYYlabel (target/2026; legacy v10 work usestarget/v10). Breaking changes additionally get abreaking-changelabel, a⚠️ Breaking changecallout, and aCHANGELOG.mdentry — recorded under the next yearly major (breaking changes are batched to the year cut, not shipped mid-year). A breaking-change PR targetsmainwith the breaking surface gated behind[Experimental("FALLOUT0xx")](or, when it can't be gated, on a short-lived topic branch offmainheld for the year cut) — never arelease/YYYYproduction train. This is non-negotiable — review will block. (Before ADR-0008 breaking work targeted theexperimentalbranch; that branch is gone.) - Default to backwards compatibility. Prefer additive over breaking changes. Before changing a public signature, removing an API, renaming a package, or altering an on-disk format, ask: can this be additive instead?
[Obsolete]markers, transition shims (seesrc/Shims/+Fallout.SourceGenerators.TransitionShimGenerator), the[Experimental("FALLOUT0xx")]opt-in escape hatch for not-yet-stable surface, feature flags, and overload-based extension are all preferred to a hard break. When a breaking change is genuinely unavoidable, it lands onmain(gated behind[Experimental("FALLOUT0xx")], or held on a short-lived topic branch for the next yearly major), and follows rule #1's flow — the break must be deliberate, named, and migration-pathed in the CHANGELOG. See #262 for the broader discussion. The[Experimental]convention (diagnostic-ID scheme + registry) is documented in docs/agents/conventions.md and docs/experimental-apis.md. - Central package versions only — add to
Directory.Packages.props, neverVersion=inline. - Tests next to code — every
src/Foohas atests/Foo.Testssibling. Mirror namespaces. - Stay on xUnit + FluentAssertions + Verify. Don't introduce new test frameworks.
- No per-file license headers. The MIT notice lives in
LICENSEat the repo root — single source of truth. Don't reintroduce header preambles on new files. - No conventional commits. Do not use
feat:,fix:,chore:,refactor:, or any other conventional-commit prefix on commit messages or PR titles. Write functional descriptions that explain what the commit or PR accomplishes — e.g. "Add retry logic to the HTTP tool wrapper" or "Fix null-reference in target dependency resolution". The only exception is the!suffix (e.g.fix(security)!: …) used as a detection signal for breaking changes, not as a general style requirement. - Write issues and PR descriptions terse. Follow docs/agents/issue-and-pr-style.md: lead with the point, cut filler, bullets over prose, link don't recap, match length to substance. Issues use the Problem → Outcome → Acceptance criteria shape.
Full conventions + what-not-to-do list: docs/agents/conventions.md.
- docs/agents/repository-layout.md — full directory structure, project groupings, transition-shim strategy
- docs/agents/release-and-versioning.md — branching, semver policy, PR-creation flow, release pipeline, NuGet gotchas
- docs/branching-and-release.md — maintainer runbook for cutting releases, hotfixing older majors, cutting new
release/vNbranches - docs/adr/ — Architecture Decision Records (read
0004-calendar-versioning-and-dual-pace-channels.mdand0001-release-branch-model.mdfor the release model) - docs/agents/conventions.md — conventions, what-not-to-do list, tool-wrapper recipe
- docs/agents/issue-and-pr-style.md — how to write terse issues, user stories, and PR descriptions
- docs/architecture.md — high-level architecture overview
- docs/rebrand-plan.md — namespace mapping + bridge strategy
- docs/roadmap.md — v11/v12/v13 milestones and RFCs
- docs/dependencies.md — third-party dependencies (update when adding meaningful libraries)
- CONTRIBUTING.md — contributor-facing flow (branching, PR review, merging convention)
- The
build/Build.*.csfiles are the canonical example of how to consume the framework — read these when reasoning about user-facing APIs. src/Fallout.Common/Tools/<Tool>/<Tool>.jsonfiles are the source of truth for tool wrappers; the.csnext to them is generated.- Source generators (
src/Fallout.SourceGenerators) produce per-target code at compile time — if a symbol seems missing, check whether it's generated. - The Verify snapshots (
*.verified.txt,*.verified.cs) undertests/are the contract for generator output; review carefully when they change.