Skip to content

T-RR9V-tabs-carry-entity-icons-and-views

State: planning/proposed · Impact: medium · Complexity: medium

Every document tab draws the same i-lucide-file-text glyph and every activation lands on the shell’s raw-text stage, so an Agent Manager note opened as a tab would look like a text file and read like one. A tab needs to carry an opaque icon and a view key the host resolves, which is what lets Agent Manager open notes as tabs at all. That is the prerequisite for the tree’s edited indicator, for the preview and Related panes following the active document, and for the split stage.

LocationRole today
packages/ts/app-frame/app/composables/useDocumentTabs.ts#DocumentTab{key, scopeItem, path, label} and nothing more; key is scopeItem plus path
packages/ts/app-frame/app/composables/useDocumentTabs.ts#openDocumentTakes {scopeItem, path, label?}, pushes the tab, activates it and publishes the selection
packages/ts/app-frame/app/components/ShellDocumentTabs.vueDraws a fixed i-lucide-file-text glyph on every tab; the dot’s hue comes from the scope roster through scopeItemHueStyle
packages/ts/app-frame/app/composables/useCapabilities.ts#CapabilitySlotAn open string. The frame ships renderers for panel and stage-card, and names lens as a host-defined slot with no renderer
solutions/determined/packages/shell/app/components/ShellVaultBrowsePane.vue#activateThe only openDocument caller: routes into the notes experience when composed, else opens a tab and pushes /apps/browse
solutions/determined/packages/shell/app/pages/apps/browse.vueThe fallback stage: reads the active document with polishScanReadFileContent and prints it into a <pre>
solutions/determined/experiences/agent-pants/app/components/ApComponentTree.vue#activateNavigates to the note or plugin route and calls selectScopeItem; opens no tab
solutions/determined/experiences/agent-pants/app/components/ApComponentTree.vue#KIND_ICONPer-kind glyphs: store, package, file-text, terminal, bot
solutions/determined/docs/planning/desktop-framework/multi-vault-ux/IMPLEMENTATION.mdRecords rule 2b.8 — the frame carries no domain vocabulary, so subjects are scopeItem and slot is an open string
packages/ts/app-frame/tests/useDocumentTabs.test.tsCovers open, re-open, activate, close and prune over the four-field tab

DocumentTab carries optional icon, hue and view — three opaque strings the frame stores, passes through and never interprets, which is rule 2b.8 held exactly as it stands. ShellDocumentTabs.vue draws tab.icon when a tab names one and keeps i-lucide-file-text as the fallback.

A host resolves view through the capability registry at slot: 'lens': the registration whose id equals the tab’s view supplies the component the stage mounts. browse.vue mounts the resolved lens and keeps its <pre> reader for a tab that names no view. Agent Manager registers one lens and opens its notes through openDocument, passing KIND_ICON[kind] and its view key, so a skill tab carries the skill glyph and activating it renders the note editor rather than raw text. ShellVaultBrowsePane.vue passes a file-type icon for the tabs it opens.

  1. useDocumentTabs.ts: add icon?, hue? and view? to DocumentTab and OpenDocumentInput and carry them through openDocument. key stays scopeItem plus path, so re-opening a document that is already open must update the stored fields rather than mint a second tab — settle that in this step and test it.
  2. ShellDocumentTabs.vue: render tab.icon with i-lucide-file-text as the fallback, and let tab.hue win over the scope roster’s hue where a tab names one.
  3. Name the slot: export a LENS_CAPABILITY_SLOT constant beside DEFAULT_CAPABILITY_SLOT and STAGE_CARD_CAPABILITY_SLOT, and add a resolveLens(view) query returning the registered capability whose id matches. Open decision in this step: whether a lens resolves by id alone or also has to match the subject. Match on id alone — a tab already names one document.
  4. browse.vue: mount the resolved lens for the active tab, keeping the <pre> path for a tab with no view.
  5. Agent Manager: register the lens in app/plugins/register.ts, and open notes from ApComponentTree.vue#activate through openDocument with the kind icon and the view key. The separate selectScopeItem call goes: openDocument already publishes the selection.
  6. Tests: extend packages/ts/app-frame/tests/useDocumentTabs.test.ts for the three fields and the re-open case, and cover lens resolution in the frame’s own useCapabilities.test.ts.
AreaNote
packages/ts/app-frame/app/composables/useDocumentTabs.tsDocumentTab and OpenDocumentInput gain icon, hue, view; re-open updates them
packages/ts/app-frame/app/components/ShellDocumentTabs.vueDraw tab.icon; prefer tab.hue over the roster hue
packages/ts/app-frame/app/composables/useCapabilities.tsAdd LENS_CAPABILITY_SLOT and resolveLens(view)
packages/ts/app-frame/tests/useDocumentTabs.test.tsCover the new fields and the re-open update
packages/ts/app-frame/tests/useCapabilities.test.tsCover lens resolution by id
solutions/determined/packages/shell/app/pages/apps/browse.vueMount the resolved lens; <pre> stays the no-view fallback
solutions/determined/packages/shell/app/components/ShellVaultBrowsePane.vuePass a file-type icon on openDocument
solutions/determined/experiences/agent-pants/app/plugins/register.tsRegister the note lens
solutions/determined/experiences/agent-pants/app/components/ApComponentTree.vueactivate opens a document tab carrying KIND_ICON[kind] and the view key
solutions/determined/experiences/agent-pants/app/components/ApComponentTree.test.tsAssert the tab is opened with the kind icon
  • AC-1: Opening a skill, a command, an agent and a plugin from the Agent Manager tree produces four tabs whose glyphs are the four KIND_ICON entries for those kinds.
  • AC-2: Activating an Agent Manager tab renders the note editor, not the <pre> reader.
  • AC-3: A tab opened by ShellVaultBrowsePane.vue with no view still renders in the <pre> reader, unchanged.
  • AC-4: openDocument called twice for one {scopeItem, path} with different icons leaves one tab carrying the second icon — asserted in useDocumentTabs.test.ts.
  • AC-5: useDocumentTabs.ts and ShellDocumentTabs.vue name no vault, note or kind: the three new fields are read and stored as opaque strings, and rule 2b.8 holds.
  • AC-6: moon run :check :test --affected passes for app-frame, the determined shell package and the agent-pants experience.
  • none

The user’s planning request of 2026-09-07 asked for document tabs to carry the icon of what they hold, and for an experience to own what a tab renders. Member of milestone M-BMFD. Rule 2b.8 — the frame stores opaque strings and never domain words — is recorded in solutions/determined/docs/planning/desktop-framework/multi-vault-ux/IMPLEMENTATION.md and holds here.


← Back to Tasks