## Summary
- Added `playwright_regression.yml` with one-shard-per-spec parallelism
(11 regression specs)
- Removed `RegressionSet` shard from main `playwright.yml` (tests now
run via dedicated regression workflow)
- Added `Cache test failures to TestDino` step to regression workflow
(matching main playwright.yml)
- Uses `ubicloud-standard-8` runners for all regression jobs
## Schedule
- Auto-triggers every 4 hours starting from 9 AM IST (3:30, 7:30, 11:30,
15:30, 19:30, 23:30 UTC)
- Manual trigger via `workflow_dispatch`
## Test Plan
- [ ] Confirm `playwright_regression.yml` appears in Actions tab
- [ ] Trigger a manual run to verify all 11 regression specs run in
parallel
- [ ] Verify `playwright.yml` no longer includes RegressionSet shard
---------
Co-authored-by: Claude Opus 4.7 <noreply@anthropic.com>
#11584
## What changed
Updated `CorrelatedLogsTable.vue` to load key fields from the service
correlation configuration and use them as default visible columns
alongside `_timestamp`. Added 5 new test cases covering key field
matching, fallback behavior, and user customization preservation.
## Why
The correlated logs table was only showing `_timestamp` by default,
missing relevant log fields that should appear as columns. Key fields
defined in the service correlation config (e.g., `field1`, `field2`)
were not being surfaced unless the user manually customized columns.
## Approach
- Imported `useServiceCorrelation` composable and its `loadKeyFields`
method
- On mount, fetch key fields config and store in `defaultLogFields` ref
- Added `initializeVisibleColumns()` that creates a default set from
`_timestamp` + any key fields present in the available fields
- Updated the `availableFields` watcher to check `visibleColumns.size <=
1` (instead of `=== 0`) — accounts for `_timestamp` being persisted in
localStorage
- Added a separate `watch` on `defaultLogFields` to re-initialize when
key fields arrive after `availableFields`
- Both watchers skip re-initialization if the user has already
customized columns (more than just `_timestamp`)
## Risk
Medium. The column initialization logic now runs in two watchers
(`availableFields` and `defaultLogFields`). If `defaultLogFields` loads
before `availableFields`, the first watcher applies (with an empty key
fields list) and the second watcher skips because `visibleColumns.size`
is already `> 1`. Reviewers should verify that the ordering of these
watchers doesn't leave key fields unapplied in edge cases.
Design at: ui/traces/trace-details/
#11581
## What changed
Added an "Error" tab to the trace details sidebar, extracted
error-detection logic from the sidebar into a dedicated
`useTraceDetails` composable, and moved the error/exception UI into a
new `TraceErrorTab` component. Active tab management was changed from
internal sidebar state to a parent-controlled prop with two-way binding.
Hover state (`hoveredSpanId`) was added to `TraceDetails` and
`TraceTree` — when set, hovered spans take visual priority over
`selectedSpanId`. A missing `hoveredSpanId` prop declaration was added
to `TraceTree.vue`. The `error` i18n key was added across all 12
languages. Test coverage spans 84 composable tests, 55 error-tab tests,
and updates to all three existing spec files.
## Why
Trace detail spans can fail for reasons beyond HTTP status codes (gRPC
errors, exception events, process exit codes, DB response codes).
Previously, there was no dedicated, consistently surfaced view for these
errors — they were either buried in the attributes tab or shown as
inline exception tables in the sidebar. The new error tab provides a
centralized home for all error indicators.
## Approach
Extracted error detection (HTTP status, gRPC status/name/message,
exception events, error type, DB response status, process exit code)
into `useTraceDetails` composable so it can be reused across sidebar and
error tab without duplication. Moved the error/exception UI into
`TraceErrorTab.vue`, keeping the sidebar as the orchestrator. Made
`activeTab` parent-controlled so `TraceDetails` can auto-select the
preview tab for LLM spans without conflicting with sidebar internal
state.
## Risk
The refactored active tab logic (parent-controlled via prop+emit instead
of internal state) could affect tab selection behavior in edge cases —
particularly the LLM preview auto-selection and the correlated-metrics
tab watch. The `hoveredSpanId` added to `TraceTree` was previously
undeclared as a prop (referenced but never defined), so adding it is an
unambiguous fix, not a behavioral risk. All 5 spec files pass with 357
total tests.
---------
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
## Summary
- Split regression tests out of main `playwright.yml` into a dedicated
`playwright_regression.yml` workflow
- Regression tests now run with **one shard per spec** for maximum
parallelism
- Removed `RegressionSet` shard from main `playwright.yml`
## Schedule
- Auto-triggers every 4 hours starting from 9 AM IST (3:30, 7:30, 11:30,
15:30, 19:30, 23:30 UTC)
- Manual trigger via `workflow_dispatch` on any branch (always runs on
localhost)
## Test Plan
- [ ] Confirm `playwright_regression.yml` appears in Actions tab
- [ ] Trigger a manual run to verify all 10 regression specs run in
parallel
- [ ] Verify `playwright.yml` no longer includes RegressionSet shard
🤖 Generated with [Claude Code](https://claude.com/claude-code)
---------
Co-authored-by: Claude Opus 4.7 <noreply@anthropic.com>
## Summary
- Fixes Playwright selectors broken by the UX revamp of buttons and tabs
(PRs #11595, #11652)
- The migration from Quasar to Reka UI changed active state from CSS
`selected` class to `data-state="on"`/`data-state="active"` attributes
## Changes
- **themePage.js**: Replace broken `button[data-o2-btn]` with
`[data-test="navbar-theme-toggle-btn"]` for theme switcher
- **logsPage.js**: Replace `toHaveClass(/selected/)` with
`toHaveAttribute('data-state', 'on')` for patterns toggle
- **serviceGraphPage.js**: Same selected→data-state fix for graph/tree
view toggle buttons
- **jobScheduler.js**: Replace `getByRole('cell', ...)` with
`:visible`-filtered `[data-test="tab-more_details"]` to handle
multi-element matches from v-show
- **org.spec.js**: Increase validation message timeout from 3s to 5s
- **jobSearch.spec.js**: Add 10s wait before `viewJobDetails()` for job
processing
## Test plan
- [x] `searchPatterns.spec.js` — 15/15 passed
- [x] `theme-management.spec.js` — 5/5 passed
- [x] `jobSearch.spec.js` — 8/8 passed (parallel)
- [x] `org.spec.js` — 11/11 passed
- [x] `join.spec.js` — 12/12 passed
- [x] `logspage.spec.js` — 22/28 passed (3 pre-existing flaky, all pass
in isolation)
🤖 Generated with [Claude Code](https://claude.com/claude-code)
---------
Co-authored-by: Claude Opus 4.7 <noreply@anthropic.com>
## Summary
- Skip TestDino "Cache test failures" and "Upload to TestDino" steps
when all tests pass
- Both steps now gate on `needs.ui_integration_tests.result ==
'failure'` so they only run when at least one test shard failed
- The retry mechanism (`tdpw last-failed`) is unaffected — when there
are failures the cache step still runs, and the re-run flow works as
before
## Why
TestDino bills per test case uploaded. Running both steps on green
builds wastes quota with zero value since the user only uses TestDino
for failure analysis.
## Changes
- `merge_and_upload_reports` job: "Cache test failures" step condition
changed from `always()` to `needs.ui_integration_tests.result ==
'failure'`
- `merge_and_upload_reports` job: "Upload to TestDino" step condition
changed from `(success() || failure())` to
`needs.ui_integration_tests.result == 'failure'`
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-authored-by: Claude Opus 4.7 <noreply@anthropic.com>
## Summary
Stabilises alpha1 cloud E2E tests across the Logs-Core shard. Fixes a
UI/API org mismatch root cause, adds env-aware query execution helpers,
and brings all 10 changed spec files into POM compliance.
## Root cause (original)
After Dex login, the Pinia store binds all API calls to the user's
*default* org. The URL `?org_identifier=...` alone does not update the
store. Ingestion went to the `.env` org while UI searches went to the
user's default org → empty results → cascading test failures.
## Changes
### Alpha1 environment / authentication
- **`global-setup-alpha1.js`** — switches active org via the navbar
dropdown after Dex login so the Pinia store adopts the correct org;
`context.storageState` captures the result for all test contexts
- **`playwright-alpha1.config.js`** — `ORGNAME` sourced purely from
`.env`; cloud-config override removed
- **`loginPage.login()` / `unflattened.spec.js`** — include
`?org_identifier=${ORGNAME}` in SPA navigation to prevent defaulting to
`_meta`
- **`unflattened.js openStreamDetail()`** — replaced broken
stream-name-text click with `Stream Detail` action button + Schema-tab
visibility wait
### Auto-run query handling (`auto_query_enabled` flag)
- **`logsPage.js`** — added `runQueryAfterModeChange()`: on alpha1
(`auto_query_enabled=true`) waits for the in-flight auto-query to
complete; on local triggers a fresh query. Fixes
`@interestingFieldsCRUD` and `@quickModeResults` tests that were passing
on alpha1 but failing locally because the old fix clicked Refresh
mid-auto-run (hitting Cancel)
- **`logsQueryPage.js`** — null-guard `textContent()` return in
`_toggleAutoRun()` (`|| ''`) to satisfy Playwright's `string | null`
type contract
### Merge conflict resolution
- **`logsPage.js enableQuickModeIfDisabled()`** — kept HEAD's version
that defines `quickModeIndicator` at the top of the function (used in
the retry loop); discarded main's version that opened the utilities menu
before the variable was defined
### POM compliance (Sentinel audit)
Added three new POM methods to **`logsPage.js`**:
- `watchForNotification(timeout)` — returns a promise for pre-action
race-condition-safe notification watching
- `expectNotificationContainsText(text)` — notification text assertion
- `waitForNotificationWithText(text, timeout)` — notification waiter
with text filter
Removed raw locators from spec files:
- **`logspage.spec.js`** — notification race pattern →
`watchForNotification()` + `expectNotificationContainsText()`; 5-line
raw histogram toggle block → `ensureHistogramState(true)` (POM method
already existed)
- **`logsqueries.spec.js`** —
`pm.logsPage.page.waitForSelector('.q-notification__message:has-text(...)')`
→ `waitForNotificationWithText()`
- **`jobSearch.spec.js`** — added `testLogger` import; replaced 14×
`console.log` with `testLogger.info`; raw Monaco editor locators (lines
158–168) → `logsPage.waitForQueryEditorVisible()` +
`logsPage.getQueryEditorText()` (both already in POM)
### Tags
- **`jobSearch.spec.js`** — all 8 tests now tagged: `@jobSearch,
@P0/@P1` with functional sub-tags (`@smoke`, `@crud`, `@validation`)
- **`logshistogram.spec.js`** — all 5 tests now include `@P1`
## Results
- All `logsquickmode.spec.js` tests pass on both local and alpha1
- Zero Sentinel critical issues remaining across all 10 changed spec
files
- Remaining warnings (old-style auth in `jobSearch.spec.js` /
`pagination.spec.js`, `pm.logsPage.page.reload()` in
`logsquickmode.spec.js`) are pre-existing tech debt deferred to a
separate PR
## Test plan
- [ ] Run `logsquickmode.spec.js` locally and on alpha1 — both should
pass
- [ ] Run full Logs-Core shard on alpha1: `npx playwright test --config
playwright-alpha1.config.js
playwright-tests/Logs/{join,logspage,logsquickmode,pagination,unflattened,logshistogram,jobSearch,logsqueries,logsAnalyzeDimensions}.spec.js`
- [ ] Verify global setup logs: `Switching active org to: <ORGNAME>` →
`Org switch complete`
- [ ] Confirm no `console.log` output in `jobSearch.spec.js` test run
(all replaced by `testLogger`)
🤖 Generated with [Claude Code](https://claude.com/claude-code)
---------
Co-authored-by: Claude Opus 4.7 <noreply@anthropic.com>
## Summary
- Adds 18 new POM methods to `alertsPage.js` for stream-type/query-mode
coherence verification, chart state assertions, query editor
interaction, and aggregation field filtering
- Adds 5 helper methods to `alertCreationWizard.js` for full editor
open/close, stream switching, and query execution
- Adds new regression spec `alerts-stream-switching-regression.spec.js`
covering 5 closed bugs:
| Bug | Description |
|-----|-------------|
| #11580 | Metrics+PromQL -> Logs, PromQL editor persists |
| #11572 | Logs -> Metrics -> Logs, chart error "No field named value" |
| #11571 | Builder -> SQL, chart blank table instead of line |
| #11573 | Full editor open/close blanks the graph |
| #11578 | Agg functions don't filter to integer fields |
## Test plan
- [ ] Run `alerts-stream-switching-regression.spec.js` against dev
environment
- [ ] All 5 tests pass with no raw selectors in spec (POM-compliant)
- [ ] Chart assertions verify canvas child exists (not just bounding
box)
🤖 Generated with [Claude Code](https://claude.com/claude-code)
---------
Co-authored-by: Claude Opus 4.7 <noreply@anthropic.com>
## Summary
Two compactor optimizations focused on the historical (old-data) merge
path:
1. **Replace `ZO_COMPACT_OLD_DATA_MIN_RECORDS` with a file-size check.**
The hour-selection SQL in `query_old_data_hours` now uses `original_size
< ZO_COMPACT_MAX_FILE_SIZE / 2` instead of `records < 100`. Record count
is a weak proxy for "mergeable" — a file's size depends on schema width
and compression, while the compactor's actual goal is to produce files
near `max_file_size`. The size check directly answers the right
question.
2. **Push the 95%-of-max-size filter into `query_for_merge` SQL.**
Previously, every file in the target hour was fetched from `file_list`,
then files at ≥95% of `max_file_size` were discarded in-process by the
worker. The filter is now applied in the SQL (`AND original_size <=
max_file_size * 95 / 100`), reducing the rowset shipped from the
database — meaningful for healthy streams where most files are already
compacted. The redundant in-process check in `merge.rs` was removed.
### Env var change (breaking)
- **Removed:** `ZO_COMPACT_OLD_DATA_MIN_RECORDS` (no replacement; the
size threshold is derived from `ZO_COMPACT_MAX_FILE_SIZE`).
- Unchanged: `ZO_COMPACT_OLD_DATA_INTERVAL`,
`ZO_COMPACT_OLD_DATA_STREAMS`, `ZO_COMPACT_OLD_DATA_MAX_DAYS`,
`ZO_COMPACT_OLD_DATA_MIN_HOURS`, `ZO_COMPACT_OLD_DATA_MIN_FILES`.
Docs PR: openobserve/openobserve-docs (separate).
## Test plan
- [x] `cargo fmt && cargo clippy --all-targets` clean for the touched
files
- [x] `cargo check --bin openobserve` succeeds
- [x] `cargo test -p config` passes (sanitizer + defaults test updated)
- [x] Manually verify on a stream with many small old files that
`query_old_data_hours` selects them and the merge proceeds
- [x] Manually verify on a stream where most files are already at full
size that `query_for_merge` returns a smaller rowset than before
🤖 Generated with [Claude Code](https://claude.com/claude-code)
---------
Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
## Summary
- Enhanced existing scheduled pipeline query builder tests with exact
default query format assertions (`max(_timestamp)`, `count(_timestamp)`,
`histogram(_timestamp)`)
- Added new P2 test verifying Run Query button transitions from disabled
to enabled after stream selection and default query population
- Verifies behavior described in Issue #11575
## Test plan
- [x] All 4 tests pass (verified on test environment)
🤖 Generated with [Claude Code](https://claude.com/claude-code)
---------
Co-authored-by: Claude Opus 4.7 <noreply@anthropic.com>
## Summary
- Normalize `ZO_FILE_FORMAT` to `parquet` for non-enterprise builds.
- Preserve configured file format values for enterprise builds.
- Add targeted tests for both non-enterprise and enterprise behavior.
## Why
Non-enterprise builds should not fail startup because `ZO_FILE_FORMAT`
is configured to an enterprise-only format. Instead, they now continue
with parquet as the supported storage format.
## Validation
- `cargo test -p config test_non_enterprise_file_format_forces_parquet`
- `cargo test -p config --features enterprise
test_enterprise_file_format_preserves_configured_value`
- `git diff --check`
Note: the test run reports an existing unrelated unused import warning
in `src/config/src/meta/user.rs`.
## What changed
Fixed `addFieldTerm` in `SearchBar.vue` so that include/exclude search
terms are inserted at the correct position in SQL aggregation queries.
Previously the code checked for `ORDER BY` before `GROUP BY`, causing
the injected `WHERE` clause to land after `GROUP BY` (invalid SQL). The
fix scans all terminating clauses (`GROUP BY`, `HAVING`, `ORDER BY`,
`LIMIT`) and inserts `WHERE` before whichever appears earliest. The
remaining diff is Prettier-driven reformatting with no logic changes.
## Why
The old sequential `if/else if` checked `ORDER BY` first. On a query
containing both `GROUP BY` and `ORDER BY`, it would split at `ORDER BY`
and produce `… WHERE <filter> ORDER BY … GROUP BY …` — structurally
invalid SQL. The fix enforces correct SQL clause ordering (`FROM → WHERE
→ GROUP BY → HAVING → ORDER BY → LIMIT`).
## Approach
The new algorithm iterates over all four terminating clauses, records
the index of each that is present, picks the one with the smallest index
(`firstClause`), then uses the existing `queryIndexSplit` utility to
splice the `WHERE <filter>` token in before it. If no terminating clause
exists the filter is appended. The spec file was extended with 14 new
unit tests covering the core bug scenario (GROUP BY + ORDER BY
together), each individual clause in isolation, all-clauses-present,
AND-append paths, and edge cases (case-insensitive matching, column
names containing clause keywords, special characters in filter values).
## Risk
The logic change is isolated to the `else` branch of `addFieldTerm` that
handles queries with no existing `WHERE` clause. Queries that already
have a `WHERE` clause follow a separate code path and are unaffected.
Reviewers should confirm the `queryIndexSplit` utility is
case-insensitive-safe (the fix lowercases only for the index scan, then
splits the original string) and verify the preserved trailing
`afterClause` string includes the space/newline that was previously part
of the `" order by"` / `" group by"` literals.
## Summary
- Add API tests verifying that stream settings fields (index_fields,
bloom_filter_fields, full_text_search_keys) are deduplicated when the
same field is added multiple times
- Tests cover: single field dedup, multiple fields, repeated adds (4x),
remove+re-add, empty payloads, and partial updates
- All tests use existing schema fields from the seed data stream
(`stream_pytest_data`)
## Test plan
- [x] All 10 tests pass against testing environment
- Tests run via `cd tests/api-testing && rye run pytest
tests/test_stream_settings_dedup.py -v`
🤖 Generated with [Claude Code](https://claude.com/claude-code)
---------
Co-authored-by: Claude <noreply@anthropic.com>
design at: designs/anomaly-detection
## Summary
Adds super cluster sync support for anomaly detection configs and fixes
a missing FK constraint on `anomaly_detection_config.folder_id`.
**Super cluster sync:**
- Add `infra::table::anomaly_detection` module with config CRUD ops
(`create`, `create_if_not_exists`, `update`, `put`, `delete`,
`get_by_id`, `list`)
- Add `super_cluster_queue::anomaly_detection` handler for
`ConfigCreate`, `ConfigUpdate`, and `ConfigDelete` events
- Refactor `service::anomaly_detection` and `scheduler::handlers` to use
the new table module instead of raw SeaORM entity queries
- Refactor `super_cluster_queue::scheduler` to use new table module
- Reschedule trigger instead of deleting when config not found locally —
handles SC race where trigger row arrives before `ConfigCreate` NATS
message is processed
**Migration / referential integrity fix:**
- Add migration `m20260504` to retrofit the missing `FOREIGN KEY
(folder_id) REFERENCES folders(id)` constraint on
`anomaly_detection_config` (alerts and dashboards have had this since
creation; anomaly detection was missing it)
- Pre-migration repair: any rows whose `folder_id` no longer exists in
`folders` (orphaned by folder deletion) are re-pointed to the org's
default Alerts folder before the constraint is added — prevents
migration failure on existing deployments
- Add folder existence check inside transaction in `create()` —
eliminates TOCTOU race between folder lookup and INSERT
- Add folder existence check in `update()` when folder is changing —
matches `alerts::update` behaviour
- Add `PutAnomalyConfigError::FolderDoesNotExist` error variant matching
the alert/dashboard error pattern
## Files changed (11)
- `src/infra/src/table/anomaly_detection/` — new module (config.rs,
mod.rs, models.rs)
- `src/super_cluster_queue/anomaly_detection.rs` — new SC queue handler
- `src/infra/src/table/mod.rs` — register new module
- `src/super_cluster_queue/mod.rs` — wire anomaly_detection handler
- `src/service/anomaly_detection.rs` — refactored to use new table
module
- `src/service/alerts/scheduler/handlers.rs` — refactored; reschedule on
missing config
- `src/super_cluster_queue/scheduler.rs` — refactored to use new table
module
- `src/infra/src/errors/mod.rs` — add
`PutAnomalyConfigError::FolderDoesNotExist`
-
`src/infra/src/table/migration/m20260504_000001_add_anomaly_detection_config_folder_fk.rs`
— new migration
- `src/infra/src/table/migration/mod.rs` — register migration
## Test plan
- [x] Anomaly config create/update/delete broadcasts appear in SC queue
logs on primary region
- [x] Follower region receives and applies `ConfigCreate`,
`ConfigUpdate`, `ConfigDelete`
- [x] Trigger reschedule (not delete) when config not yet synced to
follower
- [x] Create with non-existent folder returns clean `FolderDoesNotExist`
error
- [x] Update moving config to non-existent folder returns clean
`FolderDoesNotExist` error
- [x] Migration runs clean on existing DB with no orphaned rows
- [x] Migration repairs orphaned `folder_id` rows before adding FK
constraint
- [x] `cargo check --workspace` passes
## What changed
Replaced `VueJsonPretty` (`vue-json-pretty`) with `CodeQueryEditor.vue`
(Monaco-based) for JSON rendering in `LLMContentRenderer.vue`. Inlined
the `MessageItem` sub-component directly into the template with
`CodeQueryEditor` for JSON message content. Added `showLineNumbers` and
`stickyScroll` props to `CodeQueryEditor`. Removed the unused
`vue-json-pretty` dependency from `package.json`. Passed unique editor
IDs from `TraceDetailsSidebar` via a new `instanceId` prop to prevent
Monaco editor ID collisions.
## Why
`vue-json-pretty` formats the entire JSON tree on initial render,
causing lag on long JSON payloads. Monaco (via `CodeQueryEditor`)
renders only visible viewport lines, making performance O(visible)
instead of O(total).
## Approach
- Replaced all 7 `VueJsonPretty` instances in `LLMContentRenderer.vue`
with `<CodeQueryEditor>` in read-only mode (`:read-only="true"`,
`:show-line-numbers="false"`, `:sticky-scroll="false"`)
- Inlined the `MessageItem` sub-component as a `v-for` block with
`CodeQueryEditor` for JSON message content and the existing `v-html`
markdown renderer for non-JSON content
- Converted the component to `<script setup lang="ts">` with
`defineAsyncComponent` for `CodeQueryEditor`
- Added `showLineNumbers` and `stickyScroll` props (both default `true`)
to `CodeQueryEditor.vue` to support the JSON viewer use case
- Added a `watch` on `showLineNumbers` to dynamically toggle line
numbers in Monaco
- Passed `instanceId` from `TraceDetailsSidebar` down to
`LLMContentRenderer` to generate unique editor IDs like
`trace-id-msg-json-editor-0`
## Considered & rejected
- **Render function approach with synchronous import of
CodeQueryEditor** — rejected because it forced manual editor height
computation and module-level counters for editor IDs. Inlining
`MessageItem` as a template component was cleaner and consistent with
the other 5 template `CodeQueryEditor` locations.
- **Retaining `MessageItem` as a separate component with render
function** — rejected because the render function approach was
over-engineering for what is now a simple `v-for` with conditional
`CodeQueryEditor` / markdown branching.
## Risk
Medium. Monaco editor initialization has non-trivial overhead; rendering
multiple editors on one page (e.g., many messages in a conversation)
could impact initial render time. Reviewers should check that the
`instanceId` prop is correctly wired from `TraceDetailsSidebar` to avoid
duplicate Monaco editor IDs, and that the `tw:h-full` class application
on content-wrapper divs doesn't break non-JSON (plain text / markdown)
layouts.
Three fixes in alertCreationWizard.js:
- Align threshold operator dropdown with working SQL method pattern
(q-field__control click + role-based option + q-menu fallback)
- Narrow portal cleanup from all q-portal to q-portal--dialog only to
avoid hiding new dropdown menus
- Fix _switchToTab to target v3 inner tab divs instead of wrapper
---------
Co-authored-by: Claude Opus 4.7 <noreply@anthropic.com>
## What changed
Removed the `label` property from important field entries pushed into
`selectedStreamFields` in the traces `extractFields()` function.
## Why
The `label` field was redundant — it duplicated the `name` property —
and caused display issues in the traces fields sidebar where both `name`
and `label` were shown. The data model already uses `name` as the
display key.
## Approach
Stripped the `label: rowName` assignment from the important fields
branch in `extractFields()`.
## Risk
The field removal changes the object shape pushed to
`selectedStreamFields` for important fields. Verify that no downstream
code (field grouping, semantic matching, search building) depends on
`field.label` being present.
- API-first methods in alertTemplatesPage.js (_findTemplateViaApi,
createTemplateViaApi, deleteTemplateViaApi) to bypass fragile UI
pagination
- API-first destination lookup in alertDestinationsPage.js
(findDestinationViaApi) resolves cascade failure
- v3-compatible locators for alert type dropdown, condition operators,
deduplication flow in alertCreationWizard.js
- Self-contained test pattern with per-test random suffixes and no
shared state
- URL-based navigation with menu fallback for templates and destinations
pages
- q-portal cleanup before click interactions to prevent interception
- Conditional enterprise feature guards at runtime
🤖 Generated with [Claude Code](https://claude.com/claude-code)
---------
Co-authored-by: Claude <noreply@anthropic.com>
## Summary
- Add optional `is_llm_stream` field to `UpdateStreamSettings` so the
stream settings update API can toggle the flag.
- Apply the value in `update_stream_settings` alongside the other
boolean toggles.
## Why
`StreamSettings` already exposes `is_llm_stream`, but the update API had
no way to change it. This brings the update payload in line with the
underlying setting so callers can flip the flag without going through a
different code path.
## Test plan
- [x] `cargo check` passes (verified locally)
- [x] PATCH stream settings with `{"is_llm_stream": true}` updates the
stored value
- [x] Omitting `is_llm_stream` leaves the existing value unchanged
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-authored-by: Claude Opus 4.7 <noreply@anthropic.com>