Skip to content

KIDEx Metadata Validation

Because a Kittox application is defined almost entirely in YAML metadata, a mistake in a .yaml file — a mistyped node, a value of the wrong type, a reference to a view that does not exist — usually surfaces only at run time, when the page is opened. Metadata Validation moves those errors to design time: it reads every model, view, layout and the Config.yaml, checks them against what the framework actually understands, and reports problems before you run the app.

It is one of the most useful features for the day-to-day author of a Kittox application, and it is worth understanding well.

One schema, two jobs

Validation is not a separate rulebook. It reads the same RTTI annotations that drive the tree context menu (see KIDEx YAML Attributes). Annotating a class therefore does two things at once: it fills the Add… menu, and it teaches the validator what a correct file looks like.

Running the validator

There are two ways to run exactly the same validation engine.

Inside KIDEx

Open a project and choose Validate Metadata (it also runs the Layout validator). The messages panel is cleared, then filled with one line per finding, each tagged with a severity icon.

A recap when it finishes. As soon as the run ends, KIDEx tallies the findings and shows a summary — both as a final line in the panel and as a dialog you acknowledge:

Validation complete: 1 error(s), 2 warning(s), 3 hint(s).

The dialog's icon reflects the worst severity found — an error stop, a warning triangle, or a plain information mark when the metadata is clean — so you know the outcome at a glance without reading every line.

Double-click a finding to open the offending file. This is the fastest way to act on a result: double-click any line and KIDEx opens — or brings to the front, if already open — the editor for the model, view, layout or Config.yaml the message concerns, and moves the tree focus straight onto the node being validated. A missing required node focuses its parent; a message that is about the file as a whole focuses the root. Either way the "incriminated" file is one double-click away, already scrolled to the right place.

Re-run after refreshing

A finding remembers the exact object it came from. If you refresh the metadata (or reload the project) after validating, those objects are rebuilt, so an old finding can no longer point at them: double-clicking it then does nothing but show a short status note asking you to re-run the validation. The list is always cleared and rebuilt at the start of each run, so a fresh validation never carries stale links.

Headless, from the command line (MCP-KittoX)

The console server MCP-KittoX exposes the same validator, which makes it easy to run in a build pipeline or a pre-commit check:

MCPKittoX.exe --workspace=<project folder or .kproj> --validate

It opens the project (a folder is resolved to its .kproj, in the root or in the Home/ sub-folder), prints one line per finding — prefixed [E] error, [W] warning, [H] hint, [I] info — followed by a summary, and returns exit code 2 when any error is found (0 otherwise). A typical run:

[E]   Missing Model.
[W]   Unknown node "SportsClubName" for TKConfig (custom node?)
[H]   Node "Controller/PageRecordCount" has its default value ("100") and could be removed.

Validation complete: 1 error(s), 2 warning(s), 1 hint(s), 3 info (7 total).

Severity levels

The validator classifies every finding into one of four levels. The distinction matters: an error is something that will not work; a warning is something to look at; a hint is a tidy-up suggestion.

LevelMeaningTypical examples
Error [E]The file is wrong and the app will misbehave or fail to open the view.Missing required node (Model, ExpressionTemplate); a data view with no Model; an enum value not in the allowed set; an integer node holding a non-number; a reference to a model, view or field that does not exist; a duplicate field.
Warning [W]Probably fine, but worth a look.An unknown node the classes do not describe (a custom application key, or a coverage gap); a view with no Controller; an Upgrade needed note for a moved node.
Hint [H]Redundant, removable.A node whose value equals its declared default — deleting it changes nothing. See Boolean defaults.
Info [I]Progress and section summaries."Config validation complete. No errors detected."

What the validator checks

  • Node names — every node is validated against the RTTI schema of the class that represents it. Class-aware recursion carries the correct class down through sub-nodes and containers, so nested nodes are validated too, and the names of container items (a tool named PDFReport, a model field named STATUS) are never mistaken for schema.
  • Values — an enum node is checked against the strings declared with [YamlEnumValue]; an integer node against actually being an integer.
  • References — a Model, a view reference or a view field that names something that does not exist in the catalog is an error.
  • Structure — a data view needs a Model (unless it is a container view such as a Dashboard, whose controller drives sub-views); a grouping needs its FieldName; and so on.

Macros and disabled nodes are skipped

An empty value, or one that contains a macro (%…%), is not value-checked: its real content is not known until run time. This is what lets profile-driven names such as HomeView: %Auth:PROFILEID%_Home pass cleanly. A node whose name starts with a dot (.Filters, .Defaults) is switched off on purpose and is reported only as a gentle "probably disabled" note, never explored.

