Skip to content

fix(ir)!: tell no default from an empty one and name a writer - #1370

Open
OmarAlJarrah wants to merge 5 commits into
feat/ir-stream-and-page-inputsfrom
fix/ir-defaults-writers-overrides
Open

OmarAlJarrah wants to merge 5 commits into
feat/ir-stream-and-page-inputsfrom
fix/ir-defaults-writers-overrides

Conversation

@OmarAlJarrah

@OmarAlJarrah OmarAlJarrah commented Nov 2, 2026 •

Copy link
Copy Markdown
Member

Summary

Three fields could not say what a source left unstated, or who wrote a position.

  • An empty default is not no default (ir: ServerVariable.Default cannot tell an empty default from none #883). ServerVariable.Default becomes *string. OpenAPI requires a default, and default: "" substitutes nothing, an optional path prefix for instance. AsyncAPI allows a variable with no default. Both lowered to an empty string. The parser's own field holds both as "", so the OpenAPI compiler reads the key off the variable's node. That needs nodeview in the servers package's allowlist, with the reason beside the entry: a forwarding wrapper elsewhere would be a seam with one user.
  • Who wrote a position (ir: a Provenance naming an overlay cannot say which document its pointer is in #1035). Provenance gains WrittenBy. A construct an overlay wrote into the spec named the overlay as its Source, at a position of the patched spec. A refusal of the overlay's own actions named it at a position of the overlay. Nothing told the two apart, and morphic validate spelled patch.yaml#/components/schemas/B, a position patch.yaml does not hold. Now Source is always the document the pointer addresses, and WrittenBy the overlay that wrote what is there. The same run prints root.yaml#/components/schemas/B (written by patch.yaml), the rendering the issue proposed. report.Explain reads the source's own positions whoever wrote them, so its sources argument is gone, and irverify holds a writer to an overlay entry other than the provenance's Source (ir/provenance-writer). The issue's alternative, a flag saying the pointer addresses the patched document, keeps two meanings on Source that every reader must branch on; docs/ir/provenance.md records why it lost.
  • Override field by field (ir: the whole-struct Encoding and XMLHints override rules shadow fields a property never set #465). docs/ir/constraints.md now states that a property's Encoding and XMLHints override the type's field by field: a field the property sets replaces the type's, and one it leaves unset takes it. JSON Schema applies keywords at both places, and a whole-struct override would drop a scalar's decoded Schema whenever a property only renamed the encoding. XMLHints.Wrapped, the one field with no unset state, becomes *bool, written only where declared, so a property's false can override a type's true.

None of this touches the golden spec, which has no overlay, no empty variable default and no xml object beside a property's (spec @319dc756). That is the P3 ranking all three carry.

Closes #883
Closes #1035
Closes #465

Breaking

IRVersion moves to 0.34.0, after #1367's 0.33.0. A consumer pinned to the generation before this one refuses the document. One that read an overlay's Source as its file reads such a pointer at the wrong place, and one that read the absent default key as "no default" now reads "" where the document wrote it. In Go, ServerVariable.Default and XMLHints.Wrapped are pointers, report.Explain takes no source table, and overlay.Apply takes the patched document's index.

Stack

Base: #1367, on the rest of the IR stack. Merge in order.

Test plan

  • go test on ir/..., compilers/..., engine/..., cmd/..., pass/... and internal/.... The goldens, the shape pin and the census were regenerated. The goldens move only where an undeclared wrapped: false is no longer written, and where default: "" now is.
  • New tests:
    • servers.TestServerVariables_AnEmptyDefaultIsNotNone.
    • irverify.TestVerify_AWriterIsAnOverlayWritingIntoTheSource (six rows).
    • report.TestWriteDiagnostics_NamesTheWriterBesideTheSource.
    • TestExplain_ReadsOnlyTheSourcesCoordinates, rewritten for writers.
    • A declared wrapped: false kept in annotation.TestXMLHints_ReadsEveryFieldDirectly.
    • The overlay, load and e2e cases now read the writer where they read the source.
  • Mutants, each reddening a test: an empty default read as none; At crediting the overlay as Source; ProvenanceAt dropping the writer; the renderer dropping it; the verifier accepting a writer that is no overlay.
  • Probe: the issue's root.yaml and patch.yaml through morphic validate and morphic compile, which print and hold what is quoted above.
  • Push checklist: subject within 72 characters with the number, no artifact hits, skills_lint clean.
  • CI.

Three fields could not say what a source left unstated, or who wrote a
position.

- ServerVariable.Default becomes *string. A variable's default: ""
  substitutes nothing, and lowered to the same IR as a variable with no
  default, which AsyncAPI allows. The parser holds both as an empty
  string, so the OpenAPI compiler reads the key off the node.
- XMLHints.Wrapped becomes *bool, written only where declared, and an
  encoding's and XML hints' property-over-type override is stated field
  by field: a field the property sets replaces the type's, and one it
  leaves unset takes it. A whole-struct override would drop a scalar's
  decoded Schema whenever a property only renamed the encoding.
- Provenance gains WrittenBy. A construct an overlay wrote into the spec
  named the overlay as its Source at a position of the patched spec, so
  a reader could not tell which file the pointer was in. Source is now
  always the document the pointer addresses and WrittenBy the overlay;
  a finding about the overlay file itself keeps the overlay as Source.
  The renderer spells root.yaml#/components/schemas/B (written by
  patch.yaml), report.Explain reads the source's own positions and so
  no longer takes the source table, and irverify holds a writer to an
  overlay entry (ir/provenance-writer).

BREAKING CHANGE: IRVersion moves to 0.32.0. A consumer pinned to 0.31.0
refuses the document; one that read an overlay's Source as its file
reads its pointer at the wrong place. In Go, ServerVariable.Default and
XMLHints.Wrapped are pointers and report.Explain drops its sources
argument.
The explain test wrapped diag in a lambda of the same signature, and the
writer check's fixture named the model's embedded TypeCommon; both now
take the direct spelling the linters ask for.
…into fix/ir-defaults-writers-overrides

# Conflicts:
#	ir/document.go
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant