Fix/autofix dangling children#300
Merged
Merged
Conversation
ctate
commented
Jun 10, 2026
Collaborator
- autoFixSpec prunes dangling children references
- invalid_visible validation
- filtered repeat
Dangling references are the dominant remaining first-attempt validation failure in benchmarks, and models frequently fail to repair them even given the exact error (observed: three repair turns, same dangling footer each time). The renderer already skips missing children at runtime, so pruning yields the identical rendered output while letting the spec validate. Each removal is reported in fixes.
Pruning a dangling child reference changes what renders; relocating a misplaced field does not. Callers with a repair loop need to tell these apart: accept lossless fixes silently, prefer re-prompting over lossy fixes, and keep the lossy-fixed spec as a last resort. Adds fixDetails alongside the existing fixes strings (additive, no signature break).
…attern Malformed visible conditions (e.g. mixing $state and $item in one object) silently evaluate to hidden at runtime: evaluateCondition dispatches on the first recognized key and non-strict parsing strips the rest, so whole regions of UI disappear with a valid-looking spec. Benchmarked worst case: a kanban board that rendered zero task cards. - core: VisibilityConditionStrictSchema (strict objects, exported) - core: validateSpec rejects malformed visible with a repairable message listing the valid forms (code: invalid_visible) - framework prompts: FILTERED LISTS rule showing the repeat + per-item visible pattern models keep reaching for and inventing syntax around
Models across vendors consistently write {repeat, visible: {$item: ...}} on
one container to mean a filtered list (kanban columns, status sections).
Previously $item had no meaning outside the repeat scope, the condition
evaluated false, and the whole region silently disappeared — the worst
visual failures in benchmarks were boards rendering zero cards this way.
Outside a repeat scope that spelling was always broken, so claiming it is
backward compatible: the renderer now applies such a condition per item,
preserving original indices for item state paths. Container-level $state
conditions and per-child $item conditions behave as before.
- core: conditionUsesItemScope helper (exported)
- react: RepeatChildren filters items by the container's $item condition
- framework prompts: FILTERED LISTS rule teaches the container spelling
- react: repeat-filter test suite (filtering, no-filter, $state container
visibility, per-child $item)
Other framework renderers (vue, svelte, solid, react-native) still evaluate
the container condition outside scope and should adopt the same semantics.
Two silent empty-region failures seen repeatedly in benchmarks, both passing validation today: a repeat element with no children (nothing to clone per item) and a repeat statePath pointing at a missing or non-array state value. Both now fail validateSpec with repairable messages (repeat_without_children, repeat_state_mismatch). State checks only run when the spec provides state; runtime-fed state is unaffected.
Contributor
…e, reuse getByPath - ink/react-native useUIStream repair loops no longer accept lossy autofixes unconditionally: lossless relocations apply immediately, pruned content holds back while retries remain (so validation fails and the model repairs the missing elements) and applies only as a last resort. - FILTERED LISTS prompt rule removed from schemas whose renderers do not implement the per-item filter yet (everything except react). Renderer parity tracked as follow-up. - repeat_state_mismatch validation reuses getByPath instead of a local JSON Pointer lookup that skipped ~0/~1 unescaping.
…agerly
- splitRepeatVisibility (core, exported): AND-composed conditions on a repeat
container partition into a container gate ($state conjuncts, hides the
shell) and a per-item filter ($item/$index conjuncts). Mixed $or cannot
partition soundly and stays fully per-item, documented.
- react renderer uses the split, so {$and: [{$state gate}, {$item filter}]}
hides the empty shell when the gate is false instead of rendering a husk.
- autoFixSpec gains { lossy?: boolean } (default true, additive): ink and
react-native repair loops now apply lossless relocations immediately and
withhold only the pruning until retries are exhausted, matching the stated
intent.
- react-native useUIStream mirrors ink: when retries are exhausted and the spec still fails validation, report through onError instead of silently calling onComplete with an invalid spec. - autoFixSpec never prunes a repeat container to zero children; that would trade missing_child for repeat_without_children and leave the last-resort spec unrenderable. The dangling template reference stays visible to repair. - Docs for the new surface: core README + skill (validateSpec issue codes, fixDetails, lossy option), react README + skill and web visibility docs (filtered-list pattern, mixed-condition splitting, framework support note).
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.