Custom application keys are allowed

Config.yaml often carries application-specific keys the framework never reads (for example SportsClubName, SportsClubLogo), consumed only through macros. The framework classes do not declare them, so the validator lists them as warnings — "unknown node … (custom node?)". That is correct and expected: a custom key is legitimate, and the warning simply reminds you it is not part of the framework schema.

How KIDEx helps you write correct YAML: the tree context menu

Kittox YAML files are edited in KIDEx as a tree of nodes, not as free text. There is no code-completion in the text editor — the assistance lives entirely in the tree context menu. This is the single most important thing to know about authoring metadata in KIDEx:

Right-click a node in the tree and KIDEx offers you exactly the child nodes the framework understands at that position — with their default values pre-filled.

The menu is built on the fly by reading the RTTI annotations of the class that represents the selected node. So the Add… list is never out of date and never guesses: it is the framework schema itself.

  • Required nodes appear first.
  • Scalar and single sub-node items appear only when the node is not already present, as "Add {Name}" or "Add {Name}: {default}".
  • Container and child-type items always appear, because you can add several ("Add {Name} child", "Add {Type}: {default}").
  • The generic "Add custom node" is always available at the bottom: it adds a node you name yourself. That is how you write a legitimate application key the schema does not describe (and, as above, the validator will then list it as a custom-node warning).

Picking an item writes the node with its default value already filled in, ready to edit. Because the menu and the validator read the same annotations, anything the menu proposes is, by construction, something the validator accepts.

If the validator flags a node you know is correct

It is telling you the framework class does not (yet) declare it. Either it is a genuine custom key (leave it — the warning is harmless), or the class needs the annotation. See How to annotate a new class: once annotated, both the menu and the validator learn the node at once.

The boolean-default convention

A subtle but important point concerns default values, and especially booleans. There are three distinct places a default appears, and they must not be confused.

1. The annotation always declares the real runtime default

In the framework source, the default in [YamlNode] is the true runtime default — the value the framework uses when the node is absent — for every type, booleans included:

pascal
// IsVisible defaults to True at runtime → the annotation declares 'True'.
[YamlNode('IsVisible', 'True', 'Field visibility in views')]
property IsVisible: Boolean read GetIsVisible;

// PageRecordCount defaults to 100 → the annotation declares '100'.
[YamlNode('PageRecordCount', '100', 'Number of records per page')]
property PageRecordCount: Integer read GetPageRecordCount;

The annotation is the single source of truth for "what value does the framework assume here?". This is what lets the validator raise the hint below.

2. The tree menu proposes the meaningful value

When KIDEx builds the Add… menu it would be pointless to offer a boolean node set to its own default — the node would do nothing (you never add IsVisible: True when True is already the convention). So for booleans only, and only in the menu, KIDEx proposes the opposite of the declared default, so that Add always writes the behaviour-changing value:

NodeRuntime default (annotation)KIDEx Add writes
IsVisibleTrueIsVisible: False (hide the field)
PreventAddingFalsePreventAdding: True (hide the Add button)
IsKeyFalseIsKey: True

For strings, integers and enums there is no inversion: the menu writes the declared default as an editable starter (add PageRecordCount: 100, then change it to 20).

If you maintain framework code

The annotation always holds the true runtime default; the inversion is done for you, for booleans only, at menu-build time inside KIDEx. Declare the real default and let the menu do the flip.

3. The validator hints when a node equals its default

Because the annotation holds the true default, the validator can spot a node that carries exactly that default — a node that could be deleted with no effect — and reports it as a hint:

[H]   Node "Controller/PageRecordCount" has its default value ("100") and could be removed.

For booleans this behaves exactly as you would want: since the annotation holds the real default and the menu writes the flipped value, a boolean node you added through the menu never matches the default, so it is never hinted — only a boolean you set back to its default (a genuine no-op) is.

Summary

What it doesValidates all metadata (models, views, layouts, config) against the framework schema, at design time.
Where the schema livesIn the framework classes, as RTTI annotations — the same ones that build the tree menu.
How you run itValidate Metadata in KIDEx, or MCPKittoX.exe --validate headless.
SeveritiesError (broken), Warning (look at it), Hint (removable), Info (progress).
How KIDEx assists authoringThe tree context menu only — no editor code-completion. Right-click proposes exactly the valid nodes with defaults.
Boolean defaultsAnnotation = real runtime default; the menu proposes the inverse (booleans only); the validator hints a node equal to its default.

See also

Released under Apache License, Version 2.0.