Skip to content

Document omitted float-bar selection fields in SETTINGS_JSON.md (SBS-877) - #316

Open
tsouth89 wants to merge 3 commits into
mainfrom
fix/sbs-877-settings-json-float-bar-fields
Open

Document omitted float-bar selection fields in SETTINGS_JSON.md (SBS-877)#316
tsouth89 wants to merge 3 commits into
mainfrom
fix/sbs-877-settings-json-float-bar-fields

Conversation

@tsouth89

@tsouth89 tsouth89 commented Aug 16, 2026

Copy link
Copy Markdown
Owner

SBS-877 implementation report

Branch: fix/sbs-877-settings-json-float-bar-fields at 5ec975cd (origin/main).
Worktree: /home/box/projects/ceiling-sbs-877 only.
Linear: not commented, not closed, not edited.

Diff summary

One file: docs/SETTINGS_JSON.md.

Inserted two top-level table rows between float_bar_information_mode and float_bar_contrast:

Field Type Default Notes (as written)
float_bar_selection_mode string "pinned" "pinned" (the configured list), "active" (the focused supported app), or "activePlusCritical" (active plus any pinned provider at or above the warning threshold); an invalid string normalizes to "pinned". Safe to edit.
float_bar_foreground_detection boolean true When false, "active" / "activePlusCritical" keep the pinned list and do not read the focused window. Safe to edit.

No Rust, TS, locale, CHANGELOG, or docs/audit/ changes.

A user who hand-edits %APPDATA%\Ceiling\settings.json can now set Active / Active+critical ("active" / "activePlusCritical") and Watch focused app (float_bar_foreground_detection) from the documented table.

Every factual claim written, and where it was checked

float_bar_selection_mode

