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
20 changes: 20 additions & 0 deletions .claude/rules/archetype/library.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
# Archetype — Library (shipped, reusable package)

For code consumed by other projects (NuGet packages, shared libraries).
Compose with the five core rules.

Structure (deltas from `core/architecture.md`)
- Unit tests under `test/<ProjectName>.UnitTests/`; integration tests that need
a real dependency under `test/<ProjectName>.IntegrationTests/`.

Packaging & compatibility
- `dotnet pack` runs in CI from day one so packaging bugs surface early.
- Target the full supported TFM matrix (e.g. `net8.0;net10.0`); CI runs the
matrix on every OS you claim to support.
- The public API is a contract: follow semantic versioning, keep XML docs
complete (they ship in the package), and treat any breaking change as a
deliberate, documented major bump.

Testing
- Cover the public surface directly; internal helpers are tested through it,
not around it.
8 changes: 0 additions & 8 deletions .claude/rules/architecture.md

This file was deleted.

13 changes: 0 additions & 13 deletions .claude/rules/coding-standards.md

This file was deleted.

13 changes: 13 additions & 0 deletions .claude/rules/core/architecture.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
# Architecture

Rules governing physical project and solution structure (as opposed to logical
design, which lives in `design-principles.md`). This is the invariant skeleton;
archetype files add the parts that vary — test-project naming, `bench/`,
integration-test projects, packaging.

- Source lives under `src/<ProjectName>/`; tests under `test/` (singular).
- One solution file (`.slnx`) per repo, at its root, referencing every project
beneath it.
- Centralize shared MSBuild properties (`TargetFramework`, `Nullable`,
`TreatWarningsAsErrors`, etc.) in a `Directory.Build.props` at that same root
instead of repeating them per `.csproj`.
31 changes: 31 additions & 0 deletions .claude/rules/core/coding-standards.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
# Coding Standards

Always follow the Microsoft C# coding conventions and .NET naming guidelines:

- PascalCase for types, methods, properties, constants, and public members;
camelCase for locals and parameters; `_camelCase` for private instance
fields (`private static readonly` values are constant-like and stay
PascalCase); `I` prefix for interfaces; `Async` suffix for async methods.
- One top-level type per file; file name matches the type name. Exception: a
small supporting type (typically a record or struct) that exists only to
serve the file's primary type — a companion DTO, result, or value type it
owns and produces — may be declared in the same file. The exception covers
helpers bound to that one type; it does not license unrelated types or a type
intended for reuse across the codebase, which still get their own file.
- Use file-scoped namespaces, `var` when the type is apparent, expression-bodied
members only when they improve readability.
- Enable and respect nullable reference types (`<Nullable>enable</Nullable>`);
never suppress warnings with `!` without a comment justifying it.
- Prefer records for immutable data, `readonly` where possible, and pattern
matching over type checks/casts.
- Public APIs must have XML doc comments; internal code is documented only where
intent is not obvious from the code. Test projects are exempt — their `public`
types exist for test-framework discovery, not as a consumed API surface.
- Never include unnecessary using directives.
- Codify these conventions in an `.editorconfig` at the solution root (naming
rules, `file_scoped` namespaces, `IDE0005` for unused usings, etc.) so they
are tool-enforced rather than prose-only, and set
`<EnforceCodeStyleInBuild>true</EnforceCodeStyleInBuild>` so style violations
fail the build alongside `TreatWarningsAsErrors`.
- All code must pass `dotnet format` and build with zero warnings
(`TreatWarningsAsErrors` is on).
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
# Design Principles
# Design Principles

- Always apply well-established object-oriented design practices: favor composition over inheritance, encapsulate invariants inside domain types, keep classes small and cohesive, and depend on abstractions at layer boundaries.
- Adhere to SOLID to keep the code adaptive to change:
Expand Down
28 changes: 28 additions & 0 deletions .claude/rules/core/testing-philosophy.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
# Testing — Test-Driven Development

YOU MUST follow a test-driven development approach for all production code:

