codeburn/app
Resham Joshi dbd93fee51
app,dash: render pre-history days as no data, not a currency zero (#765)
* fix(app,dash): render pre-history days as no data, not a currency zero

Days before the first recorded day in history.daily were painted as a real
0.00/0 calls in the daily activity heatmap and the daily spend charts. That
zero is unknown, not measured, so those cells and bars now read "No data
recorded" instead of a currency zero. Genuinely idle days within recorded
history stay as real zeros.

- app: heatmap cells, the daily spend bars, and the daily-by-model columns
  get a distinct no-data style plus a "No data recorded" hover for days before
  the first recorded day.
- dash: the granular line chart drops buckets before the first recorded day so
  no flat zero line is drawn before any history exists.
- data-start is derived in the UI layer from history.daily; payload shape is
  unchanged.

Verified: app vitest 418 pass (7 new for the no-data behavior); app, dash, and
root typecheck clean; dash and app renderer vite builds succeed.

* no-data: cap guard, timezone-free dash trim, StackedBars aria

Three hardening fixes from adversarial review of the no-data rendering:

dataStartKey returns null at the payload's 365-entry history cap, where
the oldest retained entry is no longer the true data start; classifying
past it would label real aged-out history as no data on long custom
ranges. Documented that the install-to-first-use gap reading as no data
is literally accurate: nothing was recorded then either.

The dash granular chart now trims leading zero-only buckets by value
instead of comparing bucket timestamps against date keys, so producer
and viewer timezone skew can never drop a real first-day bucket, and an
all-zero series lands in the established empty state.

StackedBars no-data columns expose their state via aria-label, not only
a title on a non-focusable div.
2026-07-20 08:03:24 -07:00
..
build brand: restore binary 0101 flame across all surfaces 2026-07-17 14:14:40 -07:00
electron test(electron): make dev-resolution tests self-sufficient on fresh clones (#689) 2026-07-20 05:23:28 -07:00
renderer app,dash: render pre-history days as no data, not a currency zero (#765) 2026-07-20 08:03:24 -07:00
scripts fix(app): clean build stamp, splash without hash, About checks for updates 2026-07-17 14:30:00 -07:00
.gitignore feat(app): bundle the CLI inside the packaged app 2026-07-16 09:27:46 -07:00
DISTRIBUTION.md docs: desktop release flow + widened Linux build targets 2026-07-17 15:00:31 -07:00
package-lock.json chore: release 0.9.18 2026-07-20 07:17:05 -07:00
package.json chore: release 0.9.18 2026-07-20 07:17:05 -07:00
README.md feat(app): bundle the CLI inside the packaged app 2026-07-16 09:27:46 -07:00
tsconfig.electron.json feat(app): scaffold Electron+Vite package and codeburn CLI spawn 2026-07-10 15:16:55 -07:00
tsconfig.json fix(app): clean build stamp, splash without hash, About checks for updates 2026-07-17 14:30:00 -07:00
vite.config.ts fix(app): clean build stamp, splash without hash, About checks for updates 2026-07-17 14:30:00 -07:00
vitest.config.ts fix(app): clean build stamp, splash without hash, About checks for updates 2026-07-17 14:30:00 -07:00

CodeBurn Desktop

Electron desktop shell for CodeBurn's local-first usage views. M1 runs as a developer app and reads data by spawning the installed codeburn CLI; it does not run a daemon or HTTP server.

Development

npm --prefix app install
npm --prefix app run dev

Validation:

npm --prefix app run test
npm --prefix app run typecheck

CLI Dependency

Packaged builds ship their own version-matched copy of the codeburn CLI and require nothing installed — the app spawns the bundled CLI with Electron's own binary as Node (ELECTRON_RUN_AS_NODE). In development (Vite dev server) the app uses the repo's freshly-built CLI, and either can be overridden with CODEBURN_BIN or a persisted path file. See DISTRIBUTION.md for the bundling and resolution details. Electron resolves and spawns the CLI from the main process, then sends decoded JSON through the secure preload bridge into the renderer.

This follows the menubar pattern:

  • contextIsolation: true, nodeIntegration: false, and sandbox: true.
  • Renderer code calls window.codeburn only through app/renderer/lib/ipc.ts.
  • Main process handlers return JSON envelopes so structured CLI errors survive IPC.
  • Missing CLI, bad JSON, timeout, and nonzero exits are surfaced as honest UI states.
  • The renderer never imports CodeBurn engine code from src/; the data contract is spawn CLI, decode JSON, poll.

Data Contract

Current bridge calls:

  • Overview: codeburn status --format menubar-json --period <period> [--provider <provider>]
  • Plans: codeburn status --format json --period <period>
  • Models: codeburn models --format json --period <period> [--provider <provider>] [--by-task]
  • Optimize: codeburn yield --format json --period <period>
  • Spend flow: codeburn spend --format flow-json --period <period> [--provider <provider>]
  • Devices: codeburn devices --format json --period <period>
  • Device scan: codeburn devices scan --format json
  • Share status: codeburn share status --format json
  • Identity: codeburn identity --format json

Supported M1 periods are today, week, 30days, month, and all. Provider filtering is passed through where the CLI command supports it.

Sections

  • Overview: daily spend, spend stats, waste summary, and expensive sessions from menubar-json.
  • Spend: project/activity/tool/MCP/subagent lenses plus model-to-project flow.
  • Optimize: waste findings from menubar-json and reverted/abandoned yield data.
  • Models: model and task tables from models --format json.
  • Plans: plan pacing from status --format json.
  • Settings: device identity, nearby scan results, paired-device usage, and M2 visual affordances.

Packaging

npm run package produces an ad-hoc-signed macOS .dmg/.zip (arm64 and x64) via electron-builder, no paid Apple Developer account required. Packaging rebuilds the root CLI and bundles it into the app (Resources/cli), so installs need nothing on the target machine. See DISTRIBUTION.md for build instructions, the bundled-CLI mechanism, artifact locations, and the Gatekeeper first-open story.

M2 Backlog

  • Add Electron autoUpdater (the app already bundles its own version-matched CLI, so end-user installs need nothing on the machine; auto-update is the remaining piece).
  • Keep npm as a separate CLI-user channel at the same version as the desktop app.
  • Add macOS code signing with a paid Developer ID and notarization (ad-hoc packaging exists today; see DISTRIBUTION.md).
  • Add a codeburn desktop launcher subcommand.
  • Implement in-app pairing, approve, pull, and visibility mutations currently shown as M2 affordances.
  • Build the Models Compare sheet.
  • Add light theme support.
  • Expand codeburn optimize --format json with evidence and fix commands so Optimize can show richer actionable fixes.