You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Dynamic Cordis plugins registering into list slots always sort before shipped entries (order ignored)
Category: Bug report + proposed fix
Summary
When a dynamic Cordis plugin registers UI into a list slot (view tabs, composer tool rows, settings rows, …), the client guard forces a negative shadowing priority on the entry, so it always sorts before shipped entries — even when the caller provides an explicit order.
Example: a dynamic plugin registers a new conversation view tab (conversation.view, id jupyter-notebook, order: 20). The shipped tabs are chat (order 0) and trajectory (order 10). Expected position: third. Actual: first, because the guard overwrites the entry's priority with -1 and list slots sort by (priority ?? 0) || (order ?? 0).
// Shadowing kinds get a page-local rank. Later registrations sort first;// chain slots keep their own election (select order) untouched.constspec=(slots.specas(key: string)=>{kind?: string}|undefined)(slot)letpriority=options.priorityif(spec===undefined||spec.kind!=='chain'){priority=env.allocatePriority()// -1, -2, … (descending)options.priority=priority}
The comment scopes the page-local rank to shadowing kinds — single/keyed cells, where a later dynamic entry is supposed to replace the shipped occupant. List slots never shadow (entries coexist; the ledger order is (priority ?? 0) || (order ?? 0), see ui-slots/src/index.ts), so applying the forced rank there makes additive dynamic entries jump to the front of every ordered list regardless of their declared order.
Proposed fix (one condition)
// Shadowing kinds get a page-local rank. Later registrations sort first;// chain slots keep their own election (select order) untouched. List// slots keep the caller's order so additive entries land in their// declared position instead of jumping ahead of shipped entries.constspec=(slots.specas(key: string)=>{kind?: string}|undefined)(slot)letpriority=options.priorityif(spec===undefined||(spec.kind!=='chain'&&spec.kind!=='list')){priority=env.allocatePriority()options.priority=priority}
Behavior matrix:
Slot kind
Before
After
single / keyed
forced negative priority (dynamic wins the cell)
unchanged
list
forced negative priority → dynamic entries always first
keeps caller order
chain
untouched
unchanged
Tests
Added to packages/extensions/cordis-client-runner/tests/guard.client.spec.ts (both pass, file 19/19):
list: two dynamic entries (order: 20 / order: 5) into a declared list slot → ledger ordered [b(5), a(20)], priorities remain undefined (previously they became -1/-2 and the sort ignored order);
keyed: still receives descending shadowing priorities [-2, -1].
Is the forced priority for list slots intentional, or an oversight (the comment says "shadowing kinds")?
If acceptable, would you take this as a PR? (CONTRIBUTING.md currently says external PRs cannot be accepted — happy to follow whatever channel you prefer, e.g. issue + PR or a local patch.)
reacted with thumbs up emoji reacted with thumbs down emoji reacted with laugh emoji reacted with hooray emoji reacted with confused emoji reacted with heart emoji reacted with rocket emoji reacted with eyes emoji
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
Dynamic Cordis plugins registering into list slots always sort before shipped entries (
orderignored)Category: Bug report + proposed fix
Summary
When a dynamic Cordis plugin registers UI into a list slot (view tabs, composer tool rows, settings rows, …), the client guard forces a negative shadowing priority on the entry, so it always sorts before shipped entries — even when the caller provides an explicit
order.Example: a dynamic plugin registers a new conversation view tab (
conversation.view, idjupyter-notebook,order: 20). The shipped tabs arechat(order 0) andtrajectory(order 10). Expected position: third. Actual: first, because the guard overwrites the entry's priority with-1and list slots sort by(priority ?? 0) || (order ?? 0).Root cause
packages/extensions/cordis-client-runner/src/client/guard.ts→guardedSlots():The comment scopes the page-local rank to shadowing kinds — single/keyed cells, where a later dynamic entry is supposed to replace the shipped occupant. List slots never shadow (entries coexist; the ledger order is
(priority ?? 0) || (order ?? 0), seeui-slots/src/index.ts), so applying the forced rank there makes additive dynamic entries jump to the front of every ordered list regardless of their declaredorder.Proposed fix (one condition)
Behavior matrix:
orderTests
Added to
packages/extensions/cordis-client-runner/tests/guard.client.spec.ts(both pass, file 19/19):order: 20/order: 5) into a declared list slot → ledger ordered[b(5), a(20)], priorities remainundefined(previously they became-1/-2and the sort ignoredorder);[-2, -1].Verified locally:
vitest19/19,oxlintclean, pre-commit hooks pass.Questions for the team
All reactions