Skip to content

Chronicle.Go parity

Use this reference when moving a C# Chronicle workflow to Go: find the matching API, its executable evidence and the differences your application must handle. Chronicle.Go uses explicit ownership, contexts and typed registration. The implemented subsets below are not overall client parity or production lifecycle completeness.

Start with baselines and evidence, then the relevant capability. Migration guidance covers connections, constraints and read models; remaining work separates gaps from delivered APIs.

C# authorityGo surface and statusEvidence and limits
Source/Clients/DotNET/Identities/{IIdentityManager,IdentityManager}.cs; Source/Kernel/Core/Identities/{RenameIdentity,IdentityConverters,RenameIdentityValidator}.cs, Storage.MongoDB/Identities/IdentityStorage.cs, Contracts/Commands/CommandResult.cs at 2e31b0dfba489159b3db323238f16d0f277056b4 (unchanged from pinned ae5e00a8abaa688138b2c2f689e2b4659cccb4fd)Partial: EventStore.Identities().Rename(ctx, subject, identities.Name, ...metadata.CorrelationID) updates only a namespace-scoped display name. No registration, subject/username/stream movement, event append, catalog discovery or read-model releaseTestIdentityRenameObservedWireSequence, TestIdentityRenamePreReadSelection, TestIdentityRenameCommandEnvelopes, TestIdentityRenamePostReadKeepsAcknowledgment, TestKernelIdentityRenameObservedName. The actual pinned single-kernel command acknowledgment and two internal reads precede independent Mongo-backed listing, preserving subject/username/unrelated identities. Historical cache convergence, multi-node behavior, classified metadata, SQL and role isolation remain unqualified
C# storage UpdateOneAsync(Subject == subject) ignores matched countGo-specific: pre-list → one command → post-list; IdentityRenameResult preserves acknowledgment separately from observed name; payload-free not-found/refused/unknown contractsEmpty/alias/duplicate/corrupt pre-lists prevent commands; failed query data is unusable; all validation entries refuse, including warnings. TestIdentityRenameWirePresenceFailsClosed, TestIdentityRenameFailedQueryDataIsNotAbsence, TestIdentityRenameDecoderBypassCannotAcknowledge. Exact authorization presence is required, unknown fields fail closed. Observation is neither an atomic matched-row receipt nor proof that this command caused the name; two unfiltered O(namespace identity count) reads require listing permission and message capacity
Go generation/root registration and audit-provider contractsGo-specific: already-ready stable-generation operation, no automatic readiness or retry; invocation-local error privacy without shared producer changesTestIdentityRenameIncompleteBarrierNeverJoins, TestIdentityCompleteReadinessChecksObserversAndStages, TestIdentityRenameNamespaceAckDoesNotStartPendingObserver, TestIdentityRenameGenerationRootAndCancellationRaces, TestIdentityRenameCommandFlightReleasesAndNotifies, TestIdentityRenameCallbackCloseReentry, TestIdentityRenameHostileFailuresOpaqueAndLeasesReleased, TestIdentityRenameTokenAndInvalidatorDiscardFailures, TestIdentityRenameFrozenAuditOnceAndExplicitZero. Separate readiness calls and independent background operations retain their ordinary contracts. Actor/causation are frozen context only; rename wire lacks them. No privacy promise for borrowed implementations’ own logging or explicit reentrant operations

See Rename a stored identity display name for prerequisites, errors, listing cost and acknowledgment limitations.

C# authorityGo surface and statusEvidence and limits
DotNET/Projections/Projections.cs:363–405 and DotNET.Specs/Projections/for_Projections/when_registering_explicitly at 2e31b0dfba489159b3db323238f16d0f277056b4Partial: EventStore.RegisterProjection(ctx, projections.Declaration), ProjectionRegistration.Published plus existing RegistrationOutcome; one new ordinary model and projection using known exact event generationsTestRuntimeProjectionPublishesStoreRootAndRetainsOldReaders, TestRuntimeProjectionFalseWirePresence, TestRuntimeModelFailureRetriesCompleteModelsBeforeCumulativeProjections, TestKernelRuntimeProjectionAdditionRetainsDefinitionsAcrossReconnectAndNamespace. Same-model replacement, passive/variant/global/protected/relationship/derived shapes and runtime registration of other artifact families remain unsupported. C# supports replacement; Go deliberately rejects it
C# local composition followed by model/projection registration; no atomic remote transactionGo-specific: per-client/store publication and destructive-flight fence; sticky ErrDestructiveRegistrationUnknown refuses later mutations, not ordinary acknowledged readinessTestRuntimeUnknownInitialFullSetPreservesReadyButRefusesAdd, TestRuntimePublishedCumulativeUnknownReturnsRealAcknowledgedOutcomeAndSentinel, TestRuntimeDestructiveDispositionIsRecordedBeforeFlightRelease, TestRuntimeQueuedFullSetSupersededBeforeAndInsideAuthorization, TestRuntimeConcurrentAddCannotDispatchObsoleteSubset, TestRuntimePublishedCancellationRetainsRootAndReportsActualStage. Unknown requests cannot omit a later locally admitted addition; no remote quiescence, same-root idempotence or protection from independent clients is claimed
Go decision-read evidence and immutable catalogsGo-specific: store-wide fixed expected epochs stale issued/enrolled guards across namespaces; old ordinary readers remain coherent snapshotsTestRuntimePublicationStalesAllNamespaceGuardsAndOldReaders; Declaration.IsVariant preserves authoring identity even when wire definitions are identical (TestVariantMetadataSurvivesIdenticalOrdinaryWireShape). Tokens remain unauthenticated SDK evidence, not server revision or history/ABA fences

See runtime registration for retained-state, retry and error semantics. Earlier deferred-runtime entries below still apply to replacement, general registry mutation and other artifact families, not this bounded addition workflow.

C# authorityGo surface and statusEvidence and limits
Actual Chronicle 19.29.4 (ae5e00a8), Fundamentals 7.19.6 (14037b1f), runtime/STJ 10.0.12: client options initializer, EventSerializer, Generate and GenerateForReadModelPartial: serialization.EnumMember[T ~int32], Enum, Flags, existing immutable Codecs; exact named type and declared values onlyTestEnumPackagedProfileRegression compares all captured scalar/nullable/array observations for five Int32 declarations under both naming policies; both schema APIs retain integer enum/name arrays without an int32 format. The supplemental actual .NET decoder verifies 262 Go payloads; historical raw capture and the distinct Fundamentals source corpora are unchanged
Chronicle schema-driven Expando and Mongo conversionPartial, Go-specific narrower admission: reject unknown values and undeclared combinations, including with All=-1TestKernelDeclaredInt32EnumProfile checks captured C# and Go writes, numeric event history, named model reads, scalar/array/nullable values, signed limits, declared composites and updates to zero. Actual .NET typed decoding verifies 96 exported event/model readbacks. Unknown C# writes/string reads are not safe admission: scalar default fallback, disappearing nullable values and null array elements remain hazards
Frozen enum representations and mapping; kernel ProjectionFactory.GetMergedFromProperties / GetMergedJoinProperties at ae5e00a8, C# client variant lowering at 2e31b0dImplemented within the admitted root-member profile; Go-specific ASCII-only enum AutoMap qualification; no callback or constant discoveryTestEnumDeclarationAndRepresentationAreFrozen, TestEnumHooksAreNeverCalled, TestEnumProjectionCopyLiteralsAndRefusals, TestEnumHistoricalTablesAndMigrationBoundary, TestEnumUndeclaredValuesIssueNoAppendRPC. Final-graph case-insensitive AutoMap, EntersOn/global handlers, enum variant keys/generated joins and invalid literal targets have focused regressions; TestEnumInvalidProjectionRegistrationIssuesNoRPC asserts local refusal. TestKernelEnumProjectionCaseAndLoweredVariants checks differently cased From/Join and EntersOn/generated joins with named model readbacks. Copy requires the same table/profile; literals validate membership before hooks; arithmetic and cross-integer conversions fail. Ambiguous or Unicode enum AutoMap names and enum correlation keys fail explicitly. TestEnumAutoMapLiteralPropertyExpressions and TestEnumReboundExplicitPropertyExpressionsRefuseBeforeRPC reject literal-looking source expressions, including rendered naming policies. TestEnumCollectionAutoMapValidatesEncodedMode and TestEnumNestedAutoMapUsesContainingProjection check source-enum-only conversions against encoded collection/nested modes; TestKernelEnumExpressionAndInheritanceControls exercises safe automatic reads, literal-name exclusions/overrides and Inherit/Disabled collection controls. Collection Inherit remains enabled in the pinned merger; nested Inherit consults the containing Projection, not the immediately enclosing nested override. This is enum-boundary validation, not qualification of all C# inheritance or admission of nested enum placements. TestEnumSparseEveryUnusedCatalogRebindRefusesBeforeRPC covers absent-source enum targets after catalog-wide rebinding; TestEnumDirectDottedRootAutoMapRefusesBeforeRPC, TestEnumDottedRootJoinRegistrationRefusesBeforeRPC and TestEnumDottedRootGlobalGeneratedJoinRefusesBeforeRPC refuse raw dotted root names selected by enum-involved mappings. Field-index ownership distinguishes these from genuine nested ordinary paths without changing generic metadata APIs. TestKernelEnumSparseEveryMissingThenKnown checks a safe sparse mapping remains nil before known enum One/Zero updates, with processed markers and an ordinary nested literal control. Enum endpoint migrations return ErrUnsupported

See declared enum codecs for placement restrictions, missing/null semantics and migration guidance. This is not broad enum parity: concepts, protected/derived/nested enum shapes, alternate backing types, aliases and undeclared combinations remain unsupported. No shared Fundamentals.Go enum API or root dependency change is involved.

C# authorityGo surface and statusEvidence and limits
DotNET/Events/EventSerializer.cs:40–55, DotNET/Schemas/JsonSchemaGenerator.cs:323–332 at 2e31b0dfb; Fundamentals DerivedTypeJsonConverter.cs:26–75 at 14037b1f (7.19.6)Partial: immutable serialization.NewCodecs / Derived[Family, Concrete], CompileWith, events.WithCodecs, readmodels.WithCodecs; unprotected open-object wire schemas and a closed variant graphTestDerivedCapturedDotNETPayloadsAndOpenSchema compares actual .NET bytes under both naming policies; fixtures and source/options provenance are in serialization/testdata/derived. TestKernelDerivedCodecsCollectionsOrdinaryChildrenAndReplay covers Go and captured C# event payloads, copied collections, live ordinary model child updates, relationship-free replay and fail-closed relationship replay admission. The executed .NET probe also decodes both producers’ kernel read-back bytes under both naming policies. No protected-family claim; derived children are the next row
Fundamentals converter’s immediate reflected propertiesGo-specific: immediate acronym-preserving camelCase; nested ordinary objects use configured naming; explicit Go tags retain priorityTestDerivedMetadataSnapshotsAndTagPolicy, captured unsafe-direct fixtures. C# ignores immediate JsonPropertyName; Go does not. Direct family-valued derivative properties fail before I/O, including aliases/pointer layers/promoted fields: C# loses the nested discriminator and silently decodes null (Fundamentals #1149). Arrays are not an equivalent substitute for single-child domain semantics
Converter dispatch and kernel schema-unknown numeric conversionGo-specific fail-closed validation: exact dynamic types, required unique exact discriminator, typed-nil rejection, ±2^53 integer subtree bounds, all-variant security auditTestDerivedRegistrationValidationAndUnusedVariantAdmission, TestDerivedExactDiscriminatorAndFailureAtomicDecode, TestDerivedNilNumericMapAndCycleBoundaries, TestDerivedSecurityAuditsUnusedVariantsAndProtectedSiblings, TestDerivedCallbacksContainPanicsAndPreserveOrdinaryCauses. Classified families and active protection walks over open families remain unsupported; no metadata stripping or coarse protection promotion
Frozen catalogs, typed consumers and serialization snapshotsImplemented for admitted families: variant-qualified metadata, original historical plans, callback-free snapshot rebinding and frozen provider resultsTestHistoricalDerivedCatalogRetainsOriginalDiscriminators, TestDerivedDescriptorsFreezeOptionsProvidersAndHistoricalGenerations, TestDerivedReconnectReusesFrozenClassificationsAndCodecs, TestDerivedModelReadsReleaseWatchWindowsAndFrozenProviders, TestDerivedEventReadsAndReactorDispatchUseCompiledFamily, TestActiveReducerUsesDerivedEventAndInitialStatePlans, TestDecisionDerivedDecodeFailureIssuesNoModelOrToken, TestDerivedProjectionCopiesWholeFamiliesButDoesNotInferChildren. Variant fields are not ordinary migration paths
Derived children / DotNET/Projections/ModelBound/ChildrenDefinitionExtensions.cs (ProcessChildrenFromAttributeCore, ResolveConcreteChildType, AddDerivedTypeDiscriminatorMapping) at v19.32.3 (e72af7ea)Partial: model-bound children(...) on a slice/array of a family with exactly one registered derivative resolves that concrete type for fields, key/identity and parent inference, mapping tags, joins, removals and AutoMap exclusions, and writes _derivedTypeId: $value(<id>). Recursion identity is family plus concrete type. Go-specific: every non-join child From carries the discriminator in both front ends, where C# stamps only the model-bound [ChildrenFrom] creator; kernel ProjectionEventContextExtensions.Project at v19.32.3 adds a child for any non-join From whose identity is absent, so a keyed update after removal or before creation would otherwise write a child the family codec cannot read, and on an existing child the constant rewrite is idempotent. The captured C# definition has only the creator From, so the golden comparison is unaffected. A derivative’s key, no-auto and not-projected tags are type metadata: they neither make HasMappings discover a projection nor refuse a whole-family property, so a fluent derivative’s key tag does not block reuse of its family elsewhere. Grandchild collections tagged on the derivative are compiled, whereas C# ProcessNestedChildren walks the unresolved interface and so drops constructor-parameter grandchildren; fluent Children accepts the family with the derivative’s builder (C# fluent cannot name a concrete child type); zero or several derivatives, non-literal discriminators, globals targeting any casing of _derivedTypeId, and derivative declarations outside a children collection (including nested families) fail compilation, where C# keeps the interface and writes no discriminator or silently drops the declarationsTestSingleDerivedChildFrontendsAndCapturedCSharpDefinition compares both front ends to definitions captured by running the packaged C# 19.32.3 client (projections/testdata/derived-children, with capture harness and provenance); TestDerivedChildPayloadMatchesCapturedCSharpSerialization compares payloads and decodes the C# bytes. Qualified differences: C# DefaultNamingPolicy emits PascalCase child targets although its derived serializer writes camelCase; Go uses the derivative plan’s names, and explicit Go json tags keep their spelling under both policies. TestDerivedChildrenUseConcreteDeclaredIdentityAndPathLocalRecursion, TestDerivedChildInferenceRejectsMissingAmbiguousAndUnrepresentableFamilies, TestDerivedDiscriminatorCannotBeWrittenThroughFluentOrGlobals, TestDerivedDeclarationsOutsideChildrenCollectionsAreRefused, TestDerivedChildPreparationAuditsUnseenVariantsAndRejectsBeforeTransport, TestDerivedChildSnapshotsRebindWithoutCallbacksOrRootIndexCollisions, TestDerivedChildInitialValuesKeepCollectionsWithDiscriminatorAndRejectTypedNil, TestDerivedChildKeyedUpdatesCarryTheDiscriminator, TestDerivedChildRebindWithMissingEventFailsWithoutPanicking, TestFluentDerivativeKeyTagIsNotAProjectionDeclaration, TestNewClientAdmitsFluentDerivativeReusedAsWholeFamilyProperty. TestKernelSingleDerivedChildrenCreateJoinRemoveReaddAndReplay on 19.32.3-development covers registration, create, join update, removal, a join that does not resurrect a removed child, re-add, raw and typed read-back with the discriminator, ReplayProjection refusal, and an observer replay that records a read-model occurrence, under both naming policies; TestKernelDerivedChildKeyedUpdateRecreatesADecodableChild shows the kernel recreating a removed child, and creating a never-created one, from a keyed WithNodes update, and both read back with the discriminator. Protected families stay refused (#64)

Duplicate-member rejection is a Go-specific safety contract, not broader C# parity: TestDerivedDuplicateMembersFailBeforeDecodeOrSnapshotRebinding and TestDerivedModelDuplicatesFailBeforeIDNormalizationAndDelivery cover the entire input before lossy normalization, including unknown arrays and maps. TestDerivedHistoryUsesFrozenPlanAndRejectsAmbiguousRawDocuments also covers raw collections and snapshots without partial progress, and TestDerivedInitialStateRebindKeepsCapturedPlansAndOriginalHandles covers captured client plans, stable model handles and shadowed embedded fields. TestDerivedCaseFoldedDiscriminatorPropertiesAreNeverAdmitted reserves metadata spellings, while TestDecisionErrorCallbacksRemainInsideRecovery covers panicking error traversal and retained ordinary error identities.

See Register unprotected derived types. Enum profiles beyond the declared Int32 subset, binary map/derived/concept/protected placements, custom representation, complex map-key and GeoJSON work stays under #64. Derived children are described in project derived children.

C# authorityGo surface and statusEvidence and limits
Source/Clients/DotNET/Patterns/{Patterns.cs:21–119,IPatterns.cs,PatternConverters.cs} at 2e31b0dfb; Source/Kernel/Concepts/Patterns/{FacetSet,FacetName,PatternConfidence,TimeBucketExtensions}.csImplemented typed query workflow: EventStore.Patterns, patterns.Service.GetPatterns/GetUsualActions/GetPatternsAt/GetPatternsForScope/GetScopes, immutable facets, context-first cancellation and server-default thresholds/limitsTestCSharpQueryRequestGoldens, TestCriteriaDefaultsZerosAndNoInventedValidation, TestTimeBucketsAndExplicitZeroMoment, TestOmittedMomentUsesLocalNowAndRejectsUnrepresentableMoment, TestResponseGoldensAndSnapshotOwnership, TestScopeResponseLabelsAndEmptyFacts; fixtures are hand-derived, not captured .NET output. No SDK inference, sorting, discovery, training or scheduler
Source/Kernel/Protobuf/patterns.proto, Contracts/Queries/QueryResult.cs, Contracts/Validation/ValidationResult.cs, Core/Patterns/BehaviorPatternDetails.cs at pinned kernel ae5e00a8 (19.29.4); same query/default contracts at C# baseline aboveImplemented wire queries and explicit default semantics: zero confidence/limit request server defaults; local per-call codec preserves omitted default-true authorization and default-Error severity without changing generated contractsTestCSharpScalarDefaultWireGoldens, TestCSharpRequestZeroWireAndExplicitLimits, TestDefaultCodecThroughActualGRPC, TestEnvelopeFailuresRedactedAndUnknownSeverities, TestMalformedResponsesFailAtomically, TestResponseTimestampGrammar, TestMalformedTimestampResponsesFailAtomically, TestNilReplyAndMalformedCodec. Any validation diagnostic fails as in C#; unknown severities retain numeric values. Repeated nil/empty data are wire-equivalent; missing replies/required dates fail. Source/Kernel/Contracts/Primitives/SerializableDateTimeOffset.cs at 2e31b0dfb emits seven fractional digits using "O"; response dates accept zero to seven fractional digits with Gregorian local/UTC years 1–9999 and signed whole-minute offsets within ±14 hours. Raw offset minutes and precision are checked before Go parsing can normalize/truncate them; malformed dates fail the entire result without exposing timestamp text
C# selected-store transport and PatternsNotSupported.cs; kernel Services.PatternsPartial runtime evidence: all five public query workflows available on 19.32.3-development, with actual empty answers in a fresh namespaceTestKernelPatternsQueries uses real TLS/OAuth and selected-store queries; no seeded pattern provider or local inference. Nonempty mining, ranking and prediction accuracy remain unverified. Unsupported servers return typed UnsupportedError, not empty success; TestTransportErrorsKeepOriginalGraphWithoutSensitiveFormatting, TestCancellationDeadlineAndConstruction, TestStorePatternsCoordinatesMetadataAndNoCrossStoreCache, TestStorePatternsGenerationCancellationJoinsInflightQuery cover failure graph, lifecycle, authentication/correlation and isolation
C# PatternConverters derives specificity and discards DTO labels/correlationGo-specific: QueryResult[T] preserves response correlation; Scope additionally retains name/user name; BehaviorPattern.ID retains the server’s string facet-key ID; finite DateTimeOffset-representable time inputs and immutable copied collectionsTestResponseGoldensAndSnapshotOwnership, TestScopeResponseLabelsAndEmptyFacts, ExampleEventStore_Patterns (compiling, kernel-dependent). Grouping keys are strings, not UUIDs or event-source IDs. Actor facets are facts, not authorization

See Query established behavior. Server source resolves confidence as requested > 0 ? requested : configuration.MinimumConfidence and result limits as requested > 0 ? requested : 10; the SDK does not duplicate those defaults. Zero is not a request for zero answers or a zero-confidence override. C# performs no confidence range/finiteness validation, so Go forwards those values unchanged.

C# authorityGo surface and statusEvidence and limits
DotNET/ChronicleClient.cs:105–129 at 2e31b0dfba489159b3db323238f16d0f277056b4, optional ILoggerFactoryGo-specific: chronicle.WithLogger(*slog.Logger) captures a borrowed logger at CaptureClient (immediately for NewClientContext); scalar last-wins and nil validation; per-client logger/handler identity capture, not destination-state captureTestClientLoggerCapturePrecedenceAndArtifactOverride, TestClientLoggerDefaultIsCapturedAfterDeclarationAndBeforePreparation, TestClientLoggerValidationAndImmediateCapture, TestClientLoggersIsolateSharedRegistryConcurrentFailures; explicit reactor/reducer/read-model logger overrides survive pointer equality, store binding and reconnect. TestClientLoggerPristineDefaultBridge uses a fresh subprocess and actual preparation failure to demonstrate that the captured pristine default follows the standard logger’s current writer and a later custom-default bridge. Strict destination isolation requires an explicit stable handler/writer. No full C# logging DI parity or framework adapter dependency
Observer and lifecycle diagnostics / C# client logger collaboratorsGo-specific bounded SDK records: fixed operation/stage/category only, no arbitrary error formatting/traversal or sensitive metadata; handler panics contained without changing operational outcomesTestClientLoggerReconnectRetainsCaptureAndRedactsStatus, TestObserverResubscriptionUsesFrozenArtifactRoute, TestClientPreparationLoggingDoesNotInspectCauseOrPanic, TestArtifactLoggingContainsPanicValuesAndReporterPanics, TestDiagnosticsNeverInspectArbitraryErrors, TestLoggingHandlerPanicsDoNotEscape, ExampleWithLogger; TestClientLoggingAfterHookPanicPreservesRuntimeEffectAndCheckpoint verifies the actual returned-effect append RPC and exact success checkpoint despite after-hook failure and handler panic. TestClientLoggingReplayFailureRetainsArtifactRouteAndGeneration verifies notifier-failure resubscription on the same generation, explicit override/client fallback and custom-handler identity across later default changes, with recording and panicking handlers. These use the production runtime over bufconn, not a live kernel; no exactly-once guarantee is implied beyond controlled invocations. Borrowed handlers are never closed. Callers own concurrency, cooperative handler lifetime (no self-joining client Close), handler-added fields/mutable state, application logs and explicit error reporters. Kernel exception-message fields and returned error graphs are outside the log-redaction contract
Constructor dependencies / C# service providerGo-specific: the diagnostic option does not bind *slog.Logger; explicit constructor closures or provider bindings remain requiredTestLoggerOptionIsNotAConstructorService; the container-free resolver rejects zero logger construction. Provider API and root dependency graph are unchanged

See Use one application-owned logger.

Go-specific: WithGRPCStatsHandler(stats.Handler) borrows a trusted handler for every owned connection generation, including reconnect. This is the bounded extension approved in #53, not C# interceptor parity. The C# connection ownership/lifecycle comparison below remains authoritative for existing behavior.

TestGRPCStatsHandlerValidationAndLastWins covers nil/typed-nil rejection, borrowed-channel conflicts in both option orders, last-wins precedence and handler ownership. TestGRPCStatsHandlerOwnedGenerationsUnaryAndStream exercises real validating TLS connections, unary and streaming callbacks on initial and replacement owned channels, and verifies that neither handler is closed. Trusted callbacks must preserve contexts, return promptly and support concurrent use; arbitrary callback safety is not enforced. No arbitrary dial options, interceptors, retries or stronger write-outcome guarantees are added. The pinned otelgrpc consumer remains separate under #80.

C# reference: Cratis/Chronicle revision 2e31b0dfba489159b3db323238f16d0f277056b4, paths below relative to Source/Clients/. Generated contracts independently pin Chronicle 19.32.3, commit e72af7ead164425141f29db61a9fe7b4915767e6. That release adds generated contracts/alerts and contracts/eventsources packages and EventSource fields on append requests and event contexts; the SDK has no public surface for alerts or event-source registration yet and leaves EventSource unset. Real-kernel evidence uses 19.32.3-development, including test-owned TLS/TCP connection interruption and recovery against a running kernel. Whole-kernel restart and a real multi-node deployment remain unverified. SDK release numbers are independent of protocol versions.

Registration, namespace, serialization and concurrency corrections follow v19.29.4 (ae5e00a8): Source/Clients/DotNET/Events/EventTypes.cs, Source/Clients/DotNET/EventStoreNamespaceName.cs, Source/Infrastructure/Schemas/{TypeFormats,JsonSchemaExtensions}.cs, Source/Infrastructure/Json/ExpandoObjectConverter.cs, Source/Kernel/Storage.MongoDB/ExpandoObjectConverter.cs, and Source/Kernel/Core/{EventTypes/EventTypeRegistrar,EventSequences/Concurrency/ConcurrencyValidator}.cs (repository-root paths).

Statuses: Implemented means the named behavior has executable regression evidence; Partial names an implemented subset; Not implemented claims no usable surface; Go-specific identifies an intentional translation. The evidence column names test functions or the actual deterministic generation check, not source reading alone. Status applies to the row’s stated contract, not the entire C# feature family.

Read evidence at its actual scope:

  • Compiler and source-derived goldens check declarations and wire shape, not execution of the C# client.
  • Captured .NET fixtures are identified explicitly with their source and serializer profile; they do not qualify unrelated codecs or generations.
  • Go transport tests exercise production SDK paths against controlled replies. Named kernel tests exercise their stated profiles on the pinned server, not every protection route, restart or multi-node deployment.
  • Compiling examples and SDK adapter tests do not establish an Arc.Go consumer workflow. Borrowed-facade adoption is tracked separately in Arc.Go#29.
  • Native minimum-Go build/unit checks, integration checks and the hosted CI matrix answer different questions. Test references here are not a new run report or a claim that every gate passed on the latest source state.

The binary slice admits only these acyclic, ASCII-named shapes:

  • Event binary leaves ([]byte, including named slices over built-in byte without custom codecs) and one nullable pointer: captured BinaryEvent.Payload / Optional writes, reads and schemas in serialization/testdata/binary/profile.json, plus BinaryChanged.Payload / Optional kernel readbacks.
  • Binary event leaves in acyclic nested objects, including pointers to objects: captured BinaryEvent.Nested.Inner and the kernel event-history readback of BinaryChanged.Nested.Inner.
  • Read-model binary leaves or one nullable pointer emitted at the root, including promoted embedded leaves: captured BinaryModel.Payload / Optional schemas and Expando conversion pairs, plus BinaryWitnessModel.Payload / Optional kernel Get readbacks. Named/promoted declarations reuse the qualified emitted representation; they are not new kernel shapes.
  • Ordinary From AutoMap between identical binary leaf representations with ASCII names: TestKernelBinaryEventsProjectionAndReadModel uses only From for root Payload / Optional under Preserve and CamelCase. All kernel readbacks above belong to that same pinned witness.

Refused: binary copies through Join or VariantOf (including entering handlers and generated joins), any recursive graph containing binary (even with recursion only in an ordinary sibling), non-ASCII serialized names anywhere in the graph, nested read-model binary, whole-object and explicit binary copies, binary collections/maps/derived placements/concepts/protection/indexes/unique constraints/ subjects, migrations, literals/initial values/arithmetic, identity/key/correlation uses and runtime ordinary-scalar profiles. Collection and map capture controls are not admission evidence. Kelvin sign and long s names are refused rather than relying on different CLR ordinal and Go EqualFold classes. Reducer payload conversion retains the captured root-leaf profile; no reducer policy changes.

Surface / C# referenceGo surface and statusExecutable evidence / remaining boundary
Canonical protobuf / Kernel/Protobuf (repository root)Implemented: public contracts/, canonical embedded descriptor, immutable source/tool pinsTestCanonicalDescriptorIsEmbeddedAndCopied; scripts/generate-contracts.py --check; TestKernelRegisterAppendRead. No .NET/sibling checkout needed to generate
URI/discovery/balancing / Connections/ChronicleConnectionString*, ChronicleServerAddressResolver, ILoadBalancerStrategy, DotNET/ChronicleOptions.LoadBalancerStrategy, ChronicleConnection.cs:133,299–300 at 2e31b0dfba489159b3db323238f16d0f277056b4Partial overall: multihost/SRV, name-server override and built-in strategies; Implemented borrowed LoadBalancer via WithLoadBalancer, once per attempt including single addresses and reconnectExisting URI/discovery tests plus TestLoadBalancerSelectsEveryGenerationAndCopiesURICandidates, TestLoadBalancerSRVRefreshesCandidates, TestLoadBalancerReceivesSRVPriorityWeightOrderWithoutMutation, TestLoadBalancerFailuresRetryBeforeOAuthOrRPC, TestLoadBalancerAttemptCanceledByClose, TestLoadBalancerValidationAndLastWins; kernel witness TestKernelCustomLoadBalancerSelectsOAuthAndGRPCRelay. Go rejects URI-strategy and borrowed-channel conflicts instead of overriding URI selection, never disposes custom strategies, and always retries selection failures even for wrapped authentication statuses. API-key/certificate URI modes remain unsupported; discovery is bounded to 64 endpoints
TLS/OAuth / Connections/OAuthTokenProvider, AuthenticationClientInterceptorImplemented for TLS and selected-endpoint client-credentials acquisition/cache/refreshTestOwnedTLSAndOAuthShareTrustPolicy, TestOAuthSingleFlightAndRefreshFallback, TestTokenWaitHonorsCancellation, TestInvalidTokenResponsesFailClosed, TestRefreshFailureUsesCompletionTime, TestConnectionLossAndRejectedOAuthRecover, TestExternalTokenInvalidation; rejected credentials are invalidated, with no transparent auth retry, disk token cache or external authority URI
Connection lifecycle / Connections/ChronicleConnection, ConnectionWatchdog, CompatibilityValidator; ConnectionLifecycle.cs:102–156 at 2e31b0dfba489159b3db323238f16d0f277056b4Implemented generation supervision, stale-heartbeat detection, reconnect, readiness and joined shutdown; Go-specific WithOnConnected/WithOnDisconnected, ConnectionEvent, ConnectionHookExisting supervision/shutdown tests plus TestConnectionHooksPairReconnectAndClose, TestConnectionHooksConcurrentEventSerialTransitionsAndCoalescing, TestConnectionHooksCanCallClientWhileRegistrationPending, TestConnectionHooksCloseContextBoundsJoin, TestConnectionHooksPanicsContainedAndLogged, TestConnectionHooksFailedStartupFiresNothing, TestConnectionHooksSkipKeepAliveOnlyPairsAtShutdown, TestConnectionHooksNilRejectedAndCaptureFrozen; kernel witness TestKernelConnectionHooksPairRealReconnectAndClose. Construction-time accumulating registration replaces runtime +=/-= (dedupe is moot; Go functions have no handler identity). Async dispatch never gates reconnect and Connected cannot fail the connection, unlike C# AggregateException rollback. Unstarted generations coalesce; delivered Connected pairs with Disconnected even on Close/Shutdown. Connected means authenticated protocol readiness, not registration or attachment. Unary dispatch still rechecks generation cancellation after token callbacks; registration sends are not attachment or durable checkpoint evidence
Store/namespace / DotNET/ChronicleClient, EventStore, Registrations/*Implemented for cached handles, ensure/list, separate store/namespace barriers, event registration outcomes/retries and automatic replayTestStoreRegistrationCacheAndNamespaceIsolation, TestRegistrationFailureDoesNotPoisonCache, TestAutomaticReplaySharesStoreDefinitionsAndSeparatesNamespaces, TestFailedPassReportsProgressAndRetriesInBackground, TestReplayBarrierBlocksAppendUntilAcknowledged, TestSingleFlightRetriesAndSnapshots, TestCanceledWaiterDoesNotCancelOwnerAndFailureCanRetry, TestKernelReconnectReplaysRegistrationAndPreservesHandles. Bounded runtime projection additions are implemented; runtime registration of other artifact families, replacement and eviction remain unsupported. Startup preparation and registration of supported artifact families are described below
Offline selected-store catalogs / DotNET/ChronicleClient.cs:GetEventStore, DotNET/EventStore.cs:EventTypes,ReadModels (baseline revision above)Go-specific: Client.Catalogs(StoreName) exposes the existing frozen registry without constructing a store; connected handles share the same store bindingTestCatalogsMatchConnectedStoreAndBindProducer, TestCatalogsAreFrozenStoreReplacementsWithoutIO, ExampleClient_Catalogs; naming, producer identity, ForStore sequence binding, store replacement and immutability match connected descriptors. No registration/readiness claim; C# has no equivalent offline accessor
Event declarations / DotNET/Events/EventTypeAttribute, EventTypesPartial: Registry, RegisterEvent[T], immutable events.Type, Descriptor, CatalogTestRegistration, TestConcurrentDuplicateRegistration, TestStoreRegistrationCacheAndNamespaceIsolation, TestRegistrationValidationOptIn, TestKernelSchemaValidationPreservesExistingGeneration, TestKernelGenerationWithoutMigrationsMatchesCSharp; historical generations and migrations are detailed in the event-evolution rows below; model-bound and descriptor metadata are detailed separately
JSON/schema / DotNET/{ChronicleClient,ChronicleOptions}, DotNET/Events/EventSerializer, schema generatorPartial: one shared field plan; declaration-order objects and default System.Text.Json string escaping, preserved spelling, explicit policies/tags, Fundamentals scalars/concepts, nesting, promoted fields and typed collectionsTestDeclarationOrderMatchesCSharpGolden, TestDefaultEscapingMatchesCSharpGolden, TestDefaultEscapingAllASCII, TestEmbeddedFieldsFollowEncodingJSONOrder, TestOrderedEmbeddedFieldsHonorNamingAndOmission, TestSchemaAndSerializationShareNames, TestNumericFormatsMatchKernel, TestNullableScalars, TestDictionaryIntegerPrecision, TestUnsignedMongoDBRange, TestOmitZeroMatchesEncodingJSON, TestKernelScalarAndNullableRoundTrips, TestKernelDictionaryPrecisionGuard, TestUnsupportedShapesFailBeforeRegistration; enum profiles beyond the declared Int32 subset, custom codecs, unsupported binary placements, unregistered/protected polymorphism and GeoJSON fail explicitly. Explicit unprotected derived families are detailed below. Protection classifications are detailed below. Dictionary ordering and encoder limits are described below. Concrete recursive schemas/codecs are covered under projections part 3
Binary (byte[]) / Source/Infrastructure/Schemas/TypeFormats.cs:43,101, Source/Clients/DotNET/Schemas/JsonSchemaGenerator.cs:358–370, Source/Clients/DotNET/ReadModels/ReadModelJsonSerialization.cs:129–134 at Chronicle ae5e00a8 (19.29.4); Source/DotNET/Fundamentals/Json/JsonValueExtensions.cs:127–129,210–211 at Fundamentals 14037b1f (7.19.6)Partial: built-in []byte and named slices over built-in byte are base64 string leaves; one nullable pointer and nested event object members share the frozen plan; read models admit only emitted root binary leaves (including promoted embeddings); nested read-model binary and binary arrays are refused before registrationActual packaged binary fixture; TestBinaryPackagedWritesMatchCSharp, TestBinarySchemaMatchesPackagedGenerators, TestBinaryReadsFollowQualifiedProfile, TestBinaryMissingNullEmptyAndNullable, TestBinaryMissingFieldsPreserveAbsentEmbeddedPointers, TestBinaryFreeArrayDecodeAllocationsIgnoreAbsentItemGraph, TestBinaryDecodedValuesDoNotAliasInput, TestBinaryFieldMetadata, TestScalarArrayFieldsHaveNoElement, TestBinaryCaptureSourcesRemainOptInAndPinned, TestBinaryCaptureValidationRejectsIncompleteEvidence. C# class versus record required-list controls are captured; Go retains existing slice/pointer omission and value-struct required rules. Go refuses captured C# whitespace reads and null array elements; no unpadded/URL-safe/nonzero-padding-bit acceptance. [N]byte remains an integer array
Binary kernel conversion / Source/Kernel/Storage.MongoDB/BsonValueExtensions.cs:34–36,224–233 at Chronicle ae5e00a8; Source/Kernel/Core/Projections/Engine/Expressions/EventValues/EventValueProviderExpressionResolvers.cs:113–119,139–158, Source/Kernel/Storage.MongoDB/BsonValueExtensions.cs:176–182 at the same revisionPartial: binary uses event payloads (including nested objects), emitted root read-model leaves and qualified identical-representation leaf-to-leaf From AutoMap copies only; Join and VariantOf binary copies and recursive binary graphs are refused; field metadata distinguishes Binary from primitive String, with IsPrimitive and precomputed ContainsBinary capability checksTestKernelBinaryEventsProjectionAndReadModel appends Go values and raw packaged C# payloads, then compares typed event reads (including nested binary) and emitted root leaf AutoMap model reads under both naming policies with generation validation enabled. The former whole-object Nested.Inner AutoMap control is removed, not generalized into a supported nested read-model profile. TestBinaryCapabilitiesRefuseBeforeIO enumerates the refused capabilities. TestBinaryProjectionMappingsRequireSameRepresentation, TestBinaryExplicitProjectionMappingsAndExpressionsRefuse, TestBinaryProjectionKeysAndJoinsRefuse, TestBinaryAdditionalProjectionBoundariesRefuse, TestBinaryUnicodeAutoMapRefusesBothDirectionsAndJoins, TestBinaryNamingRebindRevalidatesFinalGraph, TestBinaryReadModelIdentitiesRefuseBeforeRegistration, TestBinaryInitialValuesRefuse, TestRuntimeOrdinaryProjectionProfilesRefuseBinary, TestBinaryNamingRebindPreservesRepresentation, TestBinaryUnsupportedPlacementsFailBeforeRegistration, TestBinaryConceptsAndUnusedDerivativesRefuse. TestBinaryArraysFailBeforeRegistration refuses all binary collections, including named/nested binary arrays. The pinned kernel preserves Chunks:["","AQ==","+/8="] in event history but returns Chunks:[[],[{}],[{},{}]] from projected model Get for both Go/C# producers and naming policies. Its event-value converter recurses with the array schema instead of the item schema, enumerates each byte array into a list of bytes, and the BSON converter’s primitive-byte fallback produces empty documents: lost bytes cannot be repaired by the client (Chronicle#4595). The witness now asserts registration refusal for that captured control and compares every admitted leaf case without accepting the corrupt representation. TestBinaryUniqueConstraintsRefuseBeforeRegistration, TestBinarySubjectsRefuseBeforeRegistration and TestBinaryIndexesRefuseBeforeRegistration cover tags and explicit declarations, including indexed/unique objects containing binary. The pinned kernel’s Source/Kernel/Core/Events/Constraints/UniqueConstraintDefinitionExtensions.cs:GetPropertiesAndValues at ae5e00a8 hashes ToString(), collapsing every byte array to System.Byte[]; Source/Clients/DotNET/SubjectResolver.cs:ResolveFrom likewise uses ToString() rather than the base64 wire value. Maps, derived variants, concepts, protection/index declarations (including WithIndexes), unique constraints, subjects (including WithSubjectProperty and ID fallback), explicit projection mappings, initial values, runtime ordinary-scalar profiles, literals and correlation/identity uses remain refused; AutoMap with binary requires qualified ASCII names and binary leaves at both endpoints, never binary-owning objects. Whole-object copies can hit the pinned converter’s unconditional single-value unwrap, recursively converting byte arrays against an object schema into lists. TestBinaryObjectAutoMapRefusesEvenIdenticalRepresentations guards From/Join and naming-recompiled graphs independently of read-model admission. TestBinaryReadModelOnlyAdmitsRootLeaves refuses arbitrary nested model shapes instead of extending the proof; nested event payloads remain supported. No protected binary, explicit binary mapping or arbitrary custom codec claim
Binary admission boundaries / Source/Kernel/Core/EventSequences/Migrations/{EventMigrationExpressions,EventTypeMigrations}.cs, Source/Kernel/Storage.MongoDB/PropertyExtensions.cs:18–19, Source/Kernel/Storage.MongoDB/ExpandoObjectConverter.cs:22–90,330–339, Source/Kernel/Storage/WellKnownProperties.cs, Source/Infrastructure/Properties/PropertyPath.cs:26–31,365–406, Source/Infrastructure/Properties/DerivedPropertyFunctions.cs:41–48, Source/Infrastructure/Json/ExpandoObjectConverter.cs:51–57,104–106, Source/Infrastructure/Schemas/JsonSchemaExtensions.cs:97,128, Source/Kernel/Core/Projections/Engine/Expressions/EventValues/LiteralExpressionResolver.cs:40–44 at Chronicle ae5e00a8 (19.29.4)Go-specific fail-closed: all migrations with binary-containing endpoints are unsupported, including identity/pass-through; binary-containing plans require ASCII, case-insensitively unique, non-reserved property names throughout their graphs, including ordinary siblings, promoted/nested fields and registered derived variants; binary-only violations return ErrUnsupported at compilation and every naming recompile; exact duplicates retain ErrInvalidConfiguration; real compile errors take precedence only in binary-containing graphs, while binary-free types retain immediate duplicate refusal and existing naming behavior; binary identities include case-insensitive id and _idTestBinaryMigrationEndpointsRefuseBeforeCallbacks covers authoring and catalog revalidation for every operation, nullable/nested endpoints and both directions; TestBinaryCapabilitiesRefuseBeforeIO includes migration cases. TestBinaryNamesRefusePlan, TestBinaryNamesValidateDerivedVariantMembers, TestBinaryNamesRefuseNonASCIIRegardlessOfCaseFolding and TestBinaryNamesRefuseNonASCIIUnderEveryNamingPolicy cover both field orders, cross-level path partitions, reserved function/accessor tokens, ASCII/Unicode case collisions, ordinary siblings, nested/collection/promoted fields, used/unused derived variants and naming recompilation. Simple names start with an ASCII letter, followed by ASCII letters, digits or underscores; no dots, expression syntax or underscore-prefixed names. Every nested case variant of id is refused across the binary-containing graph; MongoDB recursively merges id/_id, restores only id/Id and can lose nested ID bytes or overwrite Id/_id siblings. Root identity handling otherwise stays unchanged. The underscore-prefix refusal includes the full pinned sink-owned set: __lastHandledEventSequenceNumber, __initialized, __subject, __subjects. Case-insensitive value is also refused in any object containing binary, preventing the single-value unwrap. TestBinarySinkAndValueNamesRefusePlan, TestBinaryValueNamesRefuseAfterNaming, TestBinaryCompileErrorsPrecedeDeferredDuplicates, TestBinaryFreeSinkAndValueNamesRemainAdmitted and TestBinaryFreeWholeObjectAutoMapRemainsAdmitted cover these boundaries, diagnostic identity and ordinary-type controls. The full pinned derived/accessor set is Week (with or without ()), $this, plus the *NotSet* sentinel; true/false also preempt ordinary event expressions. ASCII sibling comparison agrees with CLR ordinal casing and Go EqualFold; all non-ASCII names are refused. TestBinaryNamesRefuseGoFoldAliases covers Kelvin/long-s pairs in both field orders; TestBinaryASCIIDecodeSelectsOnlyIntendedField checks exact and differently cased ASCII input. TestBinaryJoinAutoMapRefusesBeforeRegistration and TestBinaryVariantAutoMapRefusesBeforeRegistration refuse unwitnessed copies with value-free ErrUnsupported. TestBinaryCapabilityMetadataIncludesRecursiveOwners and TestBinaryGraphRefusesUnrelatedRecursiveBranch refuse recursive binary graphs; TestBinaryFreeDuplicatePrecedesLaterUnsupportedType pins origin/main duplicate precedence. TestBinaryFreeNamesKeepAdmissionAndRecompilation, TestBinaryFreeNamingRetainsExactDuplicateRefusal, TestNonBinaryDottedCollisionKeepsFirstMatchAndSnapshot and TestNonBinaryCollisionKeepsArtifactNamingBehavior retain binary-free naming, lookup, snapshots, exact-duplicate refusal and artifact rebinding. TestBinaryAmbiguousPathsRefuseBeforeIO, TestBinaryConstraintRebindRefusesNewPathAmbiguity, TestBinaryProjectionRebindAmbiguityRefusesBeforeIO, TestBinaryModelNamingAmbiguityRefusesBeforeIO and TestBinaryModelKeysRefuseNewNamingAmbiguity cover artifact admission and client construction. TestBinaryRebindRechecksEveryKeyLikePath independently checks From/Join/removal keys and parents, composite parts, model/variant keys and child identities in lowered graphs; TestBinaryAutoMapAliasCandidatesRefuseBeforeIO and TestBinaryAutoMapChecksGeneratedTargetCandidates refuse generated paths with hidden binary candidates, including excluded owning objects; TestBinaryPathCapabilityIncludesAmbiguousNestedCandidates, TestBinaryDottedInitialValuesRefuse, TestBinaryReadModelIdentitiesRefuseBeforeRegistration, TestBinaryExpressionTextDoesNotImplyEventPath cover detached nested-path ambiguity, emitted root ownership, sink key aliases and expression-kind dispatch. Kernel split/combine operate on JSON strings and then convert each migrated generation with its target schema; no packaged binary migration qualification exists. Use qualified payload/AutoMap paths only; do not migrate binary-bearing generations through generic operations
Correlation/auditing / DotNET/Auditing, Identities/Identity; connection correlation interceptorImplemented for immutable explicit correlation, ordered causation and deduplicated actor chainsTestImmutableMetadata, TestIdentityDeduplicatesCycles, TestCorrelationJSON, TestAppendMetadataAndNamedTags, TestDotNETGuidVector, TestDateTimeOffsetPreservesOffsetAndTruncates; no implicit process/program root causation or ambient context
Ordered additional event information / DotNET/Events/EventSerializer.cs:Serialize,ProvideAdditionalInformationFor at 2e31b0dfba489159b3db323238f16d0f277056b4Go-specific bounded events.EventEnricher and expiring EventContent: sequential providers share ordered content, but can only edit declared fields through the frozen codec plan; no arbitrary JSON/schema extension or DI discoveryTestAuditingSelectsSnapshotsAndRunsDuplicateEnrichersInOrder, TestEventContentOwnsOrderedValuesAndExpiresEachHandle, TestEventContentReplacementUsesNormalGraphChecks, TestEventContentUsesRegisteredDerivedPlan, TestEventContentLateCodecCannotPublishIntoNextProvider; reference
Actor/correlation/causation providers and root / DotNET/{ChronicleClient,EventSequences/EventSequence,Identities/BaseIdentityProvider,Auditing/CausationManager}.cs at 2e31b0dfba489159b3db323238f16d0f277056b4Go-specific borrowed context-first providers and opt-in root. Explicit correlation presence wins (zero generates fresh); handled empty causation masks context; root preserves upstream Root. Go defaults remain NotSet/fresh missing correlation/no implicit root, not C# System/process-root defaultsTestExplicitZeroCorrelationBypassesProvider, TestHandledAuditValuesMaskParentAndPreserveRoot, TestExplicitNotSetHasContextPresence, TestUnitOfWorkResolvesBeginThenStagesOnce, TestHandledZeroStageCorrelationDoesNotInheritBoundCorrelation; callbacks never rerun at commit/reconnect
Outgoing effect boundary / same C# serializer and event-sequence sourcesGo-specific fail-closed, payload-free callback errors; tagged subject immutable, opaque custom subject resolver read-only unless explicit subject bypasses it; SDK reactor built-ins preprepared before custom effects without growing EventAppenderTestEnrichmentFailuresArePayloadFreeAndPreventAllSDKIO, TestProviderCancellationErrorIsNotCallerCancellation, TestEnricherCanCloseClientWithoutHoldingPreparationLease, TestEnrichmentFreezesSubjectAndRefusesOpaqueDependencies, TestReactorPreparesAllBuiltinsBeforeAnyCustomEffect, TestProtectedRevisionRunsEveryProviderOnce, TestUnprotectedRevisionUsesOutgoingContentAndAuditOnce; custom appenders and multiple effects do not gain transaction atomicity
Enrichment/audit kernel witnessesGo-specific integration contract, not executed-.NET equivalenceTestKernelEnrichmentAuditAppendUnitReturnedEffectAndRevision checks stored protobuf content, actor, correlation and causation for immediate append, unit, returned effect, and unprotected revision against the pinned kernel, including the revision system-event audit. Revisions retain the kernel-generated fresh correlation (Kernel/Core/Sequences/Revise.cs:70), not the provider’s selected correlation. C# references above are source evidence only. Identity rename’s separate bounded workflow is described above
Single append / DotNET/EventSequences/EventSequence, AppendResultImplemented for single append, routing, subject/time, tags, named tags and complete resultsTestAppendScopesOnTheWire, TestAppendMetadataAndNamedTags, TestAppendDomainRejectionsPreserveEveryDiagnostic, TestMalformedAppendResponsesFailClosed, TestKernelRegisterAppendRead
Concurrency / DotNET/EventSequences/Concurrency/OptimisticConcurrencyStrategy, ConcurrencyScopeConvertersImplemented for default/resolve/exact/no-match/no-check single-event scopesTestAppendScopesOnTheWire, TestProtectedAppendCannotSilentlyDowngrade, TestAppendValidationDoesNotDispatch; TestKernelExactIsAnUpperBound accepts absent/lower tails and rejects greater tails; the smoke test rejects a second protected-empty append
Configurable concurrency / DotNET/ChronicleOptions.cs, DotNET/EventSequences/Concurrency/{ConcurrencyOptions,IConcurrencyScopeStrategy,OptimisticConcurrencyStrategy}.cs (baseline revision above)Implemented: WithCheckFirstAppendIntoAScope, WithDefaultConcurrencyStrategy, ConcurrencyScopeStrategy.GetScope(ctx, sequence, filter)TestFirstAppendPolicyAndSubjectsAcrossAllPaths, TestDefaultStrategyReplacesAutomaticScopesAndExplicitScopesWin, TestKernelConfiguredFirstAppendRejectsConcurrentWriter; defaults remain optimistic with first-append protection off. Explicit scopes bypass the replaceable strategy; Resolve still honors first-append policy. Strategy callbacks can read the sequence tail themselves or return Resolve for exactly one deferred tail read
Selected-filter concurrency / DotNET/EventSequences/Concurrency/{ConcurrencyScopeStrategies,IConcurrencyScopeStrategy,OptimisticConcurrencyStrategy}.cs, DotNET/ChronicleOptions.cs (baseline revision above); Arc Source/DotNET/Chronicle/Commands/ConcurrencyScopeBuilder.cs at 7c1e78075b737df64f69fddfaae83374f75e3612Implemented: Sequence.ResolveScope(ctx, ScopeFilter) (Scope, error) invokes the same configured strategy/first-append policy as automatic append resolutionTestResolveScopeIndependentTargetsStageWithoutReresolving, TestResolveScopeUsesCustomStrategyAndFirstAppendPolicy, TestResolveScopeExplicitStrategyExpectationsDoNotReadTail, TestResolveScopeValidationCancellationAndFailuresNeverAppendOrRetry, TestClientConfiguredPolicyResolvesExplicitFilters, ExampleSequence_ResolveScope; independent A/B expectations survive staging/batch dispatch. Go accepts an already normalized filter rather than Arc attributes; no append, retry or Arc dependency
Declared subjects / DotNET/SubjectResolver.cs, DotNET/EventSequences/EventSequence.cs:409,561,738 (baseline revision above)Go-specific: events.WithSubjectResolver[T](func(T) (events.Subject, bool)) on RegisterEvent[T]; append override → declaration resolver → source IDTestSubjectResolverDeclarationAndLookup, TestFirstAppendPolicyAndSubjectsAcrossAllPaths; typed callback and compiled subject tags both use the existing resolver slot, accept appended values and pointers, and resolve once at staging for units of work; false/nil represents C# null. Existing nonblank append-subject validation also applies to resolved subjects
Sequence-number values / DotNET/EventSequences/EventSequenceNumber.cs:15–128 at 2e31b0dfba489159b3db323238f16d0f277056b4Implemented constants/predicates and sentinel preservation: events.{First,Unavailable,Max,BeforeFirst}, SequenceNumber.{IsActualValue,IsUnavailable,IsBeforeFirst}; Go-specific checked pure Next, Add(uint64), Subtract(uint64) returning (SequenceNumber, error)TestSequenceNumberConstantsAndPredicates, TestSequenceNumberSentinelReceiversArePreserved, TestSequenceNumberCheckedArithmetic, TestSequenceNumberNextActualBoundaries, TestSequenceNumberArithmeticRoundTrips, ExampleSequenceNumber_Next; all three high values are non-actual and preserve a sentinel receiver, including BeforeFirst.Next. Actual overflow/underflow/reserved crossing returns Unavailable plus ErrSequenceNumberRange (errors.Is), not C# unchecked wrapping; unsigned amounts replace ulong/int/sequence-number operators, so callers reject negatives before casting. TestSequenceNumberHelpersPreserveServerNextContract keeps Sequence.Next(ctx) distinct; TestSequenceNumberSentinelsPreserveConcurrencyProtocol keeps exact sentinels invalid and no-match encoded as Unavailable plus explicit flag, never raw BeforeFirst. Numeric/JSON tests do not establish full uint64 BSON range parity (#8)
Empty concurrency dimensions / DotNET/Events/EventSourceType.cs, DotNET/EventSequences/Concurrency/ConcurrencyScopeConverters.cs:26-34 (baseline revision above)Implemented: empty source classification/stream type/stream ID are non-narrowing, like reads; source IDs and scope labels remain validatedTestEmptyScopeDimensionsAreConsistentWithTailReads; nonempty dimensions and append route defaults retain their existing wire spelling
Append operation metadata / DotNET/EventSequences/EventSequence.cs:463-469,606-613 (baseline revision above)Go-specific: AppendWithMetadata, AppendManyWithMetadata, AppendBatchWithMetadata return wrappers with Result() and outcome-independent Operation(); PreparedBatch.Operation() exposes staged metadataTestOperationMetadataSurvivesRejectionAndUnknownOutcome, TestManyAndPreparedOperationMetadata, TestLegacyResultLayoutsRemainUnchanged; store/namespace/sequence and distinct exact TypeRef generations are owned independently of committed-only Target. Existing AppendResult/BatchResult layouts and methods stay unchanged for Arc.Go and unkeyed literals; adding even a private metadata field would break those callers. Existing transaction results consequently retain their old layout rather than acquiring implicit metadata
Reverse event catalog / DotNET/Events/IEventTypes.cs:42-65 (baseline revision above)Implemented: Catalog.LookupID(TypeID) and Catalog.LookupRef(TypeRef) return (Descriptor, bool) including schema and Go typeTestSubjectResolverDeclarationAndLookup, TestHistoricalCatalogExactAndLatestLookup; missing IDs/generations do not match, current-ID lookup returns the highest registered generation
Canonical identities and names / DotNET/Identities/Identity.cs:28-33, DotNET/EventSequences/EventSequenceId.cs:26-66, DotNET/{EventStoreName,EventStoreNamespaceName}.cs (baseline revision above)Implemented: identities.Unknown(), identities.System(), events.{UnspecifiedSequence,SystemSequence,Outbox,Inbox,InboxPrefix,UnspecifiedSourceType}, SequenceID.IsEventLog(), metadata.{NotSetStore,SystemStore,NotSetNamespace}TestCanonicalIdentities, TestCanonicalSequences, TestCanonicalNames; identity functions return independent copies instead of mutable global values; existing EventLog and DefaultNamespace remain unchanged
Append results / DotNET/EventSequences/{EventSequence,IAppendResult}; Kernel/Core/EventSequences/EventSequence (repository root), baseline revision aboveGo-specific: C# exposes IsSuccess/Errors without a disposition. Single/batch errors-only failures are Unknown, with OutcomeUnknownError from the operation and Err(); the kernel cannot distinguish pre- from post-commit failures. Constraint/concurrency violations are Rejected, even with errorsTestAppendFailureDispositionAndErrorIdentity, TestAppendNeverRetriesAnAmbiguousWrite, TestCloseCancelsInFlightAppend; diagnostics and error identities preserved; callers must not treat errors-only results as safe to retry
Local append observation / DotNET/EventSequences/{IEventSequence.AppendOperations,EventSequence,AppendedEventWithResult} (baseline revision above)Implemented for nonempty append attempts: Sequence.OnAppend, owned AppendNotification and ordered AppendEvent identities for single/many/batch/prepared/metadata/named-tag pathsTestAppendNotificationsAcrossPathsAndDispositions, TestAppendNotificationsKeepRequestCorrelationAndGeneration, TestAppendNotificationSnapshotsDoNotAliasOtherSubscribersOrResults; one batch notification after the result, not a durable observer feed. Go carries source/type/generation/route/position rather than retaining C#‘s original object and full audit context
Command attribution and subscription ownership / DotNET/EventSequences/EventSequence.cs:80–83,470–490,805–837,872–922, DotNET/EventStore.cs:61,167,414–417; Arc Source/DotNET/Chronicle/Commands/TransactionalCommandScope.cs:83–102,132 at 7c1e78075b737df64f69fddfaae83374f75e3612Go-specific: explicit subscription/disposal shared per client/store/namespace/sequence like C# (low-level eventsequences.New remains handle-local), request correlation independent of response correlation, retained Unknown on transport/protocol/errors-only failures; callback panics become AppendCallbackPanicError without changing dispositionTestStoreSequenceHandlesShareAppendNotifications, TestConcurrentStoreSequenceCallsShareHandles, TestStoreSequenceRejectsInvalidIDs, TestAppendNotificationsRemainHandleLocal, TestConcurrentAppendSubscriptionsAndCommandAttribution, TestAppendCallbackCanReenterSubscribeAndDisposeDuringDelivery, TestAppendDisposalDoesNotWaitForAdmittedCallbacks, TestAppendCallbackPanicsPreserveDispositionAndOtherDeliveries, ExampleSequence_OnAppend; synchronous callbacks outside locks, no global interception. Unsubscribe stops admissions, not already admitted calls; join command work and synchronize shared state
Append origin attribution / DotNET/EventSequences/{EventSequence,AppendedEventWithResult}.cs, Arc Source/DotNET/Chronicle/Commands/TransactionalCommandScope.cs (revisions above; C# attributes by correlation only)Go-specific: comparable process-local eventsequences.Origin, NewOrigin, WithOrigin, OriginFrom, AppendNotification.Origin, UnitOfWork.Origin()TestConcurrentSameCorrelationUnitsAttributeNotificationsByOrigin, TestImmediateNotificationsInheritOriginAcrossPathsAndDispositions, TestPreparedNotificationUsesAppendOriginNotPreparationOrigin, TestOriginsAreUniqueUnderConcurrentAllocation, TestOriginContextInheritanceReplacementAndMasking, TestUnitOriginZeroAndRollbackLifetime, ExampleWithOrigin, ExampleSequence_OnAppend; Arc commands can share a reactor delivery or client-supplied correlation. Unit commits use a fresh Begin-assigned origin, immediate appends inherit append-time context, zero means unattributed. Tokens are never reused within a process, not durable or wire identities; no global attribution registry. Additive callback field; consumers receive SDK-constructed notifications rather than positional literals
Metadata-only append origin resolution / same C# append/Arc attribution references and revisions as above (no C# callback equivalent)Go-specific: eventsequences.AppendOriginResolver, chronicle.WithAppendOriginResolver, optional low-level AppendOriginResolverProvider, payload-free AppendOriginResolutionErrorTestAppendOriginResolverEveryVariantOnceWithActualContext, TestAppendOriginResolverHandledZeroAndUnhandledFallback, TestAppendOriginResolverFailuresRejectWithoutRPCNotificationOrPayload, TestAppendOriginResolverFailureBeforeAutomaticScopeRPC, TestPreparedAppendOriginResolverUsesDispatchContextOnly, TestUnitCommitBypassesFailingExternalAppendOriginResolver, TestUnitOriginCapabilityCannotAuthorizeOtherAppendsFromCallbackContext, TestConcurrentSameCorrelationCommandsResolveDistinctOriginsAndReenter, TestClientAppendOriginResolverFrozenAndSharedAcrossStoreCoordinates, TestClientNilAppendOriginResolverDisablesEarlierOption, ExampleWithAppendOriginResolver; handled selects even zero, unhandled falls back to OriginFrom, callback failures reject before RPC/notification without fallback. Actual dispatch context supplies metadata; synchronous borrowed callbacks run outside locks and must support concurrency. Only SDK-owned completion of the exact unit batch bypasses the resolver, not an inherited nonzero origin. No Arc dependency/context decorator, public result/configuration layout change or wire change. #47/#67 are SDK attribution contracts, not an Arc adoption claim; other clients/discarded operation contexts and durable broker identities remain outside scope
Transaction append observation / DotNET/Transactions/UnitOfWork.cs:406–470, DotNET/EventSequences/EventSequence.cs:805–837 (baseline revision above)Implemented: staging does not notify; nonempty Owner.Commit notifies through AppendPreparedBatch before unit completionTestUnitCommitNotifiesSnapshotBeforeCompletionEvenIfCallbackPanics, TestAppendNotificationsExcludePreparationRollbackAndEventlessCompletion, TestAppendNotificationsExcludeBeforeDispatchFailures, disposition matrix above. C#‘s interface remark excludes transactional staging, but actual commit calls the ordinary batch API. Empty/rollback/repeated completion cannot imply accepted events; pre-dispatch preparation failures remain returned errors, not notifications
Atomic batches / DotNET/EventSequences/EventSequence (AppendManyCore, AppendManyForEventSources, ResolveConcurrencyScopes)Implemented: AppendMany, AppendBatch, ordered Entry, LabeledScope, full BatchResultTestAppendManyRoutesAndStaticTagUnion, TestBatchPreservesOrderMetadataAndIndependentScopes, TestBatchScopeExpectationsAndResolution, TestBatchSnapshotsBeforeResolvingTail, TestBatchFailuresAndCompleteDiagnostics, TestKernelOrderedAtomicBatchAndHistory, TestKernelSameSourceBatchRoutesAndTagUnion; A1/B1/A2 is one atomic request, routed same-source batches retain the static-tag union
Eventless checks / DotNET/EventSequences/EventsWithConcurrencyScopes; Kernel/Core/Sequences/AppendMany*Validator (repository root)Implemented: protected empty AppendBatch and AppendManyTestEventlessProtectedBatchAndOlderKernelRefusal, TestResolvedEmptyEventlessScopeIsNotASuccessfulNoOp, TestKernelEventlessChecksAndUpperBoundExpectations; unsupported older kernels fail loudly
Event reads / DotNET/EventSequences/EventSequence (GetForEventSourceIdAndEventTypes, GetFromSequenceNumber, tail/next/has-events), DotNET/Events/EventContextImplemented: ReadSource, ReadFrom, Tail, Next, HasEvents; raw events.Appended and complete contextTestReadPreservesEnvelopeMetadataAndGenerations, TestTailPresenceNextAndHasEvents, TestMalformedReadsNeverProduceHistory, TestReadCancellationAndValidation, TestKernelOrderedAtomicBatchAndHistory; no pagination/live-feed claim or automatic generation decoding
Loaded-history concurrency primitive / DotNET/EventSequences/EventSequence, DotNET/Events/EventSourceId, baseline revision aboveGo-specific: ReadHistory, History.Scope; nonblank source IDs retained verbatim as in C#, other read dimensions still normalizedTestHistoryScopePreservesPaddedSourceID, TestHistoryUsesOnlyLoadedEventsAndNormalizedFilter, TestKernelOrderedAtomicBatchAndHistory; expectation comes only from loaded matching events, never a later tail; blank required sources remain invalid
Unit of work / DotNET/Transactions/{IUnitOfWork,UnitOfWork,UnitOfWorkLifecyclePolicy}Implemented for strict ordered staging, terminal completion, diagnostics, correlation and completion callback: transactions.UnitOfWork, OwnerTestStageSnapshotsEverythingAndPreservesNestedOrder, TestCommitDispositionsAreTerminalAndObservable, TestEmptyCompletionRollbackAndCancellation, TestConcurrentStageEnrollsEachCallContiguously, TestCommitFreezesParticipantsAndCancellationIsUnknown, TestKernelUnitOfWorkSnapshotsAndNestedOrder, TestKernelUnitOfWorkLoadedHistoryRejectsAllSources
Unit manager / DotNET/Transactions/{IUnitOfWorkManager,UnitOfWorkManager}Go-specific: explicit transactions.Begin, WithUnitOfWork, FromContext; no ambient manager or global correlation lookupTestStageSnapshotsEverythingAndPreservesNestedOrder, ExampleBegin; nested participants share the same unit, never the owner
Immutable transaction enrollment / DotNET/Transactions/UnitOfWork.AddEventsGo-specific: serialization at Stage; Sequence.PrepareBatch, immutable PreparedBatch.Merge, AppendPreparedBatch reuse the existing batch transportTestStageIsAtomicAndRejectsMetadataAndScopeChanges, TestScopeEventTypesJoinAsSets, TestTailFailureRejectsBeforeAppendAndDoesNotResolveDuringStage; no staging I/O, actor/correlation drift fails, conflicts do not partially enroll
Protected decisions / DotNET/ReadModels/DecisionReads, DotNET/Transactions/{DecisionReadCommitOwner,UnitOfWork.AddDecisionRead}Implemented for admitted optimistic guards: readmodels.DecisionsFor, DecisionReader.Admit/Get/GetDetached, opaque transactions.DecisionToken, UnitOfWork.Enroll, existing Owner.CommitTestKernelDecisionCompetingWriteRejectsEntireMultisourceBatch, TestKernelDecisionFirstEventAbsenceAndEventlessCompletion, TestKernelDecisionSimultaneousOwnersHaveOneWinner; no authenticated server-proof claim. Safety departures and protocol gaps are detailed below
Constraint declarations / DotNET/Events/Constraints/{ConstraintBuilder,UniqueConstraintBuilder,ConstraintConverters}Implemented: immutable constraints.UniqueValues / UniqueEventTypes builders, ordered composite paths across events, IgnoreCasing, additive RemovedWith, scope dimensions and sequence selectionTestConstraintRegistrationMatchesCSharpGoldenRequest compares a full protobuf request hand-derived from the C# converters; TestConstraintDefaultsAndSnapshotOwnership, TestMalformedConstraintDefinitionsFailBeforeRegistration, TestConstraintRegistryRejectsInvalidOrForeignDeclarations; explicit JSON paths replace CLR expressions; model-bound tags are also supported (see below)
Constraint registration / DotNET/Events/Constraints/Constraints, DotNET/EventStoreImplemented: Registry.AddConstraint, store-wide registration after event types, stage outcomes, retry, frozen per-store overrides and reconnect replayTestConstraintRegistrationOrderReplayAndAppendBarrier, TestConstraintRegistrationFailureIsReportedAndRetryable, TestConstraintSnapshotsAndStoreOverrides; no observer attachment claim; runtime constraint additions remain unsupported. See runtime projection additions for the bounded model/projection workflow
Kernel uniqueness/removal / DotNET/Events/Constraints, Kernel/Core/Events/Constraints/{UniqueConstraintValidator,UniqueEventTypeConstraintValidator} (kernel paths relative to repository root)Implemented: property ownership, removal, composite/cross-event uniqueness, event-type mutual exclusion and lifecycle cycles, batch rejection, route/sequence/namespace boundariesTestKernelUniqueValuesAndOwnerRemoval, TestKernelCompositeUniquenessAcrossEventTypes, TestKernelUniqueEventTypeLifecycleAndBatchCycles, TestKernelConstraintBatchRejectionsAreAtomic, TestKernelConstraintScopesSequencesAndNamespaces; rejected events are read back as absent, all enforcement remains in the kernel
Violation messages / DotNET/Events/Constraints/{Constraints,ConstraintViolation,WellKnownConstraintDetailKeys}Implemented: WithMessage, WithMessageProvider, complete constraints.Violation details and PropertyName / PropertyValue keys in single/batch resultsTestConstraintDetailsAndMessagesInEveryAppendResult, TestConstraintMessageTemplatesPreserveDetailsAndFallback, TestMessageDetailValuesAreLiteral, kernel composite-message test; Go eagerly resolves once per returned violation and keeps values literal
Observer-tail reads / DotNET/EventSequences/EventSequence.cs:GetTailSequenceNumberForObserverImplemented: Sequence.TailForObserver(ctx, eventTypes) reads the source tail for explicit declared types, not a checkpointTestCompletionUsesActualBatchTailsAndOriginalCoordinates, TestKernelOperationsCompletionReplayAndJobEvidence; explicit plan/snapshot types replace CLR handler discovery. Empty types fail rather than selecting every event
Read-model catalog / DotNET/ReadModels/{ReadModels,ReadModelTypeExtensions}, Sinks/WellKnownSinkTypesImplemented for explicit declarations, indexes, sink selection and registration replay: RegisterReadModel[T], readmodels.Model, Descriptor, Catalog, EventStore.ReadModelsTestReadModelRegistrationMatchesCSharpGolden, TestReadModelDefaultsAndCatalogIsolation, TestContainerNamesMatchCSharpDefaultNamingPolicy, TestReadModelRegistrySnapshotsAndConcurrentDuplicates, TestReadModelReplayBarrierAndNamespaceIsolation, TestReadModelRegistrationFailureDoesNotPublishReadiness, TestKernelReadModelRegistrationAndAbsence, TestPassiveReadModelRequiresObserver, TestReadModelPropertyOptionsAccumulate, TestGenericReadModelRequiresExplicitNames; no automatic producer discovery
One-shot model reads / DotNET/ReadModels/{IReadModels,ReadModels,ReadModelJsonSerialization}Implemented for kernel-backed reads: typed Reader[T].Get and raw Service.Get, explicit Exists and LastHandledTestReadModelPresenceAndCollectionNormalization, TestReadModelErrorsAndUnsupportedKernel, TestReadModelValidationNeverDispatches, TestKernelReadModelRegistrationAndAbsence; real-kernel evidence is registration plus absence. Presence is covered through bufconn; materializing state requires a projection/reducer
Supported typed model decoding / DotNET/ReadModels/ReadModels.cs:257–258, DotNET/ChronicleClient.cs:360–381 (baseline revision above)Implemented: typed Get, sessions, injected value/pointer models and typed Release use the registered frozen descriptor plan, as do watches/windowsTestTypedReadsUseFrozenNamingPlan, TestTypedNamingPlanPreservesMissingKeyAndDistinctID, TestTypedInjectionAbsenceNeverManufacturesState, TestReadModelPlanDoesNotReuseAnotherFieldsExactName, TestReleaseNeverUsesIndependentDeclaredIDAsSubject, TestReleaseAliasFilteringPreservesSubjectAndLineagePrecedence, TestReleaseExplicitSubjectCanSelectIndependentID; root Go ID → Id remains distinct from ExternalID tagged json:"ID", including missing/null fields and sink aliases. All three naming policies, concept codecs, collection nullability and fail-closed Release errors are covered. A missing/null/empty root ID never infers a protected-value subject from another declared ID field; explicit subjects and stored lineage retain precedence. Decode support does not imply the pinned kernel can register a projection schema containing both Id and ID; it rejects that shape
Hydration sessions / DotNET/ReadModels/{ReadModels,ReadModelSessionId}Partial: Reader[T].NewSession, Session[T].Get, Close(ctx) preserve coordinates and explicit cleanupTestReadModelSessionRetainsCoordinatesAndRetriesFailedCleanup, TestSessionCancellationStillRequiresDehydration, TestUnsupportedSessionsFailBeforeDispatch; projection-backed transport only. Reducer sessions fail explicitly. Classified projection sessions and passive/immediate Get return values the kernel released with each value’s original subject on Chronicle 19.32.2 or later (Chronicle#4561); older or unverified kernels refuse before RPC (TestProtectedProjectionRoutesUseKernelReleaseWithoutSecondDecryption, TestProtectedProjectionRoutesRefuseWithoutProtectedReleaseKernel, TestKernelModelHistoryProtectedReleaseProfile)
Protected-value release / DotNET/ReadModels/{ReadModelReleaser,ReadModelSubjectResolver}, Source/Kernel/Core/ReadModels/ReadModelsCompliance.cs (repository root, baseline revision above)Partial, Go-specific fail-closed behavior: Reader[T].Release, raw Service.Release, WithPII, WithSubjectPropertyTestReadModelReleaseFailsClosed, TestReadModelReleaseSubjectAndNoMetadata, TestReadModelReleaseMultipleSubjectGroups, TestReadModelReleaseNumericSubjects, TestReadModelReleaseRejectsMalformedLineage, TestReadModelMetadataUsesSerializationPlan; see the per-behavior compliance rows below for type/container classification, confidentiality, lifecycle APIs and kernel limitations
Projection basic declarations / DotNET/Projections/{ProjectionBuilderFor,Projections}, ModelBound/ModelBoundProjectionBuilderPartial: model-bound and fluent front ends, one immutable compiler/encoder, frozen catalog resolution, store registration and reconnectTestBothFrontEndsMatchCSharpBasicGolden, TestProjectionDiscoveryRegistrationAndFrozenReplay, TestProjectionStartupValidationIsAtomicAndStoreLocal, TestKernelProjectionMaterializesModelBoundAndPassiveReads; attribute-by-attribute boundaries below
Reducers / DotNET/Reducers/*Partial: active and passive folds with explicit callbacks and convention discoveryPer-behavior evidence and limits in Reducers below
Event seeding / DotNET/Seeding/*Partial: explicit preparation, scoped builders, final registration and kernel idempotencePer-behavior evidence and kernel limits in Event seeding below
Watches and read-model reactorsPartial: unclassified projection changes and local fold notifications; raw/typed materialized windows validate server-released values for the admitted MongoDB root-string protection profile. Classified Watch is unsupportedPer-behavior evidence in Read-model watches and reactions; no blanket protected-route safety or durable cursor/resume promise
Observer administration, jobs and completion waitsImplemented for the per-feature surface belowSee Observer and job administration; durable event subscriptions remain Not implemented

The Kotlin and TypeScript client comparisons informed vocabulary and transport translation, not behavioral authority. Unlike TypeScript’s plaintext/certificate URI conveniences, unsupported options are rejected. The canonical descriptor and public package ownership follow the cross-language contract publication convention without a separate Go module.

C# baseline: ReadModels.cs:262–328,397–449 and Reducers.cs:259–350 under Source/Clients/DotNET at 2e31b0dfba489159b3db323238f16d0f277056b4. Release ownership and capability boundaries use v19.29.4: Source/Kernel/Grpc/ReadModels/ReadModels.cs, Source/Kernel/Core/ReadModels/MaterializedReadModelStore.cs, Source/Kernel/Core/ReadModelExplorer/ReadModelSnapshotReader.cs, and Source/Kernel/Core/Projections/Projection.cs.

  • Partial: raw/typed collections, default versus explicit Unlimited routing, globally bounded generation-aware reducer folds, and admitted source-ID root projection snapshots, including classified models on kernel 19.32.2 or later. TestKernelModelHistoryProjectionCollectionsAndCorrelationGroups proves materialized absence/deletion, bounded/passive replay, namespace isolation, A/B/A global grouping, first-event occurrence and ambiguous {} deletion history. TestKernelModelHistoryReducerCollectionRoutingAndDeletion separates materialized default reads from active/passive local folds and checks deletion/present zero.
  • Go-specific safety differences: zero avoids I/O/activation. Finite values above MaxInt32 fail rather than clamp; reducer snapshots fail before RPC instead of adopting the kernel’s unconditional empty result. Nonempty defaults and unproven custom/relationship-key replay are refused (TestProjectionHistoryRefusesDefaultsAndCustomKeysWithoutRPC). Mixed ALL plus explicit event mappings is admitted: kernel 19.32.1 and later fold every event handled live (Chronicle#4562). TestMixedAllHistoryRequiresMixedAllReplayKernel (refused on older or unverified kernels) and TestKernelModelHistoryMixedAndPureAllReplay cover it; the kernel witness reads a bounded replay that must include an event only the ALL subscription handles, the complete replay, legacy replay and A/B/A history, beside pure ALL with an empty type filter. No local evaluator/default overlay or decision guard is inferred.
  • Route-specific release ownership: materialized keyed/collection reads use persisted model lineage; the SDK validates their final representation without a second decrypt. Local reducers fold released history. Projection collection replay, legacy replay, immediate Get, sessions and model history are admitted for PII and every encryption scope: kernel 19.32.2 and later release them with each value’s original subject (Chronicle#4561), and the SDK validates without a second decrypt (TestProtectedProjectionRoutesUseKernelReleaseWithoutSecondDecryption). TestKernelModelHistoryProtectedReleaseProfile exercises every route through the SDK for default Id and lowercase id, with a key that differs from the subject, before and after erasure, using legitimate cipher-shaped plaintext. Earlier kernels released replay with the source key, so these routes refuse classified models before RPC unless the verified kernel is 19.32.2 or later (TestProtectedProjectionRoutesRefuseWithoutProtectedReleaseKernel). Contributions on unclassified model history are released separately by the kernel’s event subject/schema before projection, including before/after erasure. TestKernelModelHistoryReleaseOwnershipAndErasure covers admitted collection routes and keyed passive folds. These witnesses are not general server security assurance and do not complete #33’s protected-history capability. Explicit Service.Release remains an unreleased-document API with lineage groups. Legacy PassiveReader retains that contract; WithReleasedPassiveReader explicitly selects plaintext instead.
  • Decode and lifetime evidence: TestCollectionAndSnapshotsUseFrozenNamingAndPointerConcepts, TestCollectionRejectsLateErrorsWithoutPartialProgress, TestSnapshotsRejectLateFailuresAndEnvelopeFailures, TestReadDocumentsRejectDuplicateMembersBeforePublication, TestHistoryCodecFailuresArePayloadFreeAndAtomic, and TestModelHistoryCodecsCanCloseClientAndLateCancellationDiscardsEverything. Go rejects duplicate JSON names recursively before schema checks or publication; ordinary unknown fields remain. Decoder panics discard results and never retain panic payloads; ordinary codec causes remain inspectable behind fixed messages. The raw response owns its metadata; no IDs, revision or generation copies absent from the snapshot wire are fabricated. Unknown Go event types stay raw.
  • Limits: complete matching history is fetched before local truncation, not paged/bounded on the wire. Counts are not positions or freshness proofs; progress is reported independently. Snapshot.Instance has no invented existence or last-handled marker. Catalog-only producers cannot establish replay fidelity. TestProjectionReplayPolicyOwnsBoundReplacementAndInboxDefinitions verifies immutable admission from the actual selected store’s bound definitions/models, including replacement registries and inbox sequence binding.

See the collection/history reference.

References: C# 2e31b0dfba489159b3db323238f16d0f277056b4, paths relative to Source/Clients/DotNET; kernel references use repository-root paths at contract pin ae5e00a8abaa688138b2c2f689e2b4659cccb4fd. Kernel integration uses 19.32.3-development. See the history operations reference for destructive scope, audit requirements, acceptance versus application, and recovery boundaries.

Behavior / C# sourceGo surface and statusExecutable evidence / intentional difference
Point redaction / EventSequences/EventSequence.cs:272–288Implemented: Sequence.Redact(ctx, position, events.RedactionReason)TestHistoryMutationRequestsMatchCSharp, TestKernelRedactOnePreservesMarkerAndAudit; exact position, unchanged routing, original audit in marker and operator in outer context; zero valid, all three highest reserved positions rejected before dispatch by TestPointHistoryMutationsRejectReservedPositionsBeforeDispatch; C# EventSequenceNumber.cs:IsActualValue defines Unavailable, Max, BeforeFirst
Source/type redaction / EventSequence.cs:291–305Implemented: RedactForEventSource(ctx, source, reason, ...events.TypeID)TestSourceRedactionWithoutTypesIsExplicitlyUnfiltered, TestKernelRedactSourceHonorsTypeFilterAndIsolation; registered IDs replace CLR type arguments, all generations selected; no IDs means all types, across all routes
Actor/causation / EventSequence.cs:249–305Implemented explicit context metadata; Go-specific preflight target/reason checksHand-derived full protobuf comparisons in TestHistoryMutationRequestsMatchCSharp, TestHistoryMutationsRejectInvalidInputBeforeDispatch; NotSet/empty defaults; no revision reason or caller correlation field on the wire
Revision content/generation / EventSequence.cs:249–269, Events/EventSerializer.cs, EventSequenceNumber.csImplemented: Sequence.Revise uses the registered shared codec/selected naming policy; Go-specific position/registration preflightTestRevisionUsesSelectedGenerationSerializationPlan, TestKernelRevisionPreservesOriginalAndRevisionAudit, TestKernelRevisionUsesRegisteredGeneration; pointers, invalid content, generation-specific content, retained original/revision audit; not an append or migration. TestPointHistoryMutationsRejectReservedPositionsBeforeDispatch and TestPointHistoryMutationsAllowActualBoundaryPositions pin actual positions, including zero
Asynchronous application outcomes / kernel Core/Sequences/{Revise,Redact,RedactForEventSource}.csPartial: nil error confirms request acceptance only, like C#Kernel read-after-mutation tests wait for actual changes; target/type/generation failures can happen later. No public receipt/status contract: Chronicle#4526; no invented completion result
Ambiguous outcomes and retries / EventSequence.cs:249–329, command envelopesGo-specific MutationOutcomeUnknownError; explicit authorization/validation refusals remain envelope errorsTestMutationFailuresAreNeverRetriedOrNotified, TestHistoryMutationBeforeDispatchKeepsLocalError; transport/cancellation/exception/malformed responses never imply non-application; pre-dispatch errors retain identity
Redacted payload / Events/{EventRedacted,EventRedactedConverters,RedactionEventContent}.csImplemented, Go-specific ID-first events.EventRedacted, Appended.Redaction, automatic generic/dynamic marker decodingTestRedactionDecodesOriginalIdentityAndAudit, TestRedactionRejectsNonMarkersAndMalformedContent; OriginalType(catalog) maps known IDs to the current Go type and unknown IDs to any (C# object); UUID fields permit ordinary observer registration; no original type decoded as zero-filled content
Projection/reactor effects / kernel Core/EventSequences/EventSequence.cs:RewindPartitionForAffectedObserversImplemented kernel-owned replay, no client-side mutation emulationTestKernelHistoryMutationsReplayProjectionsAndReactors observes corrected projection state, revised replay delivery, marker replay delivery, and projection recovery of the pre-redacted state; does not reverse external effects
Local append observation / IEventSequence.AppendOperations, EventSequence.cs:249–329Implemented exclusion of all history mutationsTestHistoryMutationRequestsMatchCSharp, TestMutationFailuresAreNeverRetriedOrNotified, kernel point-redaction/revision tests; no OnAppend on acceptance, refusal or unknown outcome; no UoW staging
Stream completion / EventSequence.cs:309–329, CompleteStreamError.csImplemented: CompleteStream(ctx, type, id) (SequenceNumber, error)TestStreamCompletionTypedRefusalsAndMalformedResults, TestKernelCompleteStreamRefusalsAndFutureAppends; sequence-wide tail, empty sentinel, StreamAlreadyCompleted, DefaultStreamCannotBeCompleted, later append rejection across sources; future/inconsistent responses and reserved returned tails (Max, BeforeFirst) fail unknown wrapping ErrProtocol, since closure may have occurred. Unavailable remains absence; TestStreamCompletionAllowsActualBoundaryTails pins zero/highest actual tails. Unlike C#, Go does not fall back to AlreadyCompleted
Stream/source status / kernel Core/EventSequences/IEventSequence.IsStreamCompletedNot implemented publicly: no RPC in 19.29.4 and no C# client memberGenerated EventSequencesClient has completion but no status/reopen/source-completion method; no local status cache or destructive status probe is substituted
Protected revision / C# EventSequence.cs:249–269; kernel Core/Sequences/Revise.cs:Handle at v19.32.3Implemented like C# on Chronicle 19.32.2 or later: Sequence.Revise sends plaintext and the kernel applies the replacement generation’s metadata with the original event’s subject (or source) to the revision and its EventRevised system request. Go-specific refusals, before serialization or RPC with payload-free ErrUnsupported: a protected replacement on an older or unverified kernel (which persists it unprotected, Chronicle#4525); and, on every kernel, an unclassified replacement whose type ID another registered generation classifies, because the kernel protects only with the replacement generation’s schema and erasure could not remove that plaintext. C# dispatches bothTestProtectedRevisionDispatchesPlaintextForKernelProtection, TestProtectedRevisionRefusesWithoutProtectedReleaseKernel, TestRevisionRefusesUnclassifiedGenerationOfProtectedIdentity, TestProtectedRevisionStillRejectsInvalidContentBeforeDispatch, TestKernelProtectedRevisionIsProtectedWithOriginalSubject (subject differs from source; PII, namespace and global encryption; raw MongoDB scan finds no plaintext at rest; system request free of plaintext before and after erasure; erasure shreds PII and leaves encrypted values readable). An upgrade does not repair plaintext stored by earlier kernels
Idempotence/recovery fencing / kernel revision/redaction storagePartial kernel semantics only; no safe retry protocol or frozen bulk boundaryRepeated stream refusal is kernel-tested; revision can add records, source redaction can reach later events. Durable operation identity/fencing remains Chronicle#3920; append-tail checks are not revision barriers
Composed operations / EventSequences/Operations/{IEventSequenceOperations,EventSequenceOperations,EventSourceOperations}.cs, Go #19Go-specific substitution: []Entry, AppendBatch, WithScopes, optional PrepareBatch; no second mutable builderTestBatchPreservesOrderMetadataAndIndependentScopes, TestBatchSnapshotsBeforeResolvingTail; caller owns collection/reset and default causation; entries carry overrides. Go preserves A1/B1/A2 order instead of C# grouping by source. Composition is append-only in C# too; revision/redaction/completion are not atomically mixed with appends
Offline workflow / explicit construction rather than container discoveryGo-specific zero-container exampleExampleSequence_Redact executes only an offline protocol fixture, not fake persistence. Ordinary SDK construction and registration remain unchanged

Compensation/tombstone declarations, generation migrations, subject-key erasure, and stream completion are separate behaviors. None automatically performs the others. Redaction removes targeted original/revision payloads, not backups, external effects, forwarded copies, or prior system revision request content.

The operations reference describes the public workflows. Sources below are relative to Source/Clients/DotNET at 2e31b0dfb; generated contracts remain pinned independently to 19.32.3. Request/result golden fixtures are hand-derived from C#, except the observer wire fixtures, which were emitted by protobuf-net 3.4.30 using the actual contract at kernel revision ae5e00a8. Kernel paths below are relative to Source/Kernel at that revision. Kernel witnesses use the repository’s 19.32.3-development image.

Behavior / C# sourceGo surface and statusExecutable evidence / differences
Observer listing/state / Observation/{IObservers,Observers,ObserverInformation}Implemented: EventStore.Observers().List/Get, immutable state snapshotsTestOperationsMatchHandDerivedCSharpGolden, TestAdministrationRejectsMalformedResponses; explicit sequence for Get, NotFound presence, state/tails/subscription/owner/type/count and detached event references
Replay policy and subscription availability / kernel Contracts/Observation/ObserverInformation.cs:83–85, Grpc/Observation/{ObserverInformationConverters,Observers}Implemented, Go-specific availability: IsReplayable, SubscriptionKnown, IsSubscribedTestObserverSnapshotsDecodeCSharpWirePresence, TestKernelOperationsReplayabilitySubscriptionAndCustomSequenceRemoval: a List/Get-only receive codec restores omitted field 10 to true while preserving explicit false. No generated/schema edits or global codec. List subscription is unavailable; Get queries it authoritatively. The kernel witness also exposed the same default on outgoing Contracts/Observation/Reactions/ReactorDefinition field 4: TestReactorOnceOnlyEmitsExplicitFalseForCSharpDefault ensures reactor-wide OnceOnly registration emits zero rather than silently opting into replay
Persistent removal / Observation/{Observers,ObserverRemovalResult}; kernel Core/Observation/ObserverRemover.cs:57,60,103Implemented, Go-specific safety correction: Service.Remove, RemoveFrom, Information.Remove, four outcomes and blocking namespaceTestObserverRemovalUsesAuthoritativeCustomSequence, TestObserverRemovalFailsBeforeMutationWithoutSafeTarget, TestObserverSnapshotRemovalRejectsChangedSequence, custom-sequence kernel witness. C#‘s event-log default can target the wrong subscription guard before shared-definition deletion. Go resolves the current definition and validates explicit/snapshot sequences; unavailable or ambiguous definitions fail before mutation. No atomic re-registration fence. Existing ID-only callers retain their signature but now incur a lookup and cannot remove state-only orphans
Failures / Observation/{FailedPartitions,FailedPartition,FailedPartitionAttempt}Implemented: FailedPartitions(ctx, id) with optional observer filter and immutable attemptsGolden/malformed tests, TestKernelOperationsFailedPartitionDiagnostics; UUID, partition, timestamp offset, kind, messages/stack, resolved and quarantined flags preserved. No automatic recovery
Recovery/quarantine / Reactors/Reactors.cs:RetryFailedPartitionFor, pinned Contracts/Observation/*Implemented: retry outcomes, explicit partition replay, failure/observer/partition quarantine clearingTestAdministrationPreservesRefusalsAbsenceAndTargetIsolation, golden and lost-reply tests; clear/retry distinctions retained. RetryRequested prevents treating proto3’s default Started as an actual retry when none was requested. Empty acknowledgements prove no completion
Replay / Reactors/Reactors, Reducers/Reducers, Projections/ProjectionsImplemented: Observers().Replay returns namespace-bound jobs.HandleGolden, target isolation, malformed/lost reply and kernel replay/job witness. Explicit source sequence replaces C# reactor/reducer empty-sequence inference; malformed/zero job IDs fail rather than silently returning NotSet
Jobs reads and commands / Jobs/{IJobs,Jobs,Job,JobStep}Implemented: EventStore.Jobs().List/Get/Steps/Stop/Resume/Delete; immutable job/step snapshotsGolden tests cover full requests, .NET UUID byte order and complete progress/status history. Failure tests preserve envelope authorization/validation/exception and RPC errors; Get searches List as C#. Handles and snapshots retain original store/namespace
Job waits / Jobs/JobsWaitHelpersImplemented, Go-specific safety: predicate/progress/list/deletion/terminal waits, strict successful-status wait, 50ms polling and 5s defaultTestJobWaitRequiresEvidenceAndPreservesDisappearance, TestJobWaitHelpersHonorBudgetsAndCallerCancellation; absence/disappearance stay unknown, failed/stopped states stay distinct. Strict wait adds AbsentError/TerminalError; terminal-or-absent preserves C# null semantics. WaitForNoJobs corrects C#‘s inverted selected-status predicate; caller cancellation always propagates
Append completion / Observation/AppendResultWaitForCompletionExtensionsImplemented: metadata result/notification Completion, WaitForCompletion, immutable observation.Completion and diagnosticsTestCompletionUsesActualBatchTailsAndOriginalCoordinates, TestCompletionBudgetsAbsenceCancellationAndDiagnostics; actual per-type batch tails, original first/store/namespace/sequence and maximum-position generation, 5s + 200ms/infinite behavior, missing surface vs unavailable tail. Legacy result layouts remain unchanged; metadata-bearing append methods or existing notifications supply exact input types rather than guessing from current catalogs
Completion and lifecycle kernel witnessesPartial beyond the demonstrated single-kernel workflowsTestKernelOperationsCompletionReplayAndJobEvidence holds a real handler to distinguish timed-out from successful catch-up, reads replay job/steps, observes replay-end and handles later job absence without fabricated completion. TestKernelOperationsFailedPartitionDiagnostics reads failed attempts and completion failure. No durable checkpoint or multi-node guarantee. The 19.29.4 reducer recovery (Chronicle #4540, witnessed by TestKernelReducerFailedPrefixRecovery) and catch-up race (Chronicle #4548) defects are fixed in 19.32.3
Examples and documentationImplemented for the described APIsExampleService_Replay, ExampleService_WaitForCompletion, TestOperationsDocumentationMatchesCompiledExample; offline examples explicitly label their transport. The kernel witnesses separately establish runtime behavior

All mutation failures after dispatch are conservative OutcomeUnknownError unless a local pre-dispatch or authorization/validation refusal is known. The SDK adds no mutation retries. TestAdministrationLostRepliesNeverRetry and TestUnknownOutcomeFormattingDoesNotExposeCause preserve error identities while omitting sensitive cause text from OutcomeUnknownError.Error().

Typed DTOs reject malformed required messages, IDs, mutation-outcome enums and contradictory completion replies. Diagnostic enums preserve future numeric values: TestAdministrationPreservesForwardDiagnosticValues covers observer states, failures, jobs, steps and histories, following C# JobsConverters, JobStepConverters and FailedPartitionConverters numeric casts (observer kinds retain numbers rather than C#‘s Unknown mapping). TestUnknownJobStatusIsNotCompletionOrTerminalEvidence proves unknown status waits do not manufacture success or terminal evidence. Proto3 scalar defaults and empty acknowledgements retain their protocol limits; accepted work is not completed work. The kernel’s Grpc/Observation/Observers completion method also succeeds with no matching observers: this is not expected producer readiness or durable sink/checkpoint evidence.

At the Chronicle baseline above, ChronicleOptions.cs:81 starts with default JsonSerializerOptions. ChronicleClient.cs:360–382 sets naming, null omission and compact output without changing Encoder; Events/EventSerializer.cs clones those options and calls SerializeToNode. Fundamentals Source/DotNET/Fundamentals/Json/Globals.cs at d2accc4a79b6bcf2708213c97093ab5ba6c06381 also leaves Encoder unset. DotNET/Seeding/EventSeeding.cs:128,174 serializes the resulting node using default options.

Go emits struct properties in declaration order, including nested structs, pointers and embedded/promoted fields in encoding/json index-path order. The compiled naming policy, explicit tags, nil omission, omitempty/omitzero, concept codecs and numeric validation still apply. Direct duplicate property names remain configuration errors; ambiguous promoted fields are omitted like encoding/json, but declarations on ignored fields fail closed. JSON Schema keeps its existing deterministic key ordering; schema property order does not identify seeded facts.

String values, property names, dictionary keys and string-valued concepts use JavaScriptEncoder.Default escaping: non-ASCII characters become uppercase \uXXXX escapes (UTF-16 surrogate pairs when needed), as do HTML-sensitive characters, apostrophe, plus, backtick and double quote. Backslash and the standard short control escapes are preserved. serialization/testdata/csharp-escaped-event.json and the all-ASCII test were captured from .NET 10 with the options/stages above; the ordered-object and multi-property seed fixtures are hand-derived. This does not implement arbitrary C# custom encoders or [JsonPropertyOrder]; equivalent declarations must have the same emitted property order.

Dictionary limitation: C# serializes Dictionary<string, T> in enumeration order (insertion order for ordinary additions); Go maps retain no insertion history, so their keys remain sorted by Go string order. TestDictionaryValuesRetainStructDeclarationOrder and TestEscapingAppliesToNamesConceptCodecsAndMapKeys pin deterministic keys without reordering struct values. For byte-sensitive shared seed content, use structs with matching declarations, or arrange the C# dictionary’s enumeration to match Go’s UTF-8 key order. Arbitrary dictionaries are not byte-parity compatible.

TestKernelCSharpThenGoSeedsAreIdempotent sends a C#-derived request followed by the Go request, asserts exact content bytes, and verifies one persisted event. The kernel compares seed content by ordinal string equality (Source/Kernel/Core/Seeding/EventSeeding.cs:332), not semantic JSON equality. Previously persisted Go seeds may contain alphabetically ordered properties or different escaping; upgrading does not rewrite that tracking data. Review existing Go seeds before re-registering changed bytes, which the kernel treats as new facts.

C102–C106 references below use Source/Clients/DotNET at 2e31b0dfba489159b3db323238f16d0f277056b4; kernel paths are repository-root paths at the same revision. Compliance reference documents the public workflow. Runtime fixtures use 19.32.3-development with a disposable server encryption certificate; ordinary Go tests remain container-free.

Behavior / C# sourceStatus and Go surfaceExecutable evidence / boundary
PII members and rationale / Compliance/GDPR/PIIMetadataProvider, Compliance/ComplianceDetailsExtensionsImplemented: pii, compliance-details(value=...); compliance.For[T] and WithProtectionTestClassificationSchemaMatchesCSharpCategoriesAndPropagation, TestClassificationPrecedenceAndExplicitEmptyDetails; member → declaring type → value type, explicit empty rationale preserved. Go has no constructor attributes; field tags are their equivalent
Composite/type/nullable/concept collections / Schemas/JsonSchemaGenerator:226–254,491–600Implemented for supported concrete shapes: classification follows the serialization plan; composite leaves versus coarse collection metadata remain distinctClassification test, TestRecursiveClassificationsPreserveShapeAndGuardCycles, TestKernelComplianceNestedConceptsAndCollections; no polymorphic/interface codec claim
Map-value protection / kernel Core/Schemas/JsonSchemaMetadataManager.cs at v19.32.3Implemented: metadata beneath unprotected maps (tags, type, property-path and provider declarations) registers and the kernel applies it to every map value; coarse protection of the entire map property remains supportedTestProtectionBeneathMapsAndCollectionElementsIsAdmitted, TestNestedCollectionProtectionDetectsOnlyKernelSensitivePlacements, TestNestedProtectionRegistrationRequiresProtectedReleaseKernel (registration refused before RPC on older or unverified kernels), TestCoarsePropertyProtectionCoversMapAndArrayDescendants, TestKernelComplianceProtectionBeneathMapsAndCollectionElements (map of objects with a PII member, map of PII concepts and a namespace-encrypted map, in events and a projected read model, before and after erasure, with a raw MongoDB scan for plaintext at rest; erasure fences later appends), TestKernelComplianceCoarseCollections. Requires kernel 19.32.2 or later (Chronicle#4551). Model-bound read models cannot carry chronicle tags inside map value structs (they are projection declarations); classify those values by type
Collection-valued array elements / same kernel schema managerImplemented: classified inner collections (nested lists and maps) are protected, released and erased as whole elements; elements with declared object members keep per-member protectionSame placement and kernel tests ([]ClassifiedNames, []ClassifiedLabels). Requires kernel 19.32.2 or later (Chronicle#4552)
Recursive property overrides / Schemas/JsonSchemaGenerator, same kernel schema managerImplemented for concrete recursive shapes: rebuild nullable pointer schemas from classified children and reject unresolved referencesTestRecursiveOverrideSchemaReferencesAllResolve, TestReleaseRecursiveOverrideWithPopulatedEdges, TestKernelRecursiveOverrideReleaseWithPopulatedEdges; populated edges beyond the override retain their original classification
Reserved PII subjects / kernel Core/Compliance/GDPR/PIICompliancePropertyValueHandler.cs at v19.32.3Go-specific defense in depth, kept deliberately: compliance.InvalidSubjectError rejects the $chronicle-encrypted-value$ prefix before append, batch, prepared/UoW, reactor-effect and seed admission; lifecycle prohibition remainsTestReservedSubjectsFailBeforeAdmissionOnEveryAppendPath, TestReactorEffectsRejectReservedSubjectsBeforeWrites, TestSeedSourcesCannotUseReservedSubjects, lifecycle validation test, TestKernelReservedPIISubjectsAndSDKAdmission. Since 19.32.2 the kernel refuses PII for a reserved identifier (Chronicle#4553), but it still accepts one as the subject of an unclassified event, which can later reach a protected read model and fail its projection there. The SDK check rejects every such subject at admission instead; C# has no client check. Choose an ordinary opaque subject
Catalog-local provider admission / ComplianceMetadataResolver, Confidentiality/SecurityMetadataResolverGo-specific: explicit compliance.Using providers, no assembly/global discoveryTestClassificationCatalogIsolationProviderAndNaming; deterministic metadata callbacks run during compilation, not release. Arbitrary new kernel metadata categories/handlers are not exposed
Subject confidentiality / ProtectedValues/EncryptedMetadataProvider, EncryptionScope.SubjectImplemented: encrypted defaults to subject; security / EncryptedSubject, never compliance / PIIClassification test and TestKernelConfidentialityIsIndependentOfPIIErasure prove subject encryption survives PII erasure
Namespace confidentiality / EncryptionScope.NamespaceImplemented: encrypted(scope=namespace) and subject-independent releaseClassification test, TestSubjectIndependentReleaseAndCollections, confidentiality kernel fixture; namespace scope is the store/namespace key coordinate, not cross-store tenancy authorization
Global confidentiality / EncryptionScope.Global, kernel ProtectedValues/EncryptedValueKeyIdentifiersImplemented on 19.32.3: exact security / EncryptedGlobal wire and subject-independent releaseSchema assertions and release tests pass; TestKernelGlobalConfidentiality appends, reads and erases PII beside a global confidential value, which survives. On 19.29.4 MongoDB rejects the reserved global store coordinate (Chronicle#4549, fixed in 19.32.2). No client coordinate workaround
Non-string protected scalar kinds / kernel ProtectedValues/ProtectedValueCodec, Schemas/JsonSchemaMetadataManagerImplemented on 19.32.3: C#-equivalent scalar classification, strict typed decodingTestKernelComplianceNumericScalar requires a protected integer to release as a JSON number and decode. On 19.29.4 it releases as a JSON string (Chronicle#4550, fixed in 19.32.2). The SDK does not silently coerce malformed protected payloads
Source-identity prohibition and category conflicts / PIIMetadataProvider, EncryptedMetadataProvider:42–71Go-specific safety correction: always reject protected events.SourceID, including nested/type/provider paths; reject inherited PII + EncryptedTestProtectionAlwaysRejectsEventSourceIdentity, TestProtectionConflictsFailBeforeRegistration, TestSecurityAndIgnoredEventTagsFailClosed. C103’s direct-member short circuit does not bypass Go’s guard. An unrelated string field named ID is not an EventSourceId type
Event subject / SubjectResolverImplemented for declared scalar/concept subjects: override → explicit resolver → tag → source, no event ID fallbackExisting TestFirstAppendPolicyAndSubjectsAcrossAllPaths and declared-subject tests; the kernel lifecycle fixture uses an owner different from its source
Model subject and lineage / ReadModels/ReadModelSubjectResolver, kernel ReadModels/ReadModelsComplianceGo-specific raw lineage preservation and grouping; configured/tagged subject → case-insensitive Go ID, not projection KeyTestTaggedSubjectFallsBackToIDButNotProjectionKey, TestReadModelReleaseMultipleSubjectGroups, TestReadModelReleaseNumericSubjects, TestReleasePreservesStoredLineageAgainstUnexpectedReplyFields, TestReleaseSendsDeclaredBookkeepingButKeepsUndeclaredFieldsLocal, TestKernelRawDocumentReleasePreservesBookkeeping; only schema-declared fields enter the Release RPC, while raw lineage and sink bookkeeping survive locally. The kernel fixture reconstructs a sink envelope from a materialized instance and uses real release, not direct MongoDB access. Zero UUID remains its string, numeric token spelling is exact. Nested subject tags are rejected rather than inventing per-element ownership
Model release boundaries / ReadModelReleaser, ReadModels, MaterializedReadModelsGo-specific fail closed: explicit Release/ReleaseMany accept unreleased documents only and are not idempotent. Materialized keyed/collection reads and store-owned passive folds validate final state without another decrypt. Raw/typed windows do likewise only for MongoDB root string PII/EncryptedNamespace properties, excluding classified exact _id and case-insensitive id aliases; frozen type/provider metadata must compile to that same profile. Other nested/nullable/collection/encryption-scope/sink/custom window profiles refuse before RPC. Projection replay/history/immediate/session/decision reads return kernel-released values on 19.32.2 or later (Chronicle#4561) and are validated without another decrypt. Classified Watch remains unsupportedTestProtectedMaterializedGetNeverReleasesPlaintextAgain, TestCollectionServerReleaseIsNotRepeated, TestSnapshotsValidateKnownProtectedContributionsWithoutSecondRelease, TestMaterializedWindowsNeverDecryptReleasedPlaintextAgain, TestNamespaceEncryptedWindowsValidateServerReleasedValuesWithoutRelease, TestUnwitnessedMaterializedProfilesRefuseBeforeRPC; missing/null protected window roots and invalid final values fail without partial results. TestClassifiedMongoIdentityWindowsRefuseBeforeRPC and TestFrozenProviderAndTypeClassifiedIdentityWindowsRefuse cover admission with no RPC: the identity exclusion derives from Source/Kernel/Storage.MongoDB/Sinks/ChangesetConverter.cs:333 and Sinks/Sink.cs:196,324–330 storage behavior, not a kernel fixture protecting identities. TestProtectedProjectionRoutesUseKernelReleaseWithoutSecondDecryption, TestClassifiedDecisionsAreAdmittedWithoutSecondRelease, TestKernelModelHistoryProtectedReleaseProfile and TestKernelDecisionReadsReleaseClassifiedModelsWithEventSubjects cover the replay and decision routes; TestReadModelReleaseFailsClosed retains atomic release failures; independent confidentiality metadata does not excuse missing PII ownership
Event history and typed decode / kernel Events/EventCompliance, Sequences/EventSequenceQueryingImplemented for supported protected shapes: kernel releases history before events.Decode; no second client-side cipher implementationTestKernelComplianceSubjectKeyLifecycle, nested fixture; decoder performs no I/O and cannot release arbitrary caller-supplied ciphertext. Protected event-generation migrations are only partially usable: since 19.32.2 (Chronicle#4456) the kernel transforms plaintext and protects every generation for the original subject, so the current representation and projections release correctly before and after erasure. Other generations in GenerationalContent are not released on reads or observer delivery and arrive as ciphertext (Chronicle#4623); the SDK has no client-side guard for this yet (#90), so the evolution guide documents the limit. TestKernelProtectedEventGenerationMigrationProfile characterizes 19.32.3 and fails once the kernel releases other generations
Erasure and namespace-wide reach / Compliance/GDPR/PIIManager, kernel Compliance/GDPR/PIIManager:39–99Implemented: store.Compliance().ErasePII / DeleteEncryptionKeyFor, unchanged compliance RPCTestLifecycleUsesNamespaceScopedKernelContracts, TestKernelComplianceSubjectKeyLifecycle; repeated erasure, second store, other-namespace survival, shredded events and read models. Unprotected outbox-to-inbox forwarding is implemented separately (TestKernelExternalSubscriptionForwardsOutboxToObserverInbox); protected forwarding and erasure across that path remain unverified. No multi-silo cache-eviction claim
Write fence and replacement-key authorization / same PII manager and kernel key storageImplemented: failures propagate without append retries; AllowNewEncryptionKeyFor is explicit and cannot recover old ciphertextLifecycle kernel fixture rejects writes in both stores, permits another namespace and reauthorizes new writes while old content remains shredded. Wire has no stable typed EncryptionKeyErased detail; existing append/transport identities remain inspectable
Partial lifecycle failures, unsupported kernels and confidentiality guard / IPIIManager, kernel EncryptionKeyLifecycleIncompleteImplemented transport contract with redacted public error text; no success inferred from partial server workTestLifecycleFailuresPreserveIdentityWithoutSensitiveDiagnostics, TestLifecycleRejectsReservedKeysAndCancellationBeforeDispatch; ErrLifecycle, errors.As, gRPC/context/unsupported identities. Distributed fault injection and backend recovery remain unverified

Chronicle 19.32.0 through 19.32.3 share wire contracts, so compatibility alone does not show which kernel fixes are present. The client records them from the server version the compatibility check reports, per connection; with WithSkipCompatibilityCheck or an unrecognized version it assumes none, and these routes return ErrUnsupported before any RPC (TestKernelCapabilitiesAreRecordedFromVerifiedVersion). A -development image counts as its release.

The guarantee holds at dispatch, not only when an operation starts. A gated operation records what it needs in its call context, and the transport checks those needs against the connection that is about to send each RPC, after pinning it. If the client reconnected to an older kernel while the operation was running (for example while an enricher or audit provider ran), the RPC is not sent and the operation returns ErrUnsupported, reported as not dispatched. An early check against the current connection still refuses quickly, before providers or codecs run; it is not authoritative. Registration checks the connection it registers on, and every reconnect registers again, so a store that reconnects to an older kernel refuses its nested protection again (TestDefinitionTransportRefusesTrackedNeedBeforeDispatch, TestProtectedReviseRefusesWhenReconnectedToIncapableKernelBeforeDispatch, TestClassifiedReplayRefusesWhenReconnectedToIncapableKernelBeforeDispatch, TestMixedAllReplayRefusesWhenReconnectedToIncapableKernelBeforeDispatch, TestNestedProtectionReRegistrationRefusesAfterReconnectToIncapableKernel). A gated operation that has to wait for the client to connect or a store to register does not pass its needs on to that shared work, so it cannot fail the connection or registration other callers depend on (TestRegistrationIgnoresCallerTrackedNeeds). An operation refused by the early check is not retried after a reconnect to a newer kernel; call it again (TestProtectedReviseOnIncapableKernelRefusesBeforeProviders, TestNestedProtectionRegistersAfterReconnectToCapableKernel).

RouteMinimum kernelKernel fix
Projection replay of a mixed all-event projection (bounded/passive GetAll, ReplayProjection, GetSnapshots)19.32.1Chronicle#4562
Revising an event with a protected replacement19.32.2Chronicle#4525
Classified models on projection replay, history, hydration sessions and immediate reads19.32.2Chronicle#4561
Registering protection beneath maps or on list- or map-valued array elements19.32.2Chronicle#4551, Chronicle#4552
Decision reads (any model)exactly 19.32.3characterized release

C02–C08/C10 and issues #21 / #22 reference Source/Clients/DotNET/{ClientArtifactsActivator,ActivatedArtifact}.cs, Projections/Projections.cs:536–570, Events/Constraints/ConstraintsByBuilderProvider.cs, Events/Migrations/EventTypeMigrators.cs, and Seeding/EventSeeding.cs at 2e31b0dfba489159b3db323238f16d0f277056b4. See the config-backed definition workflow.

BehaviorGo surface and statusExecutable evidence / exact boundary
Config-backed preparationPartial: RegisterProjectionFactory[P], RegisterConstraintFactory[C], RegisterEventMigrationFactory[M]; fixed family/output metadata, plain constructors or borrowed servicesTestDefinitionFactoriesPlainAndFundamentalsProduceIdenticalFrozenArtifacts, ExampleRegisterProjectionFactory; original descriptors and names are required, not callback-driven artifact discovery
Activation ownershipGo-specific: temporary scopes, owned explicit constructor results, borrowed resolved services/provider, registered-service precedenceTestDefinitionPreparationCleansPartialScopesAndConstructorResultsBeforeDependencies, TestAdapterPreservesPartiallyOpenedScopeForOwnerCleanup, Singleton/scoped equivalence fixture; unlike C# non-disposable definition activation, disposable artifacts are allowed and released before publication
Failure boundaryGo-specific: payload-free PreparationError, inspectable ordinary causes, discarded panic values, cleanup failure prevents publicationTestDefinitionPreparationDiscardsPanicsWithoutEverFormattingTheirValues, TestDefaultProviderPreparationDiscardsFactoryAndDisposalPanics, TestPartialScopeIsClosedWhenOpenErrorIsOpaqueOrPanicked, TestSanitizerNeverInvokesHooksThatMutateProviderDiagnostics, TestSanitizerDiscardsEntireSnapshotForComparableValuePanicIdentity; unlike C# log-and-skip or swallowed disposal failures, Go aborts preparation. Fundamentals.Go v0.1 provider diagnostics snapshot original fields before descent and are rebuilt without panic payloads/causes. Only exact provider diagnostics, recognized standard join/fmt wrappers, and comparable ordinary leaves without inspection hooks are admitted; only safe non-nil pointer leaf identities survive, unless quarantined as panic aliases. Opaque hooks are never called and reject the entire snapshot, as do ambiguous panic identities, cycles, or the 64-level/256-rooted-edge limits (including nil/repeated edges). Bounded inspection and cleanup/cancellation fixtures cover failure atomicity; application effects cannot be rolled back
Captured schema and definition epochsImplemented for selected registries: capture all before callbacks, freeze all base schemas before definitions, compile a shared registry onceTestClientCapturesAllRegistriesBeforeApplicationPreparation, TestAllSelectedSchemasFreezeBeforeDefinitionCallbacks, TestSkipKeepAliveRejectsCapturedObserversBeforeAnyFactoryOrClassifier, TestFactoryPreparationRetainsOriginalModelHandle; classification results use Go member identity without retaining application providers
Canonical compilation and replayImplemented for the three factory families alongside direct declarationsTestFactoryAndDirectRegistrationUnionMatchesAndReconnectIsCallbackFree compares complete gRPC requests to direct declarations and across reconnect; TestFactoryVariantsAndDirectGlobalsUseOneCanonicalGroupCompiler covers variant/global composition and frozen defaults/labels; TestKernelDefinitionFactoriesMaterializeConstrainAndEvolve covers materialization, uniqueness rejection, historical upcast and downcast on 19.32.3-development through plain, provider-scoped and provider-singleton activation; it asserts scope disposal, borrowed provider ownership and no double-close of resolved services
Identity conflicts and callback lifetimesGo-specific fail-closed metadata and output checksTestDefinitionFactoryDuplicateAdmissionIsAtomic, TestDefinitionFactoriesRequireExactOutputIdentitiesAndNoRuntimeMessages, TestDefinitionPreparationResolverIsBorrowedGuardedAndExpires; direct migration duplicates now fail registration atomically rather than waiting for NewClient. Factory constraints allow static messages only; no retained scoped message provider
Borrowed client composition / DotNET/ChronicleClientServiceCollectionExtensions.cs at 2e31b0dfbImplemented for the optional Fundamentals v0.1 adapter: CaptureClient, ClientPreparation.Client/Prepare, services.PrepareClient, BindClient, BindEventStore, BindEventLog, BindEventTypes, BindReadModels, BindComplianceTestFacadeConsumerCaptureBindPrepareAndResolveCoordinates, TestFacadeSeparateProvidersDoNotShareStoreCache, TestBindingDescriptorsUseExactKeysBorrowedFacadesAndResourceFreeOwnedCell: exact borrowed Singleton client and Scoped concrete facades; two stores × two namespaces; interface identity and provider/scope non-disposal. Existing plain constructors stay first-class. No Arc SDK adoption or other-container interoperability claim; provider-internal graphs remain an application contract
Scoped selection / same C# service registration sourceGo-specific: trusted-context StoreSelector, successful cached private cell freezes coordinates or safe error; retry registration without reselectionTestFacadeFailedRegistrationRetriesFrozenCoordinates, TestSelectorFailureFreezesSafeErrorAndRequiresNewScope, TestSelectorOwnerCancellationIsFrozenDespiteCallbackSuccess, TestFacadeConcurrentWaitersDoNotCancelSelectorOwner, TestFacadeContextGuardBelongsToHostAndChecksPrincipalOnCachedResolution; callbacks run outside locks and must not resolve services. Hidden reentrant/global resolution is prohibited because provider in-flight waits precede adapter checks. Selection is not authorization; hosts own guards
Binding admission / same C# service registration sourceGo-specific: exact keys and borrowed forwarding, Catalog preflight per helper, no generic Registrar rollbackTestBindEventStorePreflightsWholeBatchAndDependencies, TestBindingRegistrationFailuresAreReturnedWithoutRollback, TestFacadeUnpreparedDenialFreezesSelectionWithoutSDKIOOrPoisoning, TestFacadeClientClosedBeforeFirstScopeAccess; nils/duplicates fail, partial batches must be discarded. Metadata selection may precede the root preparation guard; no adapter Ready probe
Preparation lifecycleGo-specific: caller-owned synchronous attempt, guarded identity, atomic publication after cleanup, retained outcomeTestCapturedAndFailedClientsGuardEveryEntryPoint, TestHandledCallbackDenialAndExternalProbeDoNotPoisonPublication, TestPreparationCloseCancelsButDoesNotJoinCallerOwnedCleanup, TestPreparationCleanupFailurePublishesNoDefaultOrStoreSnapshots; Close cancels but does not join preparation; denied operations do not poison success
All-store preflight and frozen captureImplemented for selected definition/seeder metadata and visible constructor plansTestPreparationPreflightsLaterStoreConstructorsBeforeAnyScope, TestCaptureDefersCallbacksAndFreezesAllSelectedEpochs, TestCapturedPreparationPreservesCodecProtectionAndOriginalModelHandle; plans retain declaration identity, codec/protection snapshots and store replacement semantics

C112 and the C03/C08 final registration stage reference Source/Clients/DotNET/Seeding/* and EventStore.cs:RegisterAllArtifacts at 2e31b0dfba489159b3db323238f16d0f277056b4. Kernel paths below are repository-root paths at that revision. Integration uses 19.32.3-development. See Seed reference events for the workflow.

Behavior / C# sourceGo surface and statusExecutable evidence / exact boundary
Seeder discovery / ICanSeedEvents, EventSeeding.DiscoverGo-specific: RegisterSeeder, RegisterSeederFunc, RegisterSeederFactory; explicit admission instead of assembly discoveryTestSeederInstancesAndConstructorsHaveExplicitOwnership, ExampleRegisterSeeder; duplicate concrete types fail, plain callbacks accumulate. Borrowed instances are not disposed; constructor results are
Definition preparation / EventSeeding.Discover, IClientArtifactsActivatorGo-specific: synchronous preparation at NewClient/NewClientContext, immutable serialization snapshot, no constructor on reconnectTestSeedersPrepareInOrderAgainstSelectedFrozenNamingCatalog, TestSeedPreparationOnceAndReconnectReplaysFrozenRequest; validates unknown types and naming against the selected catalog, store overrides replace defaults. Callbacks may not perform I/O or retain builders
Scoped activation / EventSeeding.Discover, artifact activation disposalImplemented for optional service scopes, with stricter failure propagationTestSeedersUseFundamentalsPreparationScopeAndJoinCleanupFailures, TestSeederPreparationRejectsInvalidRegistrationsAndPreservesConstructionFailure; open → construct → seed → dispose → close. C# logs and skips failed activation; Go fails construction and preserves cleanup errors. No DI container is imported by the core SDK
Typed and heterogeneous declarations / IEventSeedingBuilder.For<TEvent>, ForEventSourceImplemented: seeding.For[E], Builder.ForEventSourceTestSeedRequestMatchesHandDerivedCSharpGolden, TestSeedPreparationFailsAtomically; event IDs, non-nil pointers, payload serialization and static tags; fluent errors cannot silently discard invalid entries
Scoped declarations / IEventSeedingScopeBuilder, ForNamespaceImplemented: independent scoped builder views, explicit default namespace distinct from globalGolden test and TestKernelSeedingRestartReconnectNamespaceIsolationAndObserverVisibility; red-only seeds never appear in default/blue. Namespace selection is not authorization
Wire grouping / EventSeeding.RegisterImplemented: authoritative SeedEvents request, both global and namespaced source/type indexes in first-seen orderTestSeedRequestMatchesHandDerivedCSharpGolden; fixture is hand-derived, not emitted by .NET. TestSeedSnapshotAndRepeatedFacts preserves repeated equal entries and owns input/output snapshots
Registration order / EventStore.RegisterAllArtifactsImplemented for supported observers: seeding last, including background reconnect replayTestSeedingIsLastAfterEveryObserverRegistrationSend; event types/read models precede constraints/projections and reactor/reducer registration sends. Streams have no kernel registration acknowledgement. External subscriptions now precede read-model reactors and seeding; see External integrations
Failed sends, consumption and replay / EventSeeding.RegisterImplemented: store-wide generation single-flight, retained snapshot on failure, successful send cached, same snapshot replayed on reconnectTestSeedFailureRetainsSnapshotAndManualBatchConsumesOnlySuccess, TestSeedSendIsSingleFlightAndWaiterCancellationDoesNotConsumeWork, TestSeedPreparationOnceAndReconnectReplaysFrozenRequest; bounded retry and inspectable RegistrationError/envelopes, never startup Append
Manual seeding buffers / IEventStore.Seeding, EventStoreSeedingExtensions.CreateEventSeedingGo-specific: EventStore.PrepareSeeds → SeedBatch.Register(ctx)TestSeedFailureRetainsSnapshotAndManualBatchConsumesOnlySuccess; each buffer prepares once, retries retained entries and consumes only success. New buffer for corrected definitions; unscoped entries remain global
Kernel idempotence / Source/Kernel/Core/Seeding/EventSeeding.csImplemented for ordinary seeds in existing namespaces across client restart and real connection interruptionTestKernelSeedingRestartReconnectNamespaceIsolationAndObserverVisibility, TestKernelCSharpThenGoSeedsAreIdempotent; repeated equal facts, C# → Go content-byte equality, static tags, namespace isolation, restart and reconnect readback. No client deduplication or claim about kernel crash atomicity
Seed observer visibility / kernel Observation/Observer.Catchup.cs, Observation/Jobs/CatchUpObserver.csImplemented on 19.32.3: the observer receives the global seeds and the later default-only seedTestKernelSeedingRestartReconnectNamespaceIsolationAndObserverVisibility/observer_visibility checks persisted content first and fails on any missing delivery. On 19.29.4 a finishing catch-up job could strand the next seeded partition while the observer remained Active and subscribed (Chronicle#4548, fixed in 19.32.3)
Late observer subscription / kernel observer catch-upImplemented on 19.32.3: an observer that subscribes after events exist for a key catches up without dropping later live events for other observersIntegration tests append right after WaitForRegistration, without waiting for observers to become Active. EventStore / WaitForRegistration still means registration was sent, not that observers are subscribed or caught up. On 19.29.4 the late subscription’s catch-up could drop events appended to the same key for other observers, including projections (Chronicle#4558, fixed in 19.32.3); reactors keeps the startup wait for older kernels. TestKernelCacheEvictionRetainsWatchAndExplicitReconnect still waits through awaitObserversObserving: without it the reactor received its previous event again after explicit reconnect
Global seeds in later namespaces / IEventSeedingBuilder.For, Source/Kernel/Core/Namespaces/NamespacesReactor.csPartial: correct global wire and persistence; pinned kernel does not populate later-created namespacesTestKernelGlobalSeedsReachFutureNamespaces sends a hand-derived C# request directly, confirms initial append plus global tracking, then conditionally skips the observed empty later namespace after a bounded wait. Chronicle#4547; no append workaround
Generation and rejected-seed outcomes / kernel SeedingEntry, SeedEvents.HandlePartial protocol capability, matching C#: no generation field and no per-entry append-result responseGolden request pins the available fields; kernel test proves generation one. Kernel rejection logging/response policy is recorded in Chronicle#3662. Registration success means command acknowledgement, not verified append of each seed. Protected-value compatibility limits are listed below; ordinary seeding has no such prerequisite

C113–C114 references are relative to Source/Clients/DotNET at 2e31b0dfba489159b3db323238f16d0f277056b4; kernel evidence uses the pinned 19.32.3-development image. See External integrations and Capture declarations.

Behavior / C# sourceStatus and Go surfaceExecutable evidence / boundary
Subscribe / EventStoreSubscriptions/{EventStoreSubscriptions,EventStoreSubscriptionBuilder}Implemented: EventStore.Subscriptions, immutable eventstoresubscriptions.Define, Subscribe/RegisterTestSubscriptionWireDefaultsOwnershipAndIsolation; hand-derived C# request, no filters means all current catalog IDs, first-seen deduplication, generation-one wire filters, opaque unregistered IDs supported. Go rejects blank coordinates/self-subscriptions
List/remove / IEventStoreSubscriptions.GetAll,UnsubscribeImplemented: detached definitions, GetAll, UnsubscribeSame wire test and TestKernelExternalSubscriptionForwardsOutboxToObserverInbox; store-wide coordinates, read-back generations reduced to IDs as in C#. Removal materializes asynchronously; inbox history remains
Reactor/reducer source inference / ReactorTypeExtensions, ReducerTypeExtensions, ResolveSourceStoreForObserverImplemented: event WithSourceStore, observer WithSourceStore, immutable Plan.ForStoreTestObserverOriginsBindSequencesModelsAndSubscriptionUnion, TestObserverExplicitSequencesOverrideInferenceAndMixedSourcesFail; local origin uses log, external uses inbox, unspecified origins ignored, incompatible named origins fail, observer source overrides and rejects explicit sequence combinations
Explicit sequence escape / observer type extensionsImplemented: explicit log/custom sequence suppresses reactor/reducer inference and automatic provisioningExplicit-sequence test above. C# projection exception retained: an explicitly selected inbox still provisions, unlike a reactor/reducer explicit sequence
Automatic subscription union / EventStore.RegisterExternalEventStoreSubscriptionsAsync, Projections.GetExternalEventStoreSubscriptionsImplemented, Go-specific broader projection coverage: source name is subscription ID, union distinct event IDsUnion test and TestExternalSubscriptionsFollowObserversPrecedeSeedingAndReplayPerGeneration; projections include child/nested/removal handlers to match Go inference rather than C# root From/Join-only enumeration
Registration order, failures and reconnect / EventStore.RegisterAllArtifactsImplemented: after observer sends, before read-model reactors/seeding, shared across namespaces and replayed per generationRegistration ordering test checks sends, union wire, failure outcome, blocked seeds, namespace sharing and reconnect. Stream registration has no kernel acknowledgement. Explicit user definitions are not silently retried or automatically retained for replay
Outbox → inbox → observerImplemented on the pinned kernelTestKernelExternalSubscriptionForwardsOutboxToObserverInbox; two stores, auto-provisioned subscription, source outbox append and receiving reactor. No event-log publication, exactly-once or cross-namespace forwarding claim
Webhook definitions/defaults / Webhooks/{WebhookDefinitionBuilder,WebhookDefinitionConverter}Implemented: immutable Define, explicit Register/RegisterDefinition, target, exact event generations, headers, sequence, replay/activity optionsTestWebhookWireAuthorizationReadbackAndRemoval, TestFalseFlagsAreExplicitOnCSharpWire; default log, active/replayable true and current catalog filters. Fresh outgoing wire snapshots force explicit zero booleans for protobuf-net defaults without modifying generated contracts
Webhook auth and read-back / Webhooks/{WebhookDefinitionBuilder,WebhookDefinitionConverter,Webhooks} at 2e31b0dImplemented wire and redacted authoring; Partial runtimeTestRegisterMatchesActualAuthenticationCapture compares actual packaged 19.29.4 C# Register requests for None/Basic/Bearer with Go, including catalog filters, headers and boolean presence. Go WithOAuth is converter/contract-backed convenience: the public C# Register builder exposes Basic/Bearer, not OAuth. Authentication evidence separates public-package observations from live behavior. TestWebhookBearerRegisterDefinitionWire submits bearer alone and compares the actual body, including Value1 and explicit false flags; separate Basic/OAuth wire controls prevent authorization-arm confusion. TestKernelWebhookBearerRegistrationCSharpSourceEquivalent compares SDK and independently assembled C#-source-equivalent requests, not an executed .NET capture. On 19.32.3 it requires each authorization-event schema in the selected store, the authorization kind on named read-back and WebhookAdded plus the authorization event in system history for both paths. On 19.29.4 fresh non-System stores lacked those schemas and persisted only WebhookAdded (Chronicle#4567, fixed in 19.32.3). No credential persistence, token acquisition or HTTP delivery claim
Webhook activity persistence / kernel Storage.MongoDB/Observation/Webhooks/WebhookDefinitionConverters.ToKernelPartial: explicit false wire works, replay false round-trips, MongoDB read-back drops inactive stateTestKernelWebhookInactiveCSharpWireReadback compares Go with explicit-zero C#-equivalent wire and skips only both-active/replay-false signature, citing Chronicle#4394. MongoDB converter omits IsActive and uses the concept’s true default; no client falsification of returned state
Webhook removal / kernel RemoveWebhooksGo-specific additive Remove beyond C# IWebhooksTestWebhookWireAuthorizationReadbackAndRemoval, TestKernelWebhookDefinitionRegisterListRemove; store isolation and asynchronous materialization
External HTTP/database services / ExternalServices/{ExternalServices,ExternalServiceBuilder}Implemented definitions and registration: HTTP, MSSQL, PostgreSQL, auth, headers, provider optionsTestExternalServiceWireAndSecretOwnership, capture kernel fixture confirms HTTP service persistence; ID=name, final endpoint only, port zero preserved. No Go HTTP/database drivers or endpoint-connectivity claim; no high-level administration beyond C# registration
Contexts, failure boundaries and secret ownershipGo-specific fail-closed command/query envelopes, no explicit write retries, redacted formattingTestIntegrationServicesPreserveFailuresAndCancellationWithoutRetry, ownership tests; inspectable gRPC/envelope errors, detached exports, fmt redaction. Explicit KernelDefinition, header/URL accessors and kernel diagnostic collections can contain secrets; never log them
Capture authoring / Captures/{ICapturer,CaptureBuilder,AppendBuilder,MapBuilder,*SourceBuilder,*CaptureBuilder}Partial: Capturer, Prepare, Builder, immutable UUID definition, API/webhook/topic sources, conditions, mappings and child/nested scopesTestCaptureDeclarationGoldenAndSnapshot, TestCaptureScopesConditionsAndMappings, TestCaptureValidationRejectsMissingOrInjectedDeclarations, ExampleBuilder; deterministic CDL. TestCaptureTranslationTargetsUseCDLWordGrammar, TestCaptureIdentifiersMatchConstructGrammar, TestCaptureStringLiteralsEscapeOnlyScreenplaySequences, TestCapturePropertyNamesCannotBecomeLifecycleConditions and the opt-in TestScreenplayCaptureParserPreservesGoDeclarations verify Screenplay 4.16.0 Parsing/CaptureParser and Text/StringLiteral: unquoted word translation targets, uppercase-leading single event IDs, construct-specific names, literal round trips and reserved property condition kinds. Go uses persisted event IDs, not the C# simple CLR name; unrepresentable IDs/translation targets fail explicitly rather than rename. Webhook-source authorization is authoring-only; model-bound capture attributes are not implemented
Inbound capture authorization / client Captures/{IWebhookSourceBuilder,WebhookSourceBuilder}, kernel Source/Kernel/Concepts/Captures/{SourceAuthorization,SourceAuthorizationJsonConverter} at 2e31b0df; actual NuGet 19.29.4 source ae5e00a8Partial authoring: variadic captures.Webhook, WithBasicAuth, WithBearerToken, WithOAuth, immutable SourceAuthorization, source/definition Authorization accessors; Go-specific fail-closed configuration and JSONTestSourceAuthorizationMatchesActualPackage compares 4 arms × 2 policies byte-exact; TestWebhookSourceAuthorizationMatchesActualSerialize checks 8 cases × 2 policies, retaining absent defaults and single-option bytes. Explicit None is not authorable (zero bytes only). Go rejects blank values, nil options and multiple authorization options at Build rather than C# last-wins, so no credential is silently discarded. TestCaptureAuthorizationRejectsInvalidOptions, TestCaptureAuthorizationSurvivesCopies, TestCaptureDeclarationNeverCarriesCredentials and ExampleWithBearerToken verify authoring/ownership/CDL exclusion. TestSourceAuthorizationHasNoDecoder refuses all 12 deserialize inputs × 2 policies instead of the C# missing/unknown/case-changed discriminator None fallback that drops credentials. TestCaptureAuthorizationRedacted verifies direct fmt/slog redaction and JSON import/export ErrUnsupported on authorization/source/definition/builder; TestCaptureAuthorizationHiddenInUnexportedFields verifies credentials remain hidden in private caller fields and two-level wrappers, including fmt invalid-verb fallbacks and both slog handlers. Credentials are retained behind an immutable opaque pointer, not encrypted memory; other declaration settings can appear when Go cannot invoke formatting methods. No empty-object export or public credential-export API. One-argument calls still compile, but func(string) Source values must adapt to variadic Webhook; JSON users must use explicit authoring. Fixture hashes remain checked by shared loaders. No encryption, enforcement or persistence claim; see authentication evidence
Capture submission/runtime boundary / kernel Captures/{ValidateCaptureDeclaration,SaveCapture}, Engine/{CaptureValidator,DeclarationLanguage/CaptureDefinitionSyntaxVisitor}, Source/Kernel/Protobuf/captures.proto at 2e31b0df / package ae5e00a8Partial: explicit EventStore.Captures().Validate/Save, no activation or discovery; source-authorization submission Not implemented, Go-specific local refusalTestCaptureAuthorizationSubmissionRefusedBeforeDispatch proves ErrUnsupported and zero Invoke/NewStream for every authorization kind, including canceled/expired contexts; TestCaptureWithoutAuthorizationStillSubmitsCDL preserves unprotected declaration bytes/dispatch. CDL-only Save/Validate requests cannot carry authorization; the syntax visitor builds it absent and the pinned kernel rejects non-API sources. Chronicle#4591 tracks the upstream authorization transport/kernel boundary and converter fallback. TestKernelCaptureAuthorizationSubmissionBoundary verifies an unprotected webhook persists as stopped before ValidationError, while a bearer definition is refused locally and absent from GetCaptures. TestCaptureSubmissionReportsCapabilityAndPartialSave, TestKernelCaptureCapability retain API save/read-back and unsupported translation-map partial-save behavior. Messages fail even when the outer envelope succeeds; unprotected Save may already have persisted a stopped definition. No credential storage, authentication, activation or polling claim; map/nested/children/expression runtime remains unsupported
Zero-container workflow and immutable preparationGo-specific explicit functions instead of assembly discoveryCompiled/executed examples/integrations example, existing no-container dependency gates; no registration constructor, grpc.Server, database driver or dependency-injection container in new production packages

C81–C85 references: Source/Clients/DotNET/ReadModels/ at 2e31b0dfba489159b3db323238f16d0f277056b4. Protocol/kernel evidence uses 19.29.4 (ae5e00a8abaa688138b2c2f689e2b4659cccb4fd). These rows do not claim that the wider #33 collection/history inventory is complete.

Behavior / C# sourceStatus and Go surfaceExecutable evidence / deliberate differences
Projection watch and Subscribed / IReadModels, ReadModelWatcher:65–159Implemented: typed Reader.Watch, raw Service.Watch, explicit subscriptionTestWatchReadinessOrderingAndInterruption, TestKernelProjectionWatchAndReadModelReactor; marker is not a snapshot; early racing changes are retained in order. Projection watches do not require reducers
Change type, key, model and synthesized context / ReadModelWatcherImplemented: Change[T], explicit removal/value presence, unknown event typeOrdering test verifies add/modify/remove, ID normalization, namespace, selected sequence and position. TestWatchesAndWindowsRoundTripRegisteredNamingPlan and TestReadModelReactorDispatchUsesRegisteredNamingPlan verify compiled-plan decoding distinguishes root Id from explicitly tagged ID in typed watches, windows and reactor callbacks. Unknown future wire change types fall back to Modified like C#
Interruption, disposal and bounds / ReadModelWatcher.ResetForReconnectGo-specific: Recv, Values, Done, Err, joined Close, count/byte limitsTestWatchCancellationBeforeReadyAndCloseJoin, TestWatchOverloadAndNamespaceFailClosed, TestWatchMalformedChangesAndEarlyIteratorExit, TestKernelWatchInterruptionRequiresExplicitRewatch; unlike C# auto-replacement, returned subscriptions terminate and never silently resume. Re-watch/refetch has no atomic handoff or durable cursor
Protected release ownership / ReadModelWatcher:87–100, ReadModelReleaser, MaterializedReadModels:95–115Partial, Go-specific: admitted raw/typed windows validate server-released data without another Release. Classified projection Watch refuses before streaming because the kernel can corrupt cipher-shaped plaintext before SDK decoding (Chronicle#4566; on 19.32.3 the raw watch changeset is empty for default Id as well as lowercase id); classified local reducer Watch refuses before queue attachment because it lacks a delivery-time erasure fenceTestKernelReleaseRouteProfiles covers default Id and lowercase id unclassified keys, source != explicit Owner subject, and legitimate 344-character base64 plaintext (256 decoded zero bytes): before erasure, exact PII name and namespace-encrypted secret; afterward, only PII is empty and confidentiality remains exact, with no extra Release on raw/typed windows. Public raw Watch replies expose the upstream corruption; successful reducer folds before/after erasure establish fold state, not classified local-watch safety. TestClassifiedWatchesRefuseBeforeTransportOrLocalAttachment covers both refusals. C# Watch directly deserializes server output; C# window source calls Release, with no C# window execution claim here. See the window protection profile and compliance boundaries
Session/sequence boundary / ReadModels and WatchRequestGo-specific sequence-aware request, watches cannot enroll in sessionsReadiness wire test checks the configured non-log sequence; TestWatchAndSessionHaveIndependentLifetimes proves session dehydration does not stop changes. The protocol has no session ID; no protected-decision claim
Materialized paging / IMaterializedReadModels, MaterializedReadModels.CalculatePagingImplemented: Materialized().GetInstances, raw and typedTestMaterializedWindowPaging, kernel watch test; nil = 0/50, negative skip, nonpositive take, -1 unlimited, aligned/non-aligned windows and int32 covering cap
Materialized observation / MaterializedReadModels.ObserveInstancesImplemented: Materialized().ObserveInstances returns full replacement windowsTestMaterializedObserveInitialSnapshotOrderingAndTerminal, TestMaterializedWindowsNeverDecryptReleasedPlaintextAgain and kernel watch test; no subscribed marker exists, so opening awaits the first validated snapshot. Kernel coalescing can omit intermediate states
Name conventions and callback alternative / IReadModelReactor, ReadModelReactorMethodsImplemented: RegisterReadModelReactor[R,M], RegisterReadModelReactorHandlers, exact Added/Modified/Removed discovery at NewClientTestReadModelReactorConventionsReadyEffectsScopesAndNoRetry, TestReadModelReactorValidationAtNewClientAndFrozenRegistries, TestWatchExampleRegistersWithoutAContainer; optional leading Go context; explicit callbacks replace C# same-name overloads; all matches run
Per-dispatch scope, collections, effects and failures / ReadModelReactors:133–161, ReadModelReactorInvoker:37–112Implemented, Go-specific serial dispatchConvention runtime test verifies fresh activation/cleanup, zero/one-element collections, returned event and failure reporting; existing scope/activation/effect pipeline is reused. Missing value for nonnullable M fails instead of inventing state. Errors report without retry; all callbacks still run
Materialized convention / MaterializedAttribute, MaterializedReadModelDifferImplemented: reactors.Materialized(window), WindowDifferTestReadModelReactorMaterializedUsesWindowsAndJoinsCancellation, TestMaterializedDifferUsesSerializedModelsAndExplicitWindowRemoval, TestMaterializedDifferAddsAndRemovesBooleanKeys; string, numeric and boolean keys use C# scalar stringification; key/content differ, initial Added, nil Removed. Go rejects missing/duplicate keys and prefers registered key metadata; leaving a window does not imply deletion
Selected-store callback/effect sequence / EventStore, ReducerTypeExtensions, ReadModelReactors (client revision above)Go-specific sequence-aware callback context and side-effect delivery; read-model reactor plans bind to the same selected-store model as reducers/projectionsTestReadModelReactorsBindCallbackAndEffectMetadataToSelectedStore; origin-store event-log versus external-store inbox-orders for materialized callback contexts and both materialized/change side-effect deliveries, default/store registries, immutable compiled plans. C# synthesized contexts do not carry a sequence ID; Go’s additional sequence metadata must match the selected model
Local reducer feed / ReducerObservers, ReadModelReactors.DetermineChangeTypeImplemented for unclassified models: production fold notifications, first-seen Added in reactorsTestReadModelReactorInfersFirstSeenLocalReducerAddition, TestLocalReducerWatchPlaintextRemovalAndGenerationIsolation; local Watch remains Modified/Removed, reactors forget removed keys. Final plaintext is validated without Release; classified Watch refuses before attachment. Local readiness is not a server acknowledgement or proof of sink persistence
Reactor lifetime and tenant isolation / ReadModelReactors.Start/StopImplemented: generation-owned shared observer lifecycle and unregister joinsTestReadModelReactorGenerationRetiresAndNamespacesStayIsolated, TestReadModelReactorStartupReporterCanReenterSameStore, convention runtime test; startup failure completes readiness before reporting on the owned worker; no callback under internal locks, cancellation joins cooperative workers. New generations start fresh watches; no missed-change recovery claim
C80 all-instance/event-count reads and correlation-grouped history / ReadModels.cs:262–328,397–449, Reducers.cs:259–350 at the baseline revisionPartial: raw/typed GetAll, Collection[T], events.Count/UnlimitedCount, GetSnapshots, Snapshot[T]; bounded active/passive local reducer foldsTestCollectionCountsRoutingAndReportedProgress, TestReducerCollectionsGloballyBoundHistoricalFoldsAndKeepActualPositions, TestSnapshotsOwnCompleteContributionContextWithoutInventingPresence, TestKernelModelHistoryProjectionCollectionsAndCorrelationGroups, TestKernelModelHistoryReducerCollectionRoutingAndDeletion. Zero means no I/O; nonzero explicit reducer counts fold locally; finite overflow is rejected rather than clamped. Reducer snapshots, nonempty projection defaults and unproven key/relationship replay fail explicitly; see collection/history limits

All C# paths in this section are relative to Source/Clients/DotNET at 2e31b0dfba489159b3db323238f16d0f277056b4. Registration uses the pinned 19.32.3 contract above. The shared declarations parser is used by projections, events and read-model indexes; there is no second tag grammar or uniqueness engine. Syntax and role errors can fail during registration; catalog conflicts and semantic event declarations fail atomically at NewClient, before I/O.

C# declaration / sourceGo surface and statusEvidence and exact boundary
Property [Unique] / Events/Constraints/{UniqueAttribute,UniqueConstraintProvider}Implemented for top-level fields: chronicle:"unique(...)" compiles through UniqueValues().On()TestCompositeDeclarationImprovementMatchesExplicitBuilderGolden, TestDeclarationUnrestrictedSequencesDefaultsAndFrozenStores, TestKernelModelBoundUniqueRemovalAndSubject; shared names, first nonempty message, unrestricted-sequence-wins, exact serialized paths
Same-event same-name Unique fields / UniqueConstraintProvider.cs:77–80, UniqueConstraintBuilder.cs:131–135Go-specific improvement: one ordered composite On per eventTestCompositeDeclarationImprovementMatchesExplicitBuilderGolden; C# calls On per property and throws for the repeated event. Decision: follow #24 §5’s composite lowering, not that upstream failure; duplicate directives on one field still fail
Type [Unique] / UniqueEventTypeConstraintsProviderImplemented: events.WithUnique(events.Unique{...}), shared lifecycle namesGolden test above checks both constraint kinds and per-violating-type messages with fallback. Name defaults to Go type name, independent of WithID; one declaration per type
Unique<TEvent> / IConstraintBuilder, ConstraintBuilderImplemented: constraints.UniqueEventTypes, plus WithUnique on that registered typeGolden test above. The inspected C# snapshot has a generic builder method, not a Unique<TEvent> attribute; no nonexistent generic attribute is claimed
[RemoveConstraint] / RemoveConstraintAttribute, both Unique providersImplemented: events.WithRemoveConstraints for model-bound constraints; RemovedWith for explicit buildersGolden and kernel model-bound tests attach every remover, deduplicate repeated names and release the owner’s claim. Go rejects unknown names rather than silently ignoring them
Explicit/declaration composition / Constraints duplicate-name protectionGo-specific: Registry.ConfigureDeclaredConstraint composes the same builder; AddConstraint never replaces a declarationTestDeclaredConstraintsRequireExplicitComposition; duplicate explicit definitions still fail, mixed same-name definitions produce typed errors, callbacks run once per snapshot
[Subject] / SubjectAttribute, SubjectResolverImplemented for top-level scalar/concept fields: subject, existing WithSubjectResolverTestTaggedSubjectPrecedenceAndStaging, TestTaggedSubjectScalarConversions, TestEmptyTaggedSubjectsFallBackToSourceAcrossAppendPaths, TestExplicitEmptySubjectResolverStillFails, kernel model-bound test. Append override → explicit resolver → tag → source; false explicit resolver skips the tag. Nil or empty means absent for tags, no ID-field fallback; explicit resolvers retain strict empty-subject validation. Multiple fields fail instead of C# first-property selection; non-string scalar conversion uses Go’s invariant formatting, not culture-sensitive CLR ToString
[Index] / ReadModels/{IndexAttribute,ReadModels.cs:475–527}Implemented: index tags add to existing WithIndexes metadataTestIndexTagsShareExplicitMetadataAndKeepRepeatedNestedTypes, TestIndexDeclarationsRejectDuplicatesAndWrongRoles, TestIndexTagsSkipMapValuesLikeCSharpDictionaries, TestIndexesDoNotBecomeProjectionMappings; paths include arrays/slices, but map-value descendants are skipped like C# dictionaries. Index tags on the map property itself remain supported. Go correction: path-local cycle guards preserve repeated nested types that C#‘s global visited set can omit
[EventType] / Events/{EventTypeAttribute,EventTypes}Implemented for current descriptors: RegisterEvent, WithID, WithGenerationExisting TestRegistration and registration/kernel generation tests; explicit root admission, no assembly scan. Historical generations/migrations have separate behavior rows below (#32)
[Tombstone] / Events/{TombstoneAttribute,EventTypeExtensions.cs:109–123}Go-specific: WithTombstone records descriptor-only metadata (IsTombstone())TestDescriptorMetadataRegistrationContract; C# attribute is inert; Go records it on the descriptor; wire matches C# (Tombstone=false for registration and appends). Missing C# consumer tracked in Chronicle#4541; no deletion or historical tombstoning workflow claimed
[CompensationFor<T>] / Events/CompensationForAttribute*, Schemas/JsonSchemaGenerator.cs:444–451Implemented: WithCompensationFor(handle) adds top-level schema compensationFor with the target’s persisted IDTestDescriptorMetadataRegistrationContract, TestEventDeclarationsFailAtomicallyAtNewClient, TestCompensationSchemaPreservesUnsignedBounds; same-registry reference, preserved in current schema and generation schema without changing numeric bounds. This is metadata, not compensation execution
[EventStore] / Events/EventStoreAttribute, Events/EventTypes.cs:130Implemented descriptor provenance: WithSourceStore, registration EventStore, existing observer inferenceTestDescriptorMetadataRegistrationContract and existing source-inference tests. No assembly-level default or append rerouting; observer inference and automatic provisioning are covered under External integrations
[Tag] / TagAttributeImplemented static append labels: existing WithTagsTestAppendMetadataAndNamedTags; repeated options remain last-wins, unlike additive CLR attributes. Not implemented as registration labels: 19.32.3 has no such field (TestDescriptorMetadataRegistrationContract). No event-property extraction or observer filtering
[Tags] / TagsAttributeImplemented static append label lists: existing WithTagsTestAppendManyRoutesAndStaticTagUnion; static/dynamic labels merge distinctly. Same last-wins option and absent registration-label boundary as [Tag]
[PII]Implemented for field/type schema classification; scalar runtime limits belowTestClassificationSchemaMatchesCSharpCategoriesAndPropagation, TestProtectionAlwaysRejectsEventSourceIdentity; subject identity is not protection
[Encrypted]Implemented for distinct security schema classification in all three scopes; global runtime remains PartialClassification golden assertions and TestKernelConfidentialityIsIndependentOfPIIErasure; see the scoped rows below

Blank constraint sequence IDs are errors in Go instead of C#‘s filtering. Nested event Unique/Subject tags fail explicitly because the referenced providers scan root properties only; read-model indexes do recurse. See event metadata for the public options and constraints for composition and migration guidance.

C13–C17/C48 references: Chronicle 2e31b0dfba489159b3db323238f16d0f277056b4, Source/Clients/DotNET/Events/{EventTypeExtensions,EventTypes}.cs and Events/Migrations/*; kernel Core/EventTypes/EventTypeRegistrar.cs and Core/EventSequences/Migrations/{EventTypeMigrations,EventMigrationExpressions}.cs. Wire definitions use the pinned 19.32.3 protobuf contracts. See the evolution guide and offline example.

Behavior / C# sourceStatus and Go APIExecutable evidence and differences
Historical ID derivation / EventTypeGenerationForAttribute*, EventTypeExtensions:85–130Implemented: RegisterEventGeneration[Previous](registry, current, generation)TestHistoricalCatalogExactAndLatestLookup: inherited ID, lower positive generation, registered current, no mixed/overridden identity. Explicit registration replaces markers and scanning
Exact and latest lookup / EventTypes:226–244Go-specific: LookupRef is exact; LookupID selects currentTestHistoricalCatalogExactAndLatestLookup: C# falls back to latest for missing CLR generations; Go retains explicit failure rather than guessing a codec. Duplicate current IDs remain forbidden; historical (ID, generation) pairs are distinct
Real generation schemas before migrations / EventTypes:114–198Implemented: grouped event registration with ordered concrete schemasTestMigrationRegistrationMatchesCSharpWire: real old/current schemas, one registration per ID, latest top-level schema, adjacent migration wire fields. Go requires concrete registered endpoints rather than C#‘s compatibility placeholder schemas
Adjacent shared identity and duplicate migrators / EventTypeMigration:29–49, EventTypeMigratorsImplemented: RegisterEventMigration, NewClient validationTestMigrationInvalidGraphsFailBeforeConnection: wrong IDs, gaps, duplicate pairs, missing endpoints and missing chain fail atomically without I/O
Complete chain and validation defaults / EventTypeRegistrar.ValidateMigrationChainImplemented: WithEventTypeGenerationValidation(true) checks every link at constructionTestMigrationChainIsCompleteOrderedAndStoreIsolated, TestKernelGenerationWithoutMigrationsMatchesCSharp: disabled default retained; enabled errors move earlier from kernel registration to NewClient
Rename / EventMigrationPropertyBuilder.RenamedFromImplemented: MigrationBuilder.RenamedFrom emits $renameTestMigrationRegistrationMatchesCSharpWire, TestHistoricalConceptSchemasAndMigrationNames: both directions, nested paths, explicit JSON names
Split and combine / EventMigrationPropertyBuilder.Split,CombineImplemented: zero-based Split, ordered CombineTestMigrationRegistrationMatchesCSharpWire, TestKernelHistoricalEvolutionAndSubscribedGenerations: forward split and reverse join round-trip persisted events
Defaults and explicit empty direction / EventMigrationPropertyBuilder.DefaultValue, EventMigrationBuilderImplemented: $defaultValue; mandatory callbacks may be emptyTestMigrationRegistrationMatchesCSharpWire, TestMigrationRequiresBothDirectionsAndValidLiterals, TestMigrationRecursivePropertiesAndCollectionRejection, kernel evolution test: missing target gets default, empty direction emits {}. Default semantics are executed by the kernel, not reimplemented locally
Shared numeric/property value maps / EventValueMapBuilder, ValueMapBuilderImplemented: ValueMapBuilder.For, ordered ValueMapping pairsTestMigrationRegistrationMatchesCSharpWire, kernel evolution test: ordinary unregistered named integers are numeric JSON, one declaration emits both directions; declared enum codec endpoints are explicitly unsupported; historical appends after upgrading preserve unlisted values through the kernel
Migration expression order / EventMigrationBuilder:45–49, EventMigrationPropertyBuilder; kernel EventTypeMigrations:203–205Implemented: compiled JSON preserves declaration order; repeated targets keep their first position and last expressionTestMigrationPreservesExpressionInsertionOrder, order-sensitive TestMigrationRegistrationMatchesCSharpWire: overlapping parent/child rename and default writes in both directions, repeated targets, shared maps before directional operations
Lossy inverse and directional override / EventValueMapBuilder:43–66, EventTypeMigration:80–105Implemented: first pair for each inverse target; directional operations winTestMigrationRegistrationMatchesCSharpWire, TestDirectionalMigrationOverrideAndFrozenInputs; defaults/maps/builders and returned definitions cannot mutate frozen clients
Paths and schema concepts / MigrationPropertyNames:34–62Implemented for object paths: Property[T] uses Go fields resolved through the shared serialization planTestHistoricalConceptSchemasAndMigrationNames, TestMigrationRegistrationMatchesCSharpWire, TestMigrationRecursivePropertiesAndCollectionRejection: JSON tags, policy, recursive paths, UUID concept nullable schemas. C# expression trees become typed Go field strings validated at construction; collection traversal/literal-dot names fail explicitly
Typed history / EventSerializer, AppendedEventConvertersImplemented: events.Decode[T], Appended.Decode, Descriptor.UnmarshalTestHistoricalTypedDecoding, TestPlanDecodeUsesGenerationFieldNamesAndConcepts, kernel evolution test: historical/exact and kernel-migrated representations, concept codecs, atomic decoder failure, raw fallback without fabricated migrations
Historical reactor/reducer handler expansion / EventTypeExtensions:61–76Implemented, correcting C# C15/C48 omissionTestHistoricalConcreteHandlersKeepTheirOwnExpansion: generation-only concrete reactor and reducer handlers retain themselves; subscriptions contain their selected generation, not every catalog alias; raw fallback preserves actual context
Multiple generations in one observer / Reactors:717–726Go-specific: require one generation per event ID across live/replay methods and interface familiesTestObserverRejectsMixedGenerationBindings: C# selects its first subscription for an ID; Go rejects ambiguous cross-generation bindings before activation. Use separate observers, as in the kernel evolution test
Kernel historical backfill and observer delivery / Reactors:717–726, Reducers, kernel migration engineImplemented against 19.32.3-developmentTestKernelHistoricalEvolutionAndSubscribedGenerations: register/append generation one, introduce generation two plus migration, append generation two, read both representations, current and historical observers receive subscribed shapes and generation context after historical backfill. Registration readiness is not a backfill barrier; starting earlier can legitimately receive raw fallback content
Protected generations / kernel Core/EventSequences/Migrations, Core/Events/EventCompliance.cs at v19.32.3Partial: migrations of PII/encrypted events register and transform plaintext (Chronicle#4456, fixed in 19.32.2); only the current representation is releasedTestKernelProtectedEventGenerationMigrationProfile: historical upcast, current append, projection replay and erasure are correct; GenerationalContent for other generations stays ciphertext on reads and historical-generation reactor delivery (Chronicle#4623). No SDK guard yet (#90); documented in the evolution guide

Migrations are immutable declaration output, not local payload callbacks. No assembly scanning or separate client-side migration engine is introduced. The broader enum schema/name-read conventions remain tracked by #19; this slice maps numeric enum values and does not claim that remaining serialization surface.

Deliberate differences and migration guidance

Section titled “Deliberate differences and migration guidance”
  1. TLS validates by default. C#‘s local profile skips validation. Add WithDevelopmentDefaults only for development; configure real roots/client certificates with WithTLS for production. Explicit validating TLS wins over security opt-outs.
  2. Root registration is explicit and snapshotted. Use RegisterEvent[T], RegisterReadModel[T] and Registry.AddConstraint before NewClient. Model-bound projection tags and typed type-level options preserve attribute-driven declarations alongside the fluent builder; only root admission replaces assembly scanning. No global init registry. WithRegistryForStore replaces, rather than merges with, the default catalog.
  3. Context replaces ambient state. Pass metadata.WithCorrelation, WithIdentity and WithCausation; the client does not invent application/program audit facts. Namespace selection remains explicit and does not grant tenant access.
  4. Errors describe write ambiguity. Domain rejection is a result; operation failures remain errors. Unknown outcomes are never represented as known rejection. Err exposes both constraint and concurrency categories; no transparent append retry is added.
  5. Unsupported options fail. API keys, plaintext and URI certificate/password formats return ErrUnsupported, rather than silently skipping security or routing behavior. Use WithTLS for PEM material.
  6. Serialization has a deliberately bounded schema contract. Fundamentals Concept[T] and standard codecs replace ConceptAs<T>; plain named primitives remain supported. Explicit JSON tags are recommended. Unsupported custom/protected shapes fail registration; no PII/encryption tag can silently send plaintext. Empty exact type IDs and IDs containing commas fail validation. Scalar/array integers use kernel formats; unsigned values above MaxInt64 fail before dispatch because the kernel MongoDB append path parses bare JSON integers as signed BSON integers (Chronicle#4588). Use strings for that range. Dictionary integers outside -2^53 through 2^53 fail before dispatch, including nested values, because the kernel converts dictionary numbers through double. Use typed struct properties or strings for wider values. Nullable pointer schemas preserve absence; omitzero follows Go IsZero methods, but omitted non-nullable fields may materialize as kernel defaults.
  7. Protected concurrency cannot silently downgrade. No-match uses both wire fields. A confirmed commit without the requested check returns its committed result plus ErrUnsupported: do not retry. A single append rejects scopes naming another source; AppendBatch supports independently labeled checks. Duplicate labels and source/label mismatches fail locally. Batch check flags mean every scope was checked, so mixed checked/unchecked batches may legitimately report false; the wire carries no per-scope success flags.
  8. Resource ownership is explicit. Constructors are lazy; Dial performs preflight. Close cancels/joins owned work but never closes borrowed channels/token sources. EventSequence returns a construction error for invalid IDs rather than publishing an invalid handle. Scalar options are last-wins; conflicting auth modes are errors.
  9. Generation validation matches C# defaults. Registrations include every concrete schema in Generations and default to disabling schema/migration validation, allowing generations above one without migrations. Use WithEventTypeGenerationValidation(true) to protect existing generation schemas; NewClient then requires the complete adjacent migration chain. Disabled validation permits overwriting history’s schema. Shared C#/Go IDs require compatible generated schemas when validation is enabled; identical payload names alone are insufficient.
  10. The default namespace is Default. This corrects the earlier lowercase default value to match C# and the kernel. MongoDB rejects namespaces differing only by case; callers must use the kernel spelling or explicitly select another namespace.
  11. Recovery is supervised, not application replay. Slice 3 replaces slice 1’s explicit-connect-after-loss behavior with automatic generation replacement, following Connections/ChronicleConnection and ConnectionWatchdog at the reference revision above. Old workers join before replacement. Unlike C#‘s broad gRPC retry policy and permissive compatibility fallback, Go fails compatibility/authentication closed and never retries an ambiguous append. Terminal failures require an explicit Connect; transient reconnect runs with time-bounded attempts and capped jittered backoff until shutdown.
  12. Registration outcomes describe only implemented stages. Store-wide definitions share a barrier; namespace readiness stays separate. A batch acknowledgement is not a per-artifact verdict. Transient registration failures receive bounded retries and delayed background retry; deterministic validation/authorization failures require an explicit retry rather than endlessly repeating. Go adds a per-attempt budget and a 64-endpoint discovery/probe bound. For runtime projection additions, Published records retained local admission separately from stage acknowledgements; other artifact families and replacement remain unsupported.
  13. Shutdown is context-bounded without breaking Close(). Shutdown(ctx) drains admitted RPCs, then cancels and joins; CloseContext(ctx) immediately cancels and bounds the join. A timeout reports incomplete cleanup, which continues until cooperative callbacks return. The unchanged Close() error remains an unbounded cancellation/join convenience. Borrowed channels retain caller ownership.
  14. Read filters describe kernel history, not exact routes. Empty/default sentinel dimensions do not narrow. Event types match IDs across generations; normalized history filters sort/deduplicate IDs and use generation one. Raw JSON plus generation metadata replaces automatic CLR deserialization. Read results are ordered and malformed/duplicate positions fail; these finite queries do not imply a multi-query snapshot or revision/redaction protection.
  15. Batch scope enrollment is explicit. A unique label matching a source replaces that source’s default first-entry-route scope. Independent labels need no corresponding event. Like C# EventsWithConcurrencyScopes, duplicate labels fail, including identical duplicates. Unlike that C# wrapper’s restriction on unresolved independent scopes, Go can explicitly Resolve an independent filter before the atomic append. An unchecked empty batch is rejected locally. Eventless protected checks work with 19.32.3; an older kernel’s event-required validation becomes ErrUnsupported, not a no-op success.
  16. Persisted timestamp precision is kernel-limited. The Go wire keeps 100 ns precision, but the 19.32.3-development MongoDB kernel returns occurrence/causation dates truncated to milliseconds. TestKernelOrderedAtomicBatchAndHistory records this server behavior; TestReadPreservesEnvelopeMetadataAndGenerations proves conversion retains all precision actually returned. No client-side reconstruction or extra persistence path is invented.

Batch/read C# references above use revision 2e31b0dfba489159b3db323238f16d0f277056b4; kernel behavior is exercised against the pinned 19.32.3-development image. The runnable batch example also uses the public production APIs.

Naming references: Chronicle 2e31b0dfba489159b3db323238f16d0f277056b4, Source/Clients/DotNET/ChronicleClient.cs:119–128,360–381 and Schemas/JsonSchemaGenerator.cs:62–93; Fundamentals d2accc4a79b6bcf2708213c97093ab5ba6c06381, Source/DotNET/Fundamentals/Serialization/{DefaultNamingPolicy,CamelCaseNamingPolicy,AcronymFriendlyJsonCamelCaseNamingPolicy}.cs, Strings/StringExtensions.cs and Fundamentals.Specs/Strings/for_ToCamelCase/when_converting.cs. Shared Go dependency: Fundamentals.Go v0.1.0, Go 1.26; no dependency-injection integration is introduced.

SurfaceStatus and Go behaviorEvidence / boundary
Default and explicit property namingImplemented: WithNamingPolicy, serialization.PreservePropertyNames (default), CamelCase; tags win, all schemas/payloads and paths use immutable plan metadataTestSchemaAndSerializationShareNames, TestFundamentalsCamelCaseGolden, TestNamingPoliciesCompileOneFieldPlan, TestClientNamingFreezesEveryArtifactAndPreservesRegistry, TestFluentNamingRebindsOnlyPlanPaths, TestClientNamingRejectsCollisionsBeforeIO, TestKernelFundamentalsScalarsAndDefaultNaming. C# fixture port excludes null/unpaired UTF-16 strings with no valid Go UTF-8 equivalent; supplementary letters remain unchanged
Go read-model ID ↔ C# IdGo-specific spelling translation with kernel-compatible behavior: an untagged root Go field named exactly ID uses C#‘s equivalent Id, serialized as Id under PreservePropertyNames and id under CamelCase or LegacyGoCamelCase. The read-model plan supplies schemas, JSON and all property paths; collisions fail registration. Events, nested fields, other initialisms and fields with any explicit json tag keep their policy namesTestReadModelPlanTranslatesOnlyUntaggedRootID, TestReadModelPlanHonorsEveryExplicitJSONTag, TestReadModelPlanRejectsTranslatedRootIDCollisions, TestReadModelDescriptorRejectsRootIDCollision, TestReadModelIDPathsRebindFromPlan, TestClientReadModelIDTranslationRebindsProjectionPaths, TestKernelProjectionReadsUntaggedIDWithDefaultNaming. At the Chronicle revision above, Storage.MongoDB/ExpandoObjectConverter.cs:62–77 only maps _id back to schema-declared id/Id; Infrastructure/Json/ExpandoObjectConverter.cs:26–76 otherwise drops it from the response. Use id/Id for explicitly tagged root identities that must round-trip through this kernel
Read-model root identityImplemented: root chronicle:"key" or case-insensitive Go ID field metadata supplies the serialized name; reads normalize _id/case variants only when that name is absent, and protected releases resolve the same subject fallbackTestReadModelNormalizesRootIDAlias, TestReadModelDeclaredIDIsNotOverwritten, TestReadModelNormalizesDeclaredKeyProperty, TestReadModelReleaseUntaggedIDSubject, TestRootIDNamingUsesBoundPlan. Nested keys and other kernel metadata remain unchanged; a read never invents an ID from the requested key
Earlier Go namesGo-specific: serialization.LegacyGoCamelCase preserves the original Go algorithm (URLValue → urlValue, ID → id)TestNamingPoliciesCompileOneFieldPlan, ExampleNamingPolicy; compatibility only, not C# acronym-friendly camelCase
Shared scalars and conceptsImplemented for concepts.UUID, DateOnly, TimeOnly, TimeSpan and valid Concept[T]; Underlying supplies schema shape, declared codecs plus CheckJSON supply validated JSONTestFundamentalsEventRegistrationSchemaAndJSON, TestInvalidConceptRegistrationPreservesTypedError, TestConceptCodecsAreCheckedBeforeDispatch, TestConceptIntegerRangesUseWireRepresentation, TestKernelFundamentalsScalarsAndDefaultNaming; Chronicle numeric limits still apply, google UUID shapes retained, concept map keys unsupported
Shared correlationImplemented: Chronicle metadata delegates to Fundamentals correlation.WithID / FromContext with lossless RFC bytesTestFundamentalsCorrelationContextRoundTrip, TestFundamentalsContextReachesAppendCorrelationID, TestKernelFundamentalsScalarsAndDefaultNaming; broader Chronicle parser/codecs and BCL Guid adapter remain unchanged
Projection conversionImplemented for explicit mapping representation compatibility; AutoMap performs no client-side validation, matching C#, and defers conversion to the kernelTestProjectionAcceptsKernelScalarAndObjectConversions, TestProjectionRejectsIncompatibleExplicitConversions, TestProjectionAcceptsCompatibleFormattedConversions, TestObjectAndCollectionCompatibilityUsesSerializedProperties, TestLiteralValidatesWrappedConceptIntegerRange, TestContextOnlySubscriptionDoesNotPrevalidateAutoMap, TestTypedConceptPathsPreserveDeclaredDomainIdentity; widths and source nullability do not independently reject mappings. String formats must match (uuid/guid are aliases), unless either format is empty. Integer → number is admitted. Objects compare shared target properties recursively by serialized name; missing source properties are allowed. Collections compare element representations recursively. Typed field/key metadata still uses declared types, not unwrapped ID equality

Behavior change: untagged Go properties now retain their spelling, matching C# production defaults, except that an untagged root read-model ID translates to C#‘s Id before the policy is applied. Fundamentals CamelCase preserves other leading acronyms: URLValue stays URLValue, while Person becomes person. Container naming remains case-preserving pluralization, independently of property policy.

Existing stores must select LegacyGoCamelCase explicitly to keep previous Go schemas, or retain exact persisted names with json tags. Enable WithEventTypeGenerationValidation(true) during upgrades; never overwrite a same-generation schema or rewrite history merely to change naming. Validation remains disabled by default for C# parity. Use adjacent generation migrations when changing already-persisted shapes. Author constraint, index and projection paths against declaration names; client compilation rebinds those paths by field identity. Full instructions: serialization.

Go projection paths consistently honor exact JSON tags. C# reflected paths in ModelBoundProjectionBuilder.cs:600–609 and FromDefinitionExtensions.cs:26–31 do not universally honor JsonPropertyName; migrations do. This is an intentional Go consistency improvement, not a claim of equivalence for that C# limitation. No C# executable was run here: golden names are source-derived; round-trip execution uses the pinned Chronicle kernel and the Go client.

Append configuration and declaration migration

Section titled “Append configuration and declaration migration”

Register the subject policy once alongside the event schema:

registered, err := chronicle.RegisterEvent[CustomerChanged](registry,
events.WithSubjectResolver(func(event CustomerChanged) (events.Subject, bool) {
return events.Subject(event.CustomerID), event.CustomerID != ""
}))

CustomerChanged is the application’s named event struct; the callback must match that exact declaration type. An append-level WithSubject (or Entry.Subject) wins without invoking the callback. Missing subjects fall back to the source ID.

Add chronicle.WithCheckFirstAppendIntoAScope(true) to client construction to protect first writes across all sequence handles, batches and unit-of-work commits. It stays off by default, matching C# ConcurrencyOptions. Explicit NoCheck remains unchecked. A competing writer after an empty-tail read becomes a known concurrency rejection rather than an unchecked success.

WithDefaultConcurrencyStrategy preserves C#‘s extension point without dependency injection: the callback receives the sequence and default source/route filter. Return an explicit expectation after a sequence.Tail(ctx, eventsequences.TailFilter(filter)) read, or return Resolve to have the SDK perform its existing matching-tail read. Explicit expectations do not trigger an extra read. Batch defaults invoke the strategy once per source using its first entry’s route; units of work defer it to commit, never staging. No retry or extra kernel round-trip is required by this translation.

Call sequence.ResolveScope(ctx, filter) to apply this same policy to selected concurrency dimensions before staging. Resolve each target independently, then label the returned scopes for Stage/AppendBatch. This adds no route defaults. Resolved scopes never reread their tails at dispatch, even when an empty tail is unchecked under the default first-append policy; that unchecked result retains its filter but is distinct from an unresolved Resolve expectation.

Operation metadata is available through the new *WithMetadata append methods, not by changing the original public result structs. Operation().EventTypes() retains generations on success, rejection and unknown outcomes; Result().Target still describes only confirmed committed work. Local failures include registered input types only, because an unregistered value has no persisted identity. Existing callers can keep their original methods and unkeyed literals unchanged.

This slice compares DotNET/ChronicleClient.cs, ChronicleOptions.cs, EventStore.cs, Registrations/{RegistrationRetryOptions,RegistrationBackoff,SingleFlightRegistration}.cs, and the connection sources in the table above at revision 2e31b0dfba489159b3db323238f16d0f277056b4. Go spellings avoid package stuttering and Get prefixes; the underlying concepts remain client, event store, namespace, connection and registration.

ConcernC# counterpart/defaultGo behavior and deliberate difference
Client construction and storesChronicleClient, GetEventStore, GetEventStoresNewClient/Dial, EventStore, EventStores; explicit contexts and construction errors, frozen options rather than mutable Options
Endpoint/authenticationlocalhost:35000, development client credentialsSame endpoint and credentials; validated TLS is the safety difference described above
Connection budgetConnectTimeout = 5 seconds; initial-startup and post-failure wait behavior differWithConnectTimeout, five seconds for each complete discovery/auth/handshake attempt; first attempt returns its actual failure rather than reporting an unready connection as connected. Subsequent readiness waits use the caller’s deadline
Heartbeats and transport pingsFixed five-second staleness, evaluated on a one-second watchdog tick; HTTP/2 60s/30s; SkipKeepAlive = falseSame default thresholds/pings; timer-driven staleness is configurable with WithKeepAliveTimeout, without the extra polling tick. WithSkipKeepAlive() omits the entire application session, not HTTP/2 pings
ReconnectWatchdog retries with exponential 1–30s delays, awaited lifecycle disconnect/connect notificationsSame automatic replacement and re-registration with application sessions; Go adds half-to-full downward jitter and stops on terminal authentication/compatibility errors (custom selection failures are always transient). Async application hooks never delay recovery: per-event concurrent hooks are joined in transition order with bounded coalescing. Delivered Connected pairs on Close/Shutdown too; panics cannot reject a connection. Skipped sessions have empty ConnectionID and no heartbeat-driven replacement
Calls during recoveryService accessor attempts connection, subject to failure backoffExisting handles fail before dispatch while disconnected, rather than making every RPC wait for reconnection. Use Ready(ctx) when waiting is appropriate; replay barriers block required operations
BalancingFactory defaults to least-connections; explicit ChronicleOptions.LoadBalancerStrategy overrides the URI and is disposed when disposableSame algorithms and URI names; at most 64 endpoints. WithLoadBalancer borrows a last-wins strategy, called once per attempt including single endpoints. Go rejects URI-strategy/borrowed-channel conflicts, never closes custom strategies, and retries selection failures with normal backoff. Candidate slices are copied; invalid selections fail before OAuth or dialing
OAuth60s refresh margin, 5s failure throttle, 3600s fallback lifetime, forced refresh on rejectionSame cache/refresh constants; five-second HTTP request cap and a fresh endpoint-bound OAuth cache per generation. This intentionally avoids carrying a token across server restarts; no automatic unary replay
Registration within a passFive attempts; initial 2s/max 30s half-to-full jitter, retries the full artifact passSame attempt count and delay defaults; 30s per-attempt cap. Only transient failures retry automatically; acknowledged store-level stages are shared rather than resent per namespace
Registration between passesPer-store background exponential 2–30s delay plus single-flight failed-pass backoff (1–60s)One generation-owned worker scans pending registrations at MaximumDelay (30s default), reducing background fan-out. An explicit subsequent wait may start a fresh pass immediately; it does not add C#‘s second backoff layer. Applications must not hot-loop explicit waits; use the owned background retry or a caller deadline
Readiness and outcomesRegistration, WaitForRegistration, RegisterAll, Lifecycle.IsConnectedWaitForRegistration(ctx) returns a generation/pass outcome; Ready(ctx) separates connection health from artifact readiness. The pass ensures store/namespace, registers event types/read models, constraints and projections, starts reactors/reducers, registers external subscriptions, starts read-model reactors, then seeds. TestSeedingIsLastAfterEveryObserverRegistrationSend and TestExternalSubscriptionsFollowObserversPrecedeSeedingAndReplayPerGeneration cover ordering/failure barriers. Outcomes report registration work and failures, not an attachment receipt: duplex observer readiness means sent; a watch Subscribed marker and seed command acknowledgement have their own narrower meanings. Runtime RegisterAll reload remains unsupported; bounded runtime projection additions use the existing registration barrier
Failed store creationEvicts a failed lazy task from the name/namespace cacheRetains the immutable handle but never caches failure as successful readiness; later passes and reconnect can recover it. No failed task permanently poisons admission
DisposalDispose() cancels owned connection lifetime and disposes the supplied connectionClose() cancels/joins only owned resources; CloseContext bounds joining and Shutdown adds deadline-bounded RPC draining. Borrowed channels are never disposed
Cache evictionIChronicleClient.cs:42–53, ChronicleClient.cs:289–300 at 2e31b0dfba489159b3db323238f16d0f277056b4: void EvictEventStores() removes completed stores’ connection handlers and clears all name/namespace entriesPartial lifecycle parity: Client.EvictEventStores() error clears cached membership only. Go returns existing prepared/closed state errors and shares one retained coordinate owner across distinct facades; no selector, context, cleanup or revocation. TestEviction*, ExampleClient_EvictEventStores cover admission races/cancellation, captured versus later Ready/replay, shared observers/feeds/tombstones, immutable readers/stale guards, uncertainty, identity readiness and borrowed scopes. TestKernelCacheEvictionRetainsWatchAndExplicitReconnect covers old-watch delivery, distinct reacquisition and explicit registration/rewatch after connection loss; not uninterrupted delivery, memory reclamation or authorization proof
Connection hooks and custom selectionConnectionLifecycle, ILoadBalancerStrategy at the pinned revision above#62 hooks and balancing are implemented with the deliberate Go ownership/dispatch differences above. See connection hooks and custom load balancing. Sink defaults are recorded below and captured process/software audit metadata in the enrichment section

Authority: DotNET/ChronicleOptions.cs and Connections/ChronicleConnection.cs:{ConnectInternal,CreateGrpcChannel} at C# 2e31b0dfba489159b3db323238f16d0f277056b4. The actual application protocol is server-streaming Connect plus unary ConnectionKeepAlive acknowledgments, not bidirectional streaming. All options below are client-wide, validated and frozen at NewClient; they cannot be changed on a store or namespace handle.

C# option/defaultGo option and statusExecutable evidence / intentional difference
MaxSendMessageSize = 104857600 bytesImplemented, Go-specific bounded substitution: WithMaxSendMessageSize(bytes int), last winsTestMessageSizeOptionsValidateFinalValues, TestMessageBoundsExactProtobufUnaryAndStreamingOwnedAndBorrowed, TestKernelClientTransportOptions, ExampleWithMaxSendMessageSize; accepts 1..2147483647, rejects zero/negative/overflow. No nullable/unlimited mode
MaxReceiveMessageSize = 104857600 bytesImplemented, Go-specific bounded substitution: WithMaxReceiveMessageSize(bytes int), last winsSame exact protobuf and kernel tests; TestOmittedMessageBoundsPreserveBorrowedOwnerDefaults, ExampleWithMaxReceiveMessageSize; accepts 1..2147483647. Owned replacement generations retain both frozen bounds; borrowed channels retain owner defaults unless explicitly overridden per RPC, for unary and streaming calls alike. Neither direction implicitly overrides the other
SkipKeepAlive = falseImplemented, Go-specific protected readiness: WithSkipKeepAlive()TestSkipKeepAliveProbesRegistersAndSurvivesSilence, TestSkipKeepAliveProbeFailsClosedEvenWithoutCompatibility, TestSkipKeepAliveCompatibilityStillTerminatesStartup, TestSkipKeepAliveProbeCancellationAndCloseJoin, TestSkipKeepAliveTokenFailureDoesNotDispatchProbe, TestKernelClientTransportOptions, ExampleWithSkipKeepAlive; skips Connect/first acknowledgment/receiver/watchdog entirely; HTTP/2 60s/30s settings remain unchanged
Fixed application staleness threshold; optional skipped sessionGo-specific: positive WithKeepAliveTimeout, default five secondsTestSkipKeepAliveRejectsExplicitTimeoutInEitherOrder, TestSkipKeepAliveRejectsConfiguredObserverRuntimesBeforeIO; an explicit timeout conflicts with SkipKeepAlive in either order. Configured reactors, reducers (even passive) and read-model reactors in default or per-store registries also fail before network I/O: kernel subscriptions require a registered logical session

Message bounds cover serialized protobuf messages, not just event JSON. Small limits can therefore reject compatibility, the mandatory authenticated readiness probe, registration or observer requests as well as appends and reads. Both Invoke and NewStream apply explicit settings on the shared generation transport; no borrowed channel is mutated or closed. An explicit value equal to the SDK default still overrides a borrowed owner’s limit. Omitted settings preserve that owner’s limits.

Compatibility preflight remains fail-closed unless explicitly skipped. It is anonymous on the kernel and cannot prove authenticated readiness. With a skipped application session, startup always calls protected, read-only GetConnectedClients, even when compatibility is disabled. Authentication, authorization and unsupported-method failures are surfaced without fabricating connection registration or retrying the rejected operation. The 19.32.3-development witness verifies anonymous rejection and authenticated registration/append/read. It checks for new Go session IDs belonging to its own process, not an empty or unchanged global client list: other fixture processes can have active sessions and changing heartbeat timestamps. The public SDK does not expose a skipped client’s internal connection ID; the serial process-local check is narrower than proof by individual client ID. The transport unit tests also verify that skipping keepalive dispatches no Connect RPC.

The kernel test pins the compatibility request’s exact protobuf send boundary (126854 bytes), with a separate 64 KiB bounded startup receive envelope. A 128 KiB event in a unique immutable source then supplies the target event-read receive boundary, measured from grpc-go’s uncompressed incoming payload length. Both equality and one-byte-short are asserted through owned public SDK clients, including successful startup and registration before the target read; oversize reads return no partial history. The fixture cap is 512 KiB. Re-serializing a Go-decoded response with proto.Size is not an exact wire-size witness because the kernel’s protobuf-net serializer emits explicit defaults that Go omits. The small compatibility response is not used as a client-wide receive cap: GetConnectedClients can legitimately return a larger shared-session envelope. Exact unary and streaming transport bounds remain covered by bufconn tests.

A skipped session has no application heartbeat-driven logical reconnect or registration replay guarantee after a kernel restart. grpc-go transport reconnection is not a replacement for that lifecycle. Startup/replacement registration workers still belong to their generation; cancellation, Close, CloseContext and Shutdown join client-owned work as usual. Prefer skipped sessions for short-lived one-shot clients. TLS verification, credential ownership and the no-append-retry contract are unchanged; no idle-ping guarantee is added.

Authority: C# 2e31b0dfba489159b3db323238f16d0f277056b4, DotNET/ChronicleOptions.cs:DefaultSinkTypeId, DotNET/ReadModels/ReadModels.cs:GetSinkTypeIdFor and Kernel/Concepts/Sinks/WellKnownSinkTypes.cs. The provider identities are strings MongoDB, SQL, InMemory and None; UUIDs identify provider configurations. C# defaults to MongoDB, with passive read models/projections selecting None.

SurfaceStatus / Go contractExecutable evidence and limits
Materialized client defaultImplemented: WithDefaultSinkType(kind readmodels.SinkType), MongoDB omitted; MongoDB/SQL/InMemory accepted, last winsTestDefaultSinkSelectionIsDetachedAndStoreReplacementIsNotMerged, ExampleWithDefaultSinkType; selected default and every per-store replacement resolve independently, nil remains empty. Catalog access performs no I/O
Model override/configurationGo-specific existing readmodels.WithSink takes precedence, even explicit MongoDB equal to the declaration default; canonical configuration UUIDs are retainedTestExplicitSinkSurvivesNamingAndDefaultCopies, TestDefaultSinkCSharpHandDerivedWireGoldens; goldens are hand-derived from the pinned C# contract, not captured C# runtime output
Passive producer precedenceImplemented, with Go-specific strict conflict validation: inherited materialized defaults become None; explicit materialized selections conflict with passive producers; explicit None remains valid with passive semanticsTestDefaultSinkPassiveProducerPrecedenceAndExplicitConflicts; C# has no corresponding per-model sink option in GetSinkTypeIdFor. Existing Go explicit-sink intent is retained rather than silently ignored
Global None/unknown defaultPartial, Go-specific restriction: rejected with ErrInvalidConfiguration at capture before preparationTestDefaultSinkRejectsUnknownAndNoneBeforePreparation, TestCaptureInvalidSinkRunsNoSchemaFactoryOrServiceCallbacks; C# accepts global SinkTypeId.None and registers that selection for non-passive models, allowing immediate projection instead of materialized reads. This is working C# behavior, not an inert declaration. Go restricts None to passive producers; callers using the C# global option must explicitly declare passive producers in Go
Frozen compilation and reconnectImplemented: detached sink resolution preserves original declaration identity, schema/generation, codec/classification and initial-state snapshots; producer plans bind the final catalogTestDefaultSinkFactoryProducerPlansUseFinalCatalogWithoutRepreparation, TestFactoryCodecsSurviveNamingInitialStateStoreBindingAndReconnect, TestDefaultSinkCopyPreservesFrozenClassificationAndSchema, TestDefaultSinkRegistrationFrozenReconnectAndOriginalTypedHandle; shared registry preparation runs once per client epoch and reconnect bytes are stable
Kernel-backed materializationPartial backend qualification on 19.32.3-developmentTestKernelClientDefaultSinkMongoAndExplicitMongoOverrideSQL covers unchanged MongoDB default and a MongoDB model overriding a SQL client default. It materializes MongoDB only. SQL/InMemory registration and wire selection are not proof of live backend reads; neither backend is provisioned by this fixture
Decision agreementGo-specific fail-closed check, not expanded decision capabilityTestDecisionSinkDefaultRequiresActualServerProfileBeforeFolding, TestDecisionAgreementRechecksServerShapeAndKey; actual server sink type/configuration and projection active/rewindable flags must match the admitted definition before and after folding. A sink mismatch returns no token; this is not full mapping equality or live SQL qualification

TestCaptureSinkDefaultsFreezeOptionsRegistriesCodecsAndFactoryModels covers Capture → Prepare with SQL/InMemory defaults, explicit MongoDB and passive None, shared and replacement registry snapshots, retained options/services, frozen codec initial state and final catalog/producer identity. Capture validates the sink without preparation callbacks; Prepare never rereads options or registries.

No namespace override, database dependency ownership or client driver is added. Sink selection is store-wide and does not configure kernel backend providers. This section records the default-sink slice of #62; hooks and custom balancing are covered in the connection API comparison above.

Transaction references use C# revision 2e31b0dfba489159b3db323238f16d0f277056b4, Source/Clients/DotNET/Transactions/{IUnitOfWork,IUnitOfWorkManager,UnitOfWork,UnitOfWorkManager,UnitOfWorkLifecyclePolicy}.cs. The Arc consumer reference is Source/DotNET/Chronicle/Commands/TransactionalCommandScope.cs: completion is distinct from confirmed commitment, and early commitment completes shared work.

  1. Separate participant and owner. Replace ambient IUnitOfWorkManager.Begin/Current/SetCurrent/TryGetFor with transactions.Begin and explicit participant context accessors. Go has no AsyncLocal; there is no global correlation registry. UnitOfWork.Stage translates AddEvents. Only the separately retained Owner exposes Commit/Rollback; this capability split also keeps ordinary Arc handlers from completing outer work. The store, namespace, sequence, correlation and actor are fixed at begin. Missing correlation is generated once; actor changes fail because one atomic request cannot represent several actors.
  2. Strict lifecycle and global order. Go uses C#‘s strict-policy intent, not its legacy compatibility mode. All enrollment retains A1/B1/A2 order instead of legacy single-event source grouping. Events serialize at Stage, not commit, so later mutations cannot change the transaction. Concurrent stage calls enroll atomically; no serialization callback or RPC runs under the state lock. Repeated equal explicit scopes join, while conflicting scopes fail without mutation. An explicit Resolve is not C#‘s absent NotSet: it includes a filter and cannot overwrite an enrolled expectation. Use omission for the default strategy.
  3. Inspect final disposition, not completion alone. Commit returns the existing Go BatchResult and operation error; Result, C#-named diagnostic getters, IsSuccess and TryGetLastCommittedEventSequenceNumber preserve the query workflow. GetEvents returns defensive JSON snapshots rather than mutable CLR event objects. Transport loss and errors-only kernel results remain outcome-unknown, not a successful default result or known rejection. All attempts are terminal, including local cancellation; retry requires a deliberate new unit and fresh decision, and is never safe merely because an ambiguous owner completed. The retained result survives a repeated commit error. Empty completion is successful without persistence; scope-only completion still validates through the kernel.
  4. Explicit rollback instead of disposal. Defer Owner.Rollback for pending cleanup. Unlike C#‘s repeated rollback exceptions, terminal rollback is a no-op so ordinary Go defer does not mask a successful result; it never changes a committed or ambiguous disposition. During completion it fails with ErrCompleting. Rollback reports RolledBack and is not IsSuccess, avoiding C#‘s success-shaped empty append result being mistaken for commitment.
  5. Completion notification retains the C# name and replacement semantics. OnCompleted replaces the callback and runs synchronously after final state, including commit failure and rollback. Go rejects late registration with ErrCompleted rather than silently retaining an uncallable callback. No manager-cleanup callback is replaceable, since lifetime belongs to the explicit owner. Callback panic propagates after final disposition is recorded.

The unit-of-work guide and executable example show the participant/owner workflow. Prepared batches are a lower-level serialization seam, not another owner: they do not provide once-only completion. Admitted decision reads supply opaque optimistic tokens; ordinary concurrency scopes must not be presented as decision tokens.

Decision references are Source/Clients/DotNET/ReadModels/{DecisionReads,DecisionReadAdmission,DecisionReadScopes}.cs and Transactions/{DecisionReadCommitOwner,UnitOfWork}.cs at 2e31b0dfba489159b3db323238f16d0f277056b4. Kernel semantics come from ae5e00a8abaa688138b2c2f689e2b4659cccb4fd (19.29.4), especially Kernel/Core/EventSequences/Concurrency/ConcurrencyValidator.cs and Kernel/Core/Sequences/AppendManyForEventSourcesValidator.cs.

ContractGo surface and statusExecutable evidence and differences
Local admission and canonical keysImplemented: DecisionsFor[T](service, model).Admit()TestDecisionAdmissionMatrix, TestDecisionKeySchemaAndCanonicalKeys; actual schema key is id then Id, not an arbitrary Go key tag. Frozen contract AST and event catalog avoid a second projection compiler
Selected server agreementImplemented with safety additionsTestDecisionAgreementRechecksServerShapeAndKey, TestDecisionServerGenerationAndUnreadableSchemaRefuseBeforeAndAfterFold, TestDecisionServerProtectionIsNotAnAgreementCriterion, TestDecisionAgreementAllowsPlainNonKeySchemaDifferencesAtSelectedGeneration; compare producer, model generation, sequence and dependency ID set, not full mapping equality. Re-admit server parent/All keys, key schema before and after folding. Server-side protection metadata is not compared, as in C#: the kernel releases session folds with original subjects (Chronicle#4561). No persistent agreement cache
Classified-model decisionsImplemented like C#: classified models are admitted; the kernel (19.32.2 or later) releases the session fold with each value’s original subject and the SDK validates it without a second release. DecisionProtectedModel and DecisionProtectionMetadata are deprecated and no longer producedTestClassifiedDecisionsAreAdmittedWithoutSecondRelease (PII and every encryption scope; property, type and provider declarations), TestDecisionCodecsRunAfterCleanupWithoutCountingShutdownWork, TestDecisionErrorCallbacksRemainInsideRecovery, TestKernelDecisionReadsReleaseClassifiedModelsWithEventSubjects (default Id and lowercase id, key differs from subject, before and after erasure, guarded commit). Earlier kernels released with the requested key (Chronicle#4561); decision reads already require the verified 19.32.3 profile
Fresh-session reads and presenceImplemented: Get enrolls into the existing participant; GetDetached does notTestDecisionRetriesFreshSessionsAndUsesUnfilteredBoundary, TestDecisionAttemptExhaustionAndPresence, TestDecisionGetRequiresAndEnrollsExistingParticipant; retain the pre-fold unfiltered log boundary separately from the filtered probe and reported progress
Cleanup and retry exhaustionGo-specific fail closedTestDecisionFailuresAwaitCleanupAndReturnNoToken, TestKernelDecisionCleanupFailureAfterRealFoldIssuesNoToken; await bounded metadata-preserving detached cleanup after every session. Three incomplete/ahead attempts return a refusal; the C# third-ahead boundary-5/fold-6 result is explicitly refused instead of returning a doomed guard
Decision error diagnosticsGo-specific payload-free public messages with inspectable causesTestDecisionReadErrorsDoNotDiscloseTransportDiagnostics, TestCodecErrorsPreserveCausesWithoutDisclosingMessages; fold, cleanup, codec and joined messages omit sensitive text while retaining cancellation, unsupported, protocol and returned codec causes through errors.Is/As
Application codec lifetimeGo-specific no counted decision lease across codecsTestDecisionCodecsRunAfterCleanupWithoutCountingShutdownWork; finish fold, protocol checks, cleanup and agreement before typed decoding; classified decision models refuse before lease acquisition. Synchronous codec-triggered close completes; caller cancellation, generation loss or epoch change returns no token. Typed-decoding panics return payload-free DecisionCodecPanicError, discard the panic value and issue no model/token
Opaque tokens and ownershipGo-specific permanent first-enrollment binding; existing participant/owner split retainedTestDecisionEnrollmentValidatesTargetEpochOwnerAndState, TestDecisionTokenCopiesHaveOneConcurrentFirstOwner, TestFrozenCatalogAndIssuedTokenOwnTheirInputs; copies cannot transfer to a second owner after rollback, and failed enrollment does not redeem a token. No public proof constructor or owner-from-context API
Merge and atomic completionImplemented: earliest boundary, union IDs, one frozen ordered batchTestDecisionScopesMergeEarliestBoundaryAndUnionIDs, TestDecisionCompletionPreservesSnapshotGlobalOrderAndAudit, TestKernelDecisionCompetingWriteRejectsEntireMultisourceBatch; colliding explicit labels fail in either order. Protected completion sends no automatic effect-source defaults and rejects unchecked/unresolved explicit mixtures (TestDecisionScopeCollisionsAndUncheckedMixturesAreAtomicBothOrders)
Owner append attributionImplemented with SDK-only exact-snapshot authorityTestGuardedOwnerCommitBypassesExternalOriginResolver, TestGuardedPreparedAppendResolvesOriginBeforeDecisionLease, TestUnitOriginCapabilityCannotAuthorizeOtherAppendsFromCallbackContext, TestKernelDecisionOwnerOriginBypassesResolver; guarded plain/named/eventless completion bypasses external resolution and retains unit attribution. Ordinary guarded appends resolve before acquiring a decision lease; callbacks cannot authorize an unrelated append
Eventless validationImplemented for the verified pinned profileTestKernelDecisionFirstEventAbsenceAndEventlessCompletion; plain batch RPC, no positions, dummy events or separate validation/write. Named-tag eventless overload remains excluded
Capability, epoch and generation boundariesGo-specific conservative refusalTestDecisionCapabilitiesRequireVerifiedVersionAndPreflight, TestDecisionCommitRechecksCapabilitiesAndEpochBeforeDispatch, TestDecisionEpochIsCheckedAfterAuthorizationBeforeDispatch, TestDecisionLeaseCannotSpliceRPCsAcrossGenerationLoss; compatibility success alone and skipped preflight cannot enable guards
Unsupported and ambiguous completionImplemented using existing terminal owner outcomesTestDecisionCompletionPreservesUnsupportedUnknownAndRejection; false check flags never mean success. Confirmed writes with unsupported-check errors remain committed; lost/malformed acknowledgements remain unknown; no owner retry

The pinned protocol accepts client-supplied concurrency scopes; it supplies no signed read proof, definition revision binding or history revision binding. Opaque tokens prevent unsupported SDK enrollment, not malicious direct RPCs. Definition/history races, including ABA replacement and in-place revision/redaction, cannot be eliminated by client rechecks or hashes. Detached tokens do not detect every later server definition change. Applications requiring that stronger guarantee need upstream protocol support. chronicletest deliberately cannot issue tokens. Runtime projection additions invalidate fixed expected epochs for all older issued and enrolled guards across the store before publication. Old decision readers cannot issue fresh evidence; acquire a new reader. This does not fence external server definition/history changes.

The decision guide and typed example cover admitted reads, explicit detached enrollment, checked scopes and the optimistic-versus-authenticated boundary.

Constraint references use DotNET/Events/Constraints and its matching DotNET.Specs/Events/Constraints at the baseline revision above. Request fixtures derive from ConstraintBuilder, UniqueConstraintBuilder, ConstraintConverters, and the converter/sequence/remover specs, rather than from a Go-generated expectation. Kernel behavior is exercised against 19.32.3-development. The constraint example uses the same production registry and append APIs.

  • Choose model-bound declarations or explicit definitions. Field unique tags, events.WithUnique and remover options compile through the same builders as UniqueValues(name).On(descriptor, paths...). Explicit paths are exact serialized JSON names validated against the descriptor; tags use the shared field plan. Registry.ConfigureDeclaredConstraint explicitly composes a declared constraint, while duplicate AddConstraint calls fail rather than silently merge. TestCompositeDeclarationImprovementMatchesExplicitBuilderGolden and TestDeclaredConstraintsRequireExplicitComposition cover this boundary. Same-event, same-name fields form one ordered composite in Go; the pinned C# provider instead throws on its repeated On call. Use stable explicit names for shared definitions. Empty property sets, blank names/sequence IDs and foreign descriptors fail early (TestMalformedConstraintDefinitionsFailBeforeRegistration, TestConstraintRegistryRejectsInvalidOrForeignDeclarations).
  • Existing kind constants stay compatible. constraints.Unique and constraints.UniqueEventType remain result-kind constants; builders are named UniqueValues and UniqueEventTypes to avoid breaking those exported names. The event-type builder defaults to the first persisted event ID, matching C# Unique<T>(), and accepts multiple types for mutual exclusion. Use one grouped definition instead of C#‘s same-name declaration merging; duplicate names across AddConstraint calls are rejected atomically. Repeated covered/removal IDs and selected sequences coalesce in first-declaration order. Scope calls apply to the one definition regardless of call order, avoiding C#‘s multi-definition builder’s order-sensitive scope capture.
  • Messages remain client-side. Missing/empty templates preserve the kernel text, and callbacks run once per matching returned violation as in C# append conversion. Go supplies copied details to callbacks and inserts values literally in one pass; unlike C#‘s sequential dictionary replacement, values containing {OtherDetail} cannot become a second template expansion. This removes map-iteration-order dependence and avoids interpreting event values as formatting instructions. TestMessageDetailValuesAreLiteral fixes that deliberate edge-case difference. Use a provider for intentional complex formatting; synchronize captured mutable state. Providers run outside the RPC lease so they can use client lifecycle APIs without self-deadlocking; shutdown does not wait for caller-owned message formatting.
  • Registration acknowledges a batch, not each name. Constraints use the same generation-scoped store barrier as event types, after event-type and read-model registration and before projections and reactor/reducer registration sends, as in C# EventStore.RegisterAllArtifacts. Outcomes include the constraints stage; the RPC returns google.protobuf.Empty, not a command envelope. Empty local constraint sets perform no RPC, matching the Go event-registration fast path; no API for deleting persistent definitions is implied. Store-specific registries replace both events and constraints. Adding constraints after client construction still requires a new client; runtime projection additions do not add constraints.
  • Results remain additive and kernel-owned. Append/AppendMany/AppendBatch retain their existing violation/result/error types, now resolving registered messages and exposing standard detail-key constants. No UUID dependency, new scalar type, local uniqueness algorithm or preflight read is added. Low-level eventsequences.New has no registry/message provider and preserves kernel text; obtain sequences from EventStore for registered message resolution. Claim removal and batch ordering are server behavior, not emulated by a Go test fake.

Read-model references use the C# baseline revision above, Source/Clients/DotNET/ReadModels/{IReadModels,ReadModels,ReadModelTypeExtensions,ReadModelJsonSerialization,ReadModelReleaser,ReadModelSubjectResolver}.cs and Source/Kernel/Grpc/ReadModels/ReadModels.cs. Container naming follows the Cratis.Serialization.DefaultNamingPolicy used by ChronicleClient: a case-preserving Humanizer plural of the simple type name. The vocabulary adaptation and MIT attribution are pinned in readmodels/HUMANIZER-LICENSE.

  1. Explicit declarations replace discovery. RegisterReadModel[T] supplies the schema and producer association separately from projection/reducer registration. A registered model can be read without a locally known handler, unlike C#‘s handler-existence guard; this supports catalog consumers such as Arc.Go without fabricating a producer. Registrations use generation one, MongoDB, an empty configuration UUID, Client owner, Code source and projection observer type by default. Model definitions join the registration pass immediately after event types and replay once per store/generation, with per-namespace read barriers. Passive (NoSink) models require a nonblank producer identifier; readmodels.Passive() defers that binding to a registered reducer (TestReducerPassiveAndInactiveBinding). Materialized models may omit the producer. Repeated WithIndexes and WithPII calls accumulate copied property paths in declaration order and reject duplicates within or across calls with ErrInvalidConfiguration. Runtime projection additions admit a new ordinary model together with its new projection; no standalone runtime RegisterReadModel[T] or replacement API is provided.
  2. Identity and container names stay distinct. C# uses Type.FullName; Go uses its import-qualified type name, not the simple event-type naming convention. For shared persisted models, use WithIdentifier("CSharp.Namespace.Model"). WithContainerName corresponds to C#‘s ReadModelNameAttribute, not a model identifier override. Generic Go instantiations require both WithIdentifier and WithContainerName explicitly: reflection’s argument-qualified type names are not stable persisted identities or valid conventional container names. TestGenericReadModelRequiresExplicitNames covers rejection and explicit registration. The shared serialization plan preserves property names by default, matching C# DefaultNamingPolicy; camelCase is opt-in, and explicit JSON tags take priority. An untagged root Go ID becomes C# Id; nested fields and other initialisms retain their policy names. TestNamingPoliciesCompileOneFieldPlan and TestReadModelPlanTranslatesOnlyUntaggedRootID cover these rules. Keep persisted names stable with explicit tags or a deliberate naming policy; changing policy is a schema migration, not a cosmetic rename. The golden registration request derives envelope/defaults from C# while using the Go plan’s equivalent JSON Schema, not a claim of byte-identical NJsonSchema output.
  3. Presence and progress are separate. Instance[T].Exists replaces a nullable model; LastHandled replaces C#‘s injected __lastHandledEventSequenceNumber property. A missing model never becomes a present zero value. Raw documents retain their metadata. Slice fields in present models normalize missing/null collections to empty; pointer-to-slice fields preserve nullable absence and maps are not normalized. The one-shot API rejects the kernel’s * replay wildcard rather than treating it as an ordinary key. Raw/typed GetAll, materialized paging, watches and admitted projection snapshots are available. Their count, presence and replay rules differ: use the collection/history reference and watch reference. Reducer snapshots remain unsupported.
  4. Sessions have explicit cleanup contexts. NewSession creates an opaque random ID, binds all coordinates and performs no I/O until Get. Close(ctx) dehydrates, reports errors and permits cleanup retry after failure; it is intentionally not io.Closer, so callers retain cancellation/deadline ownership. Unlike C#‘s unconditional event-log dehydration, Go sends the session’s actual sequence. Close sessions before the client. No cross-reconnect hydration continuity or decision-token guarantee is claimed. Reducer sessions remain unsupported, but passive reducer Get and explicitly bounded collection folds run locally through the registered fold plan. Classified projection sessions and immediate reads return kernel-released values on Chronicle 19.32.2 or later and refuse before RPC on older or unverified kernels (TestProtectedProjectionRoutesUseKernelReleaseWithoutSecondDecryption, TestProtectedProjectionRoutesRefuseWithoutProtectedReleaseKernel, TestKernelModelHistoryProtectedReleaseProfile); ordinary session coordinate/cleanup behavior is covered by TestReadModelSessionRetainsCoordinatesAndRetriesFailedCleanup.
  5. Release fails closed. C# returns unchanged values for missing subjects or reported release failure. Go returns ErrRelease with no value, preserves underlying error identities and redacts public error text. Release ownership is route-specific: materialized keyed/collection results, store-owned passive folds and projection replay/history/immediate/session/decision reads (kernel 19.32.2 or later, Chronicle#4561) validate already-released data without another decrypt. Admitted MongoDB root-string PII/EncryptedNamespace windows validate server-released data without Release; classified sink identity aliases and other protection profiles refuse before RPC (see the window profile). Classified projection Watch refuses before streaming (Chronicle#4566); classified local reducer Watch refuses before queue attachment without a delivery-time erasure fence. Unclassified local notifications validate final plaintext without Release. Repeated Release is not a safety check. Explicit release accepts unreleased documents only, never already-released plaintext: raw documents preserve subject lineage, with stored __subject taking precedence over a configured property and the Go ID fallback. Strings and JSON numbers resolve subjects; numeric token text is preserved without floating-point conversion. Null, empty strings, objects and arrays do not resolve a subject. As in kernel ReadModelsCompliance.HandleBySubject, top-level properties are grouped by their __subjects entry, falling back to the resolved default subject. Each group is released under its own subject and the replies are merged; any group failure returns no document. Typed release uses the same path after serialization and requires the subject on the value. This intentionally adds raw-document lineage handling absent from the typed C# helper. PII and distinct confidentiality classifications share this pipeline. Namespace/global-only values need no subject; present subject-dependent values still fail without ownership. Cryptographic/erasure semantics remain kernel-owned, not a client-side cipher heuristic.

The read-model reference, ExampleRegisterReadModel and runnable example use these public APIs. Kernel registration, absence, producer-backed materialization and passive reads are tested on 19.32.3-development. Session hydration/dehydration and explicit release failures retain bufconn evidence, not a claim of complete projection/compliance integration.

References in this section are C# revision 2e31b0dfba489159b3db323238f16d0f277056b4, Source/Clients/DotNET/Projections, Keys/KeyAttribute.cs and ReadModels/PassiveAttribute.cs. Golden projections/testdata/basic.json is hand-derived, not generated by running .NET: it combines ModelBound/FromDefinitionExtensions, ModelBoundProjectionBuilder and ProjectionBuilderFor output with the DotNET.Specs/Projections/ModelBound/for_ModelBoundProjectionBuilder cases for custom keys, explicit context, string/integer values, null values and field exclusions. The equivalent fluent fixture uses FromBuilder and SetBuilder. JSON property names are explicit Go-plan names, not a claim about C#‘s default naming policy.

C# attribute / sourceGo surface and statusEvidence and intentional difference
FromEvent<E> / ModelBound/FromEventAttributeImplemented for root subscriptions: FromEvent(handle, options...); fluent From(builder, handle, callback, options...)TestFromEventKeysFlagsAndDefaultIdentity; event-source default, property key, parent key, constant key and override order. Typed options replace class attributes; duplicate typed subscriptions fail instead of relying on dictionary overwrite. Composite/context keys are covered in the arithmetic/node section below
SetFrom<E> / ModelBound/SetFromAttributeImplemented for basic field mappings: set(E,from=path), Map and MapAsTestMapAsPreservesModelBoundCompatibility, TestMapAsRejectsIncompatibleAndIncorrectFieldTypes, TestBothFrontEndsMatchCSharpBasicGolden, TestExactSerializedPathsAndNilOptions, kernel materialization test. Omitted from uses the target’s serialized name. Paths use exact plan spelling, not C# case-insensitive CLR property lookup
SetFromContext<E> / ModelBound/SetFromContextAttribute, FromDefinitionExtensions.AddContextPropertyMapping, PropertyValidator, SetBuilder, AllSetBuilder, Events/EventContext.cs at 2e31b0dfba489159b3db323238f16d0f277056b4Partial: existing scalar context/Context, plus whole Tags/tags into string slices (optionally pointers), including Every/AllTestContextCollectionFrontEndsGolden compares both Go front ends to hand-derived testdata/context-clear.json, not an actual .NET capture. TestContextCollectionEveryAndAll, TestComplexContextRefusalAndScalarOnlyKeys, TestKernelProjectionContextCollectionClear cover shared validation, scalar-only keys, conflicting payload labels, order, empty arrays, startup typed-null collection clears/repeated clears and nonempty rewrite. Explicit NoAuto/NotProjected writes remain effective. C# model-bound/All apply naming policy to context paths; per-event fluent preserves the extracted path. Go equality uses the same explicit spelling, not a claim of universal C# byte equality. Other known complex objects fail with located ErrUnsupported; unknown paths/type mismatches remain configuration errors. Context names are the kernel contract, not Go events.Context names. Remaining depth belongs to #26
SetValue<E> / ModelBound/SetValueAttributeImplemented for supported scalar representations: value(E,value=JSON-scalar) and ValueGolden and kernel materialization tests cover string, integer, boolean and null. Nullable scalar and direct compiled slice/string-keyed map pointers clear with $null; non-nullable/array/object/element clears fail. TestPointerLiteralsRespectKernelIntegerRange guards the kernel signed-integer limit
Key / Keys/KeyAttributePartial: key retained as immutable identity metadataTestBothFrontEndsMatchCSharpBasicGolden; root metadata does not itself map or redirect an event key, matching C#. One non-nullable scalar key is enforced. Child identity conventions are implemented below; variant discovery remains #27
NoAutoMap / NoAutoMapAttributeImplemented at the root: no-auto, NoAutoMap() and AutoMap()Golden, key/flag and kernel materialization tests. Enabled by default; field exclusions coexist with explicit mappings. Immediate-parent model-bound policy, fluent Inherit defaults and local exclusions are covered by TestModelBoundAutoMapChecksOnlyImmediateParent, TestFluentChildAutoMapDefaultAndOverrides and TestNodesKeepExclusionsAndSubscriptionsLocalAndShareEveryNames
NotProjected / ModelBound/NotProjectedAttributeImplemented at the root: not-projectedGolden and kernel materialization tests prove AutoMap exclusion; provenance retains the intentional-unmapped marker. It does not silently erase an explicit mapping
NotRewindable / ModelBound/NotRewindableAttributeImplemented: NotRewindable()TestFromEventKeysFlagsAndDefaultIdentity proves wire rewind policy for both front ends
Passive / ReadModels/PassiveAttributeImplemented for source-keyed basic projections: Passive()TestKernelProjectionMaterializesModelBoundAndPassiveReads and registry tests prove inactive registration, None sink and immediate reads. Unlike a C# analyzer warning, passive key redirection fails construction because immediate reads cannot honor it
EventSequence, EventLog / EventSequences/*AttributeImplemented for explicit selection: WithEventSequence, WithEventLogTestFromEventKeysFlagsAndDefaultIdentity, TestProjectionExplicitDeclarationsAndStoreOverrides, TestProjectionDiscoveryInheritsModelDefaults, TestProjectionExplicitModelConflictsFailAtNewClient; declarations inherit the model sequence unless explicitly selected, and bound reads share it. Different explicit settings conflict, including explicit event-log. Automatic source-store/inbox inference is #27
ContextKey / Keys/ContextKeyAttributeNot implemented, upstream-inertNo consumer exists in the referenced C# client. No inert Go tag is accepted; working UsingKeyFromContext and context(path) keys have separate executable evidence below
  • declarations.Parse(declarations.V1, tag) is the shared, bounded parser. FuzzParse, grammar/error tests and TestDeclarationsOnIgnoredFieldsFailClosed cover delimiters, escaped strings, offsets, ignored fields and fail-closed role checks. Unsupported compliance and event-field directives remain errors, not no-ops. Arithmetic, global mappings and nodes use this same parser.
  • serialization.Plan.Fields() supplies detached field/index, serialized name/path, declared type, nullability and scalar/format metadata. Projection code never invents another casing policy. TestFieldMetadataSharesPlanAndOwnsSnapshots covers snapshot isolation. Fundamentals wrapper compatibility is centralized in scalarCompatible and concepts.Underlying, without calling fabricated concept values. Child parent-key inference retains declared domain-ID types.
  • All event references resolve only against the frozen store catalog: bare Go name, go("qualified.Type"), id("persisted-id"[,generation]), or a typed BindEvent alias. Tests cover aliases, exact generations, ambiguity with qualified candidates, foreign handles and store isolation. Runtime validation is mandatory; ordinary gopls rename and Go vet do not validate custom tags. Generation/analysis tooling remains deferred.
  • Model-bound precedence is C#‘s family order (set, add, subtract, increment, decrement, count, context, value, clear), with last-in-family wins and inspectable shadowing diagnostics. Fluent duplicate writers fail. TestModelBoundPrecedenceAndFluentDuplicateRejection fixes this distinction. Mixing mapping tags and fluent mappings fails rather than applying accidental precedence; identity/exclusion tags are shared.
  • The one encoder emits the canonical immutable definition. TestFluentBuildSnapshotsValuesAndCallbacks and golden mutation tests prove literal/callback/protobuf ownership. Reconnect uses those definitions without reflection or author callbacks. Defaults are {}, active, rewindable and AutoMap enabled. The model-bound/explicit projection ID defaults to the model observer ID when set, otherwise the full Go model type name, independently of an overridden read-model identifier; TestProjectionDiscoveryInheritsModelDefaults and TestFluentBuilderInheritsModelDefaults cover both front ends. Zero Definition accessors return zero metadata (TestZeroDefinitionAccessors); WithIdentifier or a builder ID selects shared C# identities. Container naming remains a read-model setting.
  • NewClient fails the whole declaration graph before I/O rather than C#‘s log-and-skip discovery. Each registry snapshot includes events, models, constraints and projections under one lock. TestProjectionStartupValidationIsAtomicAndStoreLocal proves forward references and failure atomicity. Models with mapping tags discover projections; type-level options require AddProjection. Explicit foreign model handles and conflicting producer settings fail.
  • Registration follows event types and read models, in the observers/constraints portion of the pass. TestProjectionDiscoveryRegistrationAndFrozenReplay proves store-wide sharing, producer binding, read barriers, unchanged reconnect definitions and namespace isolation. TestProjectionFailureCannotPublishReadiness proves old-kernel rejection. Nonempty projection sets register with Client ownership and FullSet=true; empty Go sets skip the RPC, so removing all local declarations does not provide a persistent-projection deletion API.
  • Kernel Source/Kernel/Core/Projections/Engine/Expressions/EventValues/{ValueExpressionResolver,LiteralExpressionResolver}.cs at the revision above restricts literals to BMP letters, combining marks, decimal digits, connector punctuation, space and ._/:*+-. TestKernelUnrepresentableModelMappingsFailAtNewClient, TestKernelUnrepresentableKeysFailAtNewClient and TestFluentLiteralUTF16Boundary cover UTF-16 limits. Exact event paths true, True, false and False fail because the kernel resolves them as boolean literals first; TestBooleanPropertyPathsRejectLiteralResolverAmbiguity covers fluent mappings. Quotes, commas, semicolons, parentheses and newlines cannot be escaped into support. The Go compiler rejects them instead of allowing the kernel’s partial regex match. Literal error strings are redacted. Schema/range/format validation remains authoritative; no arbitrary $... passthrough exists.
  • These mappings are not full projection parity. Variants, global handlers, concrete recursive prerequisites, build-local fingerprints, source inference and preview/query are covered below under projections part 3. Initial-state authoring and artifact labels are covered below. Bounded runtime projection additions are implemented; replacement and runtime registration of other artifact families remain unsupported. Explicit unprotected derived families and their single-derivative children are covered in registered derived codecs; protected families and other custom representations remain unsupported.

The projection guide presents model-bound declarations first and fluent declarations second. TestProjectionSnippetsMatchCompiledExample prevents drift from the executable example.

Projection initial values and artifact labels

Section titled “Projection initial values and artifact labels”

Authority: C# 2e31b0dfba489159b3db323238f16d0f277056b4, Source/Clients/DotNET/Projections/ProjectionBuilder.cs:55–59, ProjectionBuilderFor.cs:166–183, and Source/Clients/DotNET/TagExtensions.cs. Kernel contracts are Engine/Pipelines/Steps/{SetInitialState,HandleEvent}, ChangesetExtensions.AddPropertiesFrom, and the root initial-state specifications under Core.Specs/Projections/Engine/Pipelines/Steps/for_HandleEvent. projections/testdata/defaults.json is hand-derived, not captured from .NET; object keys are canonicalized to Go’s sorted snapshot order.

BehaviorGo surface and statusEvidence and difference
Whole-model initial valuesImplemented for supported model codecs: WithInitialValues[M](value) on both front endsTestInitialValuesAndLabelsShareCanonicalDefinition, golden fixture, TestInitialValuesPresenceAndFrozenNaming, TestProjectionInitialStateUsesEveryFrozenStoreNamingPlan, TestInitialValuesHonorKernelIntegerGuards, TestInitialValuesStringsAreJSONNotProjectionExpressions; omitted {}, zero/false, empty collections, concepts, nested objects, dictionary values and explicit names. Go snapshots a typed value instead of invoking a C# callback; model-bound authoring is a Go addition
Scalar presenceGo-specific: WithInitialValue(Path[M,V](path), value)Presence/invalid-shape tests and ExampleWithInitialValues; explicit scalar zero/null survive naming rebind without a typed round-trip. Whole-model nil properties remain omitted. Collection nulls, collection traversal, duplicate writes, overlapping scalar paths and foreign types fail
Artifact labelsImplemented: WithLabels(labels...) encodes only ProjectionDefinition.TagsShared-definition golden and reconnect tests; exact duplicates keep first occurrence, like C# GetTags().Distinct(). Go additionally rejects blank, control-containing and invalid UTF-8 labels. Kernel materialization test appends untagged events to a labeled projection, proving labels do not filter
Snapshot and definition identityImplemented through the existing canonical compiler/encoderGolden mutation/hash tests, TestInitialValuesSnapshotPopulatedPointersAndNestedConcepts, selected-store naming test and TestProjectionDiscoveryRegistrationAndFrozenReplay; caller map/slice/pointer/nested-concept/protobuf/registry mutation cannot change bytes, hash or reconnect output. TestSnapshotRebindRejectsFieldsLostToPromotion, TestSnapshotRebindPreservesEmbeddedPointerAndRecursiveFieldIdentity and TestProjectionInitialStateRejectsLostFieldBeforeClientIO require unique Go field-index/type identity and reject lost fields before I/O, rather than silently rebinding to a shadowing field. Sorted object keys differ from C# declaration order; hashes remain build-local
Protection boundaryGo-specific fail-closed protected-root initializationTestInitialValuesRejectPlaintextProtectionAndNonfiniteValues, TestInitialValuesRejectEntireProtectedRootThroughOptionsAndReferences; any supplied root with PII/confidentiality metadata, including null, is rejected because definition initialization bypasses append encryption. Omitted roots remain allowed. Encrypted defaults are not supported
Materialization and removalImplemented for the witnessed root shape on 19.32.3-developmentTestKernelProjectionDefaultsMaterializationRemovalAndReplay: registration absence, defaults plus explicit mappings/increments, subsequent updates, removal and fresh initialization. TestKernelProjectionDefaultsAutoMapAndAggregateOnly separately proves ordinary AutoMap overwrites the initialized name, while an aggregate-only increment leaves that name unchanged. Ordinary collection defaults are covered; projection-owned child roots are excluded by ChangesetExtensions.AddPropertiesFrom, so an empty initializer does not prove materialized child presence
Explicit observer replay with defaultsPartial: acceptance witnessed, completion unverified on the pinned kernelThe replay_completion subtest subscribes to ObserveJobs before requesting replay and requires CompletedSuccessfully for that exact job before comparing state. It skips when the job disappears without that evidence; unchanged read-back can be pre-replay state and is not substituted as proof. No default-aware replay-completion, automatic replay-on-default-change or revision/redaction rewind claim
Scenario replay defaultsNot implemented, fail-closedThe pinned Grpc/ReadModels/ReadModels.GetAllInstances calls projection.Process, which omits initial state in the observed kernel result. TestReadModelScenarioRefusesProjectionDefaultsBeforeConnection and TestKernelReadModelScenarioRefusesUnfaithfulProjectionDefaults refuse nonempty state with ErrFidelityUnavailable; #38 owns scenario fidelity. No test-only initial-state compiler

The initial-values guide and compiling stock example are tied together by TestProjectionDefaultsSnippetMatchesCompiledExample.

Projection attributes: arithmetic, globals and nodes

Section titled “Projection attributes: arithmetic, globals and nodes”

References use the same C# revision above, DotNET/Projections/ModelBound and the corresponding fluent builders. projections/testdata/advanced.json is hand-derived, not captured from a .NET run. TestFrontEndsMatchTheirCSharpAdvancedShapes compares model-bound output to that definition and fluent output to its distinct C# shape: children and nested objects use AutoMap Inherit, and fluent child subscriptions do not synthesize identity mappings. Both cover arithmetic, nested *NotSet*, All, joins and both removal contracts. testdata/fluent-child.json is also hand-derived from ChildrenBuilder, ProjectionBuilder.Children and KeyAndParentKeyBuilder; TestFluentChildWithoutParentKeyMatchesCSharpGolden checks that absent UsingParentKey emits the empty string, not an inferred property. C# NoExpression.Build returns string.Empty and FromBuilder.Build assigns it to contract ParentKey; protobuf scalar-default encoding can omit that empty value on the wire. Kernel ProjectionFactory:1165–1170 resolves empty to $eventSourceId.

C# attribute / sourceGo surface and statusExecutable evidence / difference
AddFrom<E> / FromDefinitionExtensions.AddAddMapping, AddBuilderImplemented: add, fluent Add; preserves $add(path)Advanced golden, TestArithmeticUsesConceptScalarRepresentation, kernel arithmetic test. Numeric representations only; arithmetic paths must fit the kernel’s stricter ASCII regex
SubtractFrom<E> / AddSubtractMapping, SubtractBuilderImplemented: subtract, fluent Subtract; preserves $subtract(path)Advanced golden and kernel arithmetic test; incompatible scalar sources/targets fail before I/O
Increment<E> / AddIncrementMappingImplemented: increment, fluent Increment; optional constant/context/composite keyAdvanced golden, TestCounterKeyTags, kernel arithmetic test
Decrement<E> / AddDecrementMappingImplemented: decrement, fluent Decrement; $decrement, not subtraction rewritingAdvanced golden, counter-key test and kernel arithmetic test
Count<E> / AddCountMappingImplemented: count, fluent Count; emits $countAdvanced golden, TestCompositeAndContextKeysMatchBothFrontEnds, kernel arithmetic test
ClearWith<E> / ScalarClear, FromDefinitionExtensions.AddClearMapping, SetBuilder.ToValue, NestedDefinitionExtensions at 2e31b0dfba489159b3db323238f16d0f277056b4Partial: scalar-pointer and direct compiled nullable slice/string-keyed map clear/Clear, value(null)/Value(nil) emit $null; nested member clear and Node[T](ClearWith(event)) remain unchangedAdvanced golden, TestNestedNodeAndMemberClearMerge, TestCollectionNullFormsShareTypedNullableContract, TestContextCollectionTargetAndNullBoundaries, unchanged TestNullableCollectionsExistingPresenceContract, TestKernelProjectionContextCollectionClear, TestKernelProjectionContextClearRuntimeAdmission. The chosen contract is ordinary typed nullable collections, not mandatory present raw null: C# ReadModels.GetInstanceByKey deserializes the materialized response directly, without another Release; ReadModelJsonSerialization:58–78 excludes nullable collections from empty normalization, and DotNET.Specs/ReadModels/for_ReadModelJsonSerialization/when_the_declaration_keeps_the_distinction:27–32 leaves both missing and explicit-null nullable collections null. No actual .NET execution/capture is claimed. C# constructors/default initializers can distinguish omission from null; these and configured serializer profiles are not covered by this ordinary Go pointer profile. The pinned 19.32.3-development witness covers both startup front ends on one event stream: ordered conflicting-payload Tags, nonempty payload map, non-nil pointer empty arrays/maps, marker-synchronized clear/repeated clear with typed nil and raw omitted-or-null properties, retained document/key/correlation/marker and real nonempty rewrite. Non-null stale/empty values after clear fail. It separately observes initial array seeding; {} registration creates no instance and is not raw-null-state evidence. No read overlay or serializer change: missing/null both decode to nil; nil outer pointers/pointers to nil collections serialize absent, empty collections serialize []/{}. Present raw null preservation is a stronger separate capability, not a blocker for this typed profile. Fixed arrays/interfaces/structural objects/element paths/bare collections remain unadmitted. Runtime collection refusal before publication/RPC and scalar-only frozen classification controls remain; other complex context sources keep #26 partial
FromEvery / ModelBoundProjectionBuilder.BuildFromEveryDefinition, FromEveryBuilderImplemented for the snapshot’s stored mappings/flag: every, Every, EveryMap, EveryContext, IncludeChildrenTestGlobalPayloadAndIncludeChildrenFrontEndEquality, TestNodesKeepExclusionsAndSubscriptionsLocalAndShareEveryNames, kernel global test. Ordinary mappings use contract All, never derivative FromEvery. Model-bound cross-node bare-name collisions retain last writer with diagnostics; fluent node Every remains node-local. Kernel does not run parent Every mappings on child-only events despite the flag
FromAll / ModelBoundProjectionBuilder.ProcessMemberImplemented: all, fluent All; merged All mappings plus root SubscribesToAllEventsTestFromAllAndFromEveryWithoutExplicitSubscriptions, TestChildFromAllDoesNotBroadenRootSubscription, TestKernelProjectionFromAllAndFromEvery. Child-level All contributes mappings without broadening the root subscription, as in C#
ChildrenFrom<E> / ChildrenDefinitionExtensions:153–168,378–403,798–895, ChildrenBuilderPartial: children, fluent Children/IdentifiedBy, WithNodes(Node[T](...))Advanced golden, TestChildIdentityPrecedenceAndAmbiguousParentKey, TestParentInferenceExcludesChildKey, TestParentInferencePreservesDeclaredConceptTypes, TestNodeFromEventDoesNotEraseCreatorKeys, kernel add/remove. Model-bound identity: explicit → property Key → case-insensitive Go Id → matching serialized key name → source. Go has no constructor attributes. Only model-bound creators infer parents and write scalar identities; fluent subscriptions retain empty parent keys and require explicit identity mappings. Parent inference selects first exact declared ID-type match excluding child key; ambiguity is diagnostic. Model-bound AutoMap checks only the node and immediate parent’s own setting; fluent defaults to Inherit. TestModelBoundAutoMapChecksOnlyImmediateParent, TestFluentChildAutoMapDefaultAndOverrides, fluent-child golden. Concrete recursive children are covered under part 3; children of a single-derivative family are covered under registered derived codecs
Join<E> / JoinDefinitionExtensions, JoinBuilderImplemented for event joins on root/collection nodes: join, fluent JoinAdvanced golden, TestJoinFirstOnAndLocalWriteDiagnostics, kernel initial/update join tests. First model-bound On wins; joins override local writes and produce overlap diagnostics. Go normalizes child joins by accepting an explicit On through either front end instead of C# fluent’s prohibition
Nested / NestedDefinitionExtensions, NestedBuilderPartial: nested on object pointers, fluent Nested; node From/AutoMap/clearsAdvanced golden, nested-node fixture and kernel test. Emits C# PropertyPath.NotSet as *NotSet*, not empty. Kernel 19.29.4 does not execute collections inside nested objects, join removals on nested objects, or nested-object joins under collection children; definitions preserve the contract but do not claim those effects
RemovedWith<E> / RemovedWithExtensionsImplemented: remove on collection/other fields, root/node RemovedWith, fluent ConfigureAdvanced golden, TestPropertyLevelGrandchildRemovalAndChildScopes, kernel child and root removal tests. A collection tag targets that child, not its parent; other field placement removes the containing instance. Parent defaults to source, without child-creation inference
RemovedWithJoin<E> / RemovedWithExtensions, ProjectionBuilderPartial: remove-join, root/node RemovedWithJoinAdvanced golden and property-level grandchild fixture prove wire definitions. TestKernelProjectionChildRemovedWithJoin executes the C# integration scenario with GroupId and Id child identifiers, and TestKernelProjectionArithmeticChildrenJoinNestedAndClear/remove_join_of_readded_id_child covers a remove/re-add content key. On 19.29.4 the MongoDB sink fails to translate child id/Id to _id in join-removal filters (Chronicle#4538, fixed in 19.32.1). TestRootRemovedWithJoinReportsKernelLimitation proves compilation diagnoses root join removal without erasing the wire definition. Root join removal is unsupported (Chronicle#4263); nested join removal is also unwired (Chronicle#4125). C# ProjectionBuilderFor.Build omits the accumulated root RemovedWithJoin dictionary; Go intentionally repairs the producer omission
Working composite/context keys / CompositeKeyBuilder, per-event key buildersImplemented for ordered flat composite parts and scalar context: tag composite(...), context(path), fluent UsingCompositeKey, UsingCompositeParentKey, KeyPart*, UsingKeyFromContext, UsingParentKeyFromContextTestCompositeAndContextKeysMatchBothFrontEnds, TestCompositeChildKeysDoNotWriteScalarIdentity, TestAdvancedFluentValidationAndSnapshots, TestCompositeKeysRejectEventAndIndexDeclarations. Event and index directives on typed composite-key structs fail explicitly rather than being ignored. Composite child keys preserve correlation but skip convention scalar identity writes; see the C# limitation below. Duplicate parts and nested composites fail; the kernel splits commas without balancing nested composites. Typed part names use K’s serialization plan; explicit JSON tags keep them stable across policies. These APIs do not implement the upstream-inert ContextKey attribute

Composite child identity safety difference: C# ChildrenDefinitionExtensions:378–403 at the revision above has no composite-key guard; it copies a non-source key string directly into the identity property mapping. Go’s structured composite keys cannot be assigned to a scalar identity field, so the model-bound convention skips that write rather than rejecting an otherwise valid correlation key. Fluent C# and Go never synthesize it. Supply an explicit scalar identity mapping when needed; composite correlation support is not a claim that C# model-bound identity synthesis supports composites.

Join-removal investigation: C# source at 2e31b0dfba489159b3db323238f16d0f277056b4, Source/Clients/DotNET/Projections/{ChildrenBuilder,RemovedWithJoinBuilder}.cs and ModelBound/{RemovedWithJoinAttribute,RemovedWithExtensions}.cs, emits the same child removal dictionary and key as Go. The C# Integration/Client/Projections/Scenarios/when_removing/child_removed_with_join.cs uses GroupId with $eventSourceId creation/removal keys and UserId as parent key. Its Go translation passes against the pinned image; changing only the child identifier to Id reproduces the failure without any re-add. The original content-key probe also passes when only its child identifier changes from id to itemId; that diagnostic change was reverted. The .NET suite itself was not run. Kernel Source/Kernel/Storage.MongoDB/Sinks/Sink.cs:RemoveChildFromAll omits ToMongoDBPropertyName, which ordinary BuildChildRemoved applies. Root and nested join-removal limitations are source-confirmed in Source/Kernel/Core/Projections/Engine/ProjectionFactory.cs, not additional live Go probes. The single Go encoder and golden fixtures remain unchanged.

Additional acceptance evidence: TestNodeRebindingUsesSerializationMetadataEverywhere checks joins, child/removal keys, nested mappings and arithmetic against a second naming plan without mutating the original. TestAdvancedInvalidDeclarationsFailBeforeIO checks malformed structural/path/literal declarations at registration/NewClient; TestArithmeticRejectsKernelUnrepresentablePath covers an otherwise valid JSON path rejected by the arithmetic resolver. TestAdvancedFluentValidationAndSnapshots checks callback ownership. Recursive guards and derivative-group production are not claimed by these nonrecursive fixtures.

The C# acceptance cases reproduced include child identity and parent-key ambiguity, with_from_all/and_it_is_combined_with_from_every, nested clear attributes and with_class_child_grandchildren_having_property_level_removed_with. Go adds atomic startup errors and inspectable diagnostics instead of C# discovery’s log-and-skip behavior. The order guide and its example have a snippet-equality test. The example explicitly maps fluent identity and checks that its only wire difference is the child’s Inherit versus model-bound Enabled AutoMap default.

References: Chronicle 2e31b0dfba489159b3db323238f16d0f277056b4, Source/Clients/DotNET/Projections/ModelBound/{ModelBoundProjectionBuilder,VariantOfExtensions,ChildrenDefinitionExtensions}.cs, VariantReclassifier.cs, Projections.cs:286–302, and the corresponding DotNET.Specs/Projections/ModelBound/for_ModelBoundProjectionBuilder/when_building_variant and with_children_having/self_referencing_children* specifications. The variant golden and recursive expectations are hand-derived from C# source; the .NET suite was not executed. Runtime evidence uses 19.32.3-development.

Attribute / C# surfaceGo status and APIEvidence and boundary
VariantOf<I> / VariantOfAttribute, VariantOfExtensionsImplemented: VariantOf[I](), group-wide compilation after explicit registrationTestVariantFrontEndsMatchCSharpGolden, TestVariantValidationAndGlobalTargets, TestKernelVariantsEnterLeaveAndDoNotResurrect. Own key required; non-entering From handlers replace matching self-joins; sibling entry events add removals. Siblings and globals must share a store registry
EntersOn<E> / EntersOnAttribute, VariantReclassifierImplemented: EntersOn(handle, ...FromOption) with optional key; VariantKey for tag-free fluent identityVariant golden covers redirected entry keys and unchanged source-key sibling removals. Kernel variant fixture covers entry, global update, exit, non-resurrection and intentional re-entry. Existing explicit sibling removals win. Joins still override local entry writes
GlobalFor<I> / GlobalForAttribute, MergeGlobalHandlers, GlobalHandlerPropertyNotOnVariantImplemented: Global[T](GlobalFor[I]()), or a local fluent builder with GlobalFor[I]TestGlobalCopiesFromPropertiesOnly, TestGlobalDoesNotMaterializeAutoMapMatches, variant golden and target validation, kernel shared title update. Only explicit root From property mappings merge, with overwrite diagnostics; class-level FromEvent adds no properties and AutoMap matches are not materialized. Go rejects a global From without explicit writes with typed GlobalFromHasNoProperties at NewClient (TestGlobalFromWithoutPropertiesFailsAtNewClient) instead of C#‘s silent no-op. No standalone model registration. Fluent reusable globals are a Go authoring extension; C# fluent repeats From mappings
Recursive ChildrenFrom<E> / ChildrenDefinitionExtensions:641–715Implemented for concrete recursive shapes and finite C# traversal: existing tags/Nodes and explicit fluent childrenTestRecursiveKeyedChildPropagationAndAncestorExclusion, TestRootSelfReferenceUsesFirstLevelFiltersAndStopsExpansion, TestRecursiveChildSetFromFiltersNonRecursiveLevelOnly, TestKernelRecursiveKeyedChildren. The first child uses normal event/member filters even for a root collection of its own type, while the traversal guard stops grandchildren. Set mappings for the child type’s own ChildrenFrom event are excluded at non-recursive levels and retained at repeated levels, reproducing C# self_referencing_children_with_set_from. Repeated nodes keep local exclusions and own creators, exclude ancestor creators, and require parent keys for keyed update propagation. Traversal guards are path-local, not global visited sets; this is not unlimited-depth recursive routing
Derived children / ResolveConcreteChildType, AddDerivedTypeDiscriminatorMappingPartial: children of a family with exactly one registered derivative; see registered derived codecsTestDerivedProjectionCopiesWholeFamiliesButDoesNotInferChildren permits whole-family copies and refuses children on a two-derivative family, which C# would keep as the undecodable interface. Direct family-valued derivative properties remain refused for Fundamentals#1149; protected families remain unsupported
Recursive schema/codec prerequisiteImplemented for concrete structs, pointers and collections using draft-07 referencesTestRecursiveSchemaCodecAndSiblingTraversal, TestGenericRecursiveSchemaReferencesUseSafeNames, TestRecursiveValuesRejectCyclesAndExcessiveDepth, TestRecursiveReadModelKeepsRootIDTranslationLocal, kernel recursive fixture. Recursive definition names use only ASCII letters, digits and underscores plus a type hash, including for instantiated generics. Cyclic runtime values fail; encoding is bounded to 256 levels. Untagged root ID normalization does not leak into nested instances
EventStore on events / InferEventSequenceId, fluent ProjectionBuilderForPartial: events.WithSourceStore, finalized projection inference, Definition.ForStoreTestSourceInferenceExplicitSequenceAndCompatibility, TestSiblingRemovalsDoNotChangeVariantSource. Local origin selects log, external selects inbox-<store>; incompatible origins fail. Generated sibling removals never affect source inference, so a local variant remains on event-log when its sibling enters from an external store. Go intentionally normalizes both front ends and includes authored joins/children/removals, excluding generated sibling removals; C# model-bound checks root From before lowering and fluent lacks local-store comparison. Subscription provisioning is covered under External integrations
EventSequence / EventLog precedenceImplemented: explicit projection or read-model sequence overrides source inferenceSource inference test covers explicit log/custom, including conflicting source stores bypassed by explicit selection. Inferred templates are specialized for each store without rediscovery
FromAll + FromEvery with variantsImplemented for C# emitted definitions; broad All fallback is not exclusiveVariant golden retains All/IncludeChildren and SubscribesToAllEvents; kernel variant fixture combines both while entering/leaving and handling global joins. Unrelated events selected by All can create a model through the kernel fallback: prefer Every for exclusive lifecycle variants
Final definition fingerprint / registration snapshotsGo-specific: Definition.Hash() returns SHA-256 of deterministic finalized protobuf encodingVariant golden compares both front ends and reordered admission, checks detached ownership; recursive fixture verifies nested naming affects the hash. TestProjectionDiscoveryRegistrationAndFrozenReplay proves frozen reconnect registration. Excludes timestamps/provenance, includes nested nodes, exclusions, source selection and sibling removals. Stable only within one build: protobuf deterministic marshaling is not guaranteed across binaries or dependency versions, so do not persist hashes across upgrades. Neither the kernel nor C# uses a client hash; reconnect reuses frozen definitions
IProjections.Query, historical ProjectionPreviewPartial: EventStore.QueryProjection / PreviewProjection, projections.QueryResult, typed QueryError; explicit-model queries workTestProjectionQueryPreviewTransportAndFailureBoundaries, TestKernelProjectionQueryAndPreview. Uses existing Preview RPC with C#‘s exact request fields; PDL executes on the kernel without permanent registration. Owned JSON entries and optional schema; malformed/ambiguous envelopes fail. TestKernelProjectionQueryInfersSchema covers inferred-schema queries on 19.32.3; on 19.29.4 the inferred schema is empty and drops projected properties (Chronicle#4539, fixed in 19.32.1). Caller context bounds the call. Kernel caps matching events at 1,000; no claim of complete large-history reads

The variant guide has model-bound and fluent examples with snippet-equality and definition-equivalence tests. Preview diagnosis sent unchanged PDL, inspected the persisted event schema, and observed a returned schema without properties despite explicit title = title mapping. An explicit target read model passes the same query assertions. The C# Query implementation sends the same four fields to Preview; no alternate Go compiler or callback is involved. The exact server root cause is not claimed. Existing remove-join limitations remain unchanged. Use registered derived codecs for admitted unprotected families; those codecs do not implement derived-child lowering. Subscription provisioning is covered under external integrations.

References in this section use C# 2e31b0dfba489159b3db323238f16d0f277056b4, relative to Source/Clients/DotNET unless marked kernel. Scope agreements follow Fundamentals.Go#9; the optional adapter pins Fundamentals.Go 0fd6b51d12e47b1ecd1d7c9b5524d0350d01c216. The reactor guide leads with plain closures, then convention discovery and optional services.

Behavior / C# sourceGo surface and statusEvidence and deliberate difference
Explicit admission and convention dispatch / Reactors/{ReactorInvoker,EventHandlerMethods}Implemented for current registered event types: RegisterReactor[R], RegisterReactorHandler, reactors.On/Returning; one compiled PlanTestDiscoveryPrecedenceAndExportedMethods, TestTypedCallbacksShareValidationAndEffects. Go explicitly admits types, adds optional leading context.Context, and can discover only exported methods. No required Handle/On name. Unregistered method parameter types are not inferred as events; explicit unknown callbacks and reactors with no known handlers fail
Event-interface families / Events/EventTypeExtensions, Reactors/ReactorInvokerImplemented for interfaces implemented by current catalog events, excluding unconstrained anyTestRegisteredEventInterfaceFamilies; value or pointer implementations participate. Current and historical codecs coexist in the catalog; each observer must select one generation per event ID (TestObserverRejectsMixedGenerationBindings). See event evolution
Method precedence / Observation/HandlerMethodPrecedenceImplemented: descending arity, then ordinal name; shadows are logged and available from Plan.ShadowsTestDiscoveryPrecedenceAndExportedMethods. All reflected methods are exported, so C#‘s public/nonpublic comparison is inapplicable. The optional Go context counts toward arity. Duplicate explicit bindings are errors
Signature validation and catalog isolation / ReactorInvoker, ReactorMethodArgumentsResolverGo-specific: typed DeclarationError, validation at NewClient, no process-global dispatch cacheTestInvalidSignaturesAreTypedAndDoNotActivate, TestPlansAreIsolatedByCatalog, TestReactorCatalogValidationAtNewClient, TestReactorDuplicateAndClientCatalogIsolation. Unsupported results/variadics fail before I/O; constructors are not executed. Catalog-capable factories validate services; factories without Catalog defer actual availability to invocation
Stable observer ID / Reactors/{ReactorAttribute,ReactorTypeExtensions}Go-specific: full Go import path plus normalized type name; WithID selects a persisted C# identityTestDiscoveryPrecedenceAndExportedMethods, duplicate/catalog tests. Renames change the default identity; choose explicit IDs for migration. Duplicate IDs/types and projection-ID collisions are rejected per registry
Parameter precedence / Reactors/ReactorMethodArgumentsResolverImplemented: event context → delivery → registered read model by source/custom key → scopeTestReactorReadModelInjectionUsesCustomKey, TestReactorFundamentalsScopeCatalogAndBorrowedSingletonOwnership. Go checks explicit model registration rather than requiring a local producer. Missing models require pointer parameters; value parameters fail instead of fabricating a zero model. Service.GetValue shares typed Reader.Get collection normalization for discovered parameters
Delivery identity / Reactors/ReactorDelivery, Source/Infrastructure/KeyHelperImplemented: reactors.Delivery, six components and C# #-joined ID()TestDeliveryIdentityMatchesCSharp, TestReactorOrderedBatchPartialFailureAndCleanupBeforeAck. Identity uses the event source ID, not an inferred custom partition. C# delimiter ambiguity is preserved; no deduplication/exactly-once claim
Default activation / DefaultServiceProvider, ClientArtifactsActivatorGo-specific: plain constructors/closures; zero-container scopes construct zero-valued structs/pointers and empty slicesTestPlainGoExampleHasNoDependencyInjectionDependency executes go list -deps as an ordinary test. No automatic NewX discovery or C# constructor enumeration. The core does not transitively import DI; Fundamentals factories enter through the separate services.WithServices adapter, not a root-package DI dependency
Service activation and ownership / ClientArtifactsActivator, ActivatedArtifactImplemented for batch artifacts: Catalog-advertised services win, constructor results owned, service results borrowed, context closer preferredTestRegisteredArtifactsWinWithoutDoubleDisposal, TestActivationFailureReleasesPartialResourcesAndPreservesCause, TestLeaseCleanupIsIdempotentAndGuardsInvocation, TestFactoryWithoutCatalogDefersResolutionAndRejectsWrongTypes. Go never double-disposes scope/provider-owned artifacts. Without Catalog, explicit constructors run; nil constructors request resolution. Unlike C# GetServiceOrCreateInstance, Chronicle does not guess whether a resolver failure permits construction fallback. ActivationError preserves factory/cleanup causes; lease invocation after Close fails
Batch/event scope boundaries / Reactors/Reactors.cs:683–708Implemented: one scope/artifact/middleware chain per received batch; PerEvent() opt-inTestReactorOrderedBatchPartialFailureAndCleanupBeforeAck, TestReactorPerEventCreatesAndClosesEachScope. BatchFromContext installs batch coordinates before scope activation without capturing a first event. Client-lifetime collaborators use provider-owned Singleton bindings; no client-lifetime scope is retained. Config-backed definitions, two-phase preparation and borrowed facade helpers are implemented separately under definition factories; they do not change the per-batch default
Per-event metadata / Reactors/ReactorHandlerImplemented for system/on-behalf-of identity, correlation and reactor causationOrdered-batch transport test. Go uses explicit derived contexts, not ambient state. Error messages reach the kernel; Go errors do not synthesize .NET exception stack traces
Middleware hooks / Reactors/{IReactorMiddleware,ReactorInvoker,ReactorMiddlewares}Implemented for before failure and after logging policies; Go-specific deterministic registration order instead of C# Task.WhenAllTestReactorMiddlewareOrderAndFailurePolicies. All before and after hooks run; before failures suppress handling, after errors never change the result after effects. Middleware receives delivery and scope directly, allowing Arc adapters to unwrap/check the borrowed Fundamentals scope
Middleware admission / Reactors/ReactorMiddlewaresActivatorImplemented: RegisterReactorMiddleware applies registry-wide middleware to every reactor, ahead of per-reactor WithMiddlewareTestRegistryMiddlewareRunsForEveryReactorBeforeLocalMiddleware, TestRegistryMiddlewareValidationAndStoreIsolation. Registration order is deterministic; NewClient freezes the list per store catalog. Later registrations do not affect existing clients
Middleware activation / ReactorMiddlewaresActivatorGo-specific fail-closed activation, rather than C# log-and-skipTestActivationFailureReleasesPartialResourcesAndPreservesCause; every successfully acquired resource is released even if a later constructor fails
Basic returned effects / Reactors/SideEffects/EventResultHandlerImplemented for no result, error, event and event+error; nil event means no effect; append to EventLog using triggering source or EventSourceIDProviderTestReturnedEventAndErrorShapes, TestTypedCallbacksShareValidationAndEffects, TestReturnedEventUsesReactorSourceProvider, TestReactorPerEventScopeAndAppendRejection, TestKernelReactorOrderingReturnedEventsAndFailedPartition. Errors suppress results; append domain rejection fails handling. Stream/source-type/subject metadata providers and custom side-effect handlers are covered in Reactors part 2
Ordered receive, generation selection and partial failure / Reactors/Reactors.cs:708–810; kernel Grpc/Observation/ReactorsImplemented: serial receive/handle/send, no application queue, acknowledgement only through the last successful eventOrdered-batch and kernel tests. Uses target generational content when available, otherwise C#‘s current-content fallback while retaining the original context generation. Invalid contexts, unknown subscribed types and non-increasing batch positions fail closed. Wire message-size limits bound transport buffering
Cleanup and acknowledgement / ActivatedArtifact, Reactors/ReactorsGo-specific cleanup before acknowledgement; cleanup errors fail handling instead of C# logging/swallowingTestReactorCleanupFailureDoesNotAcknowledgeCompletedEffects, lease cleanup tests. Batch cleanup failure resets progress to unavailable; per-event cleanup failure retains earlier successful events. Already completed effects may repeat on kernel recovery. Cleanup has a bounded context, not forcible goroutine termination
Registration order / EventStore.RegisterAllArtifacts, Reactors/ReactorsImplemented after event types, read models, constraints and projectionsTestReactorOrderedBatchPartialFailureAndCleanupBeforeAck rejects an early observer at the fake kernel. Duplex registration has no acceptance reply: readiness means registration sent, not observer catch-up (see the late-subscription row; Chronicle#4558 is fixed in 19.32.3). TestReactorOpenDoesNotBlockBackgroundArtifactReplay verifies background artifact replay does not await observer readiness. Frozen dispatch plans are reused on reconnect
Cancellation, unregister and reconnect / Reactors/Reactors.cs:106–114,542–611Implemented: generation-owned workers, independent two-second resubscription after stream error/completion or failed open, retained local unregisterTestReactorReconnectUnregisterAndWorkerJoining, TestReactorOpenFailureRetriesOnSameGeneration, TestReactorUnregisterCancelsResubscriptionDelay, TestReactorUnregisterIsRetainedAcrossReconnect. Resubscription retains the ConnectionId and does not cancel unrelated appends. Only the keep-alive watchdog replaces lost connections. Whole-kernel reactor restart remains unverified; a malformed-definition kernel regression is blocked by a separate keep-alive failure (Chronicle#4537)
Readiness cancellation / Reactors/ReactorsGo-specific: caller context bounds readiness, not the generation-owned subscriptionTestReactorOpenOutlivesCallerAndAppendDeadline, TestReactorUnregisterDuringOpenDoesNotPoisonRegistration, TestReactorOpenFailureRetriesOnSameGeneration. A failed Open releases explicit waiters with a registration outcome naming the reactor and pending subscription retry; later calls observe recovery. Removal during Open releases readiness without dropping the shared connection
Retired observer cleanup / Reactors/Reactors.cs:106–114Implemented: reconnect does not await running handlers; Go-specific explicit shutdown joinTestReactorIgnoringCancellationDoesNotBlockReconnect, TestReactorCancellationJoinsActiveHandlerAndClosesScope, TestReactorUnregisterJoinsRetiredGeneration. Retired observers are tracked until completion, and owned channels close after they finish. UnregisterReactor joins current and retired runs for its ID; both it and CloseContext report incomplete cleanup on deadline. Uncooperative handlers may overlap a newer generation; cancellation and idempotent effects remain application responsibilities
Registration policy metadata / Reactors/Reactors, kernel Grpc/Observation/ReactorsImplemented: wire registration reads replayability, artifact/filter tags and source/stream types from the compiled planTestPlanRegistrationMetadataAndDetachedTags, TestReactorMetadataProvidersAndFiltersVersusLabels. Defaults remain replayable, no tags, all source types and All streams. Public authoring and replay behavior are detailed below
Failure ownership / kernel Core/Observation/Observer.FailingImplemented: failures reported to kernel, no autonomous effect retryTestReactorActivationFailureIsReportedWithoutAdvancement, partial/rejection tests, TestKernelReactorOrderingReturnedEventsAndFailedPartition verifies persisted failed partition. Recovery/quarantine commands are available through EventStore.Observers(); administration evidence distinguishes a retry request from completed recovery

Reference: C# 2e31b0dfba489159b3db323238f16d0f277056b4, paths relative to Source/Clients/DotNET unless prefixed with Kernel. These additions extend the existing Plan/Lease invocation boundary and shared observer stream, not a second execution engine. Kernel fixtures target 19.32.3-development.

Behavior / C# sourceGo surface and statusEvidence and deliberate difference
Replay replacement / Reactors/ReactorInvoker.cs:252–342, ReplayAttributeImplemented: Replay("Method"), callback .DuringReplay(), separate live/replay maps and union subscriptionsTestReplayMapsAndOnceOnlyPolicies, TestReactorReplayDeliveryAndSeparateNotificationScopes, TestKernelReactorReplayReplacementOnceOnlyAndNotifications; replacement wins, fallback to live without a replacement, replay-only types subscribed, combined replay flags honored
Method selectors / ReplayAttribute, OnceOnlyAttributeGo-specific validated exported method names, no name-prefix semanticsTestReplaySelectorsMustIdentifyDiscoveredMethods, TestReplayNamePrefixHasNoSemantics, TestReplayTypedCallbacksFallbackSkipAndDuplicates; duplicate explicit bindings are rejected within each map; typed generated selectors await #23
Reactor-wide OnceOnly / ReactorTypeExtensions, Reactors.Register, Source/Kernel/Contracts/Observation/Reactions/ReactorDefinition.cs:33–34 (repository-root kernel path, baseline revision above)Implemented: OnceOnly() sends explicit field-4 false despite proto3 omission and C#‘s absent=true defaultTestProto3FalseReplayabilityIsAbsentAndCSharpDefaultsTrue, TestReactorRegistrationWirePreservesReplayability, TestKernelReactorWideOnceOnlyRefusesReplayJob; byte-level full registration evidence covers false, unchanged true defaults and separate method/mixed policies. The pinned kernel refuses reactor-wide replay with JobId.NotSet, while default reactors start a job and receive replay. The refused observer continues handling live events; this is not a method-handler skip or a client deduplication ledger
Method OnceOnly / ReactorInvoker.HandlerMethods.ResolveImplemented: OnceOnly("Method"), callback .OnceOnly()TestReactorOnceOnlySkipsReplayButNotRecovery, TestReplayMapsAndOnceOnlyPolicies, kernel replay fixture; a OnceOnly replacement does not fall back to live
Replay notifications / Reactors.HandleReplayNotification:814–842Implemented: ReplayNotifier, PartitionReplayNotifier, one separate artifact/scope per notification, no middlewareTestReactorReplayDeliveryAndSeparateNotificationScopes, TestReactorNotificationFailureReleasesScopeAndReconnects, kernel replay fixture. No notification ack exists. Activation failure logs like C#; Go cleanup failures propagate, as for ordinary batches
Event collections / SideEffects/EventsResultHandlerImplemented: typed slices/arrays and bare []any via existing AppendManyTestReactorRichEffectsWireShapesAndOrdering, TestReactorEffectsValidateBeforeWritesAndPropagateRejection, TestKernelReactorRichEffects; empty collection is no effect; nil items fail; finite Go collections replace IEnumerable
Targeted wrappers / SideEffects/{EventForEventSourceIdResultHandler,EventsForEventSourceIdResultHandler}Implemented: existing eventsequences.Entry, pointer and collectionsRich-effect wire and kernel fixtures preserve source, route, subject, tags, occurrence and causation. No reactor default leaks into self-describing entries
Mixed bare/targeted events / SideEffects/MixedSideEffectsResultHandlerImplemented: []any lowered to one ordered atomic AppendBatchWire and kernel rich-effect fixtures; complete classification before writes, input order preserved, no grouping by source
Concurrency effects / SideEffects/EventsWithConcurrencyScopesResultHandlerImplemented: eventsequences.EventsWithConcurrencyScopes{Events, Scopes} via existing batch/scopesRich-effect wire and kernel fixtures; ordered entries, independent protected scopes and append rejection retained. Empty batches require a protected scope
Bare-event metadata / SideEffects/*ValuesProviderImplemented: EventSourceIDProvider, EventStreamIDProvider, SubjectProvider, source/stream/stream-ID optionsTestReactorMetadataProvidersAndFiltersVersusLabels, TestReturnedEventUsesReactorSourceProvider; outputs always target EventLog, provider stream ID overrides option, ordinary event subject fallback remains in effect
All-matching custom effects / SideEffects/{IReactorSideEffectHandler,ReactorSideEffectHandlers}Implemented: RegisterReactorSideEffectHandler, WithSideEffectHandlers, SideEffectContextTestReactorCustomEffectsInvokeAllMatchesAndFailPartition, TestReactorClassifiesExtensionsBeforeBuiltinAppend; all matches selected before effects, errors joined before ack. Instances borrowed/concurrency-safe, no Arc dependency; Arc command seam tracked by #44
Store-local extension admission / SideEffects/EventStoreReactorSideEffectHandlerInstances, ReactorInvokerImplemented: registry lists frozen per store at NewClient, return-type claims participate in startup validationTestCustomEffectsFrozenPerStoreAndStartupAdmission, TestCustomEffectsReceiveReplayPolicyAndBorrowedBatchScope; delivery, scope, catalog and replay/OnceOnly policy are invocation-local
Custom/mixed collections / ReactorSideEffectHandlers extension contractGo-specific element-wise fallback when no handler claims the whole collectionTestCustomEffectCollectionPreflightAndDeterministicExecution; all elements classified before any effect; deterministic order, stop after failed item, all matching handlers for that item still run. Pure events remain atomic. External/custom mixtures have no cross-effect transaction; finite collections only (#44)
Tag filters / FilterEventsByTagAttribute, Reactors.RegisterImplemented: WithEventTagFilter sent in ObserverFilters.FilterTagsTestReactorMetadataProvidersAndFiltersVersusLabels; copied input, OR within tags. Kernel owns matching; wire verified, independent live-kernel tag-matching fixture not added here
Artifact labels / TagAttribute, TagsAttributeImplemented: WithTags sent only as definition tagsSame registration fixture distinguishes labels from filters; no event-property extraction
Source/stream filters / EventSourceTypeAttribute, EventStreamTypeAttributeImplemented: source/stream options sent as filters and used for bare-effect defaultsSame wire fixture; categories combine with AND in kernel. WithEventStreamID never filters
Explicit sequence and external inbox / ReactorTypeExtensions.GetEventSequenceIdImplemented: explicit sequence/log, event-origin inference, observer source overrides and automatic provisioningTestObserverOriginsBindSequencesModelsAndSubscriptionUnion, TestObserverExplicitSequencesOverrideInferenceAndMixedSourcesFail, TestKernelExternalSubscriptionForwardsOutboxToObserverInbox; per-behavior boundaries under External integrations
Historical-generation-only concrete handlers / Events/EventTypeExtensions.cs:61–76Implemented: historical/current catalog entries coexist; a concrete historical handler retains its exact codec and subscription generationTestConcreteHistoricalGenerationHandlerIsNotLost, TestHistoricalConcreteHandlersKeepTheirOwnExpansion, TestKernelHistoricalEvolutionAndSubscribedGenerations. Go corrects the C# historical-only discovery omission, but rejects multiple generations of one ID in a single observer (TestObserverRejectsMixedGenerationBindings). Use separate observers; event evolution describes exact/current lookup and fallback, without claiming an executed two-generation cross-language consumer witness
Read-model reactors / ReadModels/{ReadModelReactors,ReadModelReactorMethods}Implemented: explicit admission with Added/Modified/Removed discovery, callbacks and materialized differsSee Read-model watches and reactions; distinct from durable event observers
Observer admin, tails, completion waits / Reactors.Replay, ReactorWaitExtensions, Observation/AppendResultWaitForCompletionExtensionsImplemented: EventStore.Observers(), Jobs(), Sequence.TailForObserver, completion and job waitsTestOperationsMatchHandDerivedCSharpGolden, TestCompletionUsesActualBatchTailsAndOriginalCoordinates, TestJobWaitRequiresEvidenceAndPreservesDisappearance, TestKernelOperationsCompletionReplayAndJobEvidence; see operations. Accepted requests, registration sends, observed catch-up and durable checkpoints are distinct. Missing/disappearing jobs stay absent/unknown; no actual-attachment, multi-node or durable-checkpoint guarantee is inferred

References use C# 2e31b0dfba489159b3db323238f16d0f277056b4, relative to Source/Clients/DotNET. The reducer guide leads with plain Go, then conventions and optional DI. Contracts and kernel evidence target 19.32.3. The active reducer integration test requires the deletion event to be delivered. On 19.29.4 the kernel’s finishing catch-up job race could persist event 2 without delivering it; 19.32.3 fixes that race. The Go transport test independently verifies the deletion result and its checkpoint.

Behavior / C# sourceGo surface and statusEvidence and deliberate difference
Explicit admission and one-model association / Reducers/{IReducerFor,ReducerAttribute,ReducerTypeExtensions}Implemented: RegisterReducer[R,M], automatic Reducer producer binding; ID defaults to import path plus normalized type nameTestReducerDiscoveryValidatesAtNewClientWithoutConstruction, TestReducerProducerAndIdentityConflictsFailAtomically. Explicit root registration replaces assembly scanning. Duplicate model/type/ID and projection/other-observer conflicts fail; original model handles remain valid
Exported signature discovery / Reducers/ReducerTypeExtensions.cs:50–105Implemented: event, current *M, optional event context; M/*M result, optional error and leading Go contextTestInvalidFoldSignaturesAreTypedStartupErrors, TestNilDeleteRecreateAndPresentZero. Constructor-only dependencies; arbitrary fold service arguments fail. Go cannot reflect unexported methods; bare C# Task deletion is expressed as a nil *M result
Nullable current and value adaptation / Reducers/Validators/ReducerMethodCurrentReadModelMustBeNullableGo-specific: nullable *M is recommended; value M is also accepted with zero on absenceTestValueCurrentUsesZeroForAbsence. Unlike C#‘s nullable-current validator, Go permits the requested value alternative; use *M to distinguish absence from present zero
Event families and precedence / Events/EventTypeExtensions, Observation/HandlerMethodPrecedenceImplemented for current-catalog event interfaces, richest signature then ordinal name, shadow diagnosticsTestDiscoveryPrecedenceFamiliesAndCatalogIsolation. Shared discovery code with reactors; no global type-only cache. Explicit duplicate handlers fail rather than override; Go context contributes to arity
Typed callbacks and frozen fold plan / Reducers/ReducerInvokerImplemented: RegisterReducerHandlers, reducers.On[E,M]; callbacks and discovery share validation/invocationTestExplicitAndDiscoveredFoldsSharePlanAndResults, TestReducerDiscoveryValidatesAtNewClientWithoutConstruction. Equivalent semantic signatures have equal fingerprints; callbacks retain caller-owned captures
Startup validation / Reducers/ReducerInvoker, ReducerTypeExtensionsGo-specific atomic typed DeclarationError at NewClient before I/O or constructorsTestInvalidFoldSignaturesAreTypedStartupErrors, TestReducerProducerAndIdentityConflictsFailAtomically. Clearly fold-shaped unknown event methods fail instead of disappearing; a no-sink reducer model must have a matching registered plan
Sequential fold, initial state, deletion and recreate / ReducerInvoker.cs:62–142Implemented: one scope, serial folds, nil deletion distinct from present zeroTestNilDeleteRecreateAndPresentZero, TestReducerRuntimeFoldOrderDeletionGenerationAndCleanupBeforeAck, TestActiveReducerInitialStateUsesFrozenNamingPlan, TestKernelReducerMaterializationDeletionAndFailedPartition; active initial-state decoding uses the frozen model descriptor for distinct ID names, all naming policies and collection nullability
Failure and last-success position / ReducerInvoker.cs:116–142, Reducers.cs:534–578Implemented: stop at first error/panic, failed result never contains partial stateTestFirstFailureStopsAndDiscardsMutatedPartialState, TestReducerRuntimeFailureNeverReportsPartialState, kernel failed-partition test. Go does not synthesize .NET exception stack traces. Kernel owns recovery; no effect retry is added
Per-operation activation and identity / Reducers.cs:261–286,534–539, ClientArtifactsActivatorImplemented: shared artifact leases/scopes with reactors; kernel-driven operations use system identity before construction and every fold, passive reads retain caller identityTestIdentityIsSystemForConstructorsAndFolds, TestPassiveReducerReadPreservesCallerIdentityForConstructionAndFold, TestReducerRuntimeFoldOrderDeletionGenerationAndCleanupBeforeAck, TestReducerRegisteredServiceWinsAndIsDisposedOnlyByScope. No arbitrary fold parameter injection; shared optional services.WithServices adapter remains borrowed
Cleanup ownership / ActivatedArtifact, ReducerInvokerGo-specific: constructor values close before scope; cleanup errors fail operation, unavailable progressTestReducerActivationFailureReleasesPartialArtifactAndScope, TestReducerLeaseGuardsUseAfterCloseAndRetainsCleanupFailure, TestReducerRuntimeFailureNeverReportsPartialState. C# logs/swallows disposal failure. Partial resources are released; scope-owned artifacts are not disposed twice
Active/materialized and inactive modes / Reducers.ShouldReducerBeActive, ReadModels.ReadModelsImplemented: active by default; WithActive(false) preserves sink and does not select local readsTestReducerPassiveAndInactiveBinding, TestKernelReducerMaterializationDeletionAndFailedPartition. Model binding preserves configured sink/sequence and rejects incompatible producers
Passive source reads / ReadModels.cs:187–220, Reducers.GetInstanceByIdImplemented: reducers.Passive or readmodels.Passive selects local Reader.Get, no sink, absence/deletion and fold errors preservedTestKernelPassiveReducerReadsFoldLocallyWithAbsenceDeletionAndFailure. Uses 19.32.3 server-released source/type history and the same fold plan, then validates final state without another decrypt (TestKernelModelHistoryReleaseOwnershipAndErasure). Like C#, passive history reads do not apply active observer tag/source/stream filters. Unlike C# root-provider passive activation, Go uses one scope per local read
Tag/source/stream filters and artifact labels / Reducers.RegisterReducerImplemented for definition encoding: WithEventTagFilter, WithEventSourceType, WithEventStreamType, WithTagsTestReducerRuntimeFoldOrderDeletionGenerationAndCleanupBeforeAck. Filters govern active kernel delivery; labels do not filter. Real-kernel filter matching is not independently verified here
Explicit event sequence / ReducerTypeExtensions.GetEventSequenceIdImplemented: event-log default, WithEventSequence, WithEventLogTestReducerPassiveAndInactiveBinding; explicit model/producer sequence conflicts fail. Sequence selection alone does not provision an inbox
Stable behavior fingerprint / Reducers/ReducerFingerprintGo-specific: SHA-256 of canonical fold shape, model/event/observer settings and WithVersionTestExplicitAndDiscoveredFoldsSharePlanAndResults, TestReducerResubscribesAfterEOFAndGenerationReconnectWithoutRediscovery. No IL/body hashing: implementation-only changes require a version bump; generated source versioning is not implemented
Generational payload selection / Reducers.cs:509–530, Events/EventTypeExtensions.cs:61–76Implemented: current/historical codecs, exact historical handler expansion and supplied target-generation selection, else C# current-content fallbackTestReducerRuntimeFoldOrderDeletionGenerationAndCleanupBeforeAck, TestHistoricalConcreteHandlersKeepTheirOwnExpansion, TestKernelHistoricalEvolutionAndSubscribedGenerations. Catalog coexistence does not permit mixed generations of one event ID in one observer; use separate reducer plans (TestObserverRejectsMixedGenerationBindings)
Ordered stream, reconnect and cancel / Reducers.RegisterReducer, kernel Reducers contractsImplemented with reactor-shared stream loop and observer supervisorTestReducerCancellationJoinsScopeAndNeverAcknowledges, TestReducerResubscribesAfterEOFAndGenerationReconnectWithoutRediscovery, existing reactor lifecycle suite. Frozen registrations survive reconnect; stream failure is isolated. Go also resubscribes on normal EOF, unlike C#‘s missing completion callback. Whole-kernel restart remains unverified
Zero-container authoring / DefaultServiceProviderGo-specific plain constructors and closures, no runtime container requirementTestPlainGoReducerHasNoDependencyInjectionDependency runs go list -deps; TestBothAuthoringPathsCompileAndFold; compiled example and snippet-equality test
Automatic source-store/inbox inference and subscription provisioningImplemented for compiled folds and registered-store bindingTestObserverOriginsBindSequencesModelsAndSubscriptionUnion, TestExternalSubscriptionsFollowObserversPrecedeSeedingAndReplayPerGeneration; model sequence and fold fingerprint are rebound with the store. Explicit sequences suppress inference; shared provisioning is covered below
Replay-wide and partition lifecycle / Reducers.cs:580–607, Observation/{ICanBeNotifiedWhenReplay,ICanBeNotifiedWhenPartitionReplayed} at 2e31b0dfbImplemented: reducers.ReplayNotifier, PartitionReplayNotifier, explicit WithReplayCallbacks; same ordered observer runtime and activation leasesTestReducerReplayNotificationsShareProductionOrderAndFreshScopes, TestReducerNotificationSignaturesValidateAtNewClient, TestReducerFoldNamesAreNotLifecycleSelectors, TestReplayNotificationPreservesAmbientMetadataAndCleanupCauses, ExampleRegisterReducerHandlers_replay. Exact interface method pairs validate before constructors; prefixes have no policy, explicit fields are optional. Fresh scope/activation per delivery, opaque partition keys preserved, no shared folding artifact or synthetic event metadata; identity/correlation/causation preserved as in C# notification path, unlike ordinary System folds. Manual/reflective semantic plans have equal fingerprints; explicit implementation version bumps remain required
Notification failure, unknown state and lifetime / same C# notification path and kernel Contracts/Observation/ReplayStateGo-specific fail-closed activation/cleanup, Implemented cancellation/ordered dispatch without result handshakeTestReducerNotificationFailuresReconnectOnlyObserverAndNeverAcknowledge, TestReplayNotificationActivationFailureIsClosedBeforeReturn, TestReducerNotificationCancellationUnregisterAndCallbackCloseContextJoin: errors/panics/unknown enum values terminate only the observer stream, not the shared generation. C# logs/ignores activation failures; Go propagates typed errors to avoid continuing after a missed hook. Cleanup ownership reused, operation contexts canceled after cleanup, duplicate notifications dispatched again. Callback CloseContext(ctx) releases via cancellation; synchronous own-worker Close/unregister still prohibited; no exactly-once guarantee. Bufconn fixtures use WaitForHandlers(true) and joined-handler leak assertions
Kernel replay lifecycle / kernel ReducerReplayHandler, Reducers/Clients/ReducerMediator; C# reducer replay request specsImplemented for the pinned 19.32.3 reducer-wide replay witness through #59 servicesTestKernelReducerReplayLifecyclePreservesNormalFolding: Observers().Replay accepts a namespace-bound job, start/end callbacks arrive in stream order, materialized models survive replay and subsequent normal folding. Job acceptance and end notification are not durable job/checkpoint proof; partition callbacks independently covered by production-path transport tests, not a claim that every kernel-wide replay emits partition notices. Bounded collection folds are implemented below; reducer snapshots remain unsupported. This witness does not complete every #31 recovery profile
Bounded historical folds / ReadModels.GetInstances, Reducers.GetInstancesImplemented: raw/typed GetAll with globally bounded, generation-aware active/passive local foldsTestReducerCollectionsGloballyBoundHistoricalFoldsAndKeepActualPositions, TestKernelModelHistoryReducerCollectionRoutingAndDeletion; every nonzero explicit count selects local folding, including Unlimited; default active reads remain materialized. Zero returns empty without I/O, and complete matching history is fetched before local truncation, not paged on the wire
Reducer snapshots / Reducers.GetSnapshotsByIdNot implemented: GetSnapshots refuses reducer models with ErrUnsupportedTestSnapshotsRefuseReducersBeforeRPCAndReturnOwnedEmpty guards the refusal; the pinned kernel returns an unconditional empty result for reducers. Do not interpret that result as evidence of absent history; sessions and protected decisions remain separate capabilities
Local watch notifications / ReducerHandler.OnNext, IReducerObserversImplemented for unclassified models: successful production folds notify namespace/generation-local watches in order before acknowledgement, validating final plaintext without Release. Classified Watch refuses before queue attachment without a delivery-time erasure fenceTestReadModelReactorInfersFirstSeenLocalReducerAddition, TestLocalReducerWatchPlaintextRemovalAndGenerationIsolation, TestClassifiedWatchesRefuseBeforeTransportOrLocalAttachment; namespace/generation isolation and lifecycle remain unchanged, with no sink-write/durable delivery guarantee. TestKernelReleaseRouteProfiles covers successful protected fold state before/after erasure, not safe classified local-watch delivery. Reducer sessions remain explicitly unsupported
Definition preparation and borrowed client/store DI facades / ClientArtifactsActivator, ChronicleClientServiceCollectionExtensionsImplemented for config-only projection/constraint/migration factories, seed preparation, two-phase client composition and optional services.Bind* helpersTestDefinitionFactoriesPlainAndFundamentalsProduceIdenticalFrozenArtifacts, TestFacadeConsumerCaptureBindPrepareAndResolveCoordinates, TestBorrowedFacadeScopeDisposalKeepsActiveObserverStream; see definition factories and facade composition. These SDK witnesses do not cover Arc.Go#29 adoption or the separate runtime projection addition API; provider disposal does not transfer ownership of borrowed client resources

Go preserves C#‘s failed-batch response: last successful observation with no state. Up to 19.32.2 the kernel restarted recovery at that last success and lost the unpersisted prefix of the failed batch (Chronicle #4540). Kernel 19.32.3 retries a reducer batch that fails part-way from the start of the batch. TestKernelReducerFailedPrefixRecovery witnesses this against the pinned kernel: one appended batch folds 1, 2 and 3, the fold of 3 fails once, recovery folds the whole batch again from 1 and the materialized balance settles at 6 rather than 5. The kernel may fold the batch more than once during recovery; each attempt reloads the persisted state, so the result stays 6. Go does not change the failure wire contract independently.

References below are Source/Clients/Testing/ and Testing.Specs/ at Chronicle 2e31b0dfba489159b3db323238f16d0f277056b4. Kernel sibling cases use cratis/chronicle:19.32.3-development. The Go fixture package is chronicletest; these rows do not claim that a Go substitute executes C# kernel code. Root admission remains explicit; all registered conventions use the production compilation pipeline.

C# scenario type / sourceGo surface and statusExecutable evidence and exact fidelity
EventScenario, EventSequences/EventScenario.cs:89–135,187–266Partial: OpenEventScenario / NewEventScenario, Given, production EventLog / Store, kernel and substitute enginesExampleEventScenario, TestEventScenarioUsesProductionNamingAndIsolatedStorage, TestEventScenarioRefusesStrictFidelityAndConcurrency, TestEventScenarioRefusesDiscoveredConstraintsBeforeConnecting, TestEventScenarioCancellationCloseAndMissingKernel, TestKernelEventScenarioEnforcesConstraints, TestKernelEventScenarioOwnsRealObserverLifecycle. Real kernel runs registration/append/read and constraint enforcement. Substitute runs the production Go client over an in-memory grpc.ClientConnInterface, without hosting a gRPC server, with default no-check scopes (TestSubstituteUnaryCopiesRequestsAndResponses, TestSubstituteConnectSurvivesHalfCloseUntilCanceled, TestClientBorrowsSubstituteTransport); explicit concurrency and registered constraints are refused. No hashing, schema migration/validation, encryption, authorization, durable storage or observer fidelity from the substitute. Protected-data scenarios remain unimplemented, not falsely substituted
ReadModelScenario<T>, ReadModels/ReadModelScenario.cs:48–52,110–120,402–459Partial: ReadModelScenario[M], inline projection precedence, Instance / InstanceFor / Instances, reducer initial state and dependency seedingExampleReadModelScenario, TestReadModelScenarioFoldsRegisteredConventionsAndSelectsInstances, TestReadModelScenarioPropagatesFoldFailureWithoutPartialResults, TestReadModelScenarioInlineProjectionOverridesReducerWithoutMutatingRegistry, TestReadModelScenarioTypedCallbacksShareFoldPlanAndInitialState, TestReadModelScenarioRefusesModelBoundProjectionWithoutKernel, TestKernelReadModelScenarioDiscoversProjectionAndRejectsAmbiguousInstance, TestKernelReadModelScenarioInlineProjectionOverridesReducer, TestKernelReadModelScenarioRefusesCustomKeyProjectionReplay. The positive inline override uses a supported source-key projection and produces inline instead of the original reducer’s event-derived name; the original registry remains unchanged. Constant/custom-key replay is explicitly refused with ErrUnsupported by the 19.29.4 safe admission profile, with no partial instance map or manufactured key. Unlike C#‘s custom-key scenario selection, this kernel replay profile currently supports only event-source keys. Reducers use the production fold plan locally with Substitute, like C#‘s in-process processor; explicit Kernel selection fails with ErrFidelityUnavailable (TestReadModelScenarioRefusesKernelReducerRatherThanSilentlyFoldingLocally). Projections use the real kernel’s bounded replay RPC. There is no Go projection evaluator. Inline declarations override reducers in a detached registry; production declaration conflicts still fail. Multiple instances reject single-instance access. Unlike C#‘s multi-source single reducer fold, Go folds per source. Supported source-key projection access requires a returned string ID; missing keys fail, never infer seed-order identity. Projection initial state remains unimplemented and explicitly refused. Opt-in strict subscription follows kernel key-resolver membership (next row), independently of replay admission. Projection fixtures refuse other registered Go observers before connecting, avoiding unrelated side effects; use EventScenario for live lifecycle. Replay does not prove sink/observer catch-up, delivery metadata or effect acceptance (TestProjectionScenarioFidelityRefusesUnusedDeliveryAndEffects)
WithStrictEventSubscription, ReadModels/ReadModelScenario.cs:247–268, ProjectionReadModelProcessor.cs:509–529,733; kernel Source/Kernel/Core/Projections/Engine/Projection.cs:168–169,218–238, ProjectionFactory.cs:1006–1131 at v19.29.4Partial: ReadModelOptions[M].StrictEventSubscription, ErrUnsubscribedEventSeeded. Membership is the kernel key-resolver set derived from the selected compiled wire. It includes root and child From/Join/RemovedWith, child-only RemovedWithJoin, nested From/RemovedWith (Join outside child subtrees only), derivative and root/child event-property types, recursive children, and keys ignored. Nested join removals, children and event-property types are excluded. Pure or mixed All admits every registered type. Root RemovedWithJoin is not a member, matching C#. Variants and protected models/subscribed events (any generation, including child-only members) are refused before connection. Projection initial state remains refused. Reads stay bounded by the replay admission profile: relationships and custom keys return ErrUnsupportedTestStrictMembershipMatchesKernelKeyResolverSet, TestStrictProjectionAdmitsRelationshipProfilesWithKernelMembership, TestStrictRelationshipScenarioRejectsBeforeReplayRefusal, TestStrictProjectionRefusesProtectedChildSubscription, TestStrictProjectionChecksProtectionAcrossSubscribedGenerations, TestStrictProjectionRefusesProtectedModel, TestKernelStrictMembershipMatchesProjectionObserverEventTypes (projection observer EventTypes, Source/Kernel/Core/Projections/ProjectionsManager.cs:446–471 at v19.29.4), plus TestStrictProjectionGivenRejectsBeforeAnySeedEffect, TestDefaultProjectionGivenStillAcceptsRegisteredMarker, TestStrictProjectionGivenPreservesEarlierSeedsAndSyntheticOrder, TestStrictProjectionMembershipUsesCompiledRootSubscriptions, TestStrictProjectionInlineSelectionDoesNotMutateOriginalRegistry, TestStrictProjectionRefusesUnsupportedProfilesBeforeConnection, TestCompiledVariantMetadataSurvivesIdenticalWireAndClientSnapshots, TestReadModelScenarioStrictSubscriptionDoesNotChangeReducerFiltering, and TestKernelReadModelStrictEventSubscription. Default behavior is unchanged; reducers ignore the option. Rejection happens in Given before codecs/providers/append/history, preserving earlier successful seeds without rollback. Go deliberately raises from Given before remote append, unlike C# lazy result-time processing; callers must check the error. The membership witness compares admitted IDs, projection observer EventTypes and independent golden sets; it does not claim relationship delivery, sink catch-up or replay success. The root source-key sibling witnesses persisted accepted ordering/marker absence and typed synchronous replay. #60 asynchronous job completion remains unknown. No single-encoding/provider parity claim is added
ReactorScenario<T>, Reactors/ReactorScenario.cs:212–275Partial: registered ReactorScenario[R], ID-selected callbacks, seeded read-model dependencies, real plan activation/invocation, monotonic synthetic deliveriesExampleReactorScenario, TestReactorScenarioUsesProductionInvokerSeedsAndMonotonicDeliveries, TestReactorScenarioStillRejectsUnclaimedSynchronousReturnTypes. Production discovery, constructors/scopes, middleware, argument materialization, identity/causation setup and invocation are shared. Handler failures and cleanup errors propagate. Given calls are batch scopes unless production PerEvent is selected. Unsubscribed registered events advance the synthetic sequence without activation/middleware (TestReactorScenarioSkipsUnsubscribedEventsWithoutActivatingOrRunningMiddleware). Delivery metadata and read-model storage are substituted; no server retry, quarantine, checkpoint, replay lifecycle or exactly-once claim
RecordingReactorSideEffectHandlers, Reactors/RecordingReactorSideEffectHandlers.cs:44–80Implemented for finite result recording: RecordingReactorSideEffectHandlers, Produced, ShouldHaveProduced[T], ShouldNotHaveProduced[T]TestReactorScenarioUsesProductionInvokerSeedsAndMonotonicDeliveries, TestRecorderBoundsCyclicCollectionsWithoutPartialRecordings. Collections and event/source/concurrency wrappers flatten to payloads without running registered effect executors. Production declared-return validation and runtime classification apply before scenario recording (TestReactorScenarioRejectsInvalidEffectsWithoutRecordingPartialResults); invalid wrappers and unclaimed payloads fail. Unlike C#‘s permissive recorder, Go scenarios preflight the entire effect before recording through an internal hook. Recording does not prove transport acceptance, serialization, constraint checks or command execution. Nested collections are bounded at depth 64; payload objects are borrowed
Scenario naming/discovery and fidelity diagnosticsGo-specific: Config.Naming, CSharpScenarioNaming, Client.Artifacts, Registry.WithProjection, Fidelity.Substitutions/RequireNaming test above, producer-selection tests, TestWithProjectionPreservesEveryRegistryFieldExceptReplacedProducer, TestWithProjectionPreservesComposedConstraints and kernel siblings. Default naming follows production Go; C# scenario camelCase is explicit and preserves leading acronyms. No container/global registry or extra module dependency. Unknown/substituted fidelity requirements fail before an assertion can claim them; kernel encryption, generation/schema validation and multi-node fidelity remain unclaimed; zero Fidelity fails closed. Missing kernel configuration skips only through testing helpers; configured connection failures fail
Supported typed scenario decoding / ReadModels/ReadModelScenario.cs, DotNET/ReadModels/ReadModels.cs:257–258 (baseline revision above)Implemented for registered model shapes: reducer initial snapshots/results and projection Instances/Instance results use the same frozen descriptor planTestReducerScenarioUsesFrozenPlanForInitialAndResult, TestProjectionScenarioUsesFrozenNamingPlan, TestScenarioKeyRequiresNormalizedDeclaredProperty, TestScenarioKeyDoesNotInferIndependentIDWithoutDeclaredKey; distinct Id/ID and all three naming policies. Keyed replay requires the normalized declared key, never an independent ID field; missing keys fail instead of manufacturing an instance map entry. Projection decode is isolated through the substitute transport with supplied replay documents, not a Go projection evaluator or evidence that the kernel accepts case-distinct ID schemas
Kernel projection replay supporting scenarios / DotNET/ReadModels/ReadModels.cs:261–295, Kernel/Grpc/ReadModels/ReadModels.cs:GetAllInstances (kernel path from repository root)Partial: readmodels.Service.ReplayProjection, Descriptor.KeyPropertyTestProjectionReplayIsBoundedAndNormalizesKeysWithoutPartialResults and projection sibling cases above. Counts from 1 through math.MaxInt32 force kernel replay rather than an eventually consistent sink read; zero returns an empty non-nil result without an RPC and larger counts fail rather than overflow the kernel’s signed MongoDB limit. Empty scenarios borrowing populated stores remain empty (kernel projection test above). Normal registration barriers and ID normalization apply. Reducer replay through this RPC and unlimited/materialized reads are explicitly unsupported by this method

Fixtures are serial and own their clients; New* accepts testing.TB and ties cleanup to it (including NewReactorScenarioForID), while Open* returns errors and requires Close. Given-event snapshots preserve production naming. Result reads re-run reducer folds or kernel projection replay, unlike C#‘s cached processing; keep folds deterministic. Real-kernel stores are unique by default and are not deleted on Close. No full-kernel restart or production encryption assertion is established by these fixtures.

Delivered event declarations, historical catalogs, operations, bounded folds and facade helpers are not future slices. The remaining porting work is:

  • Safety: #48: on 19.32.3 the webhook authorization regression asserts the authorization schema, read-back and history in the selected store for SDK and C#-source-equivalent requests (Chronicle#4567 fixed the 19.29.4 registration scope); actual .NET client-side Register requests are now captured separately, but no actual .NET live-kernel witness or other historical intermittent trigger is established. #18 sequence sentinels, predicates and checked pure arithmetic are implemented in the sequence-number row above, not future work.
  • Read and protection routes: #33 / #35 remaining unsupported window profiles, classified projection Watch blocked by Chronicle#4566, classified local-watch delivery-time erasure fencing, reducer snapshots and protected forwarding/erasure. Protected forwarding/erasure is unverified. Count-zero success is not protected-read evidence.
  • Model-bound and representation depth: #26 other complex context mappings and clear representations beyond direct compiled nullable slice/string-keyed map pointers; #27 derived-child lowering, previously blocked by Chronicle#4564 (fixed in 19.32.1); #64 enum/flags schema and configured serializer profiles, binary/custom representations, complex/concept map keys and GeoJSON. Closed unprotected families do not imply protected polymorphism or safe direct family-valued derivative properties.
  • Runtime ownership: Store eviction, lifecycle hooks and custom balancing from #62 are recorded above with their Go differences; #63 runtime registration of other artifact families and replacement profiles. Bounded runtime projection additions and coherent store publication are implemented. Private immutable startup preparation remains a prerequisite (TestPreparedOutputCompositionNeverRepeatsApplicationPreparation, TestFailedPreparationNeverRetainsPartialOutputs), not a separate authoring framework. Registration sends still do not prove observer attachment.
  • Outgoing conventions: #65 ordered enrichment, actor/correlation/root-causation providers and high-level identity rename. Explicit metadata is not provider-discovery parity.
  • Scenarios and declaration tooling: #38 initial state, richer strict-subscription profiles and lifecycle conformance; #23 generation and #39 declaration analysis. The module policy is delivered; generators/analyzers are not. Manual/runtime/generated equivalence and body-sensitive reducer versions still need executable witnesses.

Cross-client naming and two-generation evolution evidence, independent Arc.Go consumer adoption, whole-kernel restart and multi-node behavior remain distinct from the implemented SDK contracts. Keep upstream restrictions until the exact failing profile has a passing witness; no optional adapter experiment substitutes for this remaining parity work.