Skip to content

Fundamentals Go parity map

The shared scalars preserve canonical .NET wire forms. Typed scalar concepts provide explicit domain codecs and declaration discovery; these contracts do not establish whole-product parity.

Implemented: UUID, DateOnly, TimeOnly, TimeSpan, correlation context. Partial: typed concepts, conversion, serialization naming (explicit non-pluralizing policies), dependency injection (exact typed bindings, lifetimes, scopes, an optional container and convention planning). Generation and rendering remain product-owned; no full generator parity is claimed. Go-specific: concept declaration discovery, dependency-injection conformance levels, rune-based string casing. Status is per surface: the ledgers below also record implemented DI disposal and scope-factory behavior, deliberate exclusions and the remaining Not implemented areas. See Updating this map for the status vocabulary.

Runtime APIs described here are available beginning with v0.2.0, except the explicitly opt-in ParseDotNetGUID addition, available beginning with v0.3.0 and targeting .NET 10.0.12. Enum and complex-key JSON corpora are source-distributed evidence included with v0.3.0, not Go enum or complex-key implementations, runtime or schema support. Start with the scalar reference, correlation guide or constructor-planning workflow for usage; retain this map as the source and compatibility ledger.

C# Cratis Fundamentals is the authority, pinned at d2accc4a79b6bcf2708213c97093ab5ba6c06381. Authority paths are relative to that repository at that revision, with three bases: Surfaces uses the repository root; the .NET ledger uses Source/DotNET/Fundamentals; the JS ledger uses Source/JavaScript. Guid and TimeSpan JSON strings also follow .NET System.Text.Json’s built-in converters.

The scalar implementations and existing tests are copied from Cratis/Arc.Go at 4511966526a3a646538175c20e9de5282907191e, without behavior changes. The 11 original golden fixtures are copied unchanged; fixture provenance records their authority.

Status Implemented below covers the listed canonical scalar contract, not every parsing form or operation on the corresponding .NET type.

SurfaceC# source or contractGo surfaceStatusExecutable parity evidenceDeviations
Typed scalar conceptsSource/DotNET/Fundamentals/Concepts/ConceptAs.cs, ConceptExtensions.cs, ConceptMap.cs, ConceptFactory.cs; Source/DotNET/Fundamentals/Json/ConceptAsJsonConverter.cs; Source/DotNET/Fundamentals.Specs/Json/for_ConceptAsJsonConverter including when_converting_guid_concept_to_json.cs, when_converting_date_only_concept_from_json.cs, when_converting_time_only_concept_to_json.csconcepts.Concept[T], explicit domain codecs, CheckJSONPartialconcepts/concept_codec_test.go, concepts/check_json_test.go, concepts/example_test.go; all 11 concepts/testdata/scalars.json fixtures exercised through conceptsNamed values and explicit codecs replace inheritance and the shared converter; exact scalar allowlist, integer literal policy and canonical-output validation. See concept deviations below.
Concept declaration discoveryGo adaptation of ConceptExtensions.IsConcept, GetConceptValueType and ConceptMap under Source/DotNET/Fundamentals/Conceptsconcepts.Underlying, conceptstypes.Underlying, Representation, ScalarKind, TypeError, ErrInvalidConceptGo-specificconcepts/internal/corpus shared declarations and outcomes; concepts/underlying_test.go and concepts/conceptstypes/underlying_test.go corpus parity, exact-type and concurrent tests; concepts/check_json_test.goStandard-library go/types counterpart with corpus parity. Metadata only, no application execution or cache; nesting rejected; anonymous fields rejected only in concept candidates by both recognizers. Proxy-generation agreement remains Arc.Go’s to establish.
Shared UUIDSystem.Guid, System.Text.Json; Source/DotNET/Fundamentals.Specs/Json/for_ConceptAsJsonConverter/GuidConcept.cs and when_converting_guid_concept_{to,from}_json.cs in the same directoryconcepts.UUID [16]byte; NewUUID, ParseUUID, String, IsZero, text/JSON codecsImplementedconcepts/golden_test.go, concepts/scalars_test.go, concepts/boundaries_test.go, concepts/codecs_test.go, concepts/example_test.go; testdata/scalars.jsonDefault parser and codecs accept strict dashed D input only; N/B/P/X and whitespace require the separate opt-in conversion below. Bytes are RFC/network order, not Guid.ToByteArray mixed-endian order. Callers convert transport bytes explicitly outside this module.
Explicit .NET GUID compatibility conversionSystem.Guid.Parse(string) at .NET 10.0.12; runtime Guid.cs and Number.Parsing.cs, pin 4271d88e0aebf3d04f188f1334c2220d80555ef6 (VMR 95017c711e6afc1085133d440e42b4bd78155701); Fundamentals Types/TypeConversion.cs and Json/JsonValueExtensions.cs at the authority revisionconcepts.ParseDotNetGUID (beginning with v0.3.0)Implementedconcepts/uuid_dotnet_test.go: 923 observed UTF-8 strings (641 accepted, 282 rejected), canonical D and RFC bytes, strict decoder isolation, fuzz and example; unchanged concepts/testdata/guid_parse.dotnet.json; optional ContractTests/GuidParsing reproducerExplicit compatibility conversion, not canonical-input validation, correlation admission or built-in Guid JSON parsing. Exact N/D/B/P/X, pinned whitespace, legacy X empty-prefix zeros/uint16 truncation and conditional D NUL behavior. Invalid UTF-8 rejected; null/unpaired UTF-16 diagnostics and raw JSON controls remain separate. No default parsing, codec, binding or consumer policy change; callers limit untrusted input. Provenance/schema.
UUID database/sql interoperabilitySystem.Guid; C# relies on database providers’ Guid mappingconcepts.UUID.Value, (*concepts.UUID).Scan; optional forwarding on UUID-backed conceptsGo-specificconcepts/uuid_sql_test.go, concepts/example_test.goStandard-library SQL interfaces: canonical dashed string output; strict text or 16 RFC/network-order bytes on input; failure-atomic rejection of null, malformed input and unsupported types. Nullable columns use sql.Null[T] or pointers. SQL Server uniqueidentifier raw bytes use .NET mixed-endian order: read as text or convert explicitly; no silent reordering.
DateOnlySource/DotNET/Fundamentals/Json/DateOnlyJsonConverter.cs and Source/DotNET/Fundamentals.Specs/Json/for_DateOnlyJsonConverterconcepts.DateOnly; NewDateOnly, ParseDateOnly, Date, String, text/JSON codecsImplementedconcepts/golden_test.go, concepts/scalars_test.go, concepts/boundaries_test.go, concepts/codecs_test.go, concepts/temporal_fuzz_test.go, concepts/example_test.go; testdata/scalars.jsonInvariant yyyy-MM-dd input only; C# also reads timestamps and culture-dependent date strings. Normalize to the canonical date before passing it to Go.
TimeOnlySource/DotNET/Fundamentals/Json/TimeOnlyJsonConverter.cs and Source/DotNET/Fundamentals.Specs/Json/for_TimeOnlyJsonConverterconcepts.TimeOnly; NewTimeOnly, ParseTimeOnly, Ticks, String, text/JSON codecsImplementedconcepts/golden_test.go, concepts/scalars_test.go, concepts/boundaries_test.go, concepts/codecs_test.go, concepts/temporal_fuzz_test.go, concepts/example_test.go; testdata/scalars.jsonHH:mm:ss with optional 1–7 fraction digits only; no culture-dependent TimeOnly.Parse forms. Canonical output always has seven fraction digits. Use 100 ns ticks, not nanoseconds.
TimeSpanSystem.TimeSpan constant (c) form and System.Text.Json’s built-in TimeSpan converter (primary); Source/DotNET/Fundamentals/Json/JsonValueExtensions.cs and Source/DotNET/Fundamentals.Specs/Json/for_JsonValueExtensions/when_converting_timespan_to_json_value_and_back.cs (supporting evidence only)concepts.TimeSpan int64; ParseTimeSpan, Ticks, String, text/JSON codecsImplementedconcepts/golden_test.go, concepts/scalars_test.go, concepts/boundaries_test.go, concepts/codecs_test.go, concepts/example_test.go; testdata/scalars.jsonInvariant [-][d.]HH:mm:ss[.fffffff] input only, not every TimeSpan.Parse form. Full signed int64 tick range; callers must not narrow it to Go’s nanosecond-based time.Duration.
Correlation ID and accessorSource/DotNET/Fundamentals/Execution/CorrelationId.cs, CorrelationIdAccessor.cs, ICorrelationIdAccessor.cs and ICorrelationIdModifier.cs in the same directorycorrelation.ID = concepts.UUID; WithID, FromContextImplementedcorrelation/context_test.go, correlation/example_test.goExplicit context.Context propagation replaces AsyncLocal ambient storage, and derived contexts replace the modifier interface. Alias, not a distinct concept type: any concepts.UUID is assignable; no NotSet/New members. The zero UUID replaces NotSet; generate with concepts.NewUUID. Parsing, headers and ingress policy stay in Arc.Go and Chronicle.Go.

Evidence paths are repository-relative; each testdata/scalars.json entry refers to concepts/testdata/scalars.json. JavaScript scalar types in Source/JavaScript provide consumer references, not authority to change C# behavior.

Authority: Source/DotNET/Fundamentals/DependencyInjection (principally ServiceCollectionExtensions.cs) and Types/InstancesOf.cs, Types/ImplementationsOf.cs at the pinned revision, plus Microsoft dependency injection semantics as Cratis uses them. The Go code moved from Arc.Go services at 304e97466bca594b51a3d7bbc723f4c477a6a99c. Evidence: dependencyinjection/*_test.go, dependencyinjection/container/*_test.go, and both conformance levels in dependencyinjection/ditest, which the default container passes (container/conformance_test.go). Guide: Dependency injection.

C# surfaceGo surfaceStatusNotes and deviations
Service descriptors, provider, scopes and the three lifetimesBinding, Lifetime, Provider, Scope, ScopeFactory, container.RegistryPartialExact typed bindings and explicit scopes. No root resolution, open generics, IEnumerable<T> synthesis or last-registration-wins.
Disposal, IAsyncDisposable preferred over IDisposable, supplied singleton instancesOwned bindings; Close(context.Context) error preferred over io.Closer; BindValueImplementedReverse-order disposal, repeated Close returns the retained result, ErrClosed after close, supplied values are never disposed.
IServiceProviderIsServiceOptional Catalog capability on ScopeFactory and RegistrarPartialExact keys only. Without the capability, consumers attempt resolution, as C# DefaultServiceProvider does.
IServiceScopeFactorycontainer.Registry.BindScopeFactory facadeImplementedThe facade implements ScopeFactory, Catalog and ScopeOwner, not Close or resolution. Open scopes from methods, never inside a factory callback.
Injectable IServiceProviderNoneNot implementedNo injectable current provider or resolver, by design.
ValidateScopes / ValidateOnBuildBuild validationGo-specificAlways on: missing edges, cycles and transitive captive lifetimes fail Build.
IFoo → Foo conventionbindingtypes.Analyze, opt-in MatchIFoo, explicit InterfacesPartialSame-package pairing with structural method sets across the supplied universe; aliases and pointer/value shapes count as one family. Ignored and constructorless competitors still count. Ambiguity fails unless explicitly mapped; bindingtypes/corpus_test.go and internal/bindingcorpus/cases.json cover the rules. Products own rendering (#14).
[Singleton]/[Scoped], transient fallback; [IgnoreConvention]Type doc directives normalized by bindingtypes.ReadDirectives, explicit TypePolicyPartialDuplicate/conflicting policies fail rather than singleton taking precedence. Ignore excludes DI only; export data requires supplied policies. Directive and export-data tests are in bindingtypes/corpus_test.go and validation_test.go. No TransientAttribute exists at the pinned revision. Products own rendering.
Self-bindings and generated convention metadataPure constructor plans in dependencyinjection/bindingtypesPartialExact NewX or explicit constructors, no arbitrary activation or zero-value fallback; scalar dependencies need explicit configuration. Closed generic wrappers are supported, not open activation. bindingtypes/corpus_test.go covers signatures/accessibility; generic_disposal_go127_test.go checks runtime-visible disposal promotion and rejects disposable value results with more than four dependencies (BT006), with a compiled reflection witness; render_test.go exercises hand-authored equivalent wiring. No ISelfBindable exists at the pin; product emitters remain product-owned.
Existing registrations win; convention registration is idempotentRejectDuplicates default; explicit Existing plus KeepExisting → RetainExistingPartialOnly listed keys are skipped (BT013), using attested lifetimes; generated ambiguity still fails. Unchanged registration functions remain strict and propagate duplicate errors, not silently idempotent. Refresh the manifest and replan; corpus override tests and bindingtypes/render_test.go cover this deliberate difference (#14).
IInstancesOf<T>, IImplementationsOf<T>, keyed services, diagnostics registrationNoneNot implementedKey identifies a type, not a named service. A future collection API must select a scope and report errors explicitly.
Assembly scanning, ActivatorUtilities, artifact-method invocationExplicit registration; consumer-owned activationOut of scopeExplicit or generated registration replaces scanning. Chronicle.Go may use validated registration-time reflection for its artifacts.
Separate interface and self descriptorsBindBorrowed interface forwarding over an owned concrete bindingGo-specificIntentional difference accepted on #9: forwarding shares the concrete instance and closes it once; C# may create separate instances. bindingtypes.Analyze plans borrowed forwarders with the effective concrete lifetime; bindingtypes/render_test.go verifies caching and disposal.
Provider and resolver access rulesFrozen registry, expiring restricted factory resolvers, provider drains child scopesGo-specificFactories receive a resolver limited to declared edges that expires when the callback returns.
Request isolationcontainer.WithContextGuard; singleton factories see contexts with all values hiddenGo-specificGuards run on every scoped resolution, including through factory resolvers.
Failed-value disposalIndependent cooperative 30-second cleanup budgetGo-specificNot configurable yet. Cleanup-only cancellation remains inspectable without triggering a waiter retry, including through dependencies; genuine construction cancellation still permits retry. dependencyinjection/container/creator_cancellation_test.go covers shared failure, later explicit resolution, cancellation siblings, preserved error chains and exactly-once failed-result cleanup.
Client-lifetime artifactsSingleton binding resolved from a short-lived startup scopeGo-specificThe provider owns the instance until Provider.Close; the application controls shutdown order.
Context cancellationdi.Resolve[T] checks ctx.Err() before calling the resolverGo-specificThrough di.Resolve[T], a canceled context returns the bare context error first. Calling a container scope’s or factory resolver’s Resolve directly reports ErrClosed or ErrResolverExpired before the context error.

All four scalars encode JSON strings with value receivers, including map values and non-addressable values. Text codecs support JSON map keys. Pointer receivers decode failure-atomically and reject JSON null and non-string input for scalar values. Pointer fields retain standard encoding/json nullability.

Zero values are Guid.Empty, 0001-01-01, midnight and zero duration. DateOnly spans years 0001–9999; TimeOnly spans one day at 100 ns precision. TimeSpan preserves both signed int64 tick extremes. UUID accepts uppercase hex and emits lowercase text without a BCL byte-order conversion or an external UUID dependency.

#21 ports Strings/StringExtensions.cs:16-99 and the property/model operations in Serialization/INamingPolicy.cs, DefaultNamingPolicy.cs, CamelCaseNamingPolicy.cs and NamespacedNamingPolicy.cs at the authority revision above. Go surface: naming.PascalCase, CamelCase, Policy, Default, CamelCasePolicy, Namespaced and NewNamespaced. Evidence: naming/golden_test.go, policy_test.go, example_test.go, the FuzzCase target, and 56 case/17 policy expectations in naming/testdata/*.json. The fixture provenance distinguishes copied spec expectations from source-derived cases and deliberate Go adaptations.

Casing uses BMP-aware helpers to match C#‘s UTF-16 char operations: supplementary letters are neither classified as uppercase nor case-converted. Explicit invariant exceptions preserve İ when lowercasing and ı when uppercasing, as in .NET 10 ChangeCaseInvariant. Long s (ſ) is not an explicit exception there and uppercases to S. Neither expands ß to SS or normalizes combining marks. Remaining casing differences are Go-specific: Unicode tables can differ by Go toolchain and .NET globalization runtime. Go has no null string or unpaired UTF-16 characters. Pascal reconstructs runes, replacing invalid UTF-8 bytes with U+FFFD; Camel preserves original bytes on early returns and replaces invalid bytes throughout its converting path. Separator configuration uses a Go rune, allowing supplementary characters; invalid runes become U+FFFD instead of preserving a C# surrogate char. See Naming for examples.

Policies are Partial: model inputs are explicit namespace/name strings, with pluralization disabled, not CLR types. Humanizer, ReadModelNameAttribute discovery, serializer-specific JsonPropertyNamingPolicy objects and NamingPolicyCollectionExtensions registration are not ported. If an explicit storage-name override exists, consumers use it unchanged without invoking the policy. Otherwise, they pluralize the inferred name if required before calling the policy. No shared default, serializer, field plan or tag precedence is introduced. Namespace segments always camel-case; the separator before the model remains a literal - even without a namespace.

Read-only consumer comparison for this change (not adoption evidence):

  • Arc.Go origin/develop at d7afbc20396e5386f04e93ebf252790e4f5999a1, serialization/fields.go:16-23: the same acronym/non-uppercase guards, then lowercases only the first rune. This is equivalent to the reachable C# loop for matching classification/casing tables, but shares Go’s supplementary-rune and invariant-Turkish differences; it does not port the full loop.
  • Chronicle.Go origin/develop at e2165d05a135ddc2f57190514be8f61797fddde6, serialization/plan.go:57-75: now defaults to preserved names, not urlValue. serialization/naming.go:37-60 opts into acronym-friendly camel casing and faithfully copies the loop, but restricts uppercase classification to BMP runes to approximate C# char behavior. Its unicode.ToLower still differs for Turkish İ, and converting malformed UTF-8 reconstructs replacement runes. naming.go:63-73 retains the legacy initial-uppercase-run algorithm: URLValue → urlValue, ID → id, unlike C# Fundamentals. The issue’s older default description no longer matches this consumer revision. Read-model root ID → Id handling (plan.go:62-66) remains product-owned, not this API.

Consumers must verify adoption and existing persisted names in their own tests; these inspections establish neither a migration nor a consumer release pin.

Go uses named values and explicit codecs rather than inheritance, implicit conversions, or reflection-based construction. ConceptValue on real values replaces typed value extraction; reflective untyped extraction is deferred. Explicit constructors and pointer decoders replace ConceptFactory; there is no universal wrapper or type-converter registration. Native Go comparison and conversion apply where supported, without automatic C# operator emulation.

Recognition accepts only the documented scalar set, preserves exact numeric widths, rejects nested representations and anonymous fields in concept-bearing structs, and reports pointers without assigning nullability. C# inheritance traversal is not a Go concept-valued return chain: author the final scalar directly. Value-receiver decoders are rejected. Defined unmarked DateOnly/TimeOnly replacements without either value encoder fail explicitly; codec-only replacements are not concepts. UUID and TimeSpan-derived storage alone cannot establish concept identity, so callers must add the marker and forwarding codecs.

Discovery validates declarations without executing application code. Arbitrary codec-output consistency requires CheckJSON on actual encoded bytes plus consumer round-trip and domain tests. Integer JSON fractions and exponents are rejected rather than converted through floating point; float overflow is rejected at the declared width. Shared scalar output must be canonical. Keep product-specific range and precision checks in consumers, and emit the validated bytes without re-encoding. Shared scalar behavior and codecs are unchanged.

Decimal, enum-specific conversion, DateTime/DateTimeOffset representations, reflective factories, generalized value extraction and a shared concept serializer are not implemented. Standard Go pointer null handling replaces converter-specific null behavior; CheckJSON validates non-null scalars only. The reflection corpus is not evidence of consumer schema or generated-proxy agreement.

Use this ledger to decide what to share, what to keep in a product, and what still needs implementation. It covers every capability directory and root helper under Source/DotNET/Fundamentals, the supporting production generators, and the export groups in Source/JavaScript/index.ts at the authority revision. Source inspection establishes a contract, not executable Go parity.

The dependency baseline comes from inventory issue #10. The accepted DI ownership decision on #9 supersedes the earlier suggestion to leave Arc’s container in Arc.Go. DI is Partial in Fundamentals.Go: contracts, the default container, conformance suites and convention planning are available (#14). Generation and rendering remain product-owned; this does not establish full generator parity.

Consumer baselineRevisionInspected scope
Arc7c1e78075b737df64f69fddfaae83374f75e3612Source/DotNET/Arc.Core, Chronicle, MongoDB, Tools/ProxyGenerator
Chronicle2e31b0dfba489159b3db323238f16d0f277056b4Source/Clients/DotNET, Source/Clients/Connections, Source/Infrastructure, Source/Kernel
Arc.Go comparison3f88bf71c8d08df42cee6926661d252782c96e4aShared-value extraction and product-owned serialization/context boundaries
Chronicle.Go comparison738f7dfa3677660dc178617f52a3dd5d64c4f6c6Shared-value adoption and product-owned serialization/schema/wire boundaries

These are source-search counts, reproduced from #10, not a new semantic analysis or a recount. They count distinct non-specification .cs files with textual references, once per area. The search excludes bin, obj, Specs and Tests, strips comments, and matches Cratis.<area> imports or qualified references, excluding the products’ own namespaces. Generator type-name strings count. Global-import compensation also matches public type, attribute and extension identifiers: Concepts in Arc.Core; Concepts, DependencyInjection and Execution in Chronicle DotNET; Concepts and Execution in Kernel. Chronicle’s relative Tasks.TaskFactory reference counts too. Linked Kernel concepts are not counted again under DotNET.

Arc has 707 inspected files (494 Core, 77 Chronicle integration, 77 MongoDB, 59 ProxyGenerator); Chronicle DotNET has 763 and Kernel 2,376. Connections and Infrastructure are client dependencies, shown separately. Kernel-only usage is not a Go client release requirement. In the following tables, A means Arc and C means Chronicle DotNET; the dependency/server counts remain here.

AreaACConnectionsInfrastructureKernel
Concepts277116127
Json120113
Serialization1148001
Strings90038
Types29100225
Reflection97056
DependencyInjection41160145
Execution29354087
Monads4150045
Collections01025
Guids00000
Geospatial41014
Conversion10000
Timers00000
Tasks31301
Metrics30008
Traces14120012
ReadModels00000
Reactive000027
Root ExceptionExtensions.GetAllMessages04008
Root TimedLogging00000

Import-only searches undercount globally imported concepts: an import-only search would count 9 Arc / 1 Chronicle files for Concepts and 1 Chronicle file for Execution. Conversely, importing an area does not prove every helper is called. OneOf and System.Reactive are external dependencies, not additional Fundamentals areas. UUID/calendar/duration values are BCL types; Cratis.Guids contains XOR, not those scalar definitions.

Pinned call-site samples confirm the important direct/indirect distinctions:

  • Arc Source/DotNET/Arc.Core/JsonSerializerOptionsConfiguration.cs and Chronicle Source/Clients/DotNET/ChronicleClient.cs install enum, complex-key, concept and geometry converters. Their serializer options are separate.
  • Arc Source/DotNET/MongoDB/DatabaseExtensions.cs and Chronicle Source/Clients/DotNET/ReadModels/ReadModels.cs and Reducers/Reducers.cs call GetReadModelName. Thus ReadModels’ zero direct count does not remove its indirect storage-name contract. ChronicleClient defaults to DefaultNamingPolicy, not the Arc JSON profile.
  • Chronicle Source/Clients/DotNET/Events/Constraints/Constraints.cs calls ForEach over constraint providers. This is not List<T>.ForEach.
  • ChronicleClient.cs:159 constructs new Tasks.TaskFactory(); Source/Clients/Connections/ChronicleConnection.cs, ConnectionWatchdog.cs and ServiceCollectionExtensions.cs consume it. The #10 counts include this.

Consumer counts on subrows are area totals, not counts for that individual converter. Status uses the implementation vocabulary in Updating this map; disposition records ownership and planning separately. Allowed disposition values are Ported, Planned [#n], Go-idiom replacement, Deferred, Out of scope / Not applicable, and Proposed. “Go-idiom replacement” or “Out of scope” does not claim an implemented shared package. “Deferred” remains Not implemented. Tracking issues for proposed new work are not an approved API or a v0.1.0 requirement.

Area and C# authorityConsumer evidenceStatusDisposition and trackingMigration boundary
Concepts: Concepts/ConceptAs.cs, ConceptExtensions.cs, ConceptMap.cs, ConceptFactory.cs, TypesExtensions.cs, ConceptAsTypeConverter.cs; Json/ConceptAsJsonConverterFactory.csA27/C71; domain values, binding, schema/proxy recognition; converter registration is distinct from JSONPartialPorted scalar codecs and Go-specific declaration recognition, #2/#4; compile-time declaration recognition delivered in concepts/conceptstypes #15, standard-library tooling surface #16; product generators and JavaScript parity remain separateFundamentals owns concepts; Arc owns binding/validation/proxies, Chronicle owns event-schema admission. No universal wrapper, reflective factory or process-global TypeConverter registry. Evidence and deviations are in Surfaces above.
BCL Guid, DateOnly, TimeOnly, TimeSpan; Json/DateOnlyJsonConverter.cs, TimeOnlyJsonConverter.cs, Json/ConceptAsJsonConverter.cs (Guid/DateOnly/TimeOnly/TimeSpan branches only), Json/ConceptAsJsonConverterFactory.csBoth via JSON and concepts; Arc rich JS proxy scalars; not the Guids area countImplementedPorted canonical wire subset, #2Reuse shared codecs; retain consumer parser compatibility adapters and Chronicle BCL byte conversion. Do not narrow TimeSpan to time.Duration. See executable evidence above.
Conversion: Conversion/TypeConverters.cs, DateOnlyTypeConverter.cs, TimeOnlyTypeConverter.cs; Concepts/StringExtensions.cs, Types/TypeConversion.csConversion A1/C0; Arc startup registration; general conversion reached indirectly by both concept factoriesPartialShared typed text codecs #2/#4; Go-idiom replacement for registration; explicit .NET GUID conversion beginning with v0.3.0 #28; other permissive conversions deferred → #5Shared parsers return errors, not legacy invalid-input sentinels. HTTP empty/absent/query validation remains Arc-owned; no general object-conversion package.
Json options and DOM: Json/Globals.cs, JsonElementExtensions.cs, JsonObjectExtensions.cs, JsonValueExtensions.csJson A1/C2; both configure shared converter families, not one universal Globals profileNot implementedOut of scope: general serializers, global options and heuristic DOM conversion; #5 boundaryUse encoding/json/json.RawMessage with product-owned field plans. Keep null/presence, unknown fields and numeric/schema limits local; do not globally guess dates or delete null elements.
Json concept collections: Json/EnumerableConceptAsJsonConverterFactory.cs, EnumerableConceptAsJsonConverter.csJson A1/C2; installed by both; Arc minimal-API adapter has different precedenceNot implementedGo-idiom replacement: slices/arrays invoking element codecs; shared concept scope #4, legacy extensions deferred → #5No shared collection interceptor. Each product tests null elements, malformed shapes and custom-codec precedence. The scalar corpus alone proves none of these collection policies.
Json bare enums and enum concepts: Json/EnumConverter.cs, EnumConverterFactory.cs, ConceptAsJsonConverter.cs at the authority pinJson A1/C2; Arc proxy/API contracts and Chronicle event values. Separate reviewed Chronicle.Go package profile at 747c1eb3a015a583b4fd2ffa51b6c6ab3a185087: Chronicle 19.29.4 / Fundamentals 7.19.6 / .NET STJ 10.0.12Not implemented (Go codecs)Historical 224 serializer-level observations + 12 direct diagnostics remain unchanged: testdata/enum-contract/fixtures.dotnet.json, enum_contract_test.go, optional ContractTests/EnumJson. Packaged profile and provenance: per naming policy, 586 reads, 130 independent writes, 208 Expando direction-pairs, 54 schemas; 73 mapped bare reads and 28 writes agree with the historical subset after normalization, not a whole-236 consumer pass. #17 delivered this evidence; consumer adoption is tracked in Chronicle.Go#64 and Arc.Go#32Historical and packaged bare Bits numeric 5/7 reject; newer e8ac1ec source accepts. Strings, independent writes and schema conversion stay separate. Scalar fallback, nullable omission and array nulls are not general admission. Product codecs, declarations, schemas, backend/frontend and naming profiles stay local; no enum API, Underlying change, Go parity, kernel/Mongo/BSON or general package-equivalence claim.
Json complex keys: Json/ComplexKeyDictionaryJsonConverterFactory.cs; distinct utility DictionaryJsonConverter.cs at the authority pinJson A1/C2; both serializer profiles; Arc OpenAPI/proxy ValueMap and Chronicle schema integrationNot implemented (Go implementation)Contract evidence: 151 C# + 186 typed JS + 16 C# cross-reads, 132 stimuli, 11 admission types; testdata/complex-key-contract, complex_key_contract_test.go, optional ContractTests/ComplexKeyJson. Dictionary-key compatibility; #18 delivered this contract evidence in v0.3.0. Outstanding consumer-profile verification remains product-ownedEmbedded JSON property names differ from ordinary TextMarshaler keys. Original/fixed lookups, read/entry/write outcomes and typed-field asymmetries are separate; bare Guid JS corruption is tracked in Fundamentals #1151. No shared codec/registry/API or Underlying change; product map traversal, field plans, schemas and TS generation remain local. Source extraction is not package/Globals/consumer/kernel equivalence.
Remaining Json adapters: Json/TypeJsonConverter.cs, UriJsonConverter.cs, TypeWithObjectPropertiesJsonConverter.cs, TypeWithObjectPropertiesJsonConverterFactory.cs, EnumerableModelWithIdToConceptOrPrimitiveEnumerableConverterFactory.cs, EnumerableModelWithIdToConceptOrPrimitiveEnumerableConverter.csJson A1/C2; Type/URI/legacy _id converters are registered; no direct sidecar utility use establishedNot implementedOut of scope: CLR type activation, general object mapping and legacy model-to-ID projections; #5 boundaryProduct-owned allowlisted codecs only if a wire contract needs them. URI remains scalar text. Never copy the legacy empty Write as a successful codec.
Strings: Strings/StringExtensions.cs; Serialization/AcronymFriendlyJsonCamelCaseNamingPolicy.csStrings A9/C0; direct Arc names; indirect Chronicle policy use, plus InfrastructureGo-specificPorted casing rules → #21; naming.PascalCase, CamelCasePreserve URLValue/IPAddress/ID wholesale. BMP-aware UTF-16 classification and invariant exceptions match C#; remaining Unicode-table, null and malformed-text differences are recorded in Naming evidence above; golden fixtures and fuzzing exercise the contract. Product defaults and field plans remain local.
Serialization naming: Serialization/INamingPolicy.cs, NamingPolicy.cs, DefaultNamingPolicy.cs, CamelCaseNamingPolicy.cs, NamespacedNamingPolicy.cs, NamingPolicyCollectionExtensions.csSerialization A11/C48; Arc MongoDB; Chronicle schemas, read models, reducers and projectionsPartialPorted pure non-pluralizing policies → #21; naming.Policy, Default, CamelCasePolicy, Namespaced, NewNamespacednaming/policy_test.go and testdata/policy.json cover explicit string names and literal final -. CLR metadata, Humanizer, serializer objects and DI registration are omitted; rune separator differences are documented above. Explicit storage overrides, paths, tags and defaults stay product-owned.
ReadModels: ReadModels/ReadModelNameAttribute.cs, Serialization/NamingPolicy.csA0/C0 direct; both indirectly through GetReadModelName as sampled aboveNot implementedGo-idiom replacement: explicit storage-name registration; optional string-based naming policies #21An explicit name bypasses pluralization, prefixing and casing. It is not Arc query identity or Chronicle event-type identity; no attribute package moves here.
Serialization polymorphism: Serialization/DerivedTypeAttribute.cs, DerivedTypeId.cs, DerivedTypes.cs, IDerivedTypes.cs, DerivedTypeJsonConverter.cs, DerivedTypeJsonConverterFactory.csSerialization A11/C48; Arc JSON/proxies/MongoDB, Chronicle JSON/schema and projected childrenNot implementedDeferred → existing registry proposal #5Candidate shared immutable ID/target metadata only. Product serializers and generated metadata remain local. C# IDs are globally unique, including across different targets; missing/unknown discriminators differ. No assembly scanning or shared general serializer.
Geospatial: Geospatial/Point.cs, LineString.cs, LinearRing.cs, Polygon.cs; Json/PointJsonConverter.cs, LineStringJsonConverter.cs, PolygonJsonConverter.csA4/C1; Arc MongoDB/proxy maps, Chronicle schema generation; JSON indirectly in bothNot implementedDeferred → existing geometry/GeoJSON proposal #5Potential shared values/codecs retain longitude-first coordinates, rings and holes. Slice ownership and malformed input need fixtures. Database adapters, OpenAPI and event schemas stay product-owned; no geospatial engine.

The concrete proposals on #5 record the deferred derived-type metadata and geometry candidates. #5 is closed without a planned implementation: a real consumer need opens a focused issue that starts from those proposals. Naming is implemented separately under #21. The proposals’ older blanket exclusion of shared DI is superseded by #9–#14. Small concept conversion/collection edge cases belong with #4’s existing boundary or the recorded #5 deferrals, not duplicate issues.

Area and C# authorityConsumer evidenceStatusDisposition and trackingMigration boundary
Types discovery: Types/Types.cs, ContractToImplementorsMap.cs, ProjectReferencedAssemblies.cs, PackageReferencedAssemblies.cs, CompositeAssemblyProvider.cs, GeneratedTypeDiscoveryRegistry.cs, TypesServiceCollectionExtensions.cs, TypeDiscoveryDiagnostics.csTypes A29/C10; application features, extension providers and schema universeNot implementedGo-idiom replacement: explicit catalogs/contributions; shared registration and constructor planning available #11/#14 under #9; generation remains product-ownedNo assembly loading, global Types.Instance or CLR diagnostics port. Arc/Chronicle own feature registration and completeness checks; composition must not silently omit required contributors.
Types activation: Types/InstancesOf.cs, ImplementationsOf.cs, KnownInstancesOf.cs and corresponding interfacesTypes A29/C10; discovered instances in both; no direct IImplementationsOf client use establishedNot implementedGo-idiom replacement: explicit factory/instance lists; DI work #11–#14; no promise of container-wide enumerationFactories resolve using the active operation scope; discovery is not activation. Exact instance lists stay caller-owned; do not cache request-scoped extensions globally.
Reflection: Reflection/TypeExtensions.cs, DictionaryExtensions.cs, PropertyExtensions.cs, ParameterExtensions.cs, MethodExtensions.cs, ExpressionExtensions.cs, TypeConstructorExtensions.cs, TypeInfo.cs, MethodCalls.csA9/C7; classification, schema/nullability, expression paths and invocation metadataNot implementedOut of scope; concept declaration inspection is the Go-specific row in SurfacesUse reflect, explicit tags, typed factories and generated field identifiers without conflating scalar, collection and stream kinds. Product field plans, presence and handler/schema agreement remain local.
DependencyInjection contracts/lifetimes: DependencyInjection/SingletonAttribute.cs, ScopedAttribute.cs, IgnoreConventionAttribute.cs, ConventionServiceBinding.cs, ConventionSelfBinding.cs; Microsoft DI as used by FundamentalsA41/C16; both products’ providers and operation-scoped activationPartialPorted: contracts #11, default container moved from Arc.Go #12, conformance suites #13; design accepted on #9; see Dependency injection surfacesFundamentals owns dependencyinjection, dependencyinjection/container and dependencyinjection/ditest. Plain constructors remain first-class; no product imports the container. Arc principal/tenant/staging and Chronicle delivery activation remain product-owned. Type-level lifetime directives are normalized by bindingtypes.ReadDirectives; product renderers remain responsible for applying plans (#14).
DependencyInjection conventions: DependencyInjection/ServiceCollectionExtensions.cs, ICanProvideConventionsForDependencyInjection.cs; Source/DotNET/Fundamentals.TypeDiscovery.Generator/TypeDiscoveryCollector.cs, GeneratedSourceBuilder.csDI A41/C16; Arc calls convention registration; Chronicle also explicitly registers/activates artifactsPartialPure standard-library constructor planner dependencyinjection/bindingtypes in the root module (#14); shared source/JSON corpus, directive/export-data tests and hand-authored render-equivalence tests; runtime ownership #11–#13Explicit package universes replace assembly scanning. Structural ambiguity includes ignored and constructorless families; selected constructors replace arbitrary activation. Strict duplicates, explicit existing-key decisions and borrowed forwarding intentionally differ from C#. No nested tools module or shared emitter/CLI: Arc.Go and Chronicle.Go own rendering and operation adapters.
Execution: Execution/CorrelationId.cs, CorrelationIdAccessor.cs, ICorrelationIdAccessor.cs, ICorrelationIdModifier.csA29/C35, Connections 4; HTTP/pipeline and RPC/event propagationImplementedPorted explicit-context contract #8, replacing ambient storage; tests aboveShared UUID-backed context key only. AddCorrelationIdSupport has no counterpart; WithID/FromContext need no registration (Go-idiom replacement). Ingress parsing/generation, headers, principal, tenancy, causation, store/namespace and detached-operation policy stay local. No Fundamentals ExecutionContext class exists to port.
Monads: Monads/Result.cs, Result{TError}.cs, Result{TResult,TError}.cs, Catch.cs, Catch{TResult}.cs, Catch{TResult,TError}.cs, Option.csA4/C15; Result in both, Catch in Chronicle activation/reactors; no direct client Option use establishedNot implementedOut of scope as a shared union framework; Go-idiom replacement recorded by #10Use (T, error), errors.Is/As, (T, bool) and product-specific outcomes. Preserve domain rejection versus infrastructure failure and explicit presence; do not flatten Arc command outcomes or confuse Option with three-state JSON Optional.
Collections: Collections/CollectionExtensions.cs, ItemAlreadyAddedToBinaryTree.csA0/C1; Chronicle constraint discovery; dependencies/server also use helpersNot implementedOut of scope as a shared collection framework; Go-idiom replacement, #10range, len, append, slices and maps replace helpers; preserve sequential effects and duplicate lookup values. The directory’s binary-tree exception is not a tree implementation to port.
Guids: Guids/GuidExtensions.csA0/C0; no observed dependency/server useNot implementedOut of scope: XOR has no demonstrated consumer; reconsider through #5 only on demandUUID values are already #2. Do not invent identity-combining behavior or move Chronicle’s mixed-endian BCL wire adapter.
Tasks: Tasks/AwaitableHelpers.cs, ITaskFactory.cs, TaskFactory.cs, AsyncManualResetEvent.csA3/C1, Connections 3; Arc handler awaiting; Chronicle connection lifetimeNot implementedOut of scope as Task emulation; Go-idiom replacement, #10Context-aware direct calls, channels and sync preserve result/error and cancellation semantics. Products own goroutine lifetimes; reset generations and shutdown need tests, not a renamed Task abstraction.
Timers: Timers/ITimerFactory.cs, TimerFactory.cs, ITimer.cs, Timer.csA0/C0; no observed scoped useNot implementedOut of scope: no shared timer-factory demand; Go-idiom replacement, #10Caller-owned time.Timer/Ticker or narrow clock interfaces. Specify callback overlap, cancellation and stop behavior where used rather than claiming BCL timer equivalence.
Reactive: Reactive/ObservableExtensions.cs, TransformingSubject.csA0/C0; Kernel 27 only for these helpers; external Rx use is separateNot implementedOut of scope as a shared reactive framework; Go-idiom replacement, #10Product-owned subscriptions must define replay-latest, ordering, backpressure, terminal errors, unsubscribe and producer cleanup. Kernel usage alone does not require a client package.
Metrics: Metrics/IMeter.cs, Meter.cs, KeyedMeter.cs, UnkeyedMeter.cs, MeterScope.cs, CounterAttribute.cs, GaugeAttribute.cs; DependencyInjection/DiagnosticsServiceCollectionExtensions.csA3/C0; Arc MongoDB generated metrics; Kernel 8Not implementedOut of scope as mandatory shared telemetry; Go-idiom replacement, #10Products own instrumentation/exporters. Preserve instrument names and tag spelling if adopted; allow no-exporter operation and keep scalar packages independent of telemetry backends.
Traces: Traces/IActivitySource.cs, ActivitySource.cs, KeyedActivitySource.cs, UnkeyedActivitySource.cs, ActivityScope.cs, SpanAttribute.cs; diagnostics DI extensionsA14/C12; pipeline, append, reactor/reducer and transaction spansNot implementedOut of scope as CLR activity emulation; Go-idiom replacement, #10Context propagation, explicit span completion and product-owned optional instrumentation. Retain operation/tag names; business correlation is not a trace ID.
Telemetry generation: Source/DotNET/Metrics.Roslyn/MetricsSourceGenerator.cs, Templates/Metrics.hbs, ActivityScopeUsingAnalyzer.csIndirect through Metrics/Traces counts above; no separate generator countNot implementedOut of scope: Roslyn attributes/analyzer runtime; #10Products may generate ordinary Go instrumentation calls. Do not port unsynchronized static first-meter capture; defer/lifecycle checks replace C# disposal syntax.
Root ExceptionExtensions.csA0/C4; Chronicle reactor/reducer error reporting; Kernel 8Not implementedOut of scope as global exception flattening; Go-idiom replacement, #10Preserve wrapped-error detail and structured failure categories, with product-owned redaction/envelopes. C# walks one outer-to-inner InnerException chain, not all aggregate branches.
Root TimedLogging.csA0/C0; no observed dependency/server useNot implementedOut of scope: process-global console timing is not a shared contract; #10Use monotonic elapsed time and injected log/slog in products. Do not reproduce its unsynchronized UTC timestamp and millisecond-component output.
Root Fundamentals.csprojPackage/build metadata; no usage countNot implementedOut of scope as a .NET build artifact; Go module/tooling ownership #16Keep runtime dependency direction Fundamentals → neither product; optional tools are separately versioned, not Roslyn packages or runtime compiler dependencies.

The exports remain in @cratis/fundamentals; Go proxies consume that runtime, not a Go reimplementation. Go status reports Go implementation of the JS export, not backend wire coverage. There are no JS-file counts in the .NET source-search method. Arc directly generates imports and calls the runtime; Chronicle is an indirect JSON producer, not an executor of these JS classes.

Arc proof points at its pin: Source/DotNET/Tools/ProxyGenerator/TypeExtensions.cs and Templates/Type.hbs map rich scalar/geometry/ValueMap types and emit field/derivedType; Source/JavaScript/Arc/commands/Command.ts serializes payloads and queries/deserializeQueryModel.ts reconstructs query models.

Export group and sourceConsumer evidenceGo statusDisposition and trackingMigration boundary
Guid.ts, DateOnly.ts, TimeOnly.ts, TimeSpan.ts; corresponding converters in json/index.ts; json/DateJsonConverter.tsArc rich proxy values; Chronicle scalar JSON indirectlyNot implementedJS-owned; canonical backend Go scalars implemented #2; JS round-trip agreement is not established by backend tests aloneArc.Go owns generated rich fields. JS TimeOnly truncates below milliseconds; JS-number TimeSpan cannot preserve every int64 tick. JS Date is an instant, not DateOnly; Date conversion remains product-owned.
ConceptAs.ts, typeKey.tsArc concept proxies; both products’ scalar wire contractsNot implementedJS-owned; shared backend Go concept codec/recognition #4; compile-time Go recognition delivered in concepts/conceptstypes #15; generated-proxy agreement is Arc.Go-ownedKeep TS constructors, valueType metadata and cross-copy type keys in JS. No {value: ...} wire wrapper or claim of generated-proxy agreement.
Field.ts, Fields.ts, fieldDecorator.tsArc-generated runtime field metadata; Chronicle read-model payloads indirectlyNot implementedOut of scope as Go runtime decorators; product-owned generation, #10 boundaryArc.Go must emit compatible constructors, enumerable flags, derivative lists and generic arguments, for the selected decorator mode. Plain TS declarations supply no field reconstruction metadata.
DerivedType.ts, derivedTypeDecorator.ts; discriminator handling in JsonSerializer.tsArc proxy decorators; both JSON producers’ polymorphismNot implementedBackend ID/target metadata deferred → #5TS registry/decorators and generated field metadata stay JS/Arc-owned. Preserve _derivedTypeId; C# rejects unknown IDs whereas JS field reconstruction can retain them on the declared type.
JsonSerializer.ts, json/JsonConverter.ts, json/index.ts converter registryArc command/query runtime directly; Chronicle wire shapes indirectlyNot implementedOut of scope as a shared Go serializer; #5 boundaryProducts own missing/null/empty collection rules and actual JS integration tests. Converter state is per package copy even with stable keys; compiling TS alone is insufficient.
ValueMap.ts, json/ValueMapJsonConverter.ts, map helpers in JsonSerializer.tsArc complex-key proxy fields; Chronicle JSON dictionaries indirectlyNot implemented (Go implementation)Typed-field source-runtime evidence in testdata/complex-key-contract/javascript.json, including 34 original-key lookup results and real six-field metadata; #18Standalone converter reads return an empty map and are not this capture. Native stringify equality differs from C# record equality; typed Composite field order normalization is declaration-specific. No strict validation or universal round-trip claim. Dictionary-key reference.
geospatial/index.ts: Point.ts, LineString.ts, LinearRing.ts, Polygon.ts; geometry converters in json/index.tsArc rich geometry fields; Chronicle GeoJSON/schema producerNot implementedGo values/GeoJSON deferred → #5JS classes stay JS-owned. Backend fixtures must cover longitude-first order, shell/holes and C# read validation; less strict JS construction does not authorize weakening the server contract.
Constructor.ts, IEquatable.ts, PropertyAccessor.ts, PropertyAccessorDescriptor.ts, PropertyPathResolverProxyHandler.ts; supporting reflection.ts, typeKey.ts, duplicateInstanceGuard.tsJS selector/metadata/packaging infrastructure; no direct .NET runtime dependencyNot implementedOut of scope: language/runtime mechanics; #10Use typed accessors and explicit descriptors where a Go product needs them. Arc owns client dependency deduplication; stable symbols neither share converter registrations nor fix instanceof across copies.

The original scalar fixtures are source-derived expectations, not captured .NET responses. Existing Go tests exercise codecs and context behavior; they do not prove an Arc.Go → Chronicle.Go append or generated JS round trip. Keep that consumer evidence in the consuming repositories and link exact test paths and pins when adoption lands. JS parity assertions require executing the existing runtime against emitted payloads, including its precision limits.

Easy-to-miss discovery and activation behavior

Section titled “Easy-to-miss discovery and activation behavior”

These notes retain the source inventory’s compatibility traps without turning accidental CLR behavior into a new Go guarantee.

  • Discovery snapshots: Types/Types.cs materializes provider types once; any generated provider suppresses the default reflection-provider pair. A referenced assembly therefore need not contribute to All. Types.Instance and Serialization/DerivedTypes.Instance never refresh. Go stance: explicit complete contributions, not ambient snapshots (#11/#14).
  • Current universe: Types/TypesServiceCollectionExtensions.cs ensures provider registration and caches by provider type set, not container count. Types/GeneratedTypeDiscoveryRegistry.cs loads reachable assemblies and runs module constructors. Go stance: explicit bootstrap and publication; do not silently lose late contributions or invent dynamic Go package scanning.
  • Two Chronicle discovery paths: pinned Chronicle Source/Clients/DotNET/DefaultClientArtifactsProvider.cs composes assembly providers, while TypeUniverse.cs selects the container/current universe. Go stance: Chronicle owns artifact catalogs; shared DI is not an event registry.
  • Ignore is not undiscoverable: DependencyInjection/ServiceCollectionExtensions.cs and Source/DotNET/Fundamentals.TypeDiscovery.Generator/TypeDiscoveryCollector.cs apply IgnoreConvention to DI candidates, not all discovered types. Go stance: separate feature registration from service binding.
  • Convention matching: those same files require same namespace, IFoo/Foo naming and unique implementation; existing service descriptors win. Reflection self-binding rejects a type if any public constructor has a primitive-like or record parameter. Go stance: selected typed factories and explicit duplicate/override policy under #14, not name-based runtime surprises.
  • Lifetimes and aliases: DependencyInjection/ServiceCollectionExtensions.cs defaults unmarked types to transient; no TransientAttribute exists. Its interface/self singleton bindings are separate descriptors and need not share an instance. Go stance: explicit lifetimes/owned-versus-borrowed bindings and close-once forwarding are implemented and covered by dependencyinjection/ditest (#11–#13). Convention planning is available (#14); products own generated registration and rendering.
  • Enumeration is activation: Types/InstancesOf.cs captures discovered concrete types and a provider, then calls GetService(concreteType) on every enumeration. It neither enumerates interface registrations nor falls back to ActivatorUtilities; lazy enumeration does not repair a captured root scope. Go stance: operation-scoped factories; unregistered activation policy stays with the consuming product.
  • Concept inheritance is not duck typing: Concepts/ConceptExtensions.cs uses Reflection/TypeExtensions.IsDerivedFromOpenGeneric, which includes the current type; Concepts/ConceptMap.cs looks for the generic base and returns void for raw ConceptAs<T>. Go stance: the explicit #4 declaration rules, not every Value field or a chain of concept-valued return types.
  • Construction writes twice: Concepts/ConceptAs.cs sets Value in its constructor, and ConceptFactory.cs invokes the value constructor then sets Value reflectively again, potentially replacing constructor normalization. Go stance: explicit constructors/codecs; never bypass domain validation.
  • Three separate conversion boundaries: Concepts/TypesExtensions.cs and Conversion/TypeConverters.cs register component-model converters; Json/Globals.cs registers JSON converters. Neither alone implements HTTP binding. Go stance: shared text/JSON codecs, with Arc explicitly invoking them under its own binding and validation rules.
  • Invalid input is not uniformly permissive: Concepts/StringExtensions.cs returns Guid.Empty for invalid ParseTo UUID text; Types/TypeConversion.cs uses Guid.Parse for strings, but can return empty for unsupported nonstring sources and default calendar/time values after failed parsing. Arc’s pinned Source/DotNET/Arc.Core/ConverterExtensions.cs:ConvertQueryArgument adds its own InvalidQueryArgument boundary. Go stance: shared parsers return errors; legacy forms/fallbacks remain explicitly deferred under #5, not HTTP defaults.
  • Bare enums differ from concepts: Json/EnumConverter.cs writes int32 numbers; numeric reads require Enum.IsDefined, whereas case-insensitive Enum.TryParse string reads do not recheck membership. Numeric strings and flags can therefore succeed where numeric tokens fail. Json/ConceptAsJsonConverter.cs uses case-sensitive Enum.Parse, including int32 numeric text, without the bare-enum membership check. Go stance: no shared enum-specific parity claim; acceptance/overflow fixtures were recorded under #17, keeping query parsing separate.
  • Casing is a policy: Strings/StringExtensions.cs leaves the whole name unchanged when the first two characters are uppercase: URLValue is not urlValue. Serialization/DefaultNamingPolicy.cs preserves properties and pluralizes read-model names by default; CamelCaseNamingPolicy.cs is opt-in. Pinned ChronicleClient chooses Default; Arc’s profile chooses acronym-friendly camelCase. Go stance: separate named policies (#21), never silently merge the existing Go defaults.
  • Read-model overrides and namespaces: Serialization/NamingPolicy.cs returns a directly declared ReadModelNameAttribute verbatim, bypassing all policy work. Its inherited existence check but noninherited retrieval makes inherited-only attributes an edge, not a supported inheritance promise. NamespacedNamingPolicy.cs always camelCases namespace segments, uses the configurable separator between those segments, but a literal final - before the model (even with no remaining namespace). Go stance: explicit stable storage names first; optional non-pluralizing named policies are provided by #21, with explicit string metadata.
  • Map keys contain JSON: Json/ComplexKeyDictionaryJsonConverterFactory.cs serializes complex keys to compact JSON and uses that text as property names. A string concept key contains embedded quotes; repeated decoded keys overwrite. The plain DictionaryJsonConverter.cs utility instead defaults to ToString. Go stance: shared scalar text-map-key tests are not complex-key evidence; captured C#/typed-JS evidence is now available, but no Go implementation or shared codec is introduced. Retain product serialization ownership and consumer profile checks under #18.
  • Concept collections intercept codecs: Json/EnumerableConceptAsJsonConverterFactory.cs matches generic, nondictionary enumerables whose first generic argument is a concept, not arrays. EnumerableConceptAsJsonConverter.cs directly constructs the element converter, bypasses option-selected per-concept converters and omits null read elements. Its own nonarray branch returns an empty list; this is not proof the enclosing serializer accepts every malformed token or concrete collection. Arc’s pinned Source/DotNET/Arc/ConceptEnumerableJsonConverterFactory.cs (extra sample outside the counted scope) delegates with fallback options instead. Go stance: slice element codecs and product tests for null/shape/precedence, not reproduction of the interceptor.
  • Legacy _id is not a general collection codec: Json/EnumerableModelWithIdToConceptOrPrimitiveEnumerableConverterFactory.cs checks primitive-ness on the collection, not its element; the converter’s Write is empty despite registration in Globals.cs. Go stance: no silent success or broad compatibility claim; any legacy adapter stays product-owned.
  • Derived IDs are global: Serialization/DerivedTypes.cs rejects duplicate IDs across all discovered attributed types, not merely within a target. Even an explicit target requires a non-System interface and assignability. Go stance: any future derived-type issue (see the #5 proposals) must preserve these rules or document an agreed deviation; allowing the same ID in different targets is not C# parity.
  • Declared type and discriminator matter: Serialization/DerivedTypeJsonConverterFactory.cs selects targets with derivatives, not every attributed concrete type. DerivedTypeJsonConverter.cs returns default for a missing discriminator; unknown target/ID lookup throws. Its write projects reflected public properties through ToCamelCase, not normal attribute-aware serialization or the configured property policy. Go stance: deferred explicit metadata plus product codecs, with fixtures for missing/unknown IDs and nested graphs; do not infer behavior from JS tolerance.
  • DOM conversion is different: Json/JsonElementExtensions.cs infers dates from strings; Json/JsonValueExtensions.cs represents DateOnly at noon and TimeOnly on DateTime.MinValue, unlike their ordinary JSON converters. Go stance: typed scalar codecs, no global heuristic date conversion (#5).

Easy-to-miss lifecycle and client behavior

Section titled “Easy-to-miss lifecycle and client behavior”
  • Correlation reads do not generate: Execution/CorrelationIdAccessor.cs returns empty from a static AsyncLocal slot; CorrelationId.New() is explicit. There is no Fundamentals ExecutionContext class. Go stance: correlation.FromContext never creates an ID, and explicit-zero contexts shadow parents; the executable #8 tests above cover this intentional adaptation.
  • Tagged values are not execution wrappers: Monads/Result*.cs and Catch*.cs store alternatives; Catch can rethrow an existing exception, not execute a try/catch callback. Go stance: explicit domain outcomes and errors, not universal panic recovery or shared transport envelopes.
  • Schema/runtime awaiting differ: Reflection/MethodExtensions.cs unwraps generic Task return types, not ValueTask; Tasks/AwaitableHelpers.cs handles Task and ValueTask at runtime. Go stance: keep generated/schema result metadata aligned with actual handlers in Arc; no awaitability emulation package.
  • Replay and cleanup are distinct: Reactive/ObservableExtensions.cs and TransformingSubject.cs use ReplaySubject(1) so the latest synchronous seed survives late subscription. Completion cleanup is not equivalent to error or Dispose cleanup: the wrapper’s error callback is empty and the transforming subject does not retain/dispose its upstream subscription explicitly. Go stance: product-owned replay/cancel/error/unsubscribe contracts and tests, not a blind channel replacement or copied resource leak.
  • Metric and trace tags differ: Source/DotNET/Metrics.Roslyn/MetricsSourceGenerator.cs keeps metric parameter names but snake_cases span tags. Templates/Metrics.hbs lazily caches static counter/gauge instruments from the first meter, without synchronized per-meter lookup. Go stance: preserve names but explicitly own instrumentation lifetime; no static first-meter behavior as an accidental guarantee.
  • JS reconstruction requires metadata: Source/JavaScript/Fields.ts and JsonSerializer.ts reconstruct declared fields; ordinary typed models do not copy arbitrary payload properties. Absent declared arrays become [], while explicit null remains null. Go stance: Arc-generated metadata and actual JS round trips must cover absence/null/empty; nil slices alone are not parity.
  • JS concept encoding is serializer-dependent: Source/JavaScript/ConceptAs.ts has no toJSON; JsonSerializer.ts unwraps concepts, including collection/map values. Go stance: emit underlying scalars through #4 codecs; generated clients must use the existing serializer.
  • ValueMap needs field types: Source/JavaScript/JsonSerializer.ts reads keys/values through field generic arguments; json/ValueMapJsonConverter.ts alone reads an empty map. ValueMap.ts compares object keys with stringify equality, so property order matters. Go stance: #18 fixtures must exercise actual typed fields, not only standalone converters.
  • Stable keys do not share registries: Source/JavaScript/typeKey.ts and JsonSerializer.ts recognize built-in types across package copies but retain per-copy converter maps. They cannot make different constructors equal for instanceof. Go stance: Arc owns generated-client packaging/deduplication.
  • UUID text hides byte order: Types/TypeConversion.cs uses the BCL byte-array Guid constructor; Source/JavaScript/Guid.ts reverses the first 4/2/2-byte fields. Go stance: shared UUID bytes stay RFC/network order; Chronicle.Go’s internal/wire/primitives.go alone owns the mixed-endian transport conversion.
  • Calendar, clock, duration and instant are not interchangeable: Json/DateOnlyJsonConverter.cs preserves the parsed calendar date rather than normalizing it to UTC; TimeOnlyJsonConverter.cs writes round-trip precision. Source/JavaScript/DateOnly.ts, TimeOnly.ts, TimeSpan.ts and json/DateJsonConverter.ts distinguish these values. JS TimeOnly truncates submilliseconds and TimeSpan uses numbers. Go stance: retain server-side 100 ns precision and full signed ticks; do not claim lossless browser round trips or convert all dates to UTC instants.
  • Geometry validation is asymmetric: Geospatial/*.cs records impose no constructor validation; Json/PointJsonConverter.cs, LineStringJsonConverter.cs and PolygonJsonConverter.cs check shapes/counts on read, including ring closure within 1e-9 per axis. Numeric readers count numeric tokens, not every malformed GeoJSON condition. JS geospatial/LinearRing.ts checks minimum length but not closure. Go stance: any future geometry issue (see the #5 proposals) must settle read/write and cross-language differences with fixtures; no invented geographic validation guarantee.

Go idioms change construction and ownership, not the obligation to preserve observable wire, discovery, lifecycle and error behavior. Missing behavior stays missing until executable evidence is added.

For each implemented surface, record the exact source revision and paths, Go package/API, test or fixture paths, and deliberate deviations with rationale and migration impact. Use Not implemented, Partial, Implemented or Go-specific. A compilation or documentation smoke test is not wire evidence. Missing behavior is distinct from an intentional difference; neither may be hidden behind a silent no-op.

Update the area ledger, consumer pins, evidence and ownership boundaries in the same change as each addition, exclusion or consumer extraction. Replace pending issue markers when focused work is filed. Do not turn source-search counts, Kernel-only use, accepted designs or deferred proposals into release scope or implementation claims.