Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 16 additions & 4 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,21 @@

## [Ceiling] Unreleased

## [Ceiling] 1.5.37 - 2026-09-07

Codex usage on GPT-6 Astra finally prices correctly, so an active Astra day no longer reads as $0.00 on Charts. The rest of this release applies the same honesty to failures elsewhere: a fetch that cannot read usage reports an error instead of a healthy 0%, one Claude seat's rate-limit backoff stays with that seat, and capacity baselines stop blurring directory seats that share a login email.

Local state gets more careful too. A settings file that cannot be decrypted is quarantined instead of silently replaced, timed-out provider CLIs are killed instead of orphaned, and MCP's Cursor status ranks the same window the desktop strip shows.

### Fixed
- **An unreadable `settings.json` is no longer overwritten by the next save.** Parse failures already moved the file to `.bak` (SBS-954), but a DPAPI unprotect failure, an unsupported ProtectedFile version, or IO on an existing file loaded as defaults with no backup. `try_update` then replaced the live undecodable bytes. Those read failures now quarantine the same way, and the account ledger persist path fails closed instead of rewriting sightings from an empty snapshot. Closes SBS-1074.
- **MCP `get_status` now ranks Cursor the way the strip does.** After SBS-1055, `remaining_percent` used generic exhausted-first ranking over primary/secondary/tertiary, so a hotter Plan could hide Auto, and the widget snapshot still omitted `cursor-api` / on-demand while the docs claimed strip parity. Cursor now uses `cursorStripWindow` (hottest Auto/API with room, then on-demand, Plan last), those extras persist on the snapshot, and the multi-account seat picker compares the same window. Closes SBS-1076.
- **Capacity baselines keep Codex directory seats separate.** The observation scope hashed provider, source, email, and org only, so a personal and a Team seat sharing a login email shared one baseline: a drop on one seat read as a confirmed surprise reset on the other, and a missing core window was flagged unavailable on both. The directory account id is now part of the scope. Ambient seats re-key once on upgrade and rebuild their baseline from the next reading. Fixes SBS-1079.
- **A failed usage fetch reports an error instead of a healthy 0%.** Vertex AI's Resource Manager lookup, Amp, Kiro, and MiniMax turned failed or unreadable responses into a 0% reading, so an outage painted as an empty, healthy pool. Those paths fail closed now, and an errored snapshot is dropped from the widget snapshot so MCP and the statusline cannot publish the dummy 0% either. Closes SBS-1061.
- **Timed-out Kiro, Augment, and Vertex CLI fetches no longer leave orphaned children.** Those providers spawned `tokio::process::Command` without `kill_on_drop`, so a desktop refresh timeout dropped the `Child` and the CLI kept running. Fetch-path commands now kill on cancel; Augment's inner 15s deadline also kill+waits like `command_runner`. Closes SBS-1078.
- **A 429 on one Claude seat no longer pauses the others.** The OAuth rate-limit backoff was one global gate, so a rate limit on the personal seat also stopped the work seat sharing the same login email. Backoff is now keyed by config directory, the same seat identity account isolation and pace warnings already use. Closes SBS-1064.
- **Codex usage on GPT-6 Astra now has a price.** Astra tokens scanned fine from local logs but were missing from the pricing table, so an active Astra day read as $0.00 on Charts with zero percent of tokens priced. The model is priced at OpenAI's standard rates ($10 input / $1 cached input / $50 output per 1M), bare `gpt-6` maps to it, and Codex usage of Astra does not add the long-context surcharge. Fixes #413.

## [Ceiling] 1.5.36 - 2026-08-23

This release closes out the current maintenance queue with safer local state, more accurate usage and cost reporting, and better behavior across the desktop, CLI, and MCP server. It also adds multi-account CLI usage, restores detached Settings window geometry, and strengthens accessibility regression coverage.
Expand All @@ -12,17 +27,14 @@ The Windows server token now rotates after unsafe exposure. Concurrent and corru
- **A leaked `serve.token` is rotated on Windows, not just Unix.** After SBS-953, a world-readable token was replaced on Unix, but Windows still tightened the DACL and reused the same secret. The ACL is now inspected before tightening; if anyone other than the current user, SYSTEM, or Administrators can read the file, the token is replaced. Closes SBS-1043.

