cctally 1.7.3 → 1.8.0
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 +22 -0
- package/README.md +1 -1
- package/bin/_cctally_alerts.py +12 -5
- package/bin/_cctally_cache.py +12 -11
- package/bin/_cctally_config.py +34 -19
- package/bin/_cctally_core.py +890 -0
- package/bin/_cctally_dashboard.py +175 -233
- package/bin/_cctally_db.py +89 -20
- package/bin/_cctally_record.py +76 -75
- package/bin/_cctally_refresh.py +35 -20
- package/bin/_cctally_setup.py +26 -16
- package/bin/_cctally_sync_week.py +21 -6
- package/bin/_cctally_tui.py +151 -306
- package/bin/_cctally_update.py +11 -16
- package/bin/_lib_aggregators.py +7 -1
- package/bin/_lib_diff_kernel.py +19 -21
- package/bin/_lib_subscription_weeks.py +17 -9
- package/bin/_lib_view_models.py +993 -0
- package/bin/cctally +338 -1055
- package/dashboard/static/assets/{index-DhCnIFq9.js → index-CfXu9Fx_.js} +1 -1
- package/dashboard/static/dashboard.html +1 -1
- package/package.json +10 -8
package/bin/_lib_diff_kernel.py
CHANGED
|
@@ -116,11 +116,25 @@ _resolve_tz = _lib_display_tz._resolve_tz
|
|
|
116
116
|
format_display_dt = _lib_display_tz.format_display_dt
|
|
117
117
|
|
|
118
118
|
|
|
119
|
-
#
|
|
120
|
-
#
|
|
121
|
-
#
|
|
122
|
-
#
|
|
123
|
-
|
|
119
|
+
# === Honest imports from extracted homes ===================================
|
|
120
|
+
# Spec 2026-05-17-cctally-core-kernel-extraction.md §3.3: kernel symbols
|
|
121
|
+
# (Z-leaf + Z-mid) import from _cctally_core. The legacy shim functions
|
|
122
|
+
# for these names are deleted.
|
|
123
|
+
from _cctally_core import (
|
|
124
|
+
open_db,
|
|
125
|
+
_command_as_of,
|
|
126
|
+
_canonicalize_optional_iso,
|
|
127
|
+
parse_iso_datetime,
|
|
128
|
+
)
|
|
129
|
+
|
|
130
|
+
|
|
131
|
+
# === Module-level back-ref shims for helpers that STAY in bin/cctally ======
|
|
132
|
+
# Each shim resolves ``sys.modules['cctally'].X`` at CALL TIME (not bind
|
|
133
|
+
# time), so monkeypatches on cctally's namespace propagate into the moved
|
|
134
|
+
# code unchanged. `get_claude_session_entries` STAYS as a shim even though
|
|
135
|
+
# its natural home is _cctally_cache — tests monkeypatch it via ``ns["X"]``
|
|
136
|
+
# (audited 2026-05-17); a direct import would silently bypass the patches.
|
|
137
|
+
# See spec §3.5 (carve-out) and §3.7 (stays-on-shim allowlist).
|
|
124
138
|
def get_claude_session_entries(*args, **kwargs):
|
|
125
139
|
return sys.modules["cctally"].get_claude_session_entries(*args, **kwargs)
|
|
126
140
|
|
|
@@ -129,10 +143,6 @@ def _resolve_project_key(*args, **kwargs):
|
|
|
129
143
|
return sys.modules["cctally"]._resolve_project_key(*args, **kwargs)
|
|
130
144
|
|
|
131
145
|
|
|
132
|
-
def open_db(*args, **kwargs):
|
|
133
|
-
return sys.modules["cctally"].open_db(*args, **kwargs)
|
|
134
|
-
|
|
135
|
-
|
|
136
146
|
def _iso_z(*args, **kwargs):
|
|
137
147
|
return sys.modules["cctally"]._iso_z(*args, **kwargs)
|
|
138
148
|
|
|
@@ -145,18 +155,6 @@ def _style_ansi(*args, **kwargs):
|
|
|
145
155
|
return sys.modules["cctally"]._style_ansi(*args, **kwargs)
|
|
146
156
|
|
|
147
157
|
|
|
148
|
-
def _command_as_of(*args, **kwargs):
|
|
149
|
-
return sys.modules["cctally"]._command_as_of(*args, **kwargs)
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
def _canonicalize_optional_iso(*args, **kwargs):
|
|
153
|
-
return sys.modules["cctally"]._canonicalize_optional_iso(*args, **kwargs)
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
def parse_iso_datetime(*args, **kwargs):
|
|
157
|
-
return sys.modules["cctally"].parse_iso_datetime(*args, **kwargs)
|
|
158
|
-
|
|
159
|
-
|
|
160
158
|
# Private eprint shim per spec §5.3 (pure layer does not back-import
|
|
161
159
|
# cctally for ubiquitous helpers; eprint isn't actually called by the
|
|
162
160
|
# moved code, but kept here as the canonical pure-layer pattern so
|
|
@@ -73,6 +73,18 @@ _resolve_tz = _lib_display_tz._resolve_tz
|
|
|
73
73
|
_local_tz_name = _lib_display_tz._local_tz_name
|
|
74
74
|
|
|
75
75
|
|
|
76
|
+
# === Honest imports from extracted homes ===================================
|
|
77
|
+
# Spec 2026-05-17-cctally-core-kernel-extraction.md §3.3: kernel symbols
|
|
78
|
+
# import from _cctally_core. `load_config` stays on the _cctally()
|
|
79
|
+
# accessor per spec §3.5 monkeypatch carve-out (tests reach it via
|
|
80
|
+
# ``ns["load_config"]``).
|
|
81
|
+
from _cctally_core import (
|
|
82
|
+
parse_iso_datetime,
|
|
83
|
+
get_week_start_name,
|
|
84
|
+
WEEKDAY_MAP,
|
|
85
|
+
)
|
|
86
|
+
|
|
87
|
+
|
|
76
88
|
@dataclass(frozen=True)
|
|
77
89
|
class SubWeek:
|
|
78
90
|
"""One subscription-week bounded interval.
|
|
@@ -142,7 +154,6 @@ def _clamp_end_ats_to_next_start(
|
|
|
142
154
|
`pairs` must be sorted by start_at ascending. None values are
|
|
143
155
|
passed through unchanged and never participate in clamping.
|
|
144
156
|
"""
|
|
145
|
-
parse_iso_datetime = _cctally().parse_iso_datetime
|
|
146
157
|
n = len(pairs)
|
|
147
158
|
if n < 2:
|
|
148
159
|
return [p[1] for p in pairs]
|
|
@@ -182,7 +193,6 @@ def _apply_overlap_clamp_to_subweeks(weeks: list[SubWeek]) -> list[SubWeek]:
|
|
|
182
193
|
Input must be sorted by start_ts ascending (invariant of
|
|
183
194
|
_compute_subscription_weeks in all three branches).
|
|
184
195
|
"""
|
|
185
|
-
parse_iso_datetime = _cctally().parse_iso_datetime
|
|
186
196
|
if len(weeks) < 2:
|
|
187
197
|
return weeks
|
|
188
198
|
pairs: list[tuple[str | None, str | None]] = [(w.start_ts, w.end_ts) for w in weeks]
|
|
@@ -217,7 +227,6 @@ def _apply_reset_events_to_subweeks(
|
|
|
217
227
|
raw snapshot strings that may be written in non-UTC offsets while
|
|
218
228
|
`week_reset_events.{old,new}_week_end_at` are canonicalized UTC.
|
|
219
229
|
"""
|
|
220
|
-
parse_iso_datetime = _cctally().parse_iso_datetime
|
|
221
230
|
rows = conn.execute(
|
|
222
231
|
"SELECT old_week_end_at, new_week_end_at, effective_reset_at_utc "
|
|
223
232
|
"FROM week_reset_events"
|
|
@@ -289,9 +298,6 @@ def _compute_subscription_weeks(
|
|
|
289
298
|
dates that miss actual snapshot boundaries for middle weeks. Using
|
|
290
299
|
snapshot rows directly for weeks they cover avoids that drift.
|
|
291
300
|
"""
|
|
292
|
-
cctally = _cctally()
|
|
293
|
-
parse_iso_datetime = cctally.parse_iso_datetime
|
|
294
|
-
|
|
295
301
|
# Case A: snapshots exist.
|
|
296
302
|
snap_rows = conn.execute(
|
|
297
303
|
"SELECT "
|
|
@@ -460,9 +466,11 @@ def _compute_subscription_weeks(
|
|
|
460
466
|
return _apply_overlap_clamp_to_subweeks(weeks)
|
|
461
467
|
|
|
462
468
|
# Case B: no snapshots — config-based calendar-week fallback.
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
|
|
469
|
+
# `load_config` stays on the _cctally() accessor per spec §3.5
|
|
470
|
+
# monkeypatch carve-out — tests reach it via ``ns["load_config"]``.
|
|
471
|
+
config = _cctally().load_config()
|
|
472
|
+
week_start_name = get_week_start_name(config)
|
|
473
|
+
week_start_idx = WEEKDAY_MAP[week_start_name]
|
|
466
474
|
# internal fallback: host-local intentional
|
|
467
475
|
local_start_date = range_start.astimezone().date()
|
|
468
476
|
diff = (local_start_date.weekday() - week_start_idx) % 7
|