feat(schema): make adding a key a compatible change - #201
Merged
Merged
Conversation
Plan for #200: make adding a key a compatible --json schema change.
v0.1.0 has --json consumers, and the published schema closed every object with additionalProperties: false, so a consumer validating against an older copy rejected any key added since. That made every new field a breaking change in practice. The published schema is now open, and docs/json-output.md says what is compatible (a new key, a looser constraint) and what increases schema_version (a removed, renamed or retyped key, a newly nullable key, a new enum value). Opening the schema only loosens it, so this is itself compatible and schema_version stays 1. The drift guard is unchanged: schematest validates against Closed(schema), which puts additionalProperties: false back on every object schema that lists properties. Before the edit, Closed applied to the stripped schema reproduced the old file exactly. Opening the objects made three result-or-failure unions ambiguous: a failed export row has every key singleOpFailure requires, so it matched both branches and oneOf refused it. All eight such unions are now anyOf. Fixes #200.
- Split the enums: a new command, or a new frontmatter field reported by diff, is a compatible change. diff's field is now a plain string for that reason, and command says why a new value breaks nobody. Every other enum stays closed, so a new value bumps schema_version. - The schema's description points at docs/json-output.md instead of restating part of the rule; CLAUDE.md gains the nullable case. - schema --help says the schema is open and what that asks of consumers. - The closing is unexported (closeObjects) and shares one walker with the tests. The walker skips instance data (const, enum, default, examples) and steps through name-keyed maps: infoResult has a property named "properties", which the old walk read as a schema. - TestEveryPropertiesNodeIsTyped fails a node listing properties without "type": "object", which the drift guard would otherwise leave open. - TestPublishedSchemaIsOpen fails only additionalProperties: false. - The open and closed schemas compile through one cached path.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Fixes #200. v0.1.0 has
--jsonconsumers, and the published schema closed every object withadditionalProperties: false, so any new key was a breaking change in practice. #10 needs one (update'smoved), so this comes first. Plan:_plans/054_open-json-schema.md.The published schema is open. Every
additionalProperties: falseis gone. That only loosens the schema, so it is itself compatible andschema_versionstays 1.docs/json-output.mdhas a new Compatibility section with the rule:diff.diff'sfieldis now a plain string for that reason.schema_versionincreases: a removed or renamed key, a changed type or meaning, a newly nullable key, or a new value in any other enum (code, a result'sstatus...).The drift guard is unchanged.
internal/schematestvalidates against a copy closed in memory:additionalProperties: falsegoes back on every node declaring"type": "object"withproperties. Closing the new file reproducesmain's schema exactly, apart from the union change below.markfluence schemastill prints the file byte for byte. New tests keep the file open, fail any node that lists properties without a type (which the guard would silently leave open), and pin that an unlisted key fails the closed copy and passes the published one.Result-or-failure unions are
anyOf. With open objects, a failedexportrow has every keysingleOpFailurerequires, so it matched both branches andoneOfrefused it. All eight such unions changed;anyOfis looser, so this is compatible too.Also:
markfluence schema --helpsays the schema is open and what that asks of consumers, and a few code comments that described the schema as closed now name the closed test copy.