cctally 1.10.2 → 1.10.3
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 +5 -0
- package/bin/_lib_blocks.py +4 -0
- package/bin/_lib_render.py +5 -4
- package/package.json +1 -1
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.10.3] - 2026-05-21
|
|
9
|
+
|
|
10
|
+
### Fixed
|
|
11
|
+
- `blocks` gap rows now render the correct duration. Pre-fix, `_fmt_gap_duration` in `bin/_lib_render.py` computed `round(total_seconds / 3600)` and clamped sub-hour values to 1, so every gap shorter than 30 minutes surfaced as `"1h gap"` (e.g. a 5-minute or 1-minute gap rendered identically to a 50-minute gap). The bug was hidden until #76: the pre-#76 partition floored block boundaries to 10-minute increments, which usually erased the sub-hour seam between adjacent recorded windows; once #76 routed `(bs, rs)` through `_exact_interval(R)`, real ~1-minute seams became visible and the formatter's coarseness surfaced. The fix mirrors the existing `_fmt_duration_hm` shape: sub-hour gaps render as `"Nm gap"` (with `max(N, 1)` to floor at one minute), 60+ minute gaps render as `"Hh Mm gap"` or `"Hh gap"` when minutes are zero. Additionally, gaps shorter than 60 seconds are suppressed at the phase-3 gap-insertion site in `_group_entries_into_blocks` (`bin/_lib_blocks.py`) — a 1-second seam from a `:59:59` end to a `:00:00` start no longer emits a row. Regression: new `tests/test_blocks_gap_rendering.py` (5 renderer cases — 5m / 30m / 60m / 90m / 12h — plus 2 grouper cases for sub-minute suppression and 65s-threshold boundary); `tests/fixtures/blocks/floor-band-trap/golden-terminal.txt` updated to assert `"5m gap"` on its 5-minute seam. ([#79](https://github.com/omrikais/cctally-dev/issues/79))
|
|
12
|
+
|
|
8
13
|
## [1.10.2] - 2026-05-21
|
|
9
14
|
|
|
10
15
|
### Fixed
|
package/bin/_lib_blocks.py
CHANGED
|
@@ -290,6 +290,10 @@ def _group_entries_into_blocks(
|
|
|
290
290
|
if prev.end_time < b.start_time:
|
|
291
291
|
first_entry_ts = first_entry_ts_by_block.get(id(b), b.start_time)
|
|
292
292
|
prev_actual_end = prev.actual_end_time or prev.end_time
|
|
293
|
+
gap_seconds = (first_entry_ts - prev_actual_end).total_seconds()
|
|
294
|
+
if gap_seconds < 60:
|
|
295
|
+
final_blocks.append(b)
|
|
296
|
+
continue
|
|
293
297
|
final_blocks.append(Block(
|
|
294
298
|
start_time=prev_actual_end,
|
|
295
299
|
end_time=first_entry_ts,
|
package/bin/_lib_render.py
CHANGED
|
@@ -206,10 +206,11 @@ def _render_blocks_table(
|
|
|
206
206
|
return f"{h}h {m:02d}m"
|
|
207
207
|
|
|
208
208
|
def _fmt_gap_duration(total_seconds: float) -> str:
|
|
209
|
-
|
|
210
|
-
if
|
|
211
|
-
|
|
212
|
-
|
|
209
|
+
total_minutes = int(total_seconds / 60)
|
|
210
|
+
if total_minutes < 60:
|
|
211
|
+
return f"{max(total_minutes, 1)}m gap"
|
|
212
|
+
h, m = divmod(total_minutes, 60)
|
|
213
|
+
return f"{h}h {m:02d}m gap" if m else f"{h}h gap"
|
|
213
214
|
|
|
214
215
|
# ── determine if % column is needed ─────────────────────────────────
|
|
215
216
|
max_completed_tokens = 0
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "cctally",
|
|
3
|
-
"version": "1.10.
|
|
3
|
+
"version": "1.10.3",
|
|
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": {
|