Novolis Docs
novolis-governance / frank-naming-and-structure.md

Frank.* → Novolis naming and structure

dotnetgovernancenovolis

Status: Signed off 2026-05-17 (maintainer execution). Blocks: extraction briefs and migrate-frank-slice.ps1 until this doc is updated for new packages.

Authoritative mapping for extract/rebuild migrations. Package IDs, folder paths, namespaces, and public API names must match this document.

Related: naming.md, frank-inventory.md, frank-migration-runbook.md.

Sign-off

RoleDateNotes
Migration execution2026-05-17Defaults below applied for P0 pilot + waves 0–2; storage wave 3 subset

Repo ↔ domain (reserved — do not rename)

GitHub repoDomainFrank sources (P0)Layout
`novolis-messaging`MessagingChannels.DI, PulseFlowMulti-package
`novolis-testing`TestingFrank.Testing (5 publishable facets)Multi-package
`novolis-transports`TransportsBedrockSlim, Http, WireFishMulti-package
`novolis-storage`StorageDataStorage subsetMulti-package
`novolis-security`SecurityCryptography, HIBPMulti-package
`novolis-codegen`CodeGenReflection subset + Xml/Xsd emitMulti-package
`novolis-analyzers`AnalyzersAutoMapper, CodeLengthMulti-package
`novolis-templates`TemplatesFrank.Templates (7 packs)Single template NuGet pack
`novolis-math`MathGameEngine Primitives subsetMulti-package
`novolis-machinelearning`MachineLearningFrank.ML neural foundationMulti-package
`novolis-markup`MarkupFrank.Markdown, Frank.MermaidMulti-package
`novolis-commands`CommandsGreenfield (parse → envelope → queue)Multi-package
`novolis-gaming`Game authoringGreenfield (`Novolis.Game.*`)Multi-package
`novolis-xsd`XsdFrank.UblSharp, Finance.Documents.Ubl, Libraries.Ubl/SBDHMulti-package

Structural rule (Frank → Novolis)

Frank uses project folders at repo root. Novolis uses:

novolis-<domain>/
  src/Novolis.<Domain>.<Facet>/
  tests/Novolis.<Domain>.Unit/     # single TUnit project per solution
    <Facet>/                       # tests grouped by project under test
  tests/Novolis.<Domain>.TestSupport/   # optional shared fixtures (not a test runner)
  samples/                    (when Frank had Samples/)
  Novolis.<Domain>.slnx
  .novolis/packages.json
  Directory.Build.props
  Directory.Packages.props
  global.json

On extract: move projects into src/ / tests/; do not preserve Frank flat root layout.

NuGet package naming (P0 — resolved)

