cctally 1.21.0 → 1.21.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -5,6 +5,11 @@ based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/).
5
5
 
6
6
  ## [Unreleased]
7
7
 
8
+ ## [1.21.1] - 2026-05-28
9
+
10
+ ### Fixed
11
+ - **`cctally statusline` now shows the correct 7d percentage after an Anthropic mid-week reset (or in-place credit) instead of staying pinned to the pre-reset peak.** The statusline's 7d number is monotonic-clamped against a high-water mark read from `weekly_usage_snapshots`, but the clamp keyed only on `week_start_date` — `SELECT MAX(weekly_percent) WHERE week_start_date = ?`. When Anthropic resets a 7d window mid-cycle, the post-reset snapshots keep the *same* `week_start_date` (and `week_end_at`) as the pre-reset ramp, so the bucket-wide `MAX` returned the stale pre-reset peak (e.g. 41%) and clamped the true post-reset value (e.g. 2%) back up to it; the statusline read e.g. `7d 41%` while `cctally report`/`forecast` and the dashboard — which segment the week at the reset via `week_reset_events` — correctly showed 2%. The 5h segment was never affected because a 5h reset mints a new `five_hour_window_key` that naturally scopes its `MAX`. The clamp now mirrors the CLI/dashboard segmentation (`_apply_reset_events_to_subweeks`: the post-reset window's `start_ts` becomes `effective_reset_at_utc`) by flooring the `MAX` to snapshots captured at/after the latest reset effective within the current window — `... AND unixepoch(captured_at_utc) >= unixepoch(<floor>)`, with `unixepoch()` on both sides because reset rows carry mixed offset spellings (`+00:00` and legacy `+03:00`) while `captured_at_utc` uses `Z`, so a lexical comparison would misorder them (the same rule the 5h-block cross-reset flag follows). Weeks with no reset event take the unchanged legacy query, so the normal monotonic-within-window behavior is byte-identical. Regression: new `extensions-hwm-7d-post-reset` fixture in `bin/cctally-statusline-test` (33 scenarios) seeds a pre-reset peak + post-reset row sharing one `week_start_date` plus a `week_reset_events` row and asserts the rendered line reads `7d 2%`, not `7d 41%`.
12
+
8
13
  ## [1.21.0] - 2026-05-28
9
14
 
10
15
  ### Added
package/bin/cctally CHANGED
@@ -4953,17 +4953,56 @@ def _build_statusline_injections(warn_once):
4953
4953
  pass
4954
4954
  if seven_resets is not None:
4955
4955
  try:
4956
- # Seven-day window: derive week_start_date from the
4957
- # resets_at epoch (reset - 7 days, UTC date).
4958
- week_start_date = dt.datetime.fromtimestamp(
4959
- int(seven_resets) - 7 * 86400, tz=dt.timezone.utc,
4960
- ).date().isoformat()
4961
- row = conn.execute(
4962
- "SELECT MAX(weekly_percent) "
4963
- "FROM weekly_usage_snapshots "
4964
- "WHERE week_start_date = ?",
4965
- (week_start_date,),
4956
+ # Seven-day window bounds from the resets_at epoch:
4957
+ # week_end = reset; week_start = reset - 7 days. The
4958
+ # date form is the snapshot lookup key (week_start_date
4959
+ # is deliberately NOT re-anchored across a mid-week
4960
+ # reset — see _apply_reset_events_to_subweeks).
4961
+ week_end_dt = dt.datetime.fromtimestamp(
4962
+ int(seven_resets), tz=dt.timezone.utc,
4963
+ )
4964
+ week_start_dt = week_end_dt - dt.timedelta(days=7)
4965
+ week_start_date = week_start_dt.date().isoformat()
4966
+ # Reset-aware floor. An Anthropic mid-week reset / in-
4967
+ # place credit leaves the pre-reset peak snapshots in
4968
+ # this SAME week_start_date bucket (the boundary the
4969
+ # snapshots carry does not change). A naive bucket-wide
4970
+ # MAX(weekly_percent) would clamp the post-reset value
4971
+ # UP to that stale peak — the statusline would show the
4972
+ # pre-reset 7d %. Mirror the CLI/dashboard segmentation
4973
+ # (_apply_reset_events_to_subweeks: post-reset window
4974
+ # start_ts := effective_reset_at_utc) by flooring the
4975
+ # MAX to snapshots captured at/after the latest reset
4976
+ # effective WITHIN this window. unixepoch() on both
4977
+ # sides — reset rows carry mixed offset spellings
4978
+ # (+00:00 / +03:00) while captured_at_utc uses 'Z', so a
4979
+ # lexical compare would misorder them (same rule as the
4980
+ # 5h-block cross-reset flag).
4981
+ floor_row = conn.execute(
4982
+ "SELECT MAX(effective_reset_at_utc) "
4983
+ "FROM week_reset_events "
4984
+ "WHERE unixepoch(effective_reset_at_utc) >= unixepoch(?) "
4985
+ " AND unixepoch(effective_reset_at_utc) < unixepoch(?)",
4986
+ (week_start_dt.isoformat(), week_end_dt.isoformat()),
4966
4987
  ).fetchone()
4988
+ floor_iso = (
4989
+ floor_row[0] if floor_row and floor_row[0] else None
4990
+ )
4991
+ if floor_iso is not None:
4992
+ row = conn.execute(
4993
+ "SELECT MAX(weekly_percent) "
4994
+ "FROM weekly_usage_snapshots "
4995
+ "WHERE week_start_date = ? "
4996
+ " AND unixepoch(captured_at_utc) >= unixepoch(?)",
4997
+ (week_start_date, floor_iso),
4998
+ ).fetchone()
4999
+ else:
5000
+ row = conn.execute(
5001
+ "SELECT MAX(weekly_percent) "
5002
+ "FROM weekly_usage_snapshots "
5003
+ "WHERE week_start_date = ?",
5004
+ (week_start_date,),
5005
+ ).fetchone()
4967
5006
  if row and row[0] is not None:
4968
5007
  seven_hwm = float(row[0])
4969
5008
  except Exception:
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "cctally",
3
- "version": "1.21.0",
3
+ "version": "1.21.1",
4
4
  "description": "Claude Code usage tracker and local dashboard for Pro/Max subscription limits - weekly cost-per-percent trend, quota forecasts, threshold alerts. ccusage-compatible.",
5
5
  "homepage": "https://github.com/omrikais/cctally",
6
6
  "repository": {