1. **Red** — write a failing test that specifies the desired behavior before
writing implementation code.
2. **Green** — write the minimum implementation to make the test pass.
3. **Refactor** — clean up the code and tests while keeping everything green.

Rules:

- Never write production code without a failing test that motivates it. Never
mark a task complete while any test fails. Exception: when porting or adapting
already-designed code (e.g., a pre-written draft) rather than discovering new
behavior, there is no red step — treat `dotnet test` passing as the gate.
- Ensure all relevant edge cases are covered: null/empty inputs, boundary
values, invalid state transitions, concurrency where applicable, and failure
paths (exceptions, timeouts, cancellation via `CancellationToken`).
- When a task explicitly scopes test coverage (e.g., "one test", "happy path
only"), that explicit scope takes precedence over this checklist — but say so
out loud (commit message, notes, or conversation) rather than silently
under-testing.
- Test naming: `Should_ExpectedOutcome_When_Scenario` (e.g.,
`Should_ThrowInsufficientStockException_When_InventoryInsufficient`).
- Structure tests as Arrange–Act–Assert.
- Unit tests must be fast and deterministic: no real I/O, network, clock, or
`Task.Delay`. Abstract time behind `TimeProvider`.
- Run `dotnet test` after every change and before declaring any work finished.
26 changes: 26 additions & 0 deletions .claude/rules/core/workflow-core.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
# Workflow — Core

Applies to every project regardless of team size or archetype. Compose with
exactly one of `overlays/workflow-solo.md` or `overlays/workflow-team.md`.

- Make minimal, focused changes; do not refactor unrelated code in the same
change.
- One logical change per commit, with an imperative-mood message explaining
*why*.
- In anything the forge renders — commit messages, PR titles/descriptions, and
review comments — write `#N` (or an issue/PR URL) only for an item that
actually exists and is being deliberately referenced; verify with
`gh issue view N` / `gh pr view N` when in doubt. Every other number- or
token-like reference — step numbers, analyzer IDs, external ticket keys,
version numbers — is wrapped in backticks as inline code, so autolinking
never fabricates a link and closing keywords (`Fixes #N`) never fire against
the wrong item.
- When unsure between two designs, present both with trade-offs and ask before
implementing.
- Never commit or push directly to the default branch (`master`/`main`). All
work happens on a `feature/`-prefixed branch.
- Merge by squash so each feature arrives as a single logical commit on the
default branch, consistent with the "one logical change per commit" rule
above; the squash commit message keeps the imperative, *why*-focused form.
- Update the applicable workflow rule file when a new convention or correction
is established.
10 changes: 10 additions & 0 deletions .claude/rules/overlays/benchmarks.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
# Overlay — Benchmarks (BenchmarkDotNet)

Add when the project tracks performance.

- Benchmark projects live under `bench/<ProjectName>/` and join the solution so
CI *builds* them.
- CI never *runs* benchmarks — numbers from shared runners are noise. Produce
baselines locally and record them in `docs/`.
- Smoke-test a benchmark's plumbing with `--job Dry`
(e.g. `dotnet run -c Release --project bench/<ProjectName> -- --job Dry`).
8 changes: 8 additions & 0 deletions .claude/rules/overlays/workflow-team.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
# Workflow — Team project (PR required)

Compose with `core/workflow-core.md`. Use on any multi-contributor repo.

- The branch lands on the default branch only through a reviewed pull request.
- Enforce with branch protection: require a PR, disallow direct pushes, require
the squash-merge strategy — so it can't be bypassed by accident.
- Never open a pull request automatically — confirm with the maintainer first.
9 changes: 9 additions & 0 deletions .claude/rules/profiles/library-team.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
# Profile: library-team — reusable package, multiple contributors
@../core/coding-standards.md
@../core/design-principles.md
@../core/architecture.md
@../core/testing-philosophy.md
@../core/workflow-core.md
@../overlays/workflow-team.md
@../archetype/library.md
@../overlays/benchmarks.md
53 changes: 53 additions & 0 deletions .claude/rules/project/sqlbound.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
# SqlBound — project-specific rules

Rules that apply only to this repository, composed on top of the shared
`library-team` profile. Shared modules under `core/`, `archetype/`, and
`overlays/`, plus the profile manifest under `profiles/`, are copied
verbatim from the `claude-rules` repo and must stay byte-identical so
`tools/sync.ps1 -Check` audits cleanly — never edit them here.
Sqlbound-specific conventions land in this file; corrections to a shared
rule go upstream to `claude-rules` first and are then re-synced.

## Workflow — milestones, phases, versioning

- For each milestone, draft a plan first and present it to the user; execution
starts only after the user approves the plan.
- Milestones (M1–M16) are used to track the progress of the project. All
milestone work happens on a `feature/M<number>-<desc>`-prefixed branch.
- Versioning follows semantic versioning: each phase gets its own version line
(Phase 1 → `0.1.x`, Phase 2 → `0.2.x`, …; Phase 6 ships `1.0.0`).
- Tag the default branch with an annotated tag (e.g.,
`git tag -a v0.1.0 -m "..."`) when a phase completes and for each release
candidate cut along the way, then push the tag to GitHub for reference.
- `PackageVersion` in `Directory.Build.props` carries a prerelease suffix
while a phase is in flight: `X.Y.Z-preview.N` during development, and
`X.Y.Z-rc.N` once the phase is tracking a stable release. Closing the phase
drops the suffix to the clean `X.Y.Z` in the same commit that gets tagged.
Every tag — release candidates included — is cut on a commit whose
`PackageVersion` matches the tag name minus the leading `v`, so a tag always
names its package version exactly. The next phase opens at the version the
roadmap assigns it, not at a mechanical bump of the previous minor.
- A release candidate does not close its phase: `PackageVersion` moves to
`X.Y.Z-rc.N`, `CHANGELOG.md` gets its own `## [X.Y.Z-rc.N]` entry, and the
annotated tag records that the candidate is not published to nuget.org.
Further candidates bump `N`; the clean `X.Y.Z` and its `vX.Y.Z` tag at GA
are what close the phase and its milestone.
- Each phase has one matching GitHub milestone (titled
`Phase N — <Name> (<major>.<minor>.x)`), not one per M-number; every
M-number's PR in that phase is associated with the phase's milestone on
creation, and the milestone is closed when the phase's final PR merges. The
milestone's description lists each composing M-number with its own
description as a bullet, so the phase-level summary and the per-milestone
detail both stay visible in one place.

## Testing

- Generator output is snapshot-tested with the Roslyn testing SDK.
- Benchmarks compare against Dapper and raw ADO.NET (the `bench/` layout and
CI policy come from the shared benchmarks overlay).

## Architecture

- The shared "one solution file (`.slnx`) per repo, at its root" rule extends
here to "per repo or example": a self-contained example project gets its own
`.slnx` at its own root.
19 changes: 0 additions & 19 deletions .claude/rules/testing.md

This file was deleted.

15 changes: 0 additions & 15 deletions .claude/rules/workflow.md

This file was deleted.

12 changes: 7 additions & 5 deletions CLAUDE.md
Original file line number Diff line number Diff line change
Expand Up @@ -36,8 +36,10 @@ Follow the design constraints below; they are deliberate decisions, not suggesti
Work proceeds milestone by milestone (M1–M16) across six phases: Bedrock (skeleton/CI, execution core, Dapper-coexistence sample), Codegen (materialization, query shapes, AOT + benchmarks), Verification (SQL Server introspection, diagnostics, offline snapshots), Providers, Migrations & CLI, and Ship (API freeze, NuGet 1.0). The Dapper-coexistence sample project (M3) doubles as a permanent CI regression test. Codegen precedes verification because the generator defines the shapes the verifier checks.

## Conventions
@.claude/rules/coding-standards.md
@.claude/rules/architecture.md
@.claude/rules/design-principles.md
@.claude/rules/testing.md
@.claude/rules/workflow.md

Shared rules come from the `library-team` profile of the `claude-rules` repo,
copied in with its `tools/sync.ps1` (audit drift with `-Check`); sqlbound-only
conventions live in the project file.

@.claude/rules/profiles/library-team.md
@.claude/rules/project/sqlbound.md