### Fixed
- **An unreadable `settings.json` is no longer overwritten by the next save.** Parse failures already moved the file to `.bak` (SBS-954), but a DPAPI unprotect failure, an unsupported ProtectedFile version, or IO on an existing file loaded as defaults with no backup. `try_update` then replaced the live undecodable bytes. Those read failures now quarantine the same way, and the account ledger persist path fails closed instead of rewriting sightings from an empty snapshot. Closes SBS-1074.
- **MCP `get_status` now ranks Cursor the way the strip does.** After SBS-1055, `remaining_percent` used generic exhausted-first ranking over primary/secondary/tertiary, so a hotter Plan could hide Auto, and the widget snapshot still omitted `cursor-api` / on-demand while the docs claimed strip parity. Cursor now uses `cursorStripWindow` (hottest Auto/API with room, then on-demand, Plan last), those extras persist on the snapshot, and the multi-account seat picker compares the same window. Closes SBS-1076.
- **Timed-out Kiro, Augment, and Vertex CLI fetches no longer leave orphaned children.** Those providers spawned `tokio::process::Command` without `kill_on_drop`, so a desktop refresh timeout dropped the `Child` and the CLI kept running. Fetch-path commands now kill on cancel; Augment's inner 15s deadline also kill+waits like `command_runner`. Closes SBS-1078.
- **Frontend tests now catch accessibility regressions automatically.** A shared axe assertion checks representative quota cards, mini charts, and update banners in the existing Frontend CI job. Color contrast remains outside jsdom coverage because it requires a rendered browser. Fixes #222.
- **`usage --all-accounts` now fetches every configured Codex and Claude account.** Account fetches run with bounded concurrency, preserve configured order, and report failures independently. Text and JSON identify each configured account while the default output remains unchanged. Fixes #274.
- **The detached Settings window now reopens where you left it.** Its saved size and position are restored and clamped on screen instead of being overwritten by a second frontend resize on every open. Closes #275.
- **`serve --refresh-interval` now controls response caching.** Successful usage and cost responses are cached separately by provider selection for the requested TTL. A zero interval disables caching, and provider failures are retried on the next request. Fixes #273.
- **Codex latest-session cost follows transcript time.** Copying or touching an older rollout no longer makes it replace a newer session in local cost summaries. Fixes #271.
- **A corrupt `window_geometry.json` no longer wipes other windows' saved positions.** SBS-1024 locked the persist so two surfaces could not drop each other's keys, but a file that would not read or parse still loaded as empty defaults, and the next save replaced the whole file with only the window that just moved. Persist now refuses that write — the same fail-closed rule API keys already use — instead of rewriting siblings to an empty store. Closes SBS-1041.
- **Loading settings no longer rewrites another install's start-at-login command.** Every `Settings::load` repaired `HKCU\...\Run\Ceiling` whenever the value was not the quoted path of this process. A portable CLI or a second tree therefore replaced the installed desktop's startup entry, and any extra arguments were stripped. Repair now runs only when this process owns that entry — the same intended exe, or a stale `codexbar-cli.exe` / `codexbar-desktop.exe` sibling in the same directory — and leaves custom arguments and other trees alone. Closes SBS-1053.
- **MCP `get_status` no longer hides an exhausted Weekly behind a healthy session.** Top-level `remaining_percent` copied only `usage.primary`, so a Claude/Codex 5-hour window with room made the advertised cap-check sink look fine while Weekly was already at 100%. Claude/Codex now rank primary, secondary, and tertiary (exhausted first, then highest used %). Cursor's parallel Auto/API path landed in SBS-1076. Closes SBS-1055.
- **MCP `get_status` no longer hides an exhausted Weekly behind a healthy session.** Top-level `remaining_percent` copied only `usage.primary`, so a Claude/Codex 5-hour window with room made the advertised cap-check sink look fine while Weekly was already at 100%. It now uses the same constraining-window ranking as the desktop strip across primary, secondary, and tertiary (exhausted first, then highest used %). Closes SBS-1055.
- **Remembered window positions no longer drop a sibling when two surfaces save at once.** `window_geometry.json` was updated with an unlocked read-modify-write, so moving Settings while the float bar or Pop Out also wrote could replace the file with a snapshot that had never seen the other key. Geometry persist now holds the same cross-process state lock as settings and credentials. Closes SBS-1024.
- **`codexbar` with no subcommand now runs `usage`.** CLI.md and `--help` already called usage the default command, but a bare `codexbar` printed an error asking for an explicit subcommand. It now does what those docs said. Closes SBS-1026.
- **A corrupt `settings.json` is no longer renamed to `.bak` without the state lock.** SBS-954 moved an unparseable file aside so the next save could not overwrite it, but `Settings::load` did that rename before taking the lock. A concurrent `try_update` that had already written a good repair could then have that repair moved to `settings.json.bak`. The unlocked load now only parses; if the file is corrupt (or still carries embedded credentials) it takes the lock, re-reads, and quarantines only then. Closes SBS-1029.
Expand Down
4 changes: 2 additions & 2 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion apps/desktop-tauri/package.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"name": "desktop-tauri",
"private": true,
"version": "1.5.36",
"version": "1.5.37",
"packageManager": "pnpm@10.18.1",
"type": "module",
"scripts": {
Expand Down
2 changes: 1 addition & 1 deletion apps/desktop-tauri/src-tauri/Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[package]
name = "codexbar-desktop-tauri"
version = "1.5.36"
version = "1.5.37"
edition = "2024"
publish = false

Expand Down
2 changes: 1 addition & 1 deletion apps/desktop-tauri/src-tauri/tauri.conf.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"$schema": "https://schema.tauri.app/config/2",
"productName": "Ceiling",
"version": "1.5.36",
"version": "1.5.37",
"identifier": "io.github.tsouth89.ceiling",
"build": {
"beforeDevCommand": "pnpm run dev",
Expand Down
2 changes: 1 addition & 1 deletion rust/Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[package]
name = "codexbar"
version = "1.5.36"
version = "1.5.37"
edition = "2024"
authors = ["Ceiling Contributors"]
description = "Local-first Windows companion for monitoring AI capacity and reset times"
Expand Down
4 changes: 2 additions & 2 deletions version.env
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
MARKETING_VERSION=1.5.36
BUILD_NUMBER=138
MARKETING_VERSION=1.5.37
BUILD_NUMBER=139
Loading