Skip to content
bitzorcas
中EN

Guide

Code generator

Generate industry-neutral unified-aggregate slices through bitz-codegen's business-slice production entry, with atomic placement, the BOCG error-code families, manifest evidence fields, and fail-closed legacy audit inputs.

Last updated

BitzOrcas.CodeGeneration.Cli (command name bitz-codegen) is the only tool carrying the “business-slice scaffolding” responsibility and one of just two PackAsTool tools in the repository. It has exactly one production entry point: --business-slice <schema.json>, which generates Contracts, Application, behavior tests, and trim-smoke skeletons from a strictly validated JSON slice definition.

The three historical free-form inputs (--inline, --module, --use-case) have not been deleted — they were demoted to audit entries: they generate zero C#, write a productionReady=false diagnostic manifest into .codegen-output/, and exit with code 2. If a command from an old tutorial yields no source files, that is not a bug; it is fail-closed doing its job.

Tool identity and installation

Terminal window
# Install as a dotnet tool from the local commercial feed (same channel as bitz-upgrade).
dotnet new tool-manifest
dotnet tool install BitzOrcas.CodeGeneration.Cli \
--version 1.0.0-alpha1 \
--add-source <commercial-feed>
# Or run from the repository without installing.
dotnet run --project src/Tooling/BitzOrcas.CodeGeneration.Cli -- --help

Help text is part of the template contract: verify-template.sh asserts that internal derived selectors never appear in help. Treat the help snapshot as authoritative during regressions.

Production entry: business-slice

One command, real effect (the slice is the repo fixture-shaped service-requests.v1.json; output captured from a real run):

bitz-codegen session
$ 
✔ 校验切片 schema(schemaVersion 1)完成
模块: ServiceRequests
状态: 成功
模板版本: 1.0.0
模式: 已写 manifest
输出目录: .codegen-output/ServiceRequests
文件数: 15
[written] Build Directory.Build.props
[written] Build Directory.Packages.props
[written] Solution ServiceRequests.Generated.slnx
[written] Documentation README.md
[written] Contracts.Project src/Example.Modules.ServiceRequests.Contracts/Example.Modules.ServiceRequests.Contracts.csproj
[written] Contracts src/Example.Modules.ServiceRequests.Contracts/ServiceRequestsContractAssembly.Generated.cs
[written] Contracts.Errors src/Example.Modules.ServiceRequests.Contracts/ServiceRequestsErrors.Generated.cs
[written] Domain src/Example.Modules.ServiceRequests.Contracts/ServiceRequest.Generated.cs
[written] Application.Project src/Example.Modules.ServiceRequests.Application/Example.Modules.ServiceRequests.Application.csproj
[written] Application.Composition src/Example.Modules.ServiceRequests.Application/ServiceRequestsModule.Generated.cs
[written] Application.ApplicationCommand src/Example.Modules.ServiceRequests.Application/Commands/ServiceRequests/OpenServiceRequestCommand.Generated.cs
[written] Tests.Project tests/Example.Modules.ServiceRequests.GeneratedTests/Example.Modules.ServiceRequests.GeneratedTests.csproj
[written] Tests.Behavior tests/Example.Modules.ServiceRequests.GeneratedTests/ServiceRequestGeneratedBehaviorTests.Generated.cs
[written] TrimSmoke.Project samples/Example.Modules.ServiceRequests.TrimSmoke/Example.Modules.ServiceRequests.TrimSmoke.csproj
[written] TrimSmoke samples/Example.Modules.ServiceRequests.TrimSmoke/Program.cs
invalid BOCG3xxvalidIO failure

business-slice schema v1

Strict compile-time validation

Exit with zero writes

Write to temp directory

Atomic Directory.Move

manifest Status=ready

Human wiring: slnx / governance / gates

Remove temp dir BOCG310
Target untouched

The slice schema is fixed to an industry-neutral shape: one required-tenant unified aggregate plus a single Create command, with client-allocated Guid keys; domainEvents and integrationEvents arrays must be explicitly declared empty. Below is a LegalTech example isomorphic to the repository test fixture:

matter-intakes.v1.json
{
"schemaVersion": 1,
"frameworkVersion": "1.0.0-alpha1",
"module": {
"name": "LegalCases",
"baseNamespace": "BitzOrcas.Platform.LegalCases",
"description": "Civil and commercial case module",
"code": "legal-cases",
"featureCode": "legal-cases.create"
},
"aggregate": {
"name": "MatterIntake",
"pluralName": "MatterIntakes",
"description": "Matter intake awaiting partner approval within a tenant",
"tableName": "GeneratedMatterIntake",
"idType": "guid",
"idAllocation": "client",
"tenancy": "required",
"softDelete": true,
"concurrency": true,
"fields": [
{
"name": "CaseNumber",
"description": "Court or arbitration case number",
"type": "string",
"required": true,
"maxLength": 64,
"normalize": "trim",
"errorMember": "MatterIntakeInvalidCaseNumber",
"errorCode": "LegalCases.MatterIntake.InvalidCaseNumber"
},
{
"name": "DisputeAmount",
"description": "Amount in dispute",
"type": "decimal",
"required": false,
"minimum": 0,
"maximum": 100000000000,
"normalize": "none",
"errorMember": "MatterIntakeInvalidDisputeAmount",
"errorCode": "LegalCases.MatterIntake.InvalidDisputeAmount"
}
]
},
"create": {
"commandName": "SubmitMatterIntakeCommand",
"description": "Submit a matter intake within the current tenant",
"route": "/api/matter-intakes",
"resourceType": "matter-intake",
"permissionMember": "SubmitMatterIntake",
"permissionCode": "legal-cases.matter-intake.create",
"tenantErrorMember": "TenantRequired",
"tenantErrorCode": "LegalCases.Tenant.Required"
},
"domainEvents": [],
"integrationEvents": []
}

