Skip to content

A schema cannot reference a class or enum declared in another .schema.json, so related files have to be merged or copied (architecture plan: "Multi-Schema Support") #302

Open

Description

@matt-edmondson

Plan reference

## Future Architecture Considerations
### Planned Enhancements
1. **Plugin System**: Runtime loading of custom types and generators
2. **Schema Diffing**: Compare schemas and generate migration scripts
3. **Validation Rules**: Declarative validation system
4. **Multi-Schema Support**: References between schemas

Planned Enhancements

...
4. Multi-Schema Support: References between schemas

What exists today

  • Types.Object.ClassName and Types.Enum.EnumName resolve only through the schema that owns them: Schema.GetClass / GetEnum (Schema/Models/Schema.cs:425).
  • SchemaSerializer.Load (Schema/SchemaSerializer.cs) reads one file. The file format has no property that names other schema files (see docs/schema-format.md).
  • Validation reports any name not declared in the same file as dangling.

This repository already records what the gap costs. samples/README.md ("What the migration could not preserve",

Schema/samples/README.md

Lines 29 to 41 in f461cc9

**The file boundaries.** A member's `className` names a class in the same schema, and 14 of the
references in the legacy set cross a file - 7 of those reaching out of Dungeoneer into Carbon
Monoxide's shared types. So a set of files that referred to each other becomes one schema or
nothing. `dungeoneer.schema.json` therefore carries the six Carbon Monoxide files it resolves
against (`anchor`, `collision`, `hitbox`, `line`, `rect`, `vector`); `gradient` and `spline` it
never mentions, and `EverySharedFileIsOneDungeoneerActuallyNeeds` is what stops that list quietly
growing into "all of Carbon Monoxide".
The legacy format had its own answer to this and it was never load-bearing: `rect.schema.json`
spells the list `References`, `spline.schema.json` spells it `ReferencedSchemas`, and
`line.schema.json` names `Vector2` while declaring neither. Nothing checked it, because the
generated C++ simply included everything.
) notes that 14 references in the legacy sample set point into another file, 7 of them from Dungeoneer into Carbon Monoxide's shared types. Because of that:

  • dungeoneer.schema.json has to carry copies of six Carbon Monoxide files.
  • EverySharedFileIsOneDungeoneerActuallyNeeds exists only to stop that copy from growing.
  • The legacy format's own reference lists (References / ReferencedSchemas) were never checked.

What's missing

  • A way for a schema file to name the schema files it builds on. Paths should resolve against the schema file's own directory, the same way data sources and output paths already do.
  • Resolving className / enumName (and semantic type, interface and error-type names) through those referenced schemas.
  • Validation:
    • a referenced file that is missing or does not load is an error;
    • reference cycles are rejected or handled explicitly;
    • a name declared both locally and in a referenced schema is an error, not a silent shadow.
  • Generators do not emit a referenced type's code again. C# refers to it through its namespace, and C++ #includes its header.
  • The rename cascade (Schema.Rename.cs) stays limited to the owning schema. A referenced schema's elements are read-only from the referencing file.

Acceptance criteria

  • The Dungeoneer sample can be written as a schema that references carbonmonoxide.schema.json instead of copying its six shared files, and its generated C# and C++ still compile (LegacySampleGenerationTests / LegacySampleCppTests).
  • kschema validate on a schema with a missing reference exits non-zero and names the missing file.
  • docs/schema-format.md documents the new property and bumps formatVersion, following the existing additive-migration policy.

Dependencies

There are no hard dependencies. It should be designed together with:

Activity

  1. matt-edmondson commented on Oct 19, 2026

    @matt-edmondson
    ContributorAuthor

    Triage


    Generated by Claude Code

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Labels

enhancementNew feature or request

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions