Skip to content

M3: Unknown-carrier hand-construction semantics — payload/marker agreement and round-trip (R2-7b) #33

Closed

Description

@Blind-Striker

From the second verified review of PR #26 (finding R2-7, CONFIRMED; the argument-guard half landed on the PR — carriers now refuse an unparsed default(JsonElement) payload). This issue owns the remaining design half.

Finding. The eight Unknown* carriers' public [JsonConstructor] accepts any (tag, payload) pair, while the converters' Write emits payload-only (ADR-0009 raw replay). A hand-built carrier therefore drops its stored marker on serialization: new UnknownSessionForkBoundary("custom", JsonDocument.Parse("{}").RootElement) serializes as {}, which the same converter's Read then rejects; a payload whose discriminator differs from the constructor tag round-trips into a carrier with a silently different Type.

Design question: what is the hand-construction contract? Options: refuse construction when the payload's discriminator disagrees with (or lacks) the tag; inject the stored marker on Write; or document carriers as wire-read-only artifacts whose construction surface exists solely for the serializer. The wire-replay path (carrier read from the wire, replayed verbatim) must stay byte-identical either way — that tolerance is ADR-0009's contract.

Trigger: the M3 union single-pass redesign (#23) rewrites these same converters; decide the contract there so the converters are touched once.

Milestone: M3 (rides #23).

Activity

  1. Blind-Striker commented on Aug 15, 2026

    @Blind-Striker
    CollaboratorAuthor

    Sealed as constructor refusal (research log Session 24): a carrier's payload must carry the union's marker property agreeing with the tag — never fires on the wire read path, refuses the silent marker-drop on hand-construction; Write stays payload-only verbatim replay (ADR-0009 intact). Executes inside #23's converter rewrite (M3 plan Arc 6).

  2. Blind-Striker commented on Aug 20, 2026

    @Blind-Striker
    CollaboratorAuthor

    Completed in fa6124d and passed hosted CI run 32374393085 on Linux, Windows, and macOS. Every generated Unknown carrier constructor now refuses whitespace markers, non-object/unparsed payloads, missing or disagreeing discriminators, and disagreeing fixed outer markers. Wire-read carriers derive the same marker from the payload, so unknown-union tolerance remains intact; Write still performs payload-only replay through both interface and concrete metadata. Tests cover missing/different/non-object hand construction, valid hand-constructed replay, nested fixed-marker refusal, and duplicate-discriminator last-value behavior. No public signature or generated-manifest membership changed.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    needs-triageMaintainer needs to evaluate this issue

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions