Problem
docs/ir-design.md §14's AsyncAPI row says payload JSON-Schema lowering is "shared with OpenAPI" — but the entire schema-graph machinery is package-private to compilers/openapi: schema.go (~1,150 lines), compose.go (allOf classification), constraints.go, value.go (BigVal capture), hoist.go (pointer-keyed interning), cycles.go (~400 lines of cycle detection). Both architecture.md §3 and the archtest forbid compilers importing each other.
When the AsyncAPI compiler lands it must either reimplement ~2.5k lines — guaranteeing divergence in allOf classification, hoisting, and numeric handling, exactly the duplicated-logic failure class prior-art.md §1 records for oagen — or break the layering invariant. The same tension exists for the Swagger 2.0 lift (see the doc contradiction tracked in #64).
Proposed direction
Extract the dialect-parameterized JSON-Schema→IR core into a shared Layer-1 package importable by any compiler (e.g. compilers/internal/jsonschema, importing only ir), parameterized by ID namespace/pointer prefix and dialect quirks, with its own archtest rule. Doing it now, with one consumer and 100% coverage as the safety net, is a mechanical move; after AsyncAPI lands it becomes a unification project. Size: L.
Note: a number of open compiler bugs (#26, #27, #28, #29, #30, #32, #33, #34, #35) live in exactly these files — sequencing this extraction before or after those fixes is a planning decision, but both landing orders are cheaper than doing the extraction post-AsyncAPI.
Acceptance
- A second compiler can lower a JSON-Schema payload by importing the shared package, with zero copied lowering code.
- The archtest enforces the new package's layer (imports
ir only).
- OpenAPI goldens are unchanged by the move.
Problem
docs/ir-design.md§14's AsyncAPI row says payload JSON-Schema lowering is "shared with OpenAPI" — but the entire schema-graph machinery is package-private tocompilers/openapi:schema.go(~1,150 lines),compose.go(allOf classification),constraints.go,value.go(BigVal capture),hoist.go(pointer-keyed interning),cycles.go(~400 lines of cycle detection). Botharchitecture.md§3 and the archtest forbid compilers importing each other.When the AsyncAPI compiler lands it must either reimplement ~2.5k lines — guaranteeing divergence in allOf classification, hoisting, and numeric handling, exactly the duplicated-logic failure class
prior-art.md§1 records for oagen — or break the layering invariant. The same tension exists for the Swagger 2.0 lift (see the doc contradiction tracked in #64).Proposed direction
Extract the dialect-parameterized JSON-Schema→IR core into a shared Layer-1 package importable by any compiler (e.g.
compilers/internal/jsonschema, importing onlyir), parameterized by ID namespace/pointer prefix and dialect quirks, with its own archtest rule. Doing it now, with one consumer and 100% coverage as the safety net, is a mechanical move; after AsyncAPI lands it becomes a unification project. Size: L.Note: a number of open compiler bugs (#26, #27, #28, #29, #30, #32, #33, #34, #35) live in exactly these files — sequencing this extraction before or after those fixes is a planning decision, but both landing orders are cheaper than doing the extraction post-AsyncAPI.
Acceptance
ironly).