Measured on origin/main (a39b02a6) while implementing #14106, by running runAuthoringRules('validate', { normalized: normalizeStackInput(stack) }) — the exact path os validate takes (packages/cli/src/commands/validate.ts) — over the same two list views in the two authorable container shapes:
| where the list views live |
gantt view with no gantt: block |
top-level views: [{ object: 'duly_task', listViews: { schedule: { type: 'gantt' } } }] |
view/layout-without-binding at views[0].listViews.schedule.gantt (as designed) |
object-nested objects: { duly_task: { …, listViews: { schedule: { type: 'gantt' } } } } |
nothing — 0 findings |
Why
packages/lint/src/validate-functional-completeness.ts walks objects[].fields for the field rules and only stack.views[] containers for the list-view rules. An object's built-in named list views (ObjectSchema.listViews, packages/spec/src/data/object.zod.ts — ADR-0017 nested "Object has-many View", ADR-0047 segmented tabs) and its default list slot are never handed to checkViewCompleteness. normalizeStackInput does not hoist them into stack.views either (views is not in MAP_SUPPORTED_FIELDS; the conversion layer does not move views), so on the normalized pre-parse stack the wrapper receives, object-nested list views are invisible to the whole view/* completeness family — view/layout-without-binding and, after #14106 lands, view/tree-without-parent-field.
The sibling reference-integrity rules already walk both doors: lint-view-refs.ts (containerFromObject) and validate-list-view-field-refs.ts (the objects[].listViews.* loop, resolving the object as data.object ?? obj.name). The completeness walk is the one member of the family that stopped at the top-level container, which is exactly the shape validate-functional-completeness.test.ts's own docblock warns about: "a completeness gate that walks half the stack is exactly that: green, and blind to the other half."
Expected
validateFunctionalCompleteness walks objects[].list and objects[].listViews.* through checkViewCompleteness with the object itself as the bound object (an inline data.object may retarget, per ADR-0047), reporting where as object "<name>" › listViews.<key> and path as objects[<i>].listViews.<key>.<block>, so an object-nested timeline / gantt / tree view authored without its binding gets the same warning the top-level container form gets today. A fixture pair in both spellings (map-form and array-form objects).
Scope note
Deliberately not folded into #14106 (that card is domain:spec, and its dispatch declared the lint edit as wiring only); this is a packages/lint walk defect and lands in the lint lane. #14106 remains open until its own PR merges; this issue does not depend on it.
Generated by Claude Code
Measured on
origin/main(a39b02a6) while implementing #14106, by runningrunAuthoringRules('validate', { normalized: normalizeStackInput(stack) })— the exact pathos validatetakes (packages/cli/src/commands/validate.ts) — over the same two list views in the two authorable container shapes:ganttview with nogantt:blockviews: [{ object: 'duly_task', listViews: { schedule: { type: 'gantt' } } }]view/layout-without-bindingatviews[0].listViews.schedule.gantt(as designed)objects: { duly_task: { …, listViews: { schedule: { type: 'gantt' } } } }Why
packages/lint/src/validate-functional-completeness.tswalksobjects[].fieldsfor the field rules and onlystack.views[]containers for the list-view rules. An object's built-in named list views (ObjectSchema.listViews,packages/spec/src/data/object.zod.ts— ADR-0017 nested "Object has-many View", ADR-0047 segmented tabs) and its defaultlistslot are never handed tocheckViewCompleteness.normalizeStackInputdoes not hoist them intostack.viewseither (viewsis not inMAP_SUPPORTED_FIELDS; the conversion layer does not move views), so on the normalized pre-parse stack the wrapper receives, object-nested list views are invisible to the wholeview/*completeness family —view/layout-without-bindingand, after #14106 lands,view/tree-without-parent-field.The sibling reference-integrity rules already walk both doors:
lint-view-refs.ts(containerFromObject) andvalidate-list-view-field-refs.ts(theobjects[].listViews.*loop, resolving the object asdata.object ?? obj.name). The completeness walk is the one member of the family that stopped at the top-level container, which is exactly the shapevalidate-functional-completeness.test.ts's own docblock warns about: "a completeness gate that walks half the stack is exactly that: green, and blind to the other half."Expected
validateFunctionalCompletenesswalksobjects[].listandobjects[].listViews.*throughcheckViewCompletenesswith the object itself as the bound object (an inlinedata.objectmay retarget, per ADR-0047), reportingwhereasobject "<name>" › listViews.<key>andpathasobjects[<i>].listViews.<key>.<block>, so an object-nestedtimeline/gantt/treeview authored without its binding gets the same warning the top-level container form gets today. A fixture pair in both spellings (map-form and array-form objects).Scope note
Deliberately not folded into #14106 (that card is
domain:spec, and its dispatch declared the lint edit as wiring only); this is apackages/lintwalk defect and lands in the lint lane. #14106 remains open until its own PR merges; this issue does not depend on it.Generated by Claude Code