Skip to content

M2: generator fail-closed walls batch (F08 F09 F10 F11 F13 F14 F15 + P2 fold) #21

Closed

Description

@Blind-Striker

Source: multi-agent review of PR #16, all CONFIRMED, all latent on the current pin (none active on the selected M1 surface). 2026-08-13. M-anchor: M2 boundary — exactly when pin refresh + breadth batches start stressing these walls. One batch, red-test-first per wall.

  • F08 · low — LiteralClassifier admits numeric singleton enums (LiteralClassifier.cs:76-78), TypePlanBinder maps non-boolean literals to string without a binding error (SchemaPlanBinder.cs:480), emitters throw raw InvalidOperationException. Verifier-corrected fix: do not refuse at ingestion (whole-spec projection must keep unreachable schemas); refuse at binding when a numeric literal enters the selected reachable closure; emitter throws stay as invariant backstops. ~40 pinned durable version literals make M3 the likely trigger.
  • F09 · medium — UnionNormalizer.Project accepts oneOf/anyOf (UnionNormalizer.cs:45-47) but IsMarkedUnionReference requires target.AnyOf (:189-193); a legal nested marked oneOf union is misclassified structural and refused. Fix only IsMarkedUnionReference (exclusive oneOf-or-anyOf purity); do not broaden IsPureAnyOfBranch (also serves the v2 special-number dialect). Projection + binder tests.
  • F10 · medium — BindErrorUnion (SchemaPlanBinder.cs:276-337) never checks document-wide tag uniqueness (existing check is per operation+status only); duplicate tags emit a converter whose TypesByTag initializer throws TypeInitializationException on first error deserialize. Fix: ordinal GroupBy(Tag) duplicate check → binding error, no union. Test with two Effect-tagged schemas sharing _tag.
  • F11 · medium — OperationMethodEmitter appends options/cancellationToken after bind-time collision checks (OperationMethodEmitter.cs:46-51); handle clients own pipeline/_pipeline/Pipeline. A wire parameter with those names fails at emit (CS0100) instead of bind. Fix: reserve options, cancellationToken, pipeline in binder parameter validation (naming category); never silently rename in emitters. Synthetic binder cases for normal + handle parameters.
  • F13 · medium — STJ accepts numeric enum values even with UseStringEnumConverter; ValidateGroupShape has no default arm (CurationValidator.cs:53-61) and AssembleClients partitions only Root/Client → "placement": 2 silently drops a selected group. Verifier-corrected fix: default switch arm recording a curation error naming the invalid value (do not re-add JsonStringEnumConverter — already enabled and insufficient) + numeric-placement regression fixture.
  • F14 · medium — RoutesEmitter.EmitConcatenation substitutes only the first occurrence of a repeated placeholder (RoutesEmitter.cs:107-130); PathTemplateValidator stores tokens in a HashSet so multiplicity is lost. Fix under the current dialect: validator rejects token occurrence count != 1; assert no braces remain after emission.
  • F15 · low — CheckTypeNameCollisions seeds only client+response names (OperationPlanBinder.cs:159-184). Verifier caveat: models live in OpenCode.Sdk.Models, so equal names give consumer CS0104 ambiguity, not CS0101; hard CS0101 remains for clashes with hand-written OpenCode.Sdk spine types. Fix: seed with typeNames.Values (cross-namespace shadowing) + reserve hand-written public spine names (real CS0101). Tests for both.
  • P2 fold · perf, low — ReadDataPayload double-parse (ResponseAdapter.cs:52-59): M2's {cursor,data} / {data,hasMore} envelope work introduces source-generated envelope DTOs anyway; fold the single-pass { "data": TPayload } wrapper into that design. Preserve missing/null/malformed → protocol-failure behavior.

Metadata

Metadata

Assignees

No one assigned

    Labels

    ready-for-agentSpecified enough that the work is mechanical

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions