cctally 1.79.0 → 1.79.2
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 +10 -0
- package/bin/_cctally_dashboard.py +5 -3
- package/bin/_cctally_dashboard_sources.py +24 -10
- package/bin/_cctally_milestone_history.py +275 -154
- package/bin/_lib_milestone_history.py +1 -78
- package/dashboard/static/assets/index-BDkr0bdD.js +92 -0
- package/dashboard/static/dashboard.html +1 -1
- package/package.json +1 -1
- package/dashboard/static/assets/index-BwvAcS_k.js +0 -92
|
@@ -9,22 +9,12 @@ in ``_cctally_milestone_history.py``:
|
|
|
9
9
|
rows move (spec §2 caching/invalidation).
|
|
10
10
|
* ``intersects`` — half-open interval intersection on epoch seconds
|
|
11
11
|
(a block appears in every week it intersects, spec §1b dual membership).
|
|
12
|
-
* ``coalesce_week_refs`` — collapse same-``key`` ``WeekRef`` segments
|
|
13
|
-
produced by reset correction for an in-place-credited week into ONE
|
|
14
|
-
navigation entry spanning the outer cycle boundary (spec §1a); the
|
|
15
|
-
per-segment structure lives in the detail payload, never as duplicate
|
|
16
|
-
chips.
|
|
17
|
-
|
|
18
12
|
No imports of the cctally namespace or ``_cctally_core`` — these are pure
|
|
19
|
-
functions.
|
|
20
|
-
carrying ``key`` / ``week_start_at`` / ``week_end_at`` string fields
|
|
21
|
-
(the ``WeekRef`` shape) via ``dataclasses.replace``.
|
|
13
|
+
functions.
|
|
22
14
|
"""
|
|
23
15
|
from __future__ import annotations
|
|
24
16
|
|
|
25
|
-
import datetime as dt
|
|
26
17
|
import hashlib
|
|
27
|
-
from dataclasses import replace
|
|
28
18
|
|
|
29
19
|
|
|
30
20
|
# Codex ``quota_window_blocks`` rows carry second-level capture jitter in their
|
|
@@ -89,70 +79,3 @@ def intersects(start_a: int, end_a: int, start_b: int, end_b: int) -> bool:
|
|
|
89
79
|
block straddling a week boundary is reported in every week it intersects.
|
|
90
80
|
"""
|
|
91
81
|
return start_a < end_b and start_b < end_a
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
def _parse_epoch(value: "str | None") -> "int | None":
|
|
95
|
-
"""Parse a canonical ISO-8601 timestamp to an epoch int, or ``None``.
|
|
96
|
-
|
|
97
|
-
Accepts a trailing ``Z`` or an explicit offset; a naive value is treated
|
|
98
|
-
as UTC. Returns ``None`` on empty / unparseable input so callers can skip
|
|
99
|
-
boundary-less refs.
|
|
100
|
-
"""
|
|
101
|
-
if not value:
|
|
102
|
-
return None
|
|
103
|
-
try:
|
|
104
|
-
s = value.replace("Z", "+00:00")
|
|
105
|
-
parsed = dt.datetime.fromisoformat(s)
|
|
106
|
-
except ValueError:
|
|
107
|
-
return None
|
|
108
|
-
if parsed.tzinfo is None:
|
|
109
|
-
parsed = parsed.replace(tzinfo=dt.timezone.utc)
|
|
110
|
-
return int(parsed.timestamp())
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
def coalesce_week_refs(refs: list) -> list:
|
|
114
|
-
"""Collapse same-``key`` refs into one ref spanning the outer boundary.
|
|
115
|
-
|
|
116
|
-
Input is the ``get_recent_weeks`` ``WeekRef`` list (newest-first). An
|
|
117
|
-
in-place-credited week is represented there as TWO same-``key`` refs
|
|
118
|
-
(a pre-credit segment ``[orig_start, effective)`` and a post-credit
|
|
119
|
-
segment ``[effective, orig_end)``); every other week is a single ref.
|
|
120
|
-
|
|
121
|
-
The result preserves the newest-first order of each key's FIRST
|
|
122
|
-
occurrence, and for a multi-ref key emits one ref whose
|
|
123
|
-
``week_start_at`` is the earliest segment start and ``week_end_at`` the
|
|
124
|
-
latest segment end (the outer cycle boundary). The original ISO strings
|
|
125
|
-
are carried through unchanged (no reformatting drift); comparison is on
|
|
126
|
-
parsed epochs so mixed ``Z``/offset forms order correctly.
|
|
127
|
-
"""
|
|
128
|
-
order: list = [] # keys in first-occurrence order
|
|
129
|
-
groups: dict = {} # key -> list of refs
|
|
130
|
-
for ref in refs:
|
|
131
|
-
k = ref.key
|
|
132
|
-
if k not in groups:
|
|
133
|
-
groups[k] = []
|
|
134
|
-
order.append(k)
|
|
135
|
-
groups[k].append(ref)
|
|
136
|
-
|
|
137
|
-
out: list = []
|
|
138
|
-
for k in order:
|
|
139
|
-
members = groups[k]
|
|
140
|
-
if len(members) == 1:
|
|
141
|
-
out.append(members[0])
|
|
142
|
-
continue
|
|
143
|
-
# Pick earliest start / latest end across the same-key segments.
|
|
144
|
-
earliest = members[0]
|
|
145
|
-
earliest_e = _parse_epoch(members[0].week_start_at)
|
|
146
|
-
latest_end_iso = members[0].week_end_at
|
|
147
|
-
latest_e = _parse_epoch(members[0].week_end_at)
|
|
148
|
-
for m in members[1:]:
|
|
149
|
-
se = _parse_epoch(m.week_start_at)
|
|
150
|
-
if se is not None and (earliest_e is None or se < earliest_e):
|
|
151
|
-
earliest, earliest_e = m, se
|
|
152
|
-
ee = _parse_epoch(m.week_end_at)
|
|
153
|
-
if ee is not None and (latest_e is None or ee > latest_e):
|
|
154
|
-
latest_e, latest_end_iso = ee, m.week_end_at
|
|
155
|
-
# Base on the earliest-start ref (its start_at/start date are the
|
|
156
|
-
# outer start), widen its end to the latest segment end.
|
|
157
|
-
out.append(replace(earliest, week_end_at=latest_end_iso))
|
|
158
|
-
return out
|