Frank package / projectNovolis `PackageId`Repo folder
`Frank.Channels.DependencyInjection``Novolis.Messaging.Channels``src/Novolis.Messaging.Channels/`
`Frank.PulseFlow``Novolis.Messaging``src/Novolis.Messaging/`
`Frank.BedrockSlim.Server``Novolis.Transports.Tcp.Server``src/Novolis.Transports.Tcp.Server/`
`Frank.BedrockSlim.Client``Novolis.Transports.Tcp.Client``src/Novolis.Transports.Tcp.Client/`
`Frank.BedrockSlim.Cryptography`*(deferred)*
`Frank.Http``Novolis.Transports.Http``src/Novolis.Transports.Http/`
`Frank.Http.Abstractions``Novolis.Transports.Http.Abstractions``src/Novolis.Transports.Http.Abstractions/`
`Frank.Http.Authentication``Novolis.Transports.Http.Authentication``src/Novolis.Transports.Http.Authentication/`
`Frank.Http.Extensions``Novolis.Transports.Http.Extensions``src/Novolis.Transports.Http.Extensions/`
`Frank.Testing.TestOutputExtensions`**`Novolis.Testing.TUnit`**`src/Novolis.Testing.TUnit/`
`Frank.Testing.Logging``Novolis.Testing.Logging``src/Novolis.Testing.Logging/`
`Frank.Testing.TestBases``Novolis.Testing.TestBases``src/Novolis.Testing.TestBases/`
`Frank.Testing.Testcontainers``Novolis.Testing.Testcontainers``src/Novolis.Testing.Testcontainers/`
`Frank.Testing.TestServer``Novolis.Testing.TestServer``src/Novolis.Testing.TestServer/`
`Frank.DataStorage.Abstractions``Novolis.Storage.Abstractions``src/Novolis.Storage.Abstractions/`
`Frank.DataStorage.Core`*(do not port)*
`Frank.DataStorage` (meta)*(do not port)*
`Frank.DataStorage.Json``Novolis.Storage.Json``src/Novolis.Storage.Json/`
`Frank.DataStorage.Sqlite``Novolis.Storage.Sqlite``src/Novolis.Storage.Sqlite/`
`Frank.Security.Cryptography` (generation)`Novolis.Security.Secrets``src/Novolis.Security.Secrets/`
`Frank.Security.Cryptography` (hashing)`Novolis.Security.PasswordHashing``src/Novolis.Security.PasswordHashing/`
`Frank.Security.Cryptography` (string AES)`Novolis.Security.Encryption``src/Novolis.Security.Encryption/`
`Frank.Security.HaveIBeenPwned``Novolis.Security.HaveIBeenPwned``src/Novolis.Security.HaveIBeenPwned/`
`Frank.Security.Resources``Novolis.Security.WordLists` *(internal)*`src/Novolis.Security.WordLists/`
`Frank.Reflection``Novolis.CodeGen.Reflection``src/Novolis.CodeGen.Reflection/`
`Frank.Reflection.Dump``Novolis.CodeGen.Reflection.Dump``src/Novolis.CodeGen.Reflection.Dump/`
`Frank.Reflection.Mermaid``Novolis.CodeGen.Reflection.ClassDiagram``src/Novolis.CodeGen.Reflection.ClassDiagram/`
*(greenfield)*`Novolis.CodeGen.Xml``novolis-codegen/src/Novolis.CodeGen.Xml/`
*(greenfield)*`Novolis.CodeGen.Xsd``novolis-codegen/src/Novolis.CodeGen.Xsd/`
`Frank.Analyzers.AutoMapper``Novolis.Analyzers.AutoMapper``src/Novolis.Analyzers.AutoMapper/`
`Frank.Analyzers.CodeLength``Novolis.Analyzers.CodeLength``src/Novolis.Analyzers.CodeLength/`
`Frank.Templates``Novolis.Templates``src/Novolis.Templates/` (`PackageType=Template`)
`Frank.GameEngine.Primitives/SubPrimitives``Novolis.Math.Arrays``src/Novolis.Math.Arrays/`
`Frank.GameEngine.Primitives` (geometry subset)`Novolis.Math.Geometry``src/Novolis.Math.Geometry/`
`Frank.ML.Foundation.Core``Novolis.MachineLearning.Core``src/Novolis.MachineLearning.Core/`
`Frank.ML.Foundation.Neural.Abstractions``Novolis.MachineLearning.Neural.Abstractions``src/Novolis.MachineLearning.Neural.Abstractions/`
`Frank.ML.Foundation.Neural.Implementation``Novolis.MachineLearning.Neural``src/Novolis.MachineLearning.Neural/`
`Frank.ML.Foundation.AutoMl``Novolis.MachineLearning.AutoMl``src/Novolis.MachineLearning.AutoMl/`
`Frank.ML.Domain.Racing` (sim)`Novolis.Simulation.Racing``novolis-simulation/src/Novolis.Simulation.Racing/`
`Frank.ML.Domain.Racing` (ML glue)*(dogfood app)* `NeuralRacing``novolis-dogfooding/apps/NeuralRacing/`
`Frank.WireFish``Novolis.Transports.WireFish``src/Novolis.Transports.WireFish/`
`Frank.Markdown``Novolis.Markup.Markdown``src/Novolis.Markup.Markdown/`
`Frank.Mermaid``Novolis.Markup.Mermaid``src/Novolis.Markup.Mermaid/`
`Frank.UblSharp` (+ Generation)`Novolis.Xsd.Generator``novolis-xsd/src/Novolis.Xsd.Generator/`
`Frank.UblSharp` (runtime)`Novolis.Xsd.Ubl``novolis-xsd/src/Novolis.Xsd.Ubl/`
`Frank.UblSharp.Validation``Novolis.Xsd.Ubl.Validation``novolis-xsd/src/Novolis.Xsd.Ubl.Validation/`
`Frank.Libraries.SBDH``Novolis.Xsd.Peppol``novolis-xsd/src/Novolis.Xsd.Peppol/`
`Frank.Finance.Documents.Ubl`*(regen under Ubl; do not vendor tree)*`novolis-xsd`
`Frank.XsdCodeGeneration`*(reference only; do not ship)*

Facet decisions:

  • Messaging DI: facet name `Channels`, not DependencyInjection.
  • Testing output helpers: `Novolis.Testing.TUnit` — extensions on TUnit TestContext (naming.md: TUnit only, no xUnit).
  • Bedrock: drop “BedrockSlim”; use `Tcp` segment.
  • Storage: explicit packages only; no meta Novolis.Storage umbrella in wave 3.

Namespace and assembly rules