Every field pairs a mandatory errorMember/errorCode — generated validation rules carry strongly-typed error codes so bare-string failures cannot return. Invocation:

Terminal window
dotnet bitz-codegen --business-slice ./design/matter-intakes.v1.json \
--output .codegen-output

An existing target directory refuses to be overwritten; there is no OverwriteStrategy knob. To regenerate, clear the previous output and review the diff first.

Manifest evidence fields

A successful run records more than a file list:

FieldMeaning
Statusready or blocked; blocked means a reviewable diagnostic result, not a crash
ProductionReadyproduction marker; always false for audit entries
SchemaSha256hash of the input slice — pins which definition produced this output
SourceGeneratorOwnedwiring owned by source generators: dependency-injection, endpoint, orm-fluent-configuration, module-catalog
ExplicitlyUnsupportedshapes v1 deliberately does not generate: update-command, query, domain-event, integration-event

SourceGeneratorOwned explains why you will not find DI registrations or endpoint files among outputs — Roslyn generators own those at compile time, and hand-writing them creates a second source of truth. Writing is two-phase: a temp directory is completed and then placed atomically via Directory.Move; on IO failure the temp directory is removed and BOCG310 is reported while the target stays byte-identical.

Audit entries: the old shapes, fail-closed

Three historical inputs remain callable, but their role changed:

Terminal window
# Is this a valid command? Not a production path: it writes an audit
# manifest and exits 2.
dotnet bitz-codegen --inline \
--module-name Tracker \
--aggregate MatterIntake \
--property 'CaseNumber:string:64' \
--property 'DisputeAmount:decimal'
echo $? # 2; .codegen-output contains only a manifest, zero C#
Legacy entryCurrent behavior
--module <json> (aggregate mode)writes a productionReady=false diagnostic manifest, exits 2
--inline --module-name … --aggregate …same
--module … --use-case … (use-case mode)same
--with-endpointexplicitly rejected; handwritten endpoints are gone
--dry-run / --no-stagingrejected at every entry; the tool never writes into the source tree

These entries exist so legacy scripts, courseware, and old READMEs get a deterministic “you are outdated” answer instead of silently producing half-products that violate current architecture.

Error-code families

FamilyMeaningIn common
BOCG1xx / BOCG2xxlegacy-input audit (the three entries above)zero C# output
BOCG3xxproduction schema validation failedzero writes

Automation should key on exactly two signals: the process exit code and the manifest’s ProductionReady field — never human-readable text.

Human landing process

  1. Settle business keys, permission codes ({module}.{resource}.{action}), and error-code ownership in design review before writing the schema — the schema is the contract and enters the SchemaSha256 evidence chain.
  2. Run generation; check the target directory and confirm ready/ProductionReady=true in the manifest.
  3. Wire generated projects into the Consumer Solution: add to .slnx; governance joins via the owner directory’s [AppModule] marker and its DependsOn edges.
  4. Fill behavior tests with real fixtures and assertions; the slice ships a trim smoke — make sure it runs inside your CI trim matrix.
  5. Complete XML doc comments and data-scope rules, then run Application, Architecture, and Integration gates.
  6. Remove the .codegen-output staging copy; the generated directory is the single source of truth.

Verification commands

Terminal window
# Generator templates, atomic placement, and manifest contracts.
dotnet test tests/BitzOrcas.CodeGeneration.Tests --configuration Release
# Generator-as-package contract consumed by an isolated project.
dotnet test tests/BitzOrcas.Generator.Package.Tests --configuration Release

tests/BitzOrcas.CodeGeneration.Tests/Fixtures/service-requests.v1.json is the official fixture; every field in this page’s example maps one-to-one onto it. When schema behavior is unclear, trust the fixture and its assertions — do not guess.

Common mistakes

  • Treating the legacy --inline walkthrough as the production path and discovering exit code 2;
  • leaving last-run artifacts in the target directory and getting a wholesale refusal;
  • expecting update/query or domain-event output — ExplicitlyUnsupported says otherwise on paper;
  • omitting the event arrays instead of declaring them empty;
  • treating a blocked manifest as a failure to retry blindly instead of reading its diagnostics.

See also

100%

Scroll or use controls to zoom · drag when enlarged · double-click for 100% / 200%