Skip to content

Latest commit

 

History

History
81 lines (59 loc) · 10.3 KB

File metadata and controls

81 lines (59 loc) · 10.3 KB

AGENTS.md

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.

What this project is

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 -preview channel — default branch; both deliberate improvements/bug fixes and faster AI-assisted work land here. Per-commit -preview prereleases (2026.1.0-preview.<height>.g<commit>) to GitHub Packages only — never nuget.org. Ordinary review. (The dedicated experimental -alpha lane was removed by ADR-0008 — it ran behind main and carried no unique work.)
  • release/YYYY = the production linecut from main on demand at the first release of the year, not preemptively (ADR-0007); until then main (-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 main gated behind [Experimental("FALLOUT0xx")] (or a short-lived topic branch off main when they can't be gated) and ship as next year's YYYY+1.0.0. Mid-year main/production is strictly non-breaking; the production-cut review is the backstop. Version ladder: -preview < -rc < GA.
  • Legacy support/v10 (renamed from release/v10; + hotfix/v10.x) stays on semver 10.x, security/critical fixes only; retired year lines become support/YYYY. release/v11 is 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).

Stack

  • .NET SDK pinned in global.json (currently 10.0.100, rollForward: latestMinor).
  • Central package versions in Directory.Packages.props — never add a Version= to an individual PackageReference.
  • xUnit + FluentAssertions + Verify.Xunit for tests.
  • Solution file is fallout.slnx (new XML solution format, not .sln).

Common commands

./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.csproj

Do 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.

Critical rules (read this every session)

  1. At PR-creation time, follow the PR-creation flow in docs/agents/release-and-versioning.md. Every PR gets a target/YYYY label (target/2026; legacy v10 work uses target/v10). Breaking changes additionally get a breaking-change label, a ⚠️ Breaking change callout, and a CHANGELOG.md entry — recorded under the next yearly major (breaking changes are batched to the year cut, not shipped mid-year). A breaking-change PR targets main with the breaking surface gated behind [Experimental("FALLOUT0xx")] (or, when it can't be gated, on a short-lived topic branch off main held for the year cut) — never a release/YYYY production train. This is non-negotiable — review will block. (Before ADR-0008 breaking work targeted the experimental branch; that branch is gone.)
  2. 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 (see src/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 on main (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.
  3. Central package versions only — add to Directory.Packages.props, never Version= inline.
  4. Tests next to code — every src/Foo has a tests/Foo.Tests sibling. Mirror namespaces.
  5. Stay on xUnit + FluentAssertions + Verify. Don't introduce new test frameworks.
  6. No per-file license headers. The MIT notice lives in LICENSE at the repo root — single source of truth. Don't reintroduce header preambles on new files.
  7. 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.
  8. 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.

Where to look next

Useful pointers

  • The build/Build.*.cs files are the canonical example of how to consume the framework — read these when reasoning about user-facing APIs.
  • src/Fallout.Common/Tools/<Tool>/<Tool>.json files are the source of truth for tool wrappers; the .cs next 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) under tests/ are the contract for generator output; review carefully when they change.