Claim in the table Verified against
Field exists and is persisted as float_bar_selection_mode rust/src/settings.rs:348 (pub float_bar_selection_mode: String); rust/src/settings/raw.rs:178; Settings uses default serde field names (settings.rs:93–96, no rename_all). Deserialize goes through RawSettings (settings.rs:95).
Type is string String on both Settings (settings.rs:348) and RawSettings (raw.rs:178). Table style for other String fields is string.
Default is "pinned" default_float_bar_selection_mode() returns "pinned".to_string() (settings.rs:433–435). Settings::default assigns default_float_bar_selection_mode() (settings.rs:703). Both Settings and RawSettings use #[serde(default = "default_float_bar_selection_mode")] (settings.rs:347, raw.rs:177). Test test_settings_default asserts settings.float_bar_selection_mode == "pinned" (tests.rs:12).
Allowed stored values are "pinned", "active", "activePlusCritical" Rust doc comment (settings.rs:344–346). normalize_float_bar_selection_mode match arms accept "active" and "activePlusCritical"; every other input, including "pinned", becomes "pinned" (settings.rs:440–446). Tests pin "pinned" / "active" / "activePlusCritical" (tests.rs:289–294). UI select options are exactly those three tokens (SettingsSection.tsx:510–516).
"pinned" means the configured list Quote from settings.rs:344–345: "pinned" (the configured list).
"active" means the focused supported app Quote from settings.rs:345: "active" (the focused supported app).
"activePlusCritical" means active plus any pinned provider at or above the warning threshold Quote from settings.rs:345–346: "activePlusCritical" (active plus any pinned provider at or above the warning threshold).
An invalid string normalizes to "pinned" _ arm of normalize_float_bar_selection_mode (settings.rs:444). Applied on load in From<RawSettings> (raw.rs:676–678). Tests: """pinned", "Active""pinned" (tests.rs:295–296). No other accepted tokens exist in that match.
Safe to edit User preference, not an internal migration marker. UI writes it from Preferences (SettingsSection.tsx:503–521). Not marked leave-unchanged like float_bar_show_cost / unrecognized_provider_configs.

UI (not claimed in the table; checked so the report does not invent a control): Preferences select labeled FloatBarProvidersMode = "Providers shown" (en-US.ftl:736). Help text describes pinned / active / active+critical (en-US.ftl:737). Select is disabled when saving or !settings.floatBarEnabled (SettingsSection.tsx:509).

float_bar_foreground_detection

Claim in the table Verified against
Field exists and is persisted as float_bar_foreground_detection settings.rs:353; raw.rs:180. Same default serde names.
Type is boolean bool on both (settings.rs:353, raw.rs:180). Table style for other bool fields is boolean.
Default is true (missing key is true, not the bool type default) #[serde(default = "default_true")] on Settings (settings.rs:352) and RawSettings (raw.rs:179). default_true() returns true (settings.rs:562–564). Settings::default sets float_bar_foreground_detection: true (settings.rs:704). Test test_settings_default asserts settings.float_bar_foreground_detection (tests.rs:13). There is no extra normalize: From<RawSettings> copies the bool through (raw.rs:679).
When false, "active" / "activePlusCritical" keep the pinned list and do not read the focused window Quote from settings.rs:350–351: When false, active / active-plus-critical modes keep the pinned list and do not read the focused window. Table uses the stored tokens so a hand-editor can copy them.
Safe to edit User preference. UI toggle writes it (SettingsSection.tsx:523–537).

UI (not claimed in the table): Toggle labeled WatchFocusedApp = "Watch focused app" (en-US.ftl:741). Disabled when saving or float bar is off or selection mode is "pinned" (SettingsSection.tsx:531–535).

Claims I did not write

  • I did not invent extra allowed values (Active, active_plus_critical, active+critical, etc.).
  • I did not claim a normalize function on the bool. There is none.
  • I did not put UI labels or the pinned-mode disable rule into the table. Those are UI, not the on-disk schema. The disable rule was read at SettingsSection.tsx:531–535; the persisted value still stores if a hand-edit sets it while mode is "pinned".
  • I did not add a markdown-completeness unit test. None exists (rg of rust/, apps/, .github/ for SETTINGS_JSON / settings.json.md returned no hits). Rule 6 (fail-without-fix) does not apply to a table row unless a test already pins the table.

Sweep results

1. Settings / RawSettings vs top-level table

Extracted every pub field on Settings (settings.rs:96–391) and every field on RawSettings (raw.rs:16–199), then diffed against the table after the edit.

  • Settings pub fields: 68. Table rows after the edit: 68.
  • In Settings but not table, before the edit: float_bar_selection_mode, float_bar_foreground_detection. After: none.
  • In table but not Settings: none.
  • Field order now matches Settings declaration order (python check: fields == table_fields).

RawSettings fields not on Settings (28 legacy flat keys): claude_usage_source, codex_usage_source, codex_cookie_source, codex_historical_tracking, codex_openai_web_extras, claude_cookie_source, cursor_cookie_source, opencode_cookie_source, opencode_workspace_id, factory_cookie_source, alibaba_cookie_source, alibaba_cookie_header, alibaba_api_region, kimi_cookie_source, kimi_manual_cookie_header, minimax_cookie_source, augment_cookie_source, augment_cookie_header, amp_cookie_source, amp_cookie_header, ollama_cookie_source, ollama_cookie_header, zai_api_region, jetbrains_ide_base_path, minimax_cookie_header, minimax_api_token, minimax_api_region, claude_avoid_keychain_prompts.

These are load-only migration fields (raw.rs:72–128). RawSettings docs say saves go through Settings Serialize and write only the new format (raw.rs:12–13). SETTINGS_JSON.md:100–102 (after the insert: lines 100–102 in the original file at 98–100) already says legacy flat fields are accepted on load and migrated into provider_configs. I did not add them as top-level table rows: they are not current persisted settings.

No other omitted top-level persisted Settings field. Nothing else of this class to add.

2. provider_configs vs ProviderConfig

ProviderConfig (types.rs:278–311): cookie_source, usage_source, api_region, manual_cookie_header, api_token, workspace_id, gateway_url, ide_base_path, openai_web_extras, spark_usage_visible, historical_tracking, avoid_keychain_prompts.

Documented: all of those except manual_cookie_header and api_token.

Mismatches (left out on purpose):

  • manual_cookie_header#[serde(default, skip_serializing)] (types.rs:288–289). Comment: accepted only to migrate older settings; secrets must never be serialized back into the general settings document (types.rs:285–287).
  • api_token — same skip (types.rs:290–291).

SETTINGS_JSON.md Secrets section already says API keys and manual cookies live in DPAPI stores, not settings.json. Adding those two as Safe-to-edit rows would contradict that and the skip. They are not omitted persisted settings of the same class as the float-bar fields.

Documented usage_source default "auto" is still true: accessor Settings::usage_source unwraps to DEFAULT_PROVIDER_SOURCE (settings.rs:1172–1178), and DEFAULT_PROVIDER_SOURCE is "auto" (settings.rs:574). I did not change that row.

3. Other docs (except docs/audit/)

rg for float_bar_selection_mode, float_bar_foreground_detection, settings-schema completeness, and float-bar setting lists in docs/ excluding docs/audit/:

  • docs/SETTINGS_JSON.md — the completeness claim at lines 5–6 (mirrors the fields in rust/src/settings.rs and rust/src/settings/raw.rs). This is the file that omitted the two fields. Fixed.
  • docs/CLI.md:256 — link only: - [SETTINGS_JSON.md](SETTINGS_JSON.md). Does not list fields.
  • docs/DATA_SOURCES.md:21 — link only: schema pointer to SETTINGS_JSON.md. Does not list fields.
  • docs/CEILING_UI.md — visual system; no settings-schema field list.
  • README.md, CHANGELOG.md, CONTRIBUTING.md, docs/HANDOFF.md, docs/BUILDING.md, rust/CHANGELOG.md — no hits for these two field names.

No other maintained doc claims completeness and omits these two fields. No second schema-doc fix.

4. Tests

No existing test pins SETTINGS_JSON.md. I did not invent one. Rule 6 does not apply.

I did not run cargo fmt, cargo clippy, or cargo test. CI required jobs (.github/workflows/ci.yml) are Frontend (pnpm test / pnpm build), Rust/shared (cargo fmt --all --check, cargo test --manifest-path rust/Cargo.toml, cargo clippy ... -D warnings), and Rust/desktop (cargo test / clippy on the Tauri crate). None of those read this markdown table. This change cannot make those jobs fail, and running them would not verify the table.

Gaps / what I did not do

  • Did not change Rust, TypeScript, locale, or CHANGELOG.
  • Did not touch docs/audit/.
  • Did not touch other worktrees (ceiling-sbs-872, ceiling-sbs-876, cubby*, toolport*, matteshot*).
  • Did not push, merge, open GitHub issues, or comment/close/edit Linear SBS-877.
  • Did not add a completeness test.
  • Did not re-document provider_metrics allowed values, threshold object shape, or other existing table notes. Those rows were not in this ticket; I did not re-verify every existing note, only the two new rows plus the sweep diffs above.
  • Did not verify Windows UI live (this environment is Linux; this is a schema-doc change).
  • Did not execute a hand-edit of a real settings.json on Windows.
  • Ticket notes cited settings.rs ~327–331 and raw.rs ~171–172. On this tree the fields are at settings.rs:344–353 and raw.rs:177–180. The code on disk won; I used the lines I opened.

What this change makes more likely (rule 9)

  • Hand-edits of "active" / "activePlusCritical" will happen more often. Downstream of that, foreground-window matching (apps/desktop-tauri/src-tauri/src/foreground.rs) runs when detection is on and mode is not pinned. Any latent matching bug will fire more often for people who only use the JSON file.
  • People will type "Active" or "active_plus_critical". Normalize already maps those to "pinned" (settings.rs:444, tests tests.rs:295–296). The table now states that fallback, so a failed hand-edit looks like “it ignored me and stayed pinned” rather than an undocumented no-op. That silent fallback was already the load behavior.
  • Setting float_bar_foreground_detection to false while mode is "pinned" will look like a no-op in the UI (toggle is disabled in pinned mode) but the value persists and applies the next time mode is active. That was already true; documenting the bool makes that sequence more likely.
  • The completeness claim on lines 5–6 is now true for top-level Settings fields. Future omitted fields will be harder to notice without a table test. Drift is still likely because no test pins the table.

Whether I committed

Yes. Local commit 3b66db3d on fix/sbs-877-settings-json-float-bar-fields (docs/SETTINGS_JSON.md only, +2 lines). Not pushed. Every new token was checked against source; the sweep found no second omitted persisted top-level field. Quality-gate items that apply to a table row (claims, sweep, no invented test) passed.

Note

Document float_bar_selection_mode and float_bar_foreground_detection fields in SETTINGS_JSON.md

Adds two previously undocumented top-level fields to the SETTINGS_JSON.md reference table.

  • float_bar_selection_mode (default "pinned") controls which windows are selected by the float bar, with documented behavior for "pinned", "active", and "activePlusCritical" values including matching rules and fallback behavior.
  • float_bar_foreground_detection (default true) is a boolean that affects behavior when active selection modes are in use.

Macroscope summarized 03217ee.

…in SETTINGS_JSON.md.

The schema doc claimed to mirror settings.rs while omitting two shipped float-bar fields.
@cloudflare-workers-and-pages

cloudflare-workers-and-pages Bot commented Aug 16, 2026

Copy link
Copy Markdown
Contributor

Deploying with  Cloudflare Workers  Cloudflare Workers

The latest updates on your project. Learn more about integrating Git with Workers.

Status Name Latest Commit Preview URL Updated (UTC)
✅ Deployment successful!
View logs
ceiling 03217ee Commit Preview URL

Branch Preview URL
Aug 16 2026, 11:33 AM

@coderabbitai

coderabbitai Bot commented Aug 16, 2026

Copy link
Copy Markdown

Warning

Review limit reached

You’ve reached a temporary PR review limit under our Fair Usage Limits Policy.

Your recent review volume is higher than typical usage, so adaptive limits are currently applied.

Next review available in: 59 minutes

Limit details: You’ve used all 1 included review currently available under your plan. You completed 92 included PR reviews in the past 7 days; at that activity level, included reviews refill at 1 review per hour.

Enable usage-based reviews in Billing to review now. Otherwise, wait until the next included review is available.
You're only billed for reviews past your plan's rate limits ($0.25/file).

How can I continue?

After more reviews become available, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

To avoid repeated limits, reduce automatic review volume by pausing incremental auto-reviews earlier, using label-based review opt-in, excluding WIP or generated PR titles, or requesting reviews manually when the PR is ready. If your team needs uninterrupted high-volume reviews, an organization admin can enable usage-based reviews.

How do review limits work?

CodeRabbit enforces per-developer PR review limits for each organization. Most developers receive the normal plan review availability.

For paid Pro and Pro+ PR reviews, CodeRabbit uses adaptive limits for sustained high-volume activity. When a developer's recent PR review activity reaches the 95th percentile or higher among CodeRabbit users, additional reviews become available more gradually as earlier reviews age out of the rolling window.

Please refer docs for additional details.

Review details
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro Plus

Run ID: e148fc01-f07c-4e50-8a05-f070932e8a55

📥 Commits

Reviewing files that changed from the base of the PR and between 5ec975c and 03217ee.

📒 Files selected for processing (1)
  • docs/SETTINGS_JSON.md

Comment @coderabbitai help to get the list of available commands.

@github-actions

github-actions Bot commented Aug 16, 2026

Copy link
Copy Markdown

Automated review

New in this pass: 4 issues.

  1. Stickiness sentence is false after a mapped-but-ineligible app

    docs/SETTINGS_JSON.md:73 · disposition: fix-if-quick · confidence: high · severity: medium · quick win

    The new sentence says focusing an unsupported app keeps the last matched provider. snapshot_now writes every match_foreground_provider hit into LAST_ACTIVE with no enabled/error check, and selectVisibleFloatBarProviders then looks that id up only in allEligible (enabled and error-free). Focus Cursor, then Warp/Gemini/Windsurf/Copilot while that provider is off or errored, then Chrome: last-active is the ineligible id, the lookup misses, and the bar shows the full pinned list instead of Cursor.

    Prompt for AI agents

    In docs/SETTINGS_JSON.md around line 73: Qualify the new sentence: last-active is shown only while that provider is still enabled and float-bar eligible; focusing a mapped app that is not eligible replaces last-active and the bar returns to the pinned list. Verify against the current code first; if no longer valid, skip with a brief reason. Keep the change minimal.

  2. activePlusCritical scope misstates empty float_bar_provider_ids

    docs/SETTINGS_JSON.md:73 · disposition: fix-if-quick · confidence: medium · severity: low · quick win

    The new row says activePlusCritical shows "active plus any pinned provider at or above the warning threshold". When float_bar_provider_ids is [] (the default, meaning all enabled providers) the effective pinned set is all enabled providers, not an explicit pinned subset. A user with the default empty list will read "pinned provider" as "explicitly pinned" and expect no critical overlay unless they pinned something, but the implementation will evaluate every enabled provider against the warning threshold and show more icons than documented.

    Prompt for AI agents

    In docs/SETTINGS_JSON.md around line 73: Clarify that "pinned" means the effective display set: float_bar_provider_ids when non-empty, otherwise all enabled providers. State that the warning-threshold check is applied to that effective set. Verify against the current code first; if no longer valid, skip with a brief reason. Keep the change minimal.

  3. Sticky active provider docs omit unavailable-provider fallback

    docs/SETTINGS_JSON.md:73 · disposition: fix-if-quick · confidence: medium · severity: low · quick win

    Docs state focusing an unsupported app keeps the last matched provider and the pinned list is used until something has matched. If that last-matched provider is later disabled, removed from float_bar_provider_ids, or uninstalled, the sticky reference points to a provider no longer in the enabled/effective set. Docs do not say whether the bar keeps showing a stale provider, clears, or falls back to the pinned list, so the observed fallback is undocumented.

    Prompt for AI agents

    In docs/SETTINGS_JSON.md around line 73: Document the fallback: when the sticky last-active provider is no longer enabled/effective, the bar reverts to the pinned list until the next supported foreground match. Verify against the current code first; if no longer valid, skip with a brief reason. Keep the change minimal.

  4. Invalid-string normalization omits case/whitespace handling

    docs/SETTINGS_JSON.md:73 · disposition: fix-if-quick · confidence: medium · severity: low · quick win

    Docs say an invalid string normalizes to "pinned" but do not define what counts as invalid. A user writing "Active", "ACTIVE" or " active " in settings.json will silently fall back to pinned with no error, thinking active mode is enabled. Whether the parser is case-sensitive and whitespace-sensitive determines if this silent fallback occurs on realistic hand-edits.

    Prompt for AI agents

    In docs/SETTINGS_JSON.md around line 73: Document exact matching rules (case-sensitive, no trimming) or make the parser trim/case-fold and document it; add a note that any non-exact value falls back to pinned. Verify against the current code first; if no longer valid, skip with a brief reason. Keep the change minimal.

Resolved since the previous pass: 1.

For coding agents: fix BLOCK and FIX IF QUICK findings now; everything else is tracked or informational; never exceed one CodeRev fix round per PR.

Advisory. Findings generated by grok-subscription and muse-spark-1.2-contributor, each filtered through a 3-vote refutation panel with the changed code in evidence.

…877)

`"active"` does not mean "only the app focused right now". `snapshot_now` writes
a match into `LAST_ACTIVE` and never clears it, and
`selectVisibleFloatBarProviders` keeps that id when the focused window does not
match; before anything has matched it returns the pinned list. A reader of the
old row would expect the bar to drop the provider as soon as focus left a
supported app.
Comment thread docs/SETTINGS_JSON.md Outdated
| `taskbar_widget_open_on_hover` | boolean | `true` | Open the taskbar glance panel after pointer dwell. Safe to edit. |
| `float_bar_density` | string | `"standard"` | `"compact"`, `"standard"`, or `"detailed"`. Safe to edit. |
| `float_bar_information_mode` | string | `"exact"` | `"exact"` or `"calm"`. Safe to edit. |
| `float_bar_selection_mode` | string | `"pinned"` | `"pinned"` (the configured list), `"active"` (the focused supported app), or `"activePlusCritical"` (active plus any pinned provider at or above the warning threshold); an invalid string normalizes to `"pinned"`. The active provider is sticky: focusing an unsupported app keeps the last matched provider, and the pinned list is used until something has matched at least once. Safe to edit. |

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Stickiness sentence is false after a mapped-but-ineligible app · disposition: fix-if-quick · confidence: high · severity: medium · quick win

The new sentence says focusing an unsupported app keeps the last matched provider. snapshot_now writes every match_foreground_provider hit into LAST_ACTIVE with no enabled/error check, and selectVisibleFloatBarProviders then looks that id up only in allEligible (enabled and error-free). Focus Cursor, then Warp/Gemini/Windsurf/Copilot while that provider is off or errored, then Chrome: last-active is the ineligible id, the lookup misses, and the bar shows the full pinned list instead of Cursor.

Prompt for AI agents

Qualify the new sentence: last-active is shown only while that provider is still enabled and float-bar eligible; focusing a mapped app that is not eligible replaces last-active and the bar returns to the pinned list. Verify against the current code first; if no longer valid, skip with a brief reason. Keep the change minimal.

CodeRev · advisory

Comment thread docs/SETTINGS_JSON.md Outdated
| `taskbar_widget_open_on_hover` | boolean | `true` | Open the taskbar glance panel after pointer dwell. Safe to edit. |
| `float_bar_density` | string | `"standard"` | `"compact"`, `"standard"`, or `"detailed"`. Safe to edit. |
| `float_bar_information_mode` | string | `"exact"` | `"exact"` or `"calm"`. Safe to edit. |
| `float_bar_selection_mode` | string | `"pinned"` | `"pinned"` (the configured list), `"active"` (the focused supported app), or `"activePlusCritical"` (active plus any pinned provider at or above the warning threshold); an invalid string normalizes to `"pinned"`. The active provider is sticky: focusing an unsupported app keeps the last matched provider, and the pinned list is used until something has matched at least once. Safe to edit. |

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

activePlusCritical scope misstates empty float_bar_provider_ids · disposition: fix-if-quick · confidence: medium · severity: low · quick win

The new row says activePlusCritical shows "active plus any pinned provider at or above the warning threshold". When float_bar_provider_ids is [] (the default, meaning all enabled providers) the effective pinned set is all enabled providers, not an explicit pinned subset. A user with the default empty list will read "pinned provider" as "explicitly pinned" and expect no critical overlay unless they pinned something, but the implementation will evaluate every enabled provider against the warning threshold and show more icons than documented.

Prompt for AI agents

Clarify that "pinned" means the effective display set: float_bar_provider_ids when non-empty, otherwise all enabled providers. State that the warning-threshold check is applied to that effective set. Verify against the current code first; if no longer valid, skip with a brief reason. Keep the change minimal.

CodeRev · advisory

Comment thread docs/SETTINGS_JSON.md Outdated
| `taskbar_widget_open_on_hover` | boolean | `true` | Open the taskbar glance panel after pointer dwell. Safe to edit. |
| `float_bar_density` | string | `"standard"` | `"compact"`, `"standard"`, or `"detailed"`. Safe to edit. |
| `float_bar_information_mode` | string | `"exact"` | `"exact"` or `"calm"`. Safe to edit. |
| `float_bar_selection_mode` | string | `"pinned"` | `"pinned"` (the configured list), `"active"` (the focused supported app), or `"activePlusCritical"` (active plus any pinned provider at or above the warning threshold); an invalid string normalizes to `"pinned"`. The active provider is sticky: focusing an unsupported app keeps the last matched provider, and the pinned list is used until something has matched at least once. Safe to edit. |

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sticky active provider docs omit unavailable-provider fallback · disposition: fix-if-quick · confidence: medium · severity: low · quick win

Docs state focusing an unsupported app keeps the last matched provider and the pinned list is used until something has matched. If that last-matched provider is later disabled, removed from float_bar_provider_ids, or uninstalled, the sticky reference points to a provider no longer in the enabled/effective set. Docs do not say whether the bar keeps showing a stale provider, clears, or falls back to the pinned list, so the observed fallback is undocumented.

Prompt for AI agents

Document the fallback: when the sticky last-active provider is no longer enabled/effective, the bar reverts to the pinned list until the next supported foreground match. Verify against the current code first; if no longer valid, skip with a brief reason. Keep the change minimal.

CodeRev · advisory

Comment thread docs/SETTINGS_JSON.md Outdated
| `taskbar_widget_open_on_hover` | boolean | `true` | Open the taskbar glance panel after pointer dwell. Safe to edit. |
| `float_bar_density` | string | `"standard"` | `"compact"`, `"standard"`, or `"detailed"`. Safe to edit. |
| `float_bar_information_mode` | string | `"exact"` | `"exact"` or `"calm"`. Safe to edit. |
| `float_bar_selection_mode` | string | `"pinned"` | `"pinned"` (the configured list), `"active"` (the focused supported app), or `"activePlusCritical"` (active plus any pinned provider at or above the warning threshold); an invalid string normalizes to `"pinned"`. The active provider is sticky: focusing an unsupported app keeps the last matched provider, and the pinned list is used until something has matched at least once. Safe to edit. |

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Invalid-string normalization omits case/whitespace handling · disposition: fix-if-quick · confidence: medium · severity: low · quick win

Docs say an invalid string normalizes to "pinned" but do not define what counts as invalid. A user writing "Active", "ACTIVE" or " active " in settings.json will silently fall back to pinned with no error, thinking active mode is enabled. Whether the parser is case-sensitive and whitespace-sensitive determines if this silent fallback occurs on realistic hand-edits.

Prompt for AI agents

Document exact matching rules (case-sensitive, no trimming) or make the parser trim/case-fold and document it; add a note that any non-exact value falls back to pinned. Verify against the current code first; if no longer valid, skip with a brief reason. Keep the change minimal.

CodeRev · advisory

…(SBS-877)

Four things the previous wording got wrong or left out.

"Any pinned provider at or above the warning threshold" reads as "only what I
explicitly pinned", but `float_bar_provider_ids` defaults to empty and `pinned`
in FloatBar.tsx then means every enabled provider, so the critical overlay is
evaluated against a much wider set than a hand-editor expects.

Stickiness is not just about unsupported windows. `snapshot_now` writes every
`match_foreground_provider` hit into `LAST_ACTIVE` with no enabled or error
check, and `selectVisibleFloatBarProviders` looks that id up only in the
eligible set. Focus a mapped app whose provider is off or failing and the sticky
id becomes unusable, so the bar drops back to the display set rather than
keeping the provider you last used. Same path covers a provider that is later
disabled or unpinned.

`normalize_float_bar_selection_mode` matches the three tokens exactly, with no
trim and no case folding, so `"Active"` and `" active "` silently become
`"pinned"`. The row now says so rather than leaving "an invalid string" to the
reader.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant