Measured
At the pinned .objectui-sha 53ded82b and at origin/main 3f775ee:
packages/types/src/zod/app.zod.ts — NavigationItemSchema is hand-written (not .shape-derived, so the objectui#7715 mechanism does not reach it). Its superRefine checks only id / label (separator exempt).
filters occurs once in the file: the field declaration. objectNavTargetExclusivity occurs nowhere in this repo.
- The
filters .describe() reads Precedence: recordId → filters → viewName. — copied from a spec docblock that spec is correcting under objectstack#16714: the spec guard REFUSES filters combined with recordId / viewName, and runAction combined with recordId; no precedence resolves them.
packages/types/package.json depends on @objectstack/spec: ^17.0.0 at the pin, ^17.3.0 at main.
Consequence: this door does not run the rule the spec door runs, so an object nav item carrying both filters and recordId passes here and is refused by spec.
What to do (after the spec export publishes)
Spec side (objectstack-ai/objectstack, PR linked in a comment below): objectNavTargetExclusivity is exported from @objectstack/spec/ui as function objectNavTargetExclusivity(item, ctx): void — the schema's own check, one function per refinement, the same posture as checkListViewPageMount and the other check* exports.
- Bump
@objectstack/spec in packages/types to the first published version that carries the export, and confirm against the installed package rather than upstream main — spec's own liveness ledger records, for this very guard under navigation.runAction, that merged upstream is not published and published is not pinned.
- In the existing
superRefine of the navigation item object, for item.type === 'object', call objectNavTargetExclusivity(item, ctx). Do NOT copy the rule's body; chain the import.
- Rewrite the
filters .describe(): drop Precedence: recordId → filters → viewName. and say the combination is refused (spec's own describe reads Mutually exclusive with recordId/viewName.).
- Preserve the two asymmetries the spec keeps on purpose — do not make every target field pairwise exclusive:
recordId + viewName stays tolerated; runAction is refused with recordId only and composes with filters / viewName.
- Negative controls must still pass at this door:
filters alone, recordId alone, viewName alone, recordId + viewName, runAction + filters, runAction + viewName.
- Pin it: a test that parses
filters + recordId and runAction + recordId through NavigationItemSchema and asserts refusal at filters / runAction with code: 'custom', the controls above accepted, and an identity assertion that the chained function is the one @objectstack/spec/ui exports.
Landing order
Blocked-by: objectstack-ai/objectstack#16714
Spec publishes the export first; this repo chains it after the dep bump.
Filed unlabeled by the os-dev for objectstack#16714 (execution seat domain:spec); triage and priority belong to this repo's seats.
Measured
At the pinned
.objectui-sha53ded82band atorigin/main3f775ee:packages/types/src/zod/app.zod.ts—NavigationItemSchemais hand-written (not.shape-derived, so the objectui#7715 mechanism does not reach it). ItssuperRefinechecks onlyid/label(separator exempt).filtersoccurs once in the file: the field declaration.objectNavTargetExclusivityoccurs nowhere in this repo.filters.describe()readsPrecedence: recordId → filters → viewName.— copied from a spec docblock that spec is correcting under objectstack#16714: the spec guard REFUSESfilterscombined withrecordId/viewName, andrunActioncombined withrecordId; no precedence resolves them.packages/types/package.jsondepends on@objectstack/spec:^17.0.0at the pin,^17.3.0at main.Consequence: this door does not run the rule the spec door runs, so an object nav item carrying both
filtersandrecordIdpasses here and is refused by spec.What to do (after the spec export publishes)
Spec side (objectstack-ai/objectstack, PR linked in a comment below):
objectNavTargetExclusivityis exported from@objectstack/spec/uiasfunction objectNavTargetExclusivity(item, ctx): void— the schema's own check, one function per refinement, the same posture ascheckListViewPageMountand the othercheck*exports.@objectstack/specinpackages/typesto the first published version that carries the export, and confirm against the installed package rather than upstreammain— spec's own liveness ledger records, for this very guard undernavigation.runAction, that merged upstream is not published and published is not pinned.superRefineof the navigation item object, foritem.type === 'object', callobjectNavTargetExclusivity(item, ctx). Do NOT copy the rule's body; chain the import.filters.describe(): dropPrecedence: recordId → filters → viewName.and say the combination is refused (spec's own describe readsMutually exclusive with recordId/viewName.).recordId+viewNamestays tolerated;runActionis refused withrecordIdonly and composes withfilters/viewName.filtersalone,recordIdalone,viewNamealone,recordId+viewName,runAction+filters,runAction+viewName.filters+recordIdandrunAction+recordIdthroughNavigationItemSchemaand asserts refusal atfilters/runActionwithcode: 'custom', the controls above accepted, and an identity assertion that the chained function is the one@objectstack/spec/uiexports.Landing order
Blocked-by: objectstack-ai/objectstack#16714
Spec publishes the export first; this repo chains it after the dep bump.
Filed unlabeled by the
os-devfor objectstack#16714 (execution seatdomain:spec); triage and priority belong to this repo's seats.