RuleConvention
Root namespaceMatches `PackageId` (e.g. `Novolis.Messaging.Channels`)
Internal types`Novolis.<Domain>.Internal` (e.g. `Novolis.Messaging.Internal`)
Test namespaces**Per-facet:** `Novolis.Messaging.Channels.Tests`, `Novolis.Messaging.Tests`, etc. (unchanged; folder is `tests/Novolis.Messaging.Unit/Channels/`)
Test projects**One per solution:** `Novolis.<Domain>.Unit` (TUnit). Do not add `Novolis.<Domain>.<Facet>.Tests` unless required (analyzers, golden/integration, template payloads).
Assembly nameDefault = `PackageId`
Legacy `Frank.*`Must not appear in production Novolis code

Public API vocabulary (PulseFlow — keep Frank terms)

FrankNovolisDecision
`IPulse``IPulse`Keep (product term)
`IConduit``IConduit`Keep
`IFlow``IFlow`Keep
`Nexus` / `PulseNexus`Internal only`Novolis.Messaging.Internal`
`AddPulseFlow()``AddPulseFlow()`Keep in `Novolis.Messaging`
Product docs“PulseFlow”OK in README; package ID is `Novolis.Messaging`

Public API vocabulary (Tcp / Bedrock)

FrankNovolis
`IConnectionProcessor`Keep
`UseTcpConnectionHandler<T>` etc.Align with `Novolis.Transports.Tcp.Server` namespace

Frank.* dependency removal (P0)

Former depReplacement
`Frank.Channels.DependencyInjection``Novolis.Messaging.Channels` project reference
`Frank.Reflection` / `Frank.Reflection.Dump``Novolis.CodeGen.Reflection` / `Novolis.CodeGen.Reflection.Dump` (TUnit references Dump package)
`Frank.Testing.*``Novolis.Testing.*` package references
`Frank.DataStorage.Abstractions` → Reflection packageRemove unused package reference

`.novolis/packages.json` templates

`novolis-messaging`

{
  "packages": {
    "Novolis.Messaging.Channels": {
      "project": "src/Novolis.Messaging.Channels/Novolis.Messaging.Channels.csproj",
      "paths": [
        "src/Novolis.Messaging.Channels/**",
        "tests/Novolis.Messaging.Channels.Tests/**",
        "Directory.Build.props",
        "Directory.Packages.props",
        "global.json",
        "Novolis.Messaging.slnx"
      ]
    },
    "Novolis.Messaging": {
      "project": "src/Novolis.Messaging/Novolis.Messaging.csproj",
      "paths": [
        "src/Novolis.Messaging/**",
        "tests/Novolis.Messaging.Tests/**",
        "Directory.Build.props",
        "Directory.Packages.props",
        "global.json",
        "Novolis.Messaging.slnx"
      ]
    }
  }
}

`novolis-testing`

Entries: Novolis.Testing.TUnit, .Logging, .TestBases, .Testcontainers, .TestServer — each with matching src/ + tests/ paths and shared build files.

`novolis-transports`

Entries: Novolis.Transports.Tcp.Server, .Tcp.Client, .Http, .Http.Abstractions, .Http.Authentication, .Http.Extensions, .WireFish.

`novolis-storage` (wave 3)

Entries: Novolis.Storage.Abstractions, .Json, .Sqlite.

`novolis-security` (wave 4)

Entries: Novolis.Security.Secrets, .PasswordHashing, .Encryption, .HaveIBeenPwned.

`novolis-codegen` (wave 5)

Entries: Novolis.CodeGen.Reflection, .Reflection.Dump, .Reflection.ClassDiagram, .Xml, .Xsd.

`novolis-analyzers` (wave 5)

Entries: Novolis.Analyzers.AutoMapper, .CodeLength.

`novolis-templates` (wave 6)

Entry: Novolis.Templates — paths include src/Novolis.Templates/content/**, Novolis.Templates.slnx.

`novolis-markup` (wave 10)

Entries: Novolis.Markup.Markdown, Novolis.Markup.Mermaid.

`novolis-commands`

Entries: Novolis.Commands.Abstractions, Novolis.Commands.Engine, Novolis.Commands.Queueing, Novolis.Commands.DependencyInjection, Novolis.Commands.Testing — v0 0.1.0-preview.1.

Solution and dependency graph

RepoSolutionPackage references
`novolis-messaging``Novolis.Messaging.slnx``Novolis.Messaging` → `Novolis.Messaging.Channels`
`novolis-testing``Novolis.Testing.slnx`Facets independent; tests may reference multiple facets
`novolis-transports``Novolis.Transports.slnx`Http facets → Abstractions; Tcp Server/Client independent
`novolis-storage``Novolis.Storage.slnx`Json/Sqlite → Abstractions
`novolis-security``Novolis.Security.slnx`Independent facets
`novolis-codegen``Novolis.CodeGen.slnx`Dump/Mermaid → Reflection
`novolis-analyzers``Novolis.Analyzers.slnx`Independent analyzer packages
`novolis-testing``Novolis.Testing.slnx``Novolis.Testing.TUnit` → `Novolis.CodeGen.Reflection.Dump`
`novolis-math``Novolis.Math.slnx`Geometry independent; Arrays has no deps
`novolis-machinelearning``Novolis.MachineLearning.slnx`Neural → Abstractions; Core independent
`novolis-markup``Novolis.Markup.slnx`Markdown and Mermaid independent
`novolis-commands``Novolis.Commands.slnx`Engine/Queueing/Testing/DI → Abstractions; DI → Engine + Queueing

Namespace replacement table (automation)

Use scripts/migrate-frank-slice.ps1 with these replacements (longest match first):

FromTo
`Frank.Templates.TestContainerTemplate``Novolis.Templates.TestContainerTemplate`
`Frank.Templates.NoXaml.Solution``Novolis.Templates.NoXaml.Solution`
`Frank.Templates.NoXaml.App``Novolis.Templates.NoXaml.App`
`Frank.Templates.SemanticKernel``Novolis.Templates.SemanticKernel`
`Frank.Templates.GitHubSolution``Novolis.Templates.GitHubSolution`
`Frank.Templates.Microservice``Novolis.Templates.Microservice`
`Frank.Templates.MonoGame``Novolis.Templates.MonoGame`
`Frank.Templates``Novolis.Templates`
`Frank.Reflection.Mermaid``Novolis.CodeGen.Reflection.ClassDiagram`
`Frank.Reflection.Dump``Novolis.CodeGen.Reflection.Dump`
`Frank.Reflection``Novolis.CodeGen.Reflection`
`Frank.Analyzers.AutoMapper``Novolis.Analyzers.AutoMapper`
`Frank.Analyzers.CodeLength``Novolis.Analyzers.CodeLength`
`Frank.Channels.DependencyInjection``Novolis.Messaging.Channels`
`Frank.PulseFlow.Internal``Novolis.Messaging.Internal`
`Frank.PulseFlow``Novolis.Messaging`
`Frank.Testing.TestOutputExtensions``Novolis.Testing.TUnit`
`Frank.Testing.TestBases``Novolis.Testing.TestBases`
`Frank.Testing.Testcontainers``Novolis.Testing.Testcontainers`
`Frank.Testing.TestServer``Novolis.Testing.TestServer`
`Frank.Testing.Logging``Novolis.Testing.Logging`
`Frank.Testing``Novolis.Testing`
`Frank.BedrockSlim.Server``Novolis.Transports.Tcp.Server`
`Frank.BedrockSlim.Client``Novolis.Transports.Tcp.Client`
`Frank.BedrockSlim``Novolis.Transports.Tcp`
`Frank.Http.Abstractions``Novolis.Transports.Http.Abstractions`
`Frank.Http.Authentication``Novolis.Transports.Http.Authentication`
`Frank.Http.Extensions``Novolis.Transports.Http.Extensions`
`Frank.Http``Novolis.Transports.Http`
`Frank.DataStorage.Abstractions``Novolis.Storage.Abstractions`
`Frank.DataStorage.Json``Novolis.Storage.Json`
`Frank.DataStorage.Sqlite``Novolis.Storage.Sqlite`
`Frank.DataStorage``Novolis.Storage`
`Frank.Security.HaveIBeenPwned``Novolis.Security.HaveIBeenPwned`
`Frank.Security.Cryptography``Novolis.Security.Secrets` / `.PasswordHashing` / `.Encryption`
`Frank.Security``Novolis.Security`
`Frank.ML.Foundation.Neural.Implementation``Novolis.MachineLearning.Neural`
`Frank.ML.Foundation.Neural.Abstractions``Novolis.MachineLearning.Neural.Abstractions`
`Frank.ML.Foundation.Core``Novolis.MachineLearning.Core`
`Frank.GameEngine.Primitives.SubPrimitives``Novolis.Math.Arrays`
`Frank.GameEngine.Primitives``Novolis.Math.Geometry`
`Frank.Markdown``Novolis.Markup.Markdown`
`Frank.Mermaid``Novolis.Markup.Mermaid`

Preview versioning

PackageFirst preview
`Novolis.Messaging.Channels``0.1.0-preview.1`
`Novolis.Messaging``0.1.0-preview.1`
Other P0 facets`0.1.0-preview.1` unless noted in wave brief

Migration publish gate (not org bootstrap)

First migration trusted-publish validation: `Novolis-Platform/novolis-messaging`, workflow release.yml, environment nuget.org, package `Novolis.Messaging.Channels` 0.1.0-preview.1.

novolis-smoketest remains org bootstrap / template CI only.