Document omitted float-bar selection fields in SETTINGS_JSON.md (SBS-877) - #316
Conversation
Deploying with
|
| Status | Name | Latest Commit | Preview URL | Updated (UTC) |
|---|---|---|---|---|
| ✅ Deployment successful! View logs |
ceiling | 5d154c9 | Commit Preview URL Branch Preview URL |
Aug 16 2026, 04:04 PM |
|
Warning Review limit reachedYou’ve reached a temporary PR review limit under our Fair Usage Limits Policy. Next review available in: 57 minutes Limit details: You’ve used all 1 included review currently available under your plan. You completed 93 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. How can I continue?After more reviews become available, a review can be triggered using the 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 configurationConfiguration used: Organization UI Review profile: CHILL Plan: Pro Plus Run ID: 📒 Files selected for processing (1)
Comment |
Automated reviewNew in this pass: 4 issues.
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 |
…in SETTINGS_JSON.md. The schema doc claimed to mirror settings.rs while omitting two shipped float-bar fields.
…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.
…(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.
03217ee to
5d154c9
Compare
Cuts 1.5.32 from the three PRs that landed today (#315, #316, #317) plus the work already sitting in `Unreleased`. ## Changes - Version bumped to `1.5.32` in `version.env`, `rust/Cargo.toml`, `apps/desktop-tauri/src-tauri/Cargo.toml`, `apps/desktop-tauri/package.json`, and `tauri.conf.json`. Build number 133 to 134, `Cargo.lock` follows. - `Unreleased` moved into a dated `1.5.32 - 2026-08-16` section with a summary line. `Unreleased` is left in place and empty. ## Validation `scripts\local-check.ps1 -All -Version 1.5.32`, run step by step: | Step | Result | |---|---| | Rust format | pass | | Shared Rust clippy | pass | | Tauri Rust clippy | pass | | Shared Rust tests | 1021 passed, see note | | Tauri Rust tests | 567 passed | | Frontend tests | 635 passed, 83 files | | Frontend build | pass | | Store submission preparation | pass | | Release doctor | pass, 3 warnings | **Note on the shared Rust suite.** `cli::tty_runner::tests::test_run_sends_script_through_pty` fails on this machine only, and not for any reason in this diff. It shells out through the npm shim at `%APPDATA%\npm\cmd`, which is not a valid Win32 executable on this box, so `CreateProcessW` returns error 193 before the test reaches anything Ceiling owns. The suite was re-run with `--skip tty_runner`: 1021 passed, 0 failed. CI runs this job on its own runner where the shim is intact. The three release-doctor warnings are all "does not exist yet" and clear when the tag is pushed: no local `v1.5.32` tag, no GitHub release `v1.5.32`, and a local assets directory that belongs to a different machine. ## After merge Tag `v1.5.32` on the merge commit and push it. `release.yml` then builds from the tag, signs through Azure, packages and verifies the installer, and opens a **draft** GitHub release plus the R2 upload. Publishing that draft stays a manual step. <!-- Macroscope's pull request summary starts here --> <!-- Macroscope will only edit the content between these invisible markers, and the markers themselves will not be visible in the GitHub rendered markdown. --> <!-- If you delete either of the start / end markers from your PR's description, Macroscope will append its summary at the bottom of the description. --> > [!NOTE] > ### Release version 1.5.32 > Bumps version identifiers across all package manifests and build config to 1.5.32, with build number incremented to 134. Updates [CHANGELOG.md](https://github.com/tsouth89/ceiling/pull/318/files#diff-06572a96a58dc510037d5efa622f9bec8519bc1beab13c9f251e97e657a9d4ed) with Added, Security, Fixed, and Internal notes for the release. > > <!-- Macroscope's review summary starts here --> > > <sup><a href="https://app.macroscope.com">Macroscope</a> summarized bb5b64e.</sup> > <!-- Macroscope's review summary ends here --> > <!-- Macroscope's pull request summary ends here --> <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit - **New Features** - Added provider outage badges and app-aware floating-bar selection. - Added activity heatmaps to Charts. - Added spend anomaly warnings. - Updated the release to version 1.5.32. - **Bug Fixes** - Improved provider parsing, account selection, session discovery, locking, localization, theming, and unavailable-state handling. - Improved price and chart cache reliability, credential handling, and CLI log cleanup. - **Security** - Restricted loopback access in production webview builds. <!-- end of auto-generated comment: release notes by coderabbit.ai --> --------- Co-authored-by: tsouth89 <tsouth89@users.noreply.github.com>
SBS-877 implementation report
Branch:
fix/sbs-877-settings-json-float-bar-fieldsat5ec975cd(origin/main).Worktree:
/home/box/projects/ceiling-sbs-877only.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_modeandfloat_bar_contrast:float_bar_selection_mode"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_detectiontruefalse,"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.jsoncan 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_modefloat_bar_selection_moderust/src/settings.rs:348(pub float_bar_selection_mode: String);rust/src/settings/raw.rs:178;Settingsuses default serde field names (settings.rs:93–96, norename_all). Deserialize goes throughRawSettings(settings.rs:95).Stringon bothSettings(settings.rs:348) andRawSettings(raw.rs:178). Table style for otherStringfields isstring."pinned"default_float_bar_selection_mode()returns"pinned".to_string()(settings.rs:433–435).Settings::defaultassignsdefault_float_bar_selection_mode()(settings.rs:703). BothSettingsandRawSettingsuse#[serde(default = "default_float_bar_selection_mode")](settings.rs:347,raw.rs:177). Testtest_settings_defaultassertssettings.float_bar_selection_mode == "pinned"(tests.rs:12)."pinned","active","activePlusCritical"settings.rs:344–346).normalize_float_bar_selection_modematch 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 listsettings.rs:344–345:"pinned" (the configured list)."active"means the focused supported appsettings.rs:345:"active" (the focused supported app)."activePlusCritical"means active plus any pinned provider at or above the warning thresholdsettings.rs:345–346:"activePlusCritical" (active plus any pinned provider at or above the warning threshold)."pinned"_arm ofnormalize_float_bar_selection_mode(settings.rs:444). Applied on load inFrom<RawSettings>(raw.rs:676–678). Tests:""→"pinned","Active"→"pinned"(tests.rs:295–296). No other accepted tokens exist in that match.SettingsSection.tsx:503–521). Not marked leave-unchanged likefloat_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 whensavingor!settings.floatBarEnabled(SettingsSection.tsx:509).float_bar_foreground_detectionfloat_bar_foreground_detectionsettings.rs:353;raw.rs:180. Same default serde names.boolon both (settings.rs:353,raw.rs:180). Table style for otherboolfields isboolean.true(missing key istrue, not the bool type default)#[serde(default = "default_true")]onSettings(settings.rs:352) andRawSettings(raw.rs:179).default_true()returnstrue(settings.rs:562–564).Settings::defaultsetsfloat_bar_foreground_detection: true(settings.rs:704). Testtest_settings_defaultassertssettings.float_bar_foreground_detection(tests.rs:13). There is no extra normalize:From<RawSettings>copies the bool through (raw.rs:679).false,"active"/"activePlusCritical"keep the pinned list and do not read the focused windowsettings.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.SettingsSection.tsx:523–537).UI (not claimed in the table): Toggle labeled
WatchFocusedApp="Watch focused app"(en-US.ftl:741). Disabled whensavingor float bar is off or selection mode is"pinned"(SettingsSection.tsx:531–535).Claims I did not write
Active,active_plus_critical,active+critical, etc.).SettingsSection.tsx:531–535; the persisted value still stores if a hand-edit sets it while mode is"pinned".rust/,apps/,.github/forSETTINGS_JSON/settings.json.mdreturned 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/RawSettingsvs top-level tableExtracted every
pubfield onSettings(settings.rs:96–391) and every field onRawSettings(raw.rs:16–199), then diffed against the table after the edit.Settingspub fields: 68. Table rows after the edit: 68.Settingsbut not table, before the edit:float_bar_selection_mode,float_bar_foreground_detection. After: none.Settings: none.Settingsdeclaration order (python check:fields == table_fields).RawSettingsfields not onSettings(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).RawSettingsdocs say saves go throughSettingsSerialize 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 intoprovider_configs. I did not add them as top-level table rows: they are not current persisted settings.No other omitted top-level persisted
Settingsfield. Nothing else of this class to add.2.
provider_configsvsProviderConfigProviderConfig(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_headerandapi_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.mdSecrets section already says API keys and manual cookies live in DPAPI stores, notsettings.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_sourcedefault"auto"is still true: accessorSettings::usage_sourceunwraps toDEFAULT_PROVIDER_SOURCE(settings.rs:1172–1178), andDEFAULT_PROVIDER_SOURCEis"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 indocs/excludingdocs/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 toSETTINGS_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, orcargo 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/clippyon 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
docs/audit/.ceiling-sbs-872,ceiling-sbs-876,cubby*,toolport*,matteshot*).provider_metricsallowed 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.settings.jsonon Windows.settings.rs~327–331 andraw.rs~171–172. On this tree the fields are atsettings.rs:344–353andraw.rs:177–180. The code on disk won; I used the lines I opened.What this change makes more likely (rule 9)
"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."Active"or"active_plus_critical". Normalize already maps those to"pinned"(settings.rs:444, teststests.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.float_bar_foreground_detectiontofalsewhile 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.Settingsfields. 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
3b66db3donfix/sbs-877-settings-json-float-bar-fields(docs/SETTINGS_JSON.mdonly, +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_modeandfloat_bar_foreground_detectionfields in SETTINGS_JSON.mdAdds 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(defaulttrue) is a boolean that affects behavior when active selection modes are in use.Macroscope summarized 5d154c9.