From 15ecb7879748b61919484e2faf094b350e4c1d4f Mon Sep 17 00:00:00 2001 From: Vimox Shah <10022243+vimoxshah@users.noreply.github.com> Date: Mon, 14 Sep 2026 11:41:11 +0530 Subject: [PATCH 1/2] fix(test): skip the app-bundle suite on a Mac that cannot compile SwiftUI MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The suite skipped when `swiftc` was absent, which is not the condition that matters. The Command Line Tools ship `swiftc` but not SwiftUI's macro plugins, so on a Mac with no Xcode `@State` never expands and every view in main.swift collapses into errors about assigning to an immutable `self`. Three tests failed, and the failure read as a defect in the menu bar app rather than a missing toolchain. The probe now compiles the smallest view that needs the plugin, and the skip message names Xcode. Also: the README said 836 tests where the suite has 841, and its link row printed `brew install --cask tokenflow` on its own, which fails — the cask lives in this repo's own tap, so the tap command has to come first. The row points at the Install section, which carries both lines. Co-Authored-By: Claude Opus 5 (1M context) --- README.md | 6 +++--- test/bundle.test.js | 18 ++++++++++++++---- 2 files changed, 17 insertions(+), 7 deletions(-) diff --git a/README.md b/README.md index 0f18149..e53b82a 100644 --- a/README.md +++ b/README.md @@ -49,7 +49,7 @@ per-source and per-model usage, capacity meters and forecast, in light and dark.  ·  📦 @vimoxshah/tokenflow on npm  ·  - 🍺 brew install --cask tokenflow (via this tap) + 🍺 Homebrew (tap, then cask)

