diff --git a/.github/copilot-instructions.md b/.github/copilot-instructions.md
new file mode 100644
index 0000000..514ebd5
--- /dev/null
+++ b/.github/copilot-instructions.md
@@ -0,0 +1,94 @@
+# .NET Repository
+
+**Always reference these instructions first and fallback to search or bash commands only when you encounter unexpected information that does not match the info here.**
+
+## Working Effectively
+
+### Essential Build Commands
+- **Restore dependencies**: `dotnet restore`
+
+- **Build the entire solution**: `dotnet build`
+
+- **Run tests**: `dnx --yes retest`
+ - Runs all unit tests across the solution
+ - If tests fail due to Azure Storage, run the following commands and retry: `npm install azurite` and `npx azurite &`
+
+### Build Validation and CI Requirements
+- **Always run before committing**:
+ * `dnx --yes retest`
+ * `dotnet format whitespace -v:diag --exclude ~/.nuget`
+ * `dotnet format style -v:diag --exclude ~/.nuget`
+
+### Project Structure and Navigation
+
+| Directory | Description |
+|-----------|-------------|
+| `src/` | Contains the repo source code. |
+| `bin/` | Contains built packages (if any) |
+
+### Code Style and Formatting
+
+#### EditorConfig Rules
+The repository uses `.editorconfig` at the repo root for consistent code style.
+
+- **Indentation**: 4 spaces for C# files, 2 spaces for XML/YAML/JSON
+- **Line endings**: LF (Unix-style)
+- **Sort using directives**: System.* namespaces first (`dotnet_sort_system_directives_first = true`)
+- **Type references**: Prefer language keywords over framework type names (`int` vs `Int32`)
+- **Modern C# features**: Use object/collection initializers, coalesce expressions when possible, use var when the type is apparent from the right-hand side of the assignment
+- **Visibility modifiers**: only explicitly specify visibility when different from the default (e.g. `public` for classes, no `internal` for classes or `private` for fields, etc.)
+
+#### Formatting Validation
+- CI enforces formatting with `dotnet format whitespace` and `dotnet format style`
+- Run locally: `dotnet format whitespace --verify-no-changes -v:diag --exclude ~/.nuget`
+- Fix formatting: `dotnet format` (without `--verify-no-changes`)
+
+### Testing Practices
+
+#### Test Framework
+- **xUnit** for all unit and integration tests
+- **Moq** for mocking dependencies
+- Located in `src/*.Tests/`
+
+#### Test Attributes
+Custom xUnit attributes are sometimes used for conditional test execution:
+- `[SecretsFact("XAI_API_KEY")]` - Skips test if required secrets are missing from user secrets or environment variables
+- `[LocalFact("SECRET")]` - Runs only locally (skips in CI), requires specified secrets
+- `[CIFact]` - Runs only in CI environment
+
+### Dependency Management
+
+#### Adding Dependencies
+- Add to appropriate `.csproj` file
+- Run `dotnet restore` to update dependencies
+- Ensure version consistency across projects where applicable
+
+#### CI/CD Pipeline
+- **Build workflow**: `.github/workflows/build.yml` - runs on PR and push to main/rel/feature branches
+- **Publish workflow**: Publishes to Sleet feed when `SLEET_CONNECTION` secret is available
+- **OS matrix**: Configured in `.github/workflows/os-matrix.json` (defaults to ubuntu-latest)
+
+### Special Files and Tools
+
+#### dnx Command
+- **Purpose**: built-in tool for running arbitrary dotnet tools that are published on nuget.org. `--yes` auto-confirms install before run.
+- **Example**: `dnx --yes retest` - runs tests with automatic retry on transient failures (retest being a tool package published at https://www.nuget.org/packages/retest)
+- **In CI**: `dnx --yes retest -- --no-build` (skips build, runs tests only)
+
+#### Directory.Build.rsp
+- MSBuild response file with default build arguments
+- `-nr:false` - disables node reuse
+- `-m:1` - single-threaded build (for stability)
+- `-v:m` - minimal verbosity
+
+#### Code Quality
+- All PRs must pass format validation
+- Tests must pass on all target frameworks
+- Follow existing patterns and conventions in the codebase
+
+## Documenting Work
+
+Project implemention details, design and key decisions should be documented in a top-level AGENTS.md file at the repo root.
+Keep this file updated whenever you make change significant changes for future reference.
+
+User-facing features and APIs should be documented to highlight (not extensively, as an overview) key project features and capabilities, in the readme.md file at the repo root.
diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml
index d6bd793..94db3ff 100644
--- a/.github/workflows/build.yml
+++ b/.github/workflows/build.yml
@@ -12,7 +12,7 @@ on:
- Release
- Debug
push:
- branches: [ main, dev, 'dev/*', 'feature/*', 'rel/*' ]
+ branches: [ main, 'feature/*', 'rel/*' ]
paths-ignore:
- changelog.md
- readme.md
@@ -72,9 +72,8 @@ jobs:
run: dotnet build -m:1 -bl:build.binlog
- name: 🧪 test
- run: |
- dotnet tool update -g dotnet-retest
- dotnet retest -- --no-build
+ shell: pwsh
+ run: dnx --yes retest -- --no-build
- name: 🐛 logs
uses: actions/upload-artifact@v4
diff --git a/.github/workflows/includes.yml b/.github/workflows/includes.yml
index b591d40..fc6dbeb 100644
--- a/.github/workflows/includes.yml
+++ b/.github/workflows/includes.yml
@@ -50,11 +50,11 @@ jobs:
((get-content -raw $file) -replace '\$product\$',$product).trim() | set-content $file
- name: ✍ pull request
- uses: peter-evans/create-pull-request@v6
+ uses: peter-evans/create-pull-request@v8
with:
add-paths: |
**.md
- osmfeula.txt
+ *.txt
base: main
branch: markdown-includes
delete-branch: true
diff --git a/.github/workflows/publish.yml b/.github/workflows/publish.yml
index 03e57d9..035d811 100644
--- a/.github/workflows/publish.yml
+++ b/.github/workflows/publish.yml
@@ -34,9 +34,8 @@ jobs:
run: dotnet build -m:1 -bl:build.binlog
- name: 🧪 test
- run: |
- dotnet tool update -g dotnet-retest
- dotnet retest -- --no-build
+ shell: pwsh
+ run: dnx --yes retest -- --no-build
- name: 🐛 logs
uses: actions/upload-artifact@v4
diff --git a/.github/workflows/triage.yml b/.github/workflows/triage.yml
index 56ff299..99eec76 100644
--- a/.github/workflows/triage.yml
+++ b/.github/workflows/triage.yml
@@ -49,7 +49,11 @@ jobs:
# if we don't have at least 100 requests left, wait until reset
if ($rate.remaining -lt 100) {
$wait = ($rate.reset - (Get-Date (Get-Date).ToUniversalTime() -UFormat %s))
- echo "Rate limit remaining is $($rate.remaining), waiting for $($wait / 1000) seconds to reset"
+ if ($wait -gt 300) {
+ echo "Rate limit remaining is $($rate.remaining), reset in $wait seconds (more than 5'). Aborting."
+ exit 1
+ }
+ echo "Rate limit remaining is $($rate.remaining), waiting $wait seconds to reset"
sleep $wait
$rate = gh api rate_limit | convertfrom-json | select -expandproperty rate
echo "Rate limit has reset to $($rate.remaining) requests"
diff --git a/.gitignore b/.gitignore
index 0fe79fb..dfe1fe0 100644
--- a/.gitignore
+++ b/.gitignore
@@ -12,6 +12,7 @@ BenchmarkDotNet.Artifacts
.idea
local.settings.json
.env
+*.local
*.suo
*.sdf
diff --git a/.netconfig b/.netconfig
index 2d8f60d..e9014aa 100644
--- a/.netconfig
+++ b/.netconfig
@@ -49,15 +49,15 @@
weak
[file "src/Directory.Build.props"]
url = https://github.com/devlooped/oss/blob/main/src/Directory.Build.props
- sha = 0ff8b7b79a82112678326d1dc5543ed890311366
+ sha = dd13ed3334135c30dcb1e3b2295dc7622de298d9
- etag = 3ebde0a8630d526b80f15801179116e17a857ff880a4442e7db7b075efa4fd63
+ etag = bd05f9f240823c0ac79ddfefe654061550c36f82dd94fa513b82900e92686a5f
weak
[file "src/Directory.Build.targets"]
url = https://github.com/devlooped/oss/blob/main/src/Directory.Build.targets
- sha = 4339749ef4b8f66def75931df09ef99c149f8421
+ sha = 083a37bd9307ec820bac6ee3c7384083151d36d8
- etag = 8b4492765755c030c4c351e058a92f53ab493cab440c1c0ef431f6635c4dae0e
+ etag = 907682e5632a2ba430357e6e042a4ca33cb8c94a3a215d3091aa03f5958a4877
weak
[file "src/nuget.config"]
url = https://github.com/devlooped/oss/blob/main/src/nuget.config
@@ -85,9 +85,9 @@
[file ".github/workflows/build.yml"]
url = https://github.com/devlooped/oss/blob/main/.github/workflows/build.yml
weak
- sha = 56c2b8532c2f86235a0f5bd00ba6eba126f199cf
+ sha = 5da103cfbc1c4f9b5f59cfa698d2afbd744a7525
- etag = bf99c19427f4372ecfe38ec56aa8c411058684fb717da5661f17ac00388b3602
+ etag = 851af098748f7cfa5bc3cfd4cc404a6de930532b59ceb2b3b535282c41226f3a
[file ".github/workflows/changelog.config"]
url = https://github.com/devlooped/oss/blob/main/.github/workflows/changelog.config
sha = 08d83cb510732f861416760d37702f9f55bd7f9e
@@ -99,21 +99,21 @@
skip
[file ".github/workflows/includes.yml"]
url = https://github.com/devlooped/oss/blob/main/.github/workflows/includes.yml
- sha = 2d1fb4ed52b63689f2b20b994512ebac28721243
+ sha = 06628725a6303bb8c4cf3076a384fc982a91bc0b
- etag = 34ade86f020dea717c6a27ad7dcd0069c35be2832c58b0ba961278a1efe34089
+ etag = 478f91d4126230e57cc601382da1ba23f9daa054645b4af89800d8dd862e64fd
weak
[file ".github/workflows/publish.yml"]
url = https://github.com/devlooped/oss/blob/main/.github/workflows/publish.yml
weak
- sha = 56c2b8532c2f86235a0f5bd00ba6eba126f199cf
+ sha = 7f5f9ee9f362f7e8f951d618f8f799033550e687
- etag = 2ef43521627aa3a91dd55bdc2856ec0c6a93b42485d4fe9d6b181f9ee42c8e18
+ etag = c60411d1aa4e98e7f69e2d34cbccb8eb7e387ec11f6f8e78ee8d8b92122d7025
[file ".gitignore"]
url = https://github.com/devlooped/oss/blob/main/.gitignore
- sha = 3776526342afb3f57da7e80f2095e5fdca3c31c9
+ sha = a225b7a9f609f26bcc24e0d84f663387be251a7d
- etag = 11767f73556aa4c6c8bcc153b77ee8e8114f99fa3b885b0a7d66d082f91e77b3
+ etag = 20a8b49d57024abbd85aac5b0020c30e5eb68e0384b2761e93727c8780c4a991
weak
[file "Directory.Build.rsp"]
url = https://github.com/devlooped/oss/blob/main/Directory.Build.rsp
@@ -148,9 +148,9 @@
skip
[file ".github/workflows/triage.yml"]
url = https://github.com/devlooped/oss/blob/main/.github/workflows/triage.yml
- sha = 33000c0c4ab4eb4e0e142fa54515b811a189d55c
+ sha = 61a602fc61eedbdae235f01e93657a6219ac2427
- etag = 013a47739e348f06891f37c45164478cca149854e6cd5c5158e6f073f852b61a
+ etag = 152cd3a559c08da14d1da12a5262ba1d2e0ed6bed6d2eabf5bd209b0c35d8a75
weak
[file ".github/workflows/dotnet-env.yml"]
url = https://github.com/devlooped/oss/blob/main/.github/workflows/dotnet-env.yml
@@ -162,3 +162,14 @@
sha = 666a2a7c315f72199c418f11482a950fc69a8901
etag = 91ea15c07bfd784036c6ca931f5b2df7e9767b8367146d96c79caef09d63899f
weak
+[file "readme.tmp.md"]
+ url = https://github.com/devlooped/oss/blob/main/readme.tmp.md
+ skip
+[file "oss.cs"]
+ url = https://github.com/devlooped/oss/blob/main/oss.cs
+ skip
+[file ".github/copilot-instructions.md"]
+ url = https://github.com/devlooped/oss/blob/main/.github/copilot-instructions.md
+ sha = e616d89d9537c4b8ccf1c20dd277ab82104167c4
+ etag = 6ee650d118a57494d3545d54718ccaa5257b09d54504e9c21514fe596edd9678
+ weak
diff --git a/readme.md b/readme.md
index c7b6376..099e1b7 100644
--- a/readme.md
+++ b/readme.md
@@ -494,19 +494,17 @@ The versioning scheme for packages is:
[](https://github.com/clarius)
[](https://github.com/MFB-Technologies-Inc)
+[](https://github.com/khamza85)
[](https://github.com/sandrock)
[](https://github.com/drivenet)
[](https://github.com/Keflon)
[](https://github.com/tbolon)
[](https://github.com/kfrancis)
-[](https://github.com/unoplatform)
[](https://github.com/rbnswartz)
[](https://github.com/jfoshee)
[](https://github.com/Mrxx99)
[](https://github.com/eajhnsn1)
-[](https://github.com/davidjenni)
[](https://github.com/Jonathan-Hickey)
-[](https://github.com/akunzai)
[](https://github.com/KenBonny)
[](https://github.com/SimonCropp)
[](https://github.com/agileworks-eu)
@@ -514,15 +512,14 @@ The versioning scheme for packages is:
[](https://github.com/vezel-dev)
[](https://github.com/ChilliCream)
[](https://github.com/4OTC)
-[](https://github.com/v-limo)
[](https://github.com/DominicSchell)
-[](https://github.com/jwendl)
[](https://github.com/adalon)
-[](https://github.com/Eule02)
[](https://github.com/torutek)
-[](https://github.com/mccaffers)
-[](https://github.com/christoh)
-[](https://github.com/ADS-Fund)
+[](https://github.com/mccaffers)
+[](https://github.com/SeikaLogiciel)
+[](https://github.com/wizardness)
+[](https://github.com/latonz)
+[](https://github.com/prime167)
diff --git a/src/Directory.Build.props b/src/Directory.Build.props
index 29281ee..91e383a 100644
--- a/src/Directory.Build.props
+++ b/src/Directory.Build.props
@@ -166,6 +166,10 @@
+
+
+
+
diff --git a/src/Directory.Build.targets b/src/Directory.Build.targets
index 083afa6..a3df56d 100644
--- a/src/Directory.Build.targets
+++ b/src/Directory.Build.targets
@@ -174,7 +174,7 @@
@@ -184,6 +184,16 @@
+
+
+
+
+ OSMFEULA.txt
+ true
+
+
+
+