feat(schema): Support additionalProperties map schemas#114
Open
feat(schema): Support additionalProperties map schemas#114
Conversation
`inject_object_constraints()` unconditionally injected `required` and
`additionalProperties: false` into every object-typed schema property. This broke
dynamic map schemas like `{"type": "object", "additionalProperties": {"type": "string"}}`,
which are valid but have no fixed property names to enumerate as required.
The fix: skip constraint injection when the schema already declares `additionalProperties`.
The schema author controls validation explicitly in that case.
The namespace meta-schema (`namespace-schema.json`) is updated to allow
`additionalProperties` on both top-level and nested object properties, restricted to
scalar value types. A `not: {required: [additionalProperties]}` guard ensures the
existing `required`/`additionalProperties: false` injection path only applies to
structured objects, not dynamic maps.
9e684c8 to
2ac74d3
Compare
Some options need to represent dynamic key-value mappings rather than fixed-shape objects. This adds support for schemas that use `additionalProperties` to describe maps with dynamic keys and a known value type (e.g. `BTreeMap<String, String>`). Previously, `inject_object_constraints()` would unconditionally inject `required` and `additionalProperties: false` into every object-typed property, which broke any schema that already declared `additionalProperties`. Now, `required` is still injected from declared `properties`, but `additionalProperties: false` is only injected when the schema doesn't already declare it. The namespace meta-schema is updated to allow `additionalProperties` on object properties, restricted to scalar value types via a shared `$defs/map_value_type` definition. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
eae10f8 to
b26b08c
Compare
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
There was a problem hiding this comment.
Cursor Bugbot has reviewed your changes and found 1 potential issue.
❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.
Reviewed by Cursor Bugbot for commit 6b6ae28. Configure here.
Shape fields with `type: "object"` now require `additionalProperties` to
be declared explicitly, matching the same constraint already enforced on
top-level option definitions and `items` definitions.
Without this, a shape entry like `{"type": "object"}` would pass
meta-schema validation but produce an unconstrained object at runtime
since `inject_object_constraints` does not recurse into shape entries.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
hubertdeng123
approved these changes
Apr 9, 2026
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.

Some options need to represent dynamic key-value mappings rather than fixed-shape objects. A concrete example is a killswitch type with arbitrary scope keys:
Previously, the only way to define an object in a schema was with an explicit
propertiesmap — every key had to be declared up front. This made it impossible to represent dynamic mappings.Now, schemas can use
additionalPropertiesto describe a map where keys are dynamic but values have a known type:{ "scopes": { "type": "object", "additionalProperties": { "type": "string" }, "optional": true } }The validation layer now recognises this pattern and skips the automatic
required/additionalProperties: falseinjection that would otherwise break it.