**How deep it goes** @@ -62,7 +62,7 @@ per-source and per-model usage, capacity meters and forecast, in light and dark. | **Analytics** | 21 views: overview KPIs with a story strip, receipts per branch and pull request, cost per ticket, session anatomy, live, composition, provider/model intelligence, interfaces, hour×weekday heatmap + calendar, peaks, efficiency ratios, cache health, cost with coverage, model what-if, git correlations (labelled), rhythm and focus, period compare, compare branches, searchable data explorer, annotations, per-field data health | | **Integrations** | A GitHub Action and a **self-hosted GitHub App** (your App, your server, our code) that put a receipt comment and a budget check run on every pull request; receipts as git notes that travel with the code; an **MCP server** so the agent can read its own bill; a **FOCUS-shaped export** for a FinOps tool; **org policy** pulled from a team server you run | | **Live mode** | Watcher daemon, native Swift menu bar app (live sessions, today's receipts, guard state, provider/source/model breakdowns, capacity meters with reset countdowns & ETAs, forecast with stated confidence, MAD-based anomaly alerts, per-source sparklines, appearance toggle), SwiftBar/xbar plugin | -| **Engineering** | Zero runtime dependencies · 836 tests · lint invariants (e.g. "no `\|\| 0` on a token field") · tsc-clean JSDoc types · CI on macOS/Linux/Windows × Node 22/24 | +| **Engineering** | Zero runtime dependencies · 841 tests · lint invariants (e.g. "no `\|\| 0` on a token field") · tsc-clean JSDoc types · CI on macOS/Linux/Windows × Node 22/24 | Zero runtime dependencies. Nothing leaves your machine. No API keys, no accounts, no telemetry. @@ -332,7 +332,7 @@ from `file://` with no server. A full CSV export doubles as a portable dataset: ## Contributing ```bash -npm test # 836 tests: normalization, adapters, analytics, store, receipts, guard +npm test # 841 tests: normalization, adapters, analytics, store, receipts, guard npm run lint # project invariants (incl. "no || 0 on a token field") npm run typecheck # tsc over JSDoc types — must be zero errors npm run validate # self-check: runtime, adapters, store↔cube agreement diff --git a/test/bundle.test.js b/test/bundle.test.js index 7a0cb83..7906e36 100644 --- a/test/bundle.test.js +++ b/test/bundle.test.js @@ -14,22 +14,32 @@ import { execFileSync } from 'node:child_process'; * had a menu bar app with nothing to drive. Both are build-script properties, * invisible to every other test, and only a real build can prove them. * - * Building takes swiftc, so this suite skips anywhere it cannot run: off - * macOS, or on a macOS box without the Command Line Tools. + * Building takes a toolchain that can compile SwiftUI, so this suite skips + * anywhere it cannot run. `swiftc --version` is not that test: the Command Line + * Tools ship swiftc but not SwiftUI's macro plugins, so on a Mac with no Xcode + * `@State` fails to expand and every view in main.swift collapses into errors + * about assigning to an immutable self. That reads as a product defect and is + * not one, so the probe below compiles the smallest thing that needs the + * plugin and skips when it cannot. */ const REPO = path.resolve(path.dirname(url.fileURLToPath(import.meta.url)), '..'); function canBuild() { if (process.platform !== 'darwin') return false; + const dir = fs.mkdtempSync(path.join(os.tmpdir(), 'tf-swift-probe-')); + const file = path.join(dir, 'probe.swift'); try { - execFileSync('swiftc', ['--version'], { stdio: 'ignore', timeout: 20000 }); + fs.writeFileSync(file, 'import SwiftUI\nstruct P: View { @State private var x = 0\n var body: some View { Color.clear.onHover { _ in x = 1 } } }\n'); + execFileSync('swiftc', ['-typecheck', file], { stdio: 'ignore', timeout: 120000 }); return true; } catch { return false; + } finally { + fs.rmSync(dir, { recursive: true, force: true }); } } -const skip = canBuild() ? false : 'needs macOS with swiftc'; +const skip = canBuild() ? false : 'needs macOS with a toolchain that can compile SwiftUI (Xcode, not the Command Line Tools alone)'; function build(outDir, { portable }) { execFileSync('bash', [path.join(REPO, 'scripts', 'build-menubar-app.sh'), outDir], { From 42cdc71e989c2cddb877684ce6619118ef196a3c Mon Sep 17 00:00:00 2001 From: Vimox Shah <10022243+vimoxshah@users.noreply.github.com> Date: Mon, 14 Sep 2026 11:41:28 +0530 Subject: [PATCH 2/2] chore(release): 1.3.5 Co-Authored-By: Claude Opus 5 (1M context) --- CHANGELOG.md | 23 +++++++++++++++++++++++ action/README.md | 2 +- docs/receipts-on-github.md | 2 +- package.json | 2 +- 4 files changed, 26 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index b413ba2..c2147a7 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,6 +3,29 @@ All notable changes to TokenFlow are recorded here. Versions follow [semantic versioning](https://semver.org/spec/v2.0.0.html). +## 1.3.5 — 2026-09-14 + +No change to how TokenFlow reads or prices anything. One test-suite defect and two +documentation corrections. + +### Fixed + +- **`npm test` no longer fails on a Mac without Xcode.** The app-bundle suite skipped when + `swiftc` was absent, which is not the condition that matters: the Command Line Tools ship + `swiftc` but not SwiftUI's macro plugins, so `@State` never expands and every view in + `main.swift` collapses into errors about assigning to an immutable `self`. Three tests + failed, and the failure read as a defect in the menu bar app rather than a missing toolchain. + The probe now compiles the smallest view that needs the plugin, and the skip message names + Xcode. The shipped app is unaffected: CI builds it on a runner with the full toolchain. + +### Docs + +- **The test count reads 841**, which is what the suite has. The README said 836. +- **The README's link row no longer prints half the Homebrew command.** `brew install --cask + tokenflow` on its own fails, because the cask lives in this repo's own tap and the tap + command has to come first. The row now points at the Install section, which carries both + lines. + ## 1.3.4 — 2026-09-07 Interface fixes only; nothing about how TokenFlow reads or prices usage changes. Every one of diff --git a/action/README.md b/action/README.md index fe14fd6..b7cc04b 100644 --- a/action/README.md +++ b/action/README.md @@ -34,7 +34,7 @@ jobs: - uses: actions/checkout@v4 with: fetch-depth: 0 # notes live outside the default shallow fetch - - uses: vimoxshah/tokenflow@v1.3.4 + - uses: vimoxshah/tokenflow@v1.3.5 # or, dogfooding this repo's own checkout: uses: ./ with: token: ${{ secrets.GITHUB_TOKEN }} # default; only pass to override diff --git a/docs/receipts-on-github.md b/docs/receipts-on-github.md index 1cd0855..22e13ec 100644 --- a/docs/receipts-on-github.md +++ b/docs/receipts-on-github.md @@ -44,7 +44,7 @@ network call. - uses: actions/checkout@v4 with: fetch-depth: 0 # notes live outside the default shallow fetch - - uses: vimoxshah/tokenflow@v1.3.4 + - uses: vimoxshah/tokenflow@v1.3.5 with: max-usd: '50' max-usd-per-100-lines: '5' diff --git a/package.json b/package.json index 44fd017..e532c8b 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@vimoxshah/tokenflow", - "version": "1.3.4", + "version": "1.3.5", "description": "Local-first, provider-agnostic analytics for the AI tokens you actually spend. Zero dependencies, nothing leaves your machine.", "type": "module", "license": "MIT",