NuGet-only dependency policy
Policies that keep the org coherent
Indisputable rule: In committed source, any dependency on another Novolis repository is expressed only via PackageReference from GitHub Packages or nuget.org. Cross-repo ProjectReference in .csproj, sibling-checkout MSBuild properties (NovolisRenderingSrc, etc.), conditional dual reference blocks in projects, and local folder feeds in nuget.config are forbidden.
Exception (build-time only): When building the meta solution Novolis.Platform (or with -p:NovolisUseProjectReferences=true), MSBuild may substitute existing Novolis.* PackageReferences for sibling ProjectReferences. See platform-project-ref-mode.md. That does not change committed .csproj files.
Allowed committed alternative: LibraryReference. Governance expands it when `Novolis.Packaging.targets` is imported: sibling .csproj → ProjectReference, otherwise PackageReference at 2026.1.*. Do not commit cross-repo ProjectReference or dual Package/Project conditionals. Do not PackageReference Novolis.MSBuild.LibraryReference inside the forest; that package is for consumers outside the workspace.
Git submodules are allowed as source checkouts for novolis-lab
experiments. A lab may record selected library repositories in .gitmodules
and use the workspace ProjectReference-mode mechanism during local iteration.
The submodule path must never appear as a committed ProjectReference, source
path property, or local feed. CI checks out labs without initializing
submodules and restores the committed PackageReference graph from GitHub
Packages.
Cursor agents: Use GPR for publish/CI consumers — neverartifacts/nuget-local,pack-local.ps1, ornovolis-localsources. For local multi-repo iteration before publish, useNovolis.Platform.slnx(ProjectReference mode). See.cursor/rules/nuget-only-dependencies.mdc.
Allowed
| Scope | Reference style |
|---|---|
| Same repository | ProjectReference to projects under that repo's src/, codegen/, or tests/ |
| Another Novolis repo (committed) | LibraryReference (governance expands it; version float 2026.1.*) |
| Another Novolis repo (local meta build) | LibraryReference resolves the sibling project with no mode flag. Remaining PackageReference items still substitute via platform-project-ref-mode.md |
| Third-party | PackageReference with a pinned version on nuget.org |
Float Novolis packages only on the platform line (2026.1.*). Do not use build-line floats such as 2026.1.10.* or 2026.1.1.* — those resolve to the latest CI build number and fail restore when that build was never published (publish race / failed merge).
Never publish throwaway versions such as 2026.1.99 or 1.0.0 to GitHub Packages. Under a 2026.1.* float, 2026.1.99 sorts above real CI builds like 2026.1.10.36 and will silently win restore. Delete such versions from the org feed if they appear.
Direct Novolis PackageReference is reserved for reviewed exceptions:
Novolis.RaylibandNovolis.Raylib.Native, because their packages carry native runtime assets and transitive native build targets.Novolis.Avalonia.Packaging.Inno, because its package supplies installer MSBuild targets.- The explicit external-host package allowlist in
scripts/verify-library-reference-usage.ps1, until those hosts opt into
governance packaging imports.
verify-library-reference-usage.ps1 enforces this distinction for governed
novolis-* repositories and the explicitly listed external hosts. A new
exception must be added deliberately to that script and documented here.
GPR maintenance
pwsh -File D:\novolis\novolis-governance\scripts\gpr-health-check.ps1
pwsh -File D:\novolis\novolis-governance\scripts\gpr-health-check.ps1 -SkipRemoteCovers: junk versions, build-line floats, local folder feeds, stale package ids
(Host.NAudio → Output.NAudio, …), committed cross-repo ProjectReference leaks, and ProjectReference-mode map health.
Optional: -CheckBrokenDeps for latest-nuspec → missing dependency versions.
Full runbook: gpr-maintenance.md.
Forbidden
ProjectReferencein a committed `.csproj` whose path crosses into a siblingnovolis-*directory- MSBuild properties that auto-detect sibling clones (
NovolisRenderingSrc,UseLocalNovolis, …) ItemGroup Conditionblocks in `.csproj` that switch betweenProjectReferenceandPackageReference- Submodule or junction paths used for compile-time dependencies in apps or libraries
- Local folder NuGet feeds (
novolis-local,artifacts/nuget-local, …)
Validation (required before merge)
dotnet run --file d:\novolis\novolis-governance\scripts\verify-nuget-only.cs
dotnet run --file d:\novolis\novolis-governance\scripts\verify-library-reference-usage.cs
dotnet run --project d:\novolis\novolis-tools\src\Novolis.Solution.Tool\Novolis.Solution.Tool.csproj --no-launch-profile -- verify --root d:\novolis
dotnet run --file d:\novolis\novolis-governance\scripts\verify-banned-packages.csCI should run verify-nuget-only.cs and
verify-library-reference-usage.cs on every library repo and on
novolis-lab, novolis-utilities, and novolis-apps. Banned third-party
stacks (Markdig, QuestPDF): markdown-and-pdf-policy.md.
Proving a change is done
A dependency cleanup is not complete until:
verify-nuget-only.ps1andverify-library-reference-usage.ps1exit 0
across the org checkout.
- Affected libraries are published to GitHub Packages (merge to
main→ CI publish). - Consumers restore and build using nuget.org + github only (
dotnet restore,dotnet build).
Local meta-solution builds prove API shape early; they do not replace step 2–3 for ship.
See nuget-setup.md and platform-project-ref-mode.md.
Related
- platform-project-ref-mode.md — meta-solution ProjectReference substitution
- gpr-maintenance.md — GitHub Packages inventory and junk-version cleanup
- markdown-and-pdf-policy.md — Markdig / QuestPDF banned; Documents + Novolis Markdown
- repository-policy.md
- novolis-lab design