Skip to content

[OPIK-7532] [QA] Proposed taxonomy changes from app surface - #8144

Draft
CometActions wants to merge 1 commit into
mainfrom
qa-bot/OPIK-7532/taxonomy-discovery-2026-09-04
Draft

[OPIK-7532] [QA] Proposed taxonomy changes from app surface#8144
CometActions wants to merge 1 commit into
mainfrom
qa-bot/OPIK-7532/taxonomy-discovery-2026-09-04

Conversation

@CometActions

@CometActions CometActions commented Sep 4, 2026

Copy link
Copy Markdown
Collaborator

Proposed by nightly taxonomy discovery

Read the app's route/nav/tab surface and compared it against taxonomy.yaml.
Baseline before this change: 19 areas, 203 functional capabilities.

Taxonomy discovery — proposal

Target: opik/tests_end_to_end/coverage/taxonomy.yaml
Date: 2026-09-04

Measured against

opik ref 4ef186c6c7OPIK-8192 [BE] fix: drop undecodable scoring stream messages instead of wedging the stream (#8089)
opik tree state clean (git status --porcelain empty)
surface ./surface.json, pre-generated by the caller — 60 routes, 20 nav items, 8 tab components, 1 unmatched surface

The single unmatched surface matches the documented baseline exactly
(/$workspaceName/home, the known borderline). The proposal below therefore
comes not from unmatched_surfaces but from the tab diff, which
surface.py does not do for you.


1. What changed

One capability added. One line inserted; git diff --stat is 1 insertion(+).

traces.messages-tab — new, covered: false, no tier

      messages-tab:           { covered: false, note: "MessagesTab — conditional on input/output parsing as LLM messages (detectLLMMessages); is the default tab when shown" }

Evidence.

  • The surface. src/v2/pages-shared/traces/TraceDetailsPanel/TraceDataViewer/TraceDataViewer.tsx:271-277
    renders a <TabsTrigger value="messages">Messages</TabsTrigger>, with content at
    :309-317 delegating to a dedicated 281-line MessagesTab.tsx in the same
    directory. This is not a view/format toggle — it is one of five sibling tabs
    in the trace details panel, each rendering different content.

  • It is the default tab for LLM traces.
    TraceDataViewer.tsx:98const defaultTab = canShowMessagesTab ? "messages" : "details";
    canShowMessagesTab (:84-96) is content-conditional: true when the trace's
    input or output parses as LLM messages via detectLLMMessages, and neither
    side fails to parse. So for a chat/LLM trace, Messages is the first thing the
    user sees on opening the panel.

  • Its four siblings are all already capabilities; it is the only one missing.
    The functional block enumerates the panel's tabs individually rather than
    folding them into one entry:

    Tab in TraceDataViewer Functional capability
    Details open-trace-panel
    Feedback scores manual-feedback-score
    Prompts prompts-tab
    Agent graph agent-graph-tab
    Messages — none —

    The visual dimension of the same area already enumerates all five
    (taxonomy.yaml:283-288): trace-sidebar-messages, -details, -feedback,
    -prompts, -agent-graph. So the functional dimension is missing exactly the
    one tab the visual dimension has. That asymmetry is what this fixes.

  • Not already covered under another name. grep -nEi 'message|conversation|llm|chat'
    over the whole taxonomy returns only: the visual trace-sidebar-messages
    entry, threads.thread-message-count / thread-level-metrics (a different
    area — the Threads list and the thread panel, not the trace panel),
    prompts.create-chat-prompt-ui, and unrelated comments.

  • Not already covered by open-trace-panel. That capability's only tagged
    spec is trace-explore/trace-explore-smoke.spec.ts:48, which asserts
    panel.inputSection / panel.outputSection / inputValue / outputValue
    i.e. the Details tab. Its fixture is a plain @opik.track leaf function
    whose I/O does not parse as LLM messages, so canShowMessagesTab is false and
    the Messages tab is not rendered at all in that run. No functional spec
    touches it.

  • Altitude. Placed deliberately adjacent to agent-graph-tab and
    prompts-tab — same component, same conditional-tab shape, same granularity.
    Worth flagging honestly: this makes traces the largest area at 22
    capabilities, above the 5-15 guide. I judged that the guide's own carve-out
    applies (configuration legitimately carries 19) — traces is a genuinely
    wide surface, and the alternative, folding Messages into open-trace-panel,
    would be inconsistent with how the file already models the other four tabs.
    If a reviewer disagrees, the right fix is a conversation about all three
    *-tab entries, not about this one.

  • cloud_only: not set. The tab is gated by nothing but trace content —
    no usePluginsStore component, no FeatureToggleKey. Per the skill's rule,
    cloud_only is omitted entirely rather than written as false.


2. Coverage arithmetic

Recounted from the file, before and after, per dimension. rules.cloud_only_separate_view
is true, so the self-hosted denominator (excluding the 2 cloud-only areas and 4
cloud-only capabilities) is shown alongside.

Dimension Before After
functional (all) 117/203 (57.6%) 117/204 (57.4%)
functional (self-hosted) 107/179 (59.8%) 107/180 (59.4%)
visual (all) 30/54 (55.6%) 30/54 (55.6%) — unchanged
visual (self-hosted) 30/50 (60.0%) 30/50 (60.0%) — unchanged
load (all) 0/9 (0.0%) 0/9 (0.0%) — unchanged

Functional coverage drops 57.6% → 57.4%. That is the point: the Messages tab
has been in the product untested this whole time, and the denominator was hiding
it. Nothing here asserts a new test exists — the entry lands covered: false
with no tier:, for reconcile.py to fill in if and when a spec is tagged.

2b. Rejected surfaces

Everything considered and ruled out, with the evidence that ruled it out.

From unmatched_surfaces (1 of 1 rejected)

/$workspaceName/homeHomePage — rejected: it is a redirect, not a page.

src/v2/pages/HomePage/HomePage.tsx is 21 lines whose entire body is a
useEffect calling navigate({ to: "/$workspaceName/projects", replace: true }),
rendering <Loader /> while it does. router.tsx:157 labels it in a comment:
"home (redirects to the workspace Projects tab)". It has no UI of its own and
no behaviour a test could assert beyond "landing lands on Projects", which is
the existing projects area.

This is the kind: redirect class the skill says to skip; surface.py
classified it as surface because it is implemented as a useEffect + navigate
component rather than a beforeLoad redirect or a *Redirect-named component,
which the classifier recognises. Worth a note to whoever next touches
surface.py.

Correcting one surface.json field: it reports has_nav_entry: true for
this route. That is a false positive from suffix-matching /home. The "Home"
nav item is getMenuItems.ts:70path: projectPath("/home") → resolves to
/projects/$projectId/homeProjectHomePage, which is a different component
already owned by the taxonomy (projects area, route /projects/$projectId/home,
capability project-home). The workspace-level /$workspaceName/home has no
nav entry of its own, and has_api_client: false. Relatedly, the
PROJECT_HOMEPAGE_ENABLED toggle in nav_gating.flags.showHomePage gates that
project home nav item, not this route.

It does have many inbound links (SideBar.tsx:13 HOME_PATH, the quickstart
<Navigate>s, NoAccessPageGuard, the comet plugin's workspace selectors).
That confirms it is a real, load-bearing entry-point URL — it just confirms it as
plumbing, which is exactly why it is not a capability.

From the tab diff (7 of 8 tab components rejected)

unmatched_surfaces covers routes only, so all 8 entries in tabs were opened
and judged by hand.

Component Tab values Verdict
TraceDataViewer.tsx details, feedback_scores, graph, messages, prompts 1 gap — see §1. Details→open-trace-panel, feedback→manual-feedback-score, graph→agent-graph-tab, prompts→prompts-tab all exist.
AgentRunnerEmptyState.tsx python, typescript Rejected — format toggle, not a capability. :65-75 switches one CodeSnippet between two renderings of the same entrypoint. One feature with a switch.
CreateDatasetSidebar.tsx python, typescript Rejected — same format-toggle shape. SDK creation itself is datasets.create-dataset-sdk.
AnnotationQueuePage.tsx configuration, items Rejected — annotation-queues.queue-configuration-tab exists (covered: false); the items tab is the default content, covered by score-queue-item / skip-item / score-with-reason.
TrialSidebarContent.tsx prompt, results Rejected — optimization-studio.trial-detail (covered) and best-trial-prompt (covered: false) already span both.
PromptPage.tsx experiments, prompt Rejected — prompts.experiments-tab exists, with the note "prompt detail -> Experiments tab". The prompt tab is the default view.
DatasetItemsPage.tsx items, version-history Rejected — datasets.view-items and datasets.version-history-view both exist.
ThreadDetailsPanel.tsx feedback_scores, messages Rejected — threads.open-thread-panel, turn-order-io (the messages content) and thread-feedback-score all exist. Note this is the thread panel, a different area from the trace panel in §1.

From the nav diff (20 of 20 rejected)

All 20 nav_items resolve to an existing area: Home→projects.project-home,
Opik Connect→ollie, Logs→traces/threads, Diagnostics→diagnostics,
Dashboards→dashboards, Prompt library→prompts, Agent playground→
agent-playground, Prompt playground→playground, Optimization runs→
optimization-studio, Test suites→test-suites, Datasets→datasets,
Experiments→experiments, Annotation queues→annotation-queues, Online
evaluation→online-evaluation, Alerts→alerts, Workspace/Projects→projects,
Configuration→configuration/workspace-roles. No new area is warranted.

3. Removals

None.

I checked the reverse direction as well — every routes: entry across all 19
areas against the 60 routes in surface.json. One apparent miss, and it is not
a removal:

  • annotation-queues declares /annotation-queues/$id; the app mounts
    /$workspaceName/projects/$projectId/annotation-queues/$annotationQueueId
    (AnnotationQueuePage). The surface is present — only the param is written in
    shorthand in the taxonomy's informational routes: field. No edit made;
    correcting it would add diff noise for zero denominator effect. Flagging it
    for a human in case the exactness of routes: matters to them.

No capability's surface is gone from the app, so nothing shrinks the
denominator. (A removal is the one change that raises coverage without a test
being written, so the bar for proposing one is deliberately high, and nothing
met it.)

4. Rename notes for a human

None. No key was renamed and none needs to be — the one addition is new, so
no @cap: tag is orphaned and reconcile.py has nothing to fail on.

Two naming observations, offered as notes only, with no action taken:

  • traces carries spec_dir: trace-explore against product vocabulary "Logs".
    This is already deliberate and documented in the file's own comment. Left alone.
  • The new messages-tab sits beside agent-graph-tab and prompts-tab, so the
    -tab suffix is consistent within the area — but it is inconsistent with the
    visual dimension's trace-sidebar-* prefix for the same five tabs. Not worth
    churning either set of keys over; noted so nobody "fixes" it into a rename.

5. The blind spot

This sweep reads only what is in the opik repo.
PluginsStore.collectRoutes() and PluginsStore.sidebarSections let the
out-of-tree comet plugin inject routes and nav entries that are invisible
here, so surfaces that exist only in the commercial build are not covered by
this diff.

surface.json's own caveats says the same thing, and it is visible in the
tree: src/plugins/comet/ contains real components (SidebarWorkspaceSelector,
UserMenuAppLinks, WorkspaceSelector) that link into routes this sweep cannot
enumerate. nav_gating.plugin_components lists AssistantSidebar,
SidebarWorkspaceSelectorComponent and sidebarSections as plugin-supplied.

Two further limits specific to this run, so nobody reads it as exhaustive:

  • surface.py under-classifies redirects. As shown in §2b, a useEffect +
    navigate redirect component is reported as kind: surface. Other such
    redirects would also surface as false candidates — and, more importantly, the
    reverse error is possible in principle too.
  • has_nav_entry matches by path suffix and produced a confirmed false
    positive here (§2b). It is corroboration, not a gate — I judged it by opening
    getMenuItems.ts directly.

Status

No commit, no branch, no PR — as instructed, later steps do that.

The working tree now carries exactly one modified file:

 tests_end_to_end/coverage/taxonomy.yaml | 1 +
 1 file changed, 1 insertion(+)

python3 -c "import yaml; yaml.safe_load(...)" → valid.


Why this is a draft

The denominator is a reviewed file — adding a capability lowers coverage
until a test exists, and removing one raises it. Both need a human.
New capabilities land covered: false with no tier:; reconcile.py
fills those in once a tagged spec exists.

Run: https://github.com/comet-ml/comet-automation-tests/actions/runs/33839963538

Proposed by the nightly taxonomy-discovery job. Draft: the denominator is
a reviewed file, so this needs a human decision before it lands.
@github-actions github-actions Bot added the tests Including test files, or tests related like configuration. label Sep 4, 2026
@github-actions

github-actions Bot commented Sep 4, 2026

Copy link
Copy Markdown
Contributor

📋 PR Linter Failed

Missing Section. The description is missing the ## Details section.


Missing Section. The description is missing the ## Change checklist section.


Missing Section. The description is missing the ## Issues section.


Missing Section. The description is missing the ## Testing section.


Missing Section. The description is missing the ## Documentation section.

@github-actions

github-actions Bot commented Sep 4, 2026

Copy link
Copy Markdown
Contributor

⏱️ pre-commit per-hook timing

No linted files changed — nothing to run.

⏭️ 44 skipped (no matching files changed)
Hook Description Result
🐍 trim trailing whitespace — python sdk Strip trailing whitespace ⏭️
🐍 fix end of files — python sdk Ensure files end in a newline ⏭️
🐍 ruff — python sdk Lint + autofix Python (ruff) ⏭️
🐍 ruff-format — python sdk Format Python code (ruff) ⏭️
🐍 mypy — python sdk Static type check ⏭️
🤖 trim trailing whitespace — optimizer Strip trailing whitespace ⏭️
🤖 fix end of files — optimizer Ensure files end in a newline ⏭️
🤖 check yaml — optimizer Validate YAML syntax ⏭️
🤖 check json — optimizer Validate JSON syntax ⏭️
🤖 check toml — optimizer Validate TOML syntax ⏭️
🤖 check for added large files — optimizer Block large files (>1MB) ⏭️
🔐 detect private key — optimizer Block committed private keys ⏭️
🤖 check for merge conflicts — optimizer Block merge-conflict markers ⏭️
🤖 check for case conflicts — optimizer Block case-only name clashes ⏭️
🤖 pyupgrade — optimizer Modernize Python syntax ⏭️
🤖 ruff — optimizer Lint + autofix Python (ruff) ⏭️
🤖 ruff-format — optimizer Format Python code (ruff) ⏭️
🤖 mypy — optimizer Static type check ⏭️
📓 nbstripout — optimizer notebooks Strip notebook output ⏭️
📝 markdownlint — optimizer Lint Markdown ⏭️
🔤 codespell — optimizer Fix common misspellings ⏭️
📊 radon cc — optimizer Cyclomatic-complexity gate ⏭️
📊 radon raw — optimizer Raw size metrics gate ⏭️
📊 xenon — optimizer Fail on complexity thresholds ⏭️
📊 lizard — optimizer Cyclomatic-complexity gate ⏭️
🧹 vulture — optimizer Find dead code ⏭️
🛡️ trim trailing whitespace — guardrails Strip trailing whitespace ⏭️
🛡️ fix end of files — guardrails Ensure files end in a newline ⏭️
🛡️ ruff — guardrails Lint + autofix Python (ruff) ⏭️
🛡️ ruff-format — guardrails Format Python code (ruff) ⏭️
🛡️ mypy — guardrails Static type check ⏭️
⚓ helm-docs Regenerate Helm chart README ⏭️
block non-public FE plugins Block non-public FE plugins ⏭️
☕ spotless — java backend Format Java code ⏭️
🧪 pre-commit wrapper smoke tests Self-test the wrapper scripts ⏭️
🧪 rebaseline script tests Self-test the changelog re-baseline script ⏭️
🌐 eslint — frontend Lint + autofix JS/TS ⏭️
🌐 typecheck — frontend Whole-project tsc type check ⏭️
📘 eslint — typescript sdk Lint + autofix JS/TS ⏭️
📘 typecheck — typescript sdk Whole-project tsc type check ⏭️
⚙️ actionlint — github workflows Lint GitHub Actions workflows ⏭️
🐳 hadolint — dockerfiles Lint Dockerfiles ⏭️
🌈 zizmor — github workflows security Security-scan GitHub Actions workflows ⏭️
🛡️ semgrep — java backend sql Block SQL injection-prone string formatting ⏭️

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

🔵 size/XS tests Including test files, or tests related like configuration.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant