cctally 1.117.2 → 1.118.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 +37 -0
- package/README.md +7 -3
- package/bin/_cctally_cache.py +2873 -193
- package/bin/_cctally_completion.py +106 -33
- package/bin/_cctally_core.py +69 -4
- package/bin/_cctally_dashboard.py +188 -13
- package/bin/_cctally_dashboard_conversation.py +5 -1
- package/bin/_cctally_dashboard_envelope.py +50 -19
- package/bin/_cctally_dashboard_sources.py +23 -1
- package/bin/_cctally_db.py +193 -153
- package/bin/_cctally_diagnosis_sources.py +63 -7
- package/bin/_cctally_doctor.py +865 -93
- package/bin/_cctally_five_hour.py +67 -50
- package/bin/_cctally_forecast.py +35 -13
- package/bin/_cctally_journal.py +186 -18
- package/bin/_cctally_milestone_history.py +859 -62
- package/bin/_cctally_oauth_samples.py +286 -15
- package/bin/_cctally_parser.py +2 -2
- package/bin/_cctally_quota.py +104 -12
- package/bin/_cctally_record.py +153 -29
- package/bin/_cctally_rederive.py +608 -68
- package/bin/_cctally_statusline.py +108 -81
- package/bin/_cctally_store.py +179 -38
- package/bin/_cctally_tui.py +892 -181
- package/bin/_cctally_update.py +32 -13
- package/bin/_lib_codex_conversation_query.py +52 -14
- package/bin/_lib_codex_drain_admission.py +224 -6
- package/bin/_lib_codex_metadata.py +39 -0
- package/bin/_lib_conversation_anon.py +15 -8
- package/bin/_lib_conversation_dispatch.py +7 -0
- package/bin/_lib_conversation_query.py +289 -70
- package/bin/_lib_dashboard_sources.py +37 -1
- package/bin/_lib_detector_access_registry.py +497 -26
- package/bin/_lib_doctor.py +85 -20
- package/bin/_lib_doctor_scan_index.py +321 -0
- package/bin/_lib_ingest_frontier.py +20 -1
- package/bin/_lib_oauth_samples.py +23 -7
- package/bin/_lib_pricing.py +146 -16
- package/bin/_lib_quota.py +19 -0
- package/bin/_lib_rederive.py +11 -6
- package/bin/_lib_retained_records.py +516 -0
- package/bin/_lib_snapshot_cache.py +10 -0
- package/bin/_lib_stale_proof.py +272 -43
- package/bin/_lib_stats_content_revision.py +831 -0
- package/bin/_lib_write_io.py +11 -4
- package/bin/cctally +4 -1
- package/dashboard/static/assets/ConversationsView-D4Iv4ku0.js +72 -0
- package/dashboard/static/assets/{DoctorModal-B0DnU9d9.js → DoctorModal-D4QSq6uz.js} +1 -1
- package/dashboard/static/assets/ModalRoot-C9F5dhZi.js +1 -0
- package/dashboard/static/assets/{ProjectsDrillPanel-DSxXQSa-.js → ProjectsDrillPanel-WxAdRDMt.js} +1 -1
- package/dashboard/static/assets/{SourceDetailModal-BleDpQqG.js → SourceDetailModal-NyyEfXmc.js} +1 -1
- package/dashboard/static/assets/{UpdateModal-CMqaAkSK.js → UpdateModal-CFLq9pT1.js} +1 -1
- package/dashboard/static/assets/{index-BjQV-0-D.js → index-BKTWH9JE.js} +2 -2
- package/dashboard/static/assets/{outlineNavigation-CO-VWBm7.js → outlineNavigation-BnGUwCS3.js} +3 -3
- package/dashboard/static/dashboard.html +1 -1
- package/package.json +4 -1
- package/dashboard/static/assets/ConversationsView-oqNsWzWV.js +0 -72
- package/dashboard/static/assets/ModalRoot-CYua2wP_.js +0 -1
|
@@ -41,9 +41,24 @@ window (spec D9) and an unavailable projection raises
|
|
|
41
41
|
* `claude_weekly_correction_ops`, the op's journal coordinate, written by
|
|
42
42
|
:func:`record_correction_op` on the published paths only (live ingest and
|
|
43
43
|
the rebuild). A scratch replay never writes it.
|
|
44
|
+
|
|
45
|
+
#1018 twin (spec 5.1, stats epoch 1024) enriches each observation-index row
|
|
46
|
+
with the record's raw weekly value, its normalized provider window, whether
|
|
47
|
+
it is a genuine weekly reading for the account the row receives (the
|
|
48
|
+
detector mask's weekly element, :func:`weekly_reading_genuine`) and whether it
|
|
49
|
+
may confirm a displayed weekly value (`weekly_freshness_eligible`: genuine,
|
|
50
|
+
both values present, captured strictly before the reset, and not held by the
|
|
51
|
+
effective reviewed decision). Every path computes them through
|
|
52
|
+
:func:`weekly_observation_facts`; the decision applier keeps eligibility
|
|
53
|
+
current, and an insert consults the decisions already folded, so the fold
|
|
54
|
+
order cannot change the final row. :func:`latest_weekly_reading_at` (spec
|
|
55
|
+
5.2) is the one read: the newest eligible confirmation of one displayed
|
|
56
|
+
value.
|
|
44
57
|
"""
|
|
45
58
|
from __future__ import annotations
|
|
46
59
|
|
|
60
|
+
import dataclasses
|
|
61
|
+
import datetime as dt
|
|
47
62
|
import sqlite3
|
|
48
63
|
from typing import Literal
|
|
49
64
|
|
|
@@ -86,21 +101,75 @@ _READ_FIVE_HOUR = (
|
|
|
86
101
|
" < MIN(unixepoch(s.five_hour_resets_at_utc), s.five_hour_window_key)"
|
|
87
102
|
" ORDER BY s.requested_at_utc"
|
|
88
103
|
)
|
|
104
|
+
#: #1018 twin spec 5.1: the eligibility bound on insert is the caller's
|
|
105
|
+
#: account-specific value AND no effective `hold` already folded, so a
|
|
106
|
+
#: decision folded before its observation still applies.
|
|
89
107
|
_INSERT_OBSERVATION = (
|
|
90
108
|
"INSERT OR IGNORE INTO claude_weekly_observation_index (observation_id,"
|
|
91
|
-
" account_key, captured_at_utc
|
|
109
|
+
" account_key, captured_at_utc, weekly_percent, weekly_resets_at_utc,"
|
|
110
|
+
" weekly_reading_genuine, weekly_freshness_eligible)"
|
|
111
|
+
" VALUES (?, ?, ?, ?, ?, ?, ? AND NOT EXISTS (SELECT 1"
|
|
112
|
+
" FROM claude_weekly_observation_decisions AS d"
|
|
113
|
+
" WHERE d.observation_id = ? AND d.disposition = 'hold'))"
|
|
114
|
+
)
|
|
115
|
+
#: The apply-only rebuild's insert. Its read pass flushes every queued row
|
|
116
|
+
#: before the Phase 1 fold applies any reviewed decision op, and the applier
|
|
117
|
+
#: then maintains eligibility on the indexed row, so the rebuild binds the
|
|
118
|
+
#: account-specific value directly: no statement of the pass reads a projected
|
|
119
|
+
#: table before the final flush (#1003 D7), and the batch size cannot change
|
|
120
|
+
#: a published row.
|
|
121
|
+
_INSERT_OBSERVATION_REBUILD = (
|
|
122
|
+
"INSERT OR IGNORE INTO claude_weekly_observation_index (observation_id,"
|
|
123
|
+
" account_key, captured_at_utc, weekly_percent, weekly_resets_at_utc,"
|
|
124
|
+
" weekly_reading_genuine, weekly_freshness_eligible)"
|
|
125
|
+
" VALUES (?, ?, ?, ?, ?, ?, ?)"
|
|
92
126
|
)
|
|
93
127
|
#: The rebuild's staging table for observations whose account is the cutover
|
|
94
128
|
#: op's (known only after the read pass). Scratch-index only; dropped by
|
|
95
|
-
#: :func:`attribute_staged_observations` before the inventory check.
|
|
129
|
+
#: :func:`attribute_staged_observations` before the inventory check. #1018
|
|
130
|
+
#: twin: it carries the account-independent facts, so genuineness and
|
|
131
|
+
#: eligibility are computed against the cutover account when the row moves.
|
|
132
|
+
#: `pre_reset` is 1 exactly when both values are present and parseable and
|
|
133
|
+
#: the capture is strictly before the reset (parsed instants).
|
|
96
134
|
STAGING_TABLE = "rebuild_weekly_observation_unstamped"
|
|
97
135
|
_CREATE_STAGING = (
|
|
98
136
|
"CREATE TABLE IF NOT EXISTS rebuild_weekly_observation_unstamped ("
|
|
99
|
-
" observation_id TEXT PRIMARY KEY, captured_at_utc TEXT NOT NULL
|
|
137
|
+
" observation_id TEXT PRIMARY KEY, captured_at_utc TEXT NOT NULL,"
|
|
138
|
+
" weekly_percent REAL, weekly_resets_at_utc TEXT,"
|
|
139
|
+
" base_genuine INTEGER NOT NULL, required_account TEXT,"
|
|
140
|
+
" pre_reset INTEGER NOT NULL)"
|
|
100
141
|
)
|
|
101
142
|
_INSERT_STAGED = (
|
|
102
143
|
"INSERT OR IGNORE INTO rebuild_weekly_observation_unstamped"
|
|
103
|
-
" (observation_id, captured_at_utc
|
|
144
|
+
" (observation_id, captured_at_utc, weekly_percent, weekly_resets_at_utc,"
|
|
145
|
+
" base_genuine, required_account, pre_reset) VALUES (?, ?, ?, ?, ?, ?, ?)"
|
|
146
|
+
)
|
|
147
|
+
_ATTRIBUTE_STAGED = (
|
|
148
|
+
"INSERT OR IGNORE INTO claude_weekly_observation_index"
|
|
149
|
+
" (observation_id, account_key, captured_at_utc, weekly_percent,"
|
|
150
|
+
" weekly_resets_at_utc, weekly_reading_genuine, weekly_freshness_eligible)"
|
|
151
|
+
" SELECT s.observation_id, ?, s.captured_at_utc, s.weekly_percent,"
|
|
152
|
+
" s.weekly_resets_at_utc,"
|
|
153
|
+
" s.base_genuine AND (s.required_account IS NULL OR s.required_account = ?),"
|
|
154
|
+
" s.base_genuine AND (s.required_account IS NULL OR s.required_account = ?)"
|
|
155
|
+
" AND s.pre_reset AND NOT EXISTS (SELECT 1"
|
|
156
|
+
" FROM claude_weekly_observation_decisions AS d"
|
|
157
|
+
" WHERE d.observation_id = s.observation_id AND d.disposition = 'hold')"
|
|
158
|
+
" FROM rebuild_weekly_observation_unstamped AS s"
|
|
159
|
+
)
|
|
160
|
+
#: #1018 twin spec 5.1: the decision applier's eligibility maintenance.
|
|
161
|
+
_HOLD_ELIGIBILITY = (
|
|
162
|
+
"UPDATE claude_weekly_observation_index SET weekly_freshness_eligible = 0"
|
|
163
|
+
" WHERE observation_id = ?"
|
|
164
|
+
)
|
|
165
|
+
_READ_ELIGIBILITY_FACTS = (
|
|
166
|
+
"SELECT weekly_reading_genuine, weekly_percent, weekly_resets_at_utc,"
|
|
167
|
+
" captured_at_utc FROM claude_weekly_observation_index"
|
|
168
|
+
" WHERE observation_id = ?"
|
|
169
|
+
)
|
|
170
|
+
_SET_ELIGIBILITY = (
|
|
171
|
+
"UPDATE claude_weekly_observation_index SET weekly_freshness_eligible = ?"
|
|
172
|
+
" WHERE observation_id = ?"
|
|
104
173
|
)
|
|
105
174
|
_INSERT_HISTORY = (
|
|
106
175
|
"INSERT OR IGNORE INTO claude_weekly_correction_history (decision_op_id,"
|
|
@@ -206,6 +275,116 @@ def _weekly_observation_key(rec) -> "tuple[str, str] | None":
|
|
|
206
275
|
return None
|
|
207
276
|
|
|
208
277
|
|
|
278
|
+
@dataclasses.dataclass(frozen=True)
|
|
279
|
+
class WeeklyObservationFacts:
|
|
280
|
+
"""The account-independent weekly facts of one indexed observation
|
|
281
|
+
(#1018 twin spec 5.1). ``required_account`` is the one account a v2
|
|
282
|
+
publication's provenance names (None for a historical-policy or direct
|
|
283
|
+
record); ``base_genuine`` is False for a withheld or unclassifiable
|
|
284
|
+
detector step and for a `projection` (store-filled) weekly axis."""
|
|
285
|
+
|
|
286
|
+
weekly_percent: "float | None"
|
|
287
|
+
weekly_resets_at_utc: "str | None"
|
|
288
|
+
base_genuine: bool
|
|
289
|
+
required_account: "str | None"
|
|
290
|
+
|
|
291
|
+
|
|
292
|
+
#: The publication provenance kinds `_detector_observation_mask` classifies.
|
|
293
|
+
_PROVENANCE_KINDS = ("candidate", "projection", "retained_low")
|
|
294
|
+
|
|
295
|
+
|
|
296
|
+
def _weekly_genuineness(payload) -> "tuple[bool, str | None]":
|
|
297
|
+
"""``(base_genuine, required_account)`` of one raw payload: the weekly
|
|
298
|
+
element of `_cctally_record._detector_observation_mask` with its account
|
|
299
|
+
comparison factored out, so a staged row can apply it once its account is
|
|
300
|
+
known. Reads only the payload."""
|
|
301
|
+
import _cctally_journal
|
|
302
|
+
policy = _cctally_journal.detector_policy_of(payload)
|
|
303
|
+
if policy == "unsupported":
|
|
304
|
+
return False, None
|
|
305
|
+
if policy == "historical" or "publication_id" not in payload:
|
|
306
|
+
return True, None
|
|
307
|
+
provenance = payload.get("publication")
|
|
308
|
+
if not isinstance(provenance, dict):
|
|
309
|
+
return False, None
|
|
310
|
+
accounts = set()
|
|
311
|
+
for axis, present in (("sevenDay", True),
|
|
312
|
+
("fiveHour",
|
|
313
|
+
payload.get("five_hour_percent") is not None)):
|
|
314
|
+
if not present:
|
|
315
|
+
continue
|
|
316
|
+
source = provenance.get(axis)
|
|
317
|
+
if (not isinstance(source, dict)
|
|
318
|
+
or source.get("kind") not in _PROVENANCE_KINDS):
|
|
319
|
+
return False, None
|
|
320
|
+
account = source.get("account")
|
|
321
|
+
if not isinstance(account, str) or not account:
|
|
322
|
+
return False, None
|
|
323
|
+
accounts.add(account)
|
|
324
|
+
if len(accounts) != 1:
|
|
325
|
+
# The axes name different accounts: no row account matches both.
|
|
326
|
+
return False, None
|
|
327
|
+
return provenance["sevenDay"]["kind"] != "projection", accounts.pop()
|
|
328
|
+
|
|
329
|
+
|
|
330
|
+
def weekly_observation_facts(rec) -> "WeeklyObservationFacts | None":
|
|
331
|
+
"""The enriched facts of one record, or None exactly when
|
|
332
|
+
:func:`_weekly_observation_key` projects no index row for it."""
|
|
333
|
+
if _weekly_observation_key(rec) is None:
|
|
334
|
+
return None
|
|
335
|
+
payload = rec["payload"]
|
|
336
|
+
base_genuine, required_account = _weekly_genuineness(payload)
|
|
337
|
+
return WeeklyObservationFacts(
|
|
338
|
+
weekly_percent=_lib_oauth_samples.finite_percent(
|
|
339
|
+
payload.get("weekly_percent")),
|
|
340
|
+
weekly_resets_at_utc=_lib_oauth_samples.weekly_reset_identity(
|
|
341
|
+
payload.get("resets_at")),
|
|
342
|
+
base_genuine=base_genuine,
|
|
343
|
+
required_account=required_account,
|
|
344
|
+
)
|
|
345
|
+
|
|
346
|
+
|
|
347
|
+
def weekly_reading_genuine(facts: WeeklyObservationFacts,
|
|
348
|
+
account_key: str) -> bool:
|
|
349
|
+
"""Whether the observation is a genuine weekly reading for the row's
|
|
350
|
+
``account_key``: `_detector_observation_mask`'s weekly element for that
|
|
351
|
+
account (spec 5.1)."""
|
|
352
|
+
return bool(facts.base_genuine and (
|
|
353
|
+
facts.required_account is None
|
|
354
|
+
or facts.required_account == account_key))
|
|
355
|
+
|
|
356
|
+
|
|
357
|
+
def _before_reset(captured_at_utc, weekly_resets_at_utc) -> bool:
|
|
358
|
+
"""Both instants parse and the capture is strictly before the reset,
|
|
359
|
+
compared as parsed instants: the two columns are spelled at different
|
|
360
|
+
precisions, so a text comparison would admit a capture at the reset."""
|
|
361
|
+
if weekly_resets_at_utc is None:
|
|
362
|
+
return False
|
|
363
|
+
try:
|
|
364
|
+
captured = _lib_oauth_samples.canonical_instant(captured_at_utc)
|
|
365
|
+
reset = _lib_oauth_samples.canonical_instant(weekly_resets_at_utc)
|
|
366
|
+
except (TypeError, ValueError):
|
|
367
|
+
return False
|
|
368
|
+
# Both are now the same full-precision spelling, so text order is
|
|
369
|
+
# chronological.
|
|
370
|
+
return captured < reset
|
|
371
|
+
|
|
372
|
+
|
|
373
|
+
def _pre_reset(facts: WeeklyObservationFacts, captured_at_utc) -> bool:
|
|
374
|
+
"""Eligibility's account- and decision-independent half."""
|
|
375
|
+
return (facts.weekly_percent is not None
|
|
376
|
+
and _before_reset(captured_at_utc, facts.weekly_resets_at_utc))
|
|
377
|
+
|
|
378
|
+
|
|
379
|
+
def _observation_params(observation_id, account, captured_at_utc,
|
|
380
|
+
facts: WeeklyObservationFacts) -> tuple:
|
|
381
|
+
genuine = weekly_reading_genuine(facts, account)
|
|
382
|
+
return (observation_id, account, captured_at_utc, facts.weekly_percent,
|
|
383
|
+
facts.weekly_resets_at_utc, int(genuine),
|
|
384
|
+
int(genuine and _pre_reset(facts, captured_at_utc)),
|
|
385
|
+
observation_id)
|
|
386
|
+
|
|
387
|
+
|
|
209
388
|
def project_observation(conn, rec, *, cutover_account=None) -> None:
|
|
210
389
|
"""#1015 spec 5.1: project ``rec`` into `claude_weekly_observation_index`
|
|
211
390
|
on live ingest and the scratch replays, under the one attribution rule:
|
|
@@ -226,7 +405,8 @@ def project_observation(conn, rec, *, cutover_account=None) -> None:
|
|
|
226
405
|
if (cutover_account is not None
|
|
227
406
|
and _cctally_journal.needs_cutover_attribution(rec)):
|
|
228
407
|
account = cutover_account()
|
|
229
|
-
conn.execute(_INSERT_OBSERVATION, (
|
|
408
|
+
conn.execute(_INSERT_OBSERVATION, _observation_params(
|
|
409
|
+
key[0], account, key[1], weekly_observation_facts(rec)))
|
|
230
410
|
|
|
231
411
|
|
|
232
412
|
def attribute_staged_observations(conn, claude_account: str) -> int:
|
|
@@ -242,11 +422,8 @@ def attribute_staged_observations(conn, claude_account: str) -> int:
|
|
|
242
422
|
conn.execute("BEGIN IMMEDIATE")
|
|
243
423
|
try:
|
|
244
424
|
moved = conn.execute(
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
" SELECT observation_id, ?, captured_at_utc"
|
|
248
|
-
" FROM rebuild_weekly_observation_unstamped",
|
|
249
|
-
(claude_account,)).rowcount
|
|
425
|
+
_ATTRIBUTE_STAGED,
|
|
426
|
+
(claude_account, claude_account, claude_account)).rowcount
|
|
250
427
|
conn.execute("DROP TABLE rebuild_weekly_observation_unstamped")
|
|
251
428
|
conn.commit()
|
|
252
429
|
except BaseException:
|
|
@@ -261,7 +438,13 @@ class RebuildProjector:
|
|
|
261
438
|
index in bounded batches (one transaction each), so the pass never holds
|
|
262
439
|
the whole sample population in memory."""
|
|
263
440
|
|
|
264
|
-
|
|
441
|
+
#: #1003 D7: queued items (samples plus observation-index rows) per flush.
|
|
442
|
+
#: Each flush is a `BEGIN IMMEDIATE … COMMIT` on the rebuild scratch, which
|
|
443
|
+
#: keeps the store policy (a synced rollback journal per transaction), so
|
|
444
|
+
#: 2,048 cost ≈ 1.8 GB of physical writes per rebuild. Every reader of the
|
|
445
|
+
#: projected tables runs after the pass's final flush, so the batch moves
|
|
446
|
+
#: only when rows are written, never what is read.
|
|
447
|
+
BATCH = 65536
|
|
265
448
|
|
|
266
449
|
def __init__(self, conn) -> None:
|
|
267
450
|
self._conn = conn
|
|
@@ -283,14 +466,20 @@ class RebuildProjector:
|
|
|
283
466
|
# the end of the pass knows, so it is staged; every other record
|
|
284
467
|
# keeps its stamp or `unattributed` (spec 5.1's three cases).
|
|
285
468
|
import _cctally_journal
|
|
469
|
+
facts = weekly_observation_facts(rec)
|
|
286
470
|
if _cctally_journal.needs_cutover_attribution(rec):
|
|
287
|
-
self._observations.append((_INSERT_STAGED,
|
|
471
|
+
self._observations.append((_INSERT_STAGED, (
|
|
472
|
+
key[0], key[1], facts.weekly_percent,
|
|
473
|
+
facts.weekly_resets_at_utc, int(facts.base_genuine),
|
|
474
|
+
facts.required_account,
|
|
475
|
+
int(_pre_reset(facts, key[1])))))
|
|
288
476
|
else:
|
|
289
477
|
import _lib_accounts
|
|
290
478
|
self._observations.append(
|
|
291
|
-
(
|
|
292
|
-
|
|
293
|
-
|
|
479
|
+
(_INSERT_OBSERVATION_REBUILD, _observation_params(
|
|
480
|
+
key[0],
|
|
481
|
+
rec.get("account") or _lib_accounts.UNATTRIBUTED,
|
|
482
|
+
key[1], facts)[:-1]))
|
|
294
483
|
if len(self._pending) + len(self._observations) >= self.BATCH:
|
|
295
484
|
self.flush()
|
|
296
485
|
|
|
@@ -347,6 +536,7 @@ def apply_weekly_observation_decision_op(conn, record) -> None:
|
|
|
347
536
|
and disposition in _DISPOSITIONS):
|
|
348
537
|
conn.execute(_UPSERT_DECISION,
|
|
349
538
|
(observation_id, disposition, op_id))
|
|
539
|
+
_maintain_freshness_eligibility(conn, observation_id, disposition)
|
|
350
540
|
conn.execute(_INSERT_HISTORY, (
|
|
351
541
|
op_id, observation_id,
|
|
352
542
|
"retract" if (disposition == "hold"
|
|
@@ -354,6 +544,26 @@ def apply_weekly_observation_decision_op(conn, record) -> None:
|
|
|
354
544
|
else disposition))
|
|
355
545
|
|
|
356
546
|
|
|
547
|
+
def _maintain_freshness_eligibility(conn, observation_id: str,
|
|
548
|
+
disposition: str) -> None:
|
|
549
|
+
"""#1018 twin spec 5.1: the decided observation's freshness eligibility,
|
|
550
|
+
in the applier's transaction. A `hold` (a schema-3 retraction is one)
|
|
551
|
+
clears it; an `accept` recomputes it from the stored genuine flag and the
|
|
552
|
+
parsed pre-reset condition. An observation not yet indexed (a decision
|
|
553
|
+
folded before it, or still staged in a rebuild) is covered by the insert,
|
|
554
|
+
which consults the decisions table."""
|
|
555
|
+
if disposition == "hold":
|
|
556
|
+
conn.execute(_HOLD_ELIGIBILITY, (observation_id,))
|
|
557
|
+
return
|
|
558
|
+
row = conn.execute(_READ_ELIGIBILITY_FACTS, (observation_id,)).fetchone()
|
|
559
|
+
if row is None:
|
|
560
|
+
return
|
|
561
|
+
genuine, weekly_percent, weekly_resets_at_utc, captured_at_utc = row
|
|
562
|
+
eligible = bool(genuine) and weekly_percent is not None and _before_reset(
|
|
563
|
+
captured_at_utc, weekly_resets_at_utc)
|
|
564
|
+
conn.execute(_SET_ELIGIBILITY, (int(eligible), observation_id))
|
|
565
|
+
|
|
566
|
+
|
|
357
567
|
def record_correction_op(conn, record, coordinate) -> None:
|
|
358
568
|
"""#1015 spec 5.1: record where a reviewed weekly decision op sits in the
|
|
359
569
|
journal — ``coordinate`` is the END ``(segment, offset)`` of its line, as
|
|
@@ -456,3 +666,64 @@ def projection_covered(conn, *, account_key: str) -> bool:
|
|
|
456
666
|
except sqlite3.Error:
|
|
457
667
|
return False
|
|
458
668
|
return names == {SAMPLES_TABLE, DECISIONS_TABLE}
|
|
669
|
+
|
|
670
|
+
|
|
671
|
+
@dataclasses.dataclass(frozen=True)
|
|
672
|
+
class WeeklyReadingScope:
|
|
673
|
+
"""The displayed weekly value a confirming reading must repeat (#1018
|
|
674
|
+
twin spec 5.2). Built by the current-week card from its displayed row's
|
|
675
|
+
originating observation; server-private, never serialized."""
|
|
676
|
+
|
|
677
|
+
account_key: str
|
|
678
|
+
#: The window identity, in the samples' second-precision spelling, read
|
|
679
|
+
#: from the displayed row's originating observation (never the stored
|
|
680
|
+
#: `week_end_at`, which may be a first-established boundary).
|
|
681
|
+
weekly_resets_at_utc: str
|
|
682
|
+
#: The displayed `used_pct` as stored: matched by exact float equality.
|
|
683
|
+
weekly_percent: float
|
|
684
|
+
#: Canonical full-precision text, inclusive: the card's segment start.
|
|
685
|
+
lower_bound_utc: str
|
|
686
|
+
#: Canonical full-precision text, exclusive: the earlier of the provider
|
|
687
|
+
#: reset and the displayed window's end.
|
|
688
|
+
upper_bound_utc: str
|
|
689
|
+
|
|
690
|
+
|
|
691
|
+
_LATEST_WEEKLY_READING = (
|
|
692
|
+
"SELECT captured_at_utc FROM claude_weekly_observation_index"
|
|
693
|
+
" WHERE account_key = ? AND weekly_resets_at_utc = ? AND weekly_percent = ?"
|
|
694
|
+
" AND weekly_freshness_eligible = 1"
|
|
695
|
+
" AND captured_at_utc >= ? AND captured_at_utc < ?"
|
|
696
|
+
" ORDER BY captured_at_utc DESC LIMIT 1"
|
|
697
|
+
)
|
|
698
|
+
|
|
699
|
+
|
|
700
|
+
def latest_weekly_reading_at(conn, scope: WeeklyReadingScope,
|
|
701
|
+
now_utc: dt.datetime) -> "dt.datetime | None":
|
|
702
|
+
"""The capture instant of the newest eligible observation-index row that
|
|
703
|
+
confirms ``scope``'s displayed value (same account, window and exact
|
|
704
|
+
value; captured in ``[lower, upper)`` and at or before ``now_utc``), or
|
|
705
|
+
None when none does. One statement on the freshness partial index, so it
|
|
706
|
+
needs no transaction. Raises ``sqlite3.Error`` to the caller, which keeps
|
|
707
|
+
its prior value rather than publishing a guess.
|
|
708
|
+
|
|
709
|
+
The two upper limits (``< upper`` and ``<= now``) are bound as ONE
|
|
710
|
+
exclusive bound, the earlier of ``upper`` and ``now`` + 1 µs: captures
|
|
711
|
+
are canonical microsecond text, so ``<= now`` is exactly ``< now + 1 µs``.
|
|
712
|
+
With both written as separate terms SQLite seeks on one and filters the
|
|
713
|
+
other, so a suffix of readings captured after now (a clock step, a
|
|
714
|
+
replayed future capture) would be walked on every tick; one bound keeps
|
|
715
|
+
the lookup a single index seek."""
|
|
716
|
+
upper = _lib_oauth_samples.canonical_instant(scope.upper_bound_utc)
|
|
717
|
+
not_after_now = _lib_oauth_samples.canonical_instant(
|
|
718
|
+
now_utc + dt.timedelta(microseconds=1))
|
|
719
|
+
row = conn.execute(_LATEST_WEEKLY_READING, (
|
|
720
|
+
scope.account_key, scope.weekly_resets_at_utc,
|
|
721
|
+
float(scope.weekly_percent),
|
|
722
|
+
_lib_oauth_samples.canonical_instant(scope.lower_bound_utc),
|
|
723
|
+
min(upper, not_after_now))).fetchone()
|
|
724
|
+
if row is None:
|
|
725
|
+
return None
|
|
726
|
+
text = str(row[0])
|
|
727
|
+
return dt.datetime.fromisoformat(
|
|
728
|
+
text[:-1] + "+00:00" if text.endswith("Z") else text
|
|
729
|
+
).astimezone(dt.timezone.utc)
|
package/bin/_cctally_parser.py
CHANGED
|
@@ -3428,8 +3428,8 @@ def _build_doctor_parser(subparsers, name, *, help_text, xref=None):
|
|
|
3428
3428
|
actionable remediation guidance for non-OK rows.
|
|
3429
3429
|
|
|
3430
3430
|
Exit code: 0 unless any check is FAIL (then exit 2). WARN
|
|
3431
|
-
rows do not change the exit code — doctor
|
|
3432
|
-
|
|
3431
|
+
rows do not change the exit code — doctor never changes
|
|
3432
|
+
your data and warn-class findings are advisories.
|
|
3433
3433
|
|
|
3434
3434
|
See docs/commands/doctor.md for the full check inventory
|
|
3435
3435
|
and JSON schema reference.
|
package/bin/_cctally_quota.py
CHANGED
|
@@ -450,6 +450,14 @@ PROJECTION_DYNAMIC_READ_SITES: "dict[str, int]" = {
|
|
|
450
450
|
# `PROJECTION_DYNAMIC_READ_ACTIONS` classification applies.
|
|
451
451
|
"_lib_ingest_frontier.py": 8,
|
|
452
452
|
"_lib_snapshot_cache.py": 1,
|
|
453
|
+
# Three (#1050), each over a hardcoded Claude stats table set:
|
|
454
|
+
# `_trigger_sql`'s below-max INSERT predicate `SELECT 1 FROM {table}` and
|
|
455
|
+
# `trigger_lookup_queries`' `EXPLAIN` twin of it range over the kernel's
|
|
456
|
+
# `TRACKED_TABLES`, and `child_set_unchanged`'s `SELECT * FROM {table}`
|
|
457
|
+
# over `CHILD_TABLES` (the two five-hour block child tables), checked
|
|
458
|
+
# before the query is built. None is a quota projection table, so no
|
|
459
|
+
# `PROJECTION_DYNAMIC_READ_ACTIONS` classification applies.
|
|
460
|
+
"_lib_stats_content_revision.py": 3,
|
|
453
461
|
"_lib_subscription_weeks.py": 1,
|
|
454
462
|
}
|
|
455
463
|
|
|
@@ -4674,6 +4682,100 @@ def _first_block_physical_tuple(
|
|
|
4674
4682
|
return None
|
|
4675
4683
|
|
|
4676
4684
|
|
|
4685
|
+
def codex_entry_selection_bounds(
|
|
4686
|
+
start_captured_at: dt.datetime, last_captured_at_utc: object,
|
|
4687
|
+
) -> tuple[str, str]:
|
|
4688
|
+
"""The SQL text bounds of ``codex_quota_breakdown``'s accounting read.
|
|
4689
|
+
|
|
4690
|
+
``timestamp_utc`` is stored in canonical ``Z`` form, while retained quota
|
|
4691
|
+
observations may have arrived as ``+00:00``. Keep this SQL bound
|
|
4692
|
+
deliberately one second wider and let the physical-tuple comparison in the
|
|
4693
|
+
breakdown enforce the exact inclusive endpoint. This preserves same-second
|
|
4694
|
+
path/offset ordering without relying on mixed-spelling text equality.
|
|
4695
|
+
|
|
4696
|
+
One definition (#1050 spec 4.7), because the Codex cycle-detail stamp's
|
|
4697
|
+
per-selection aggregate (``codex_entry_selection_aggregate``) must select
|
|
4698
|
+
exactly the rows the breakdown prices.
|
|
4699
|
+
"""
|
|
4700
|
+
query_start = (
|
|
4701
|
+
start_captured_at - dt.timedelta(seconds=1)
|
|
4702
|
+
).astimezone(UTC).strftime("%Y-%m-%dT%H:%M:%S.%fZ")
|
|
4703
|
+
query_end = (
|
|
4704
|
+
_parse_utc(str(last_captured_at_utc), "captured_at_utc")
|
|
4705
|
+
+ dt.timedelta(seconds=1)
|
|
4706
|
+
).astimezone(UTC).strftime("%Y-%m-%dT%H:%M:%S.%fZ")
|
|
4707
|
+
return query_start, query_end
|
|
4708
|
+
|
|
4709
|
+
|
|
4710
|
+
def codex_entry_models(cache_conn: sqlite3.Connection) -> tuple[str, ...]:
|
|
4711
|
+
"""Every distinct ``codex_session_entries.model``, ascending (#1050).
|
|
4712
|
+
|
|
4713
|
+
One ``model > ?`` seek per model through ``idx_codex_entries_model_time``
|
|
4714
|
+
rather than a ``SELECT DISTINCT`` over the table: the population is a few
|
|
4715
|
+
dozen models, the table is history-sized.
|
|
4716
|
+
"""
|
|
4717
|
+
models: list[str] = []
|
|
4718
|
+
last = None
|
|
4719
|
+
while True:
|
|
4720
|
+
if last is None:
|
|
4721
|
+
row = cache_conn.execute(
|
|
4722
|
+
"SELECT MIN(model) FROM codex_session_entries").fetchone()
|
|
4723
|
+
else:
|
|
4724
|
+
row = cache_conn.execute(
|
|
4725
|
+
"SELECT MIN(model) FROM codex_session_entries WHERE model > ?",
|
|
4726
|
+
(last,)).fetchone()
|
|
4727
|
+
if row is None or row[0] is None:
|
|
4728
|
+
return tuple(models)
|
|
4729
|
+
last = str(row[0])
|
|
4730
|
+
models.append(last)
|
|
4731
|
+
|
|
4732
|
+
|
|
4733
|
+
def codex_entry_selection_aggregate(
|
|
4734
|
+
cache_conn: sqlite3.Connection, *, source_root_key: str,
|
|
4735
|
+
query_start: str, query_end: str, account_key: str | None,
|
|
4736
|
+
models: tuple[str, ...],
|
|
4737
|
+
) -> tuple:
|
|
4738
|
+
"""The aggregate twin of ``codex_quota_breakdown``'s accounting read.
|
|
4739
|
+
|
|
4740
|
+
#1050 spec 4.7: the same ``source_root_key``, the same text timestamp
|
|
4741
|
+
bounds (``codex_entry_selection_bounds``) and the same STRICT account
|
|
4742
|
+
predicate, returning ``(COUNT(*), MAX(rowid), per_model)`` where
|
|
4743
|
+
``per_model`` is ``(model, count, TOTAL input, TOTAL cached input, TOTAL
|
|
4744
|
+
output, TOTAL reasoning output, TOTAL total)`` for every model with a row,
|
|
4745
|
+
ascending by model. A Codex cycle-detail stamp carries it, so a late entry
|
|
4746
|
+
inside a past milestone interval, a removed one or a re-tokenized one
|
|
4747
|
+
re-stamps the cycle whose dollars it moves.
|
|
4748
|
+
|
|
4749
|
+
One statement per model, so each seeks ``idx_codex_entries_model_time``
|
|
4750
|
+
(``model``, ``timestamp_utc``) and SQLite builds no temp b-tree: a
|
|
4751
|
+
``GROUP BY model`` over the timestamp range sorts every row it selects. The
|
|
4752
|
+
unary ``+`` keeps the planner off the root-only index, which on a one-root
|
|
4753
|
+
install is a scan of the whole table; it removes the column's affinity,
|
|
4754
|
+
which is equivalent here because the root key is TEXT bound as a string.
|
|
4755
|
+
"""
|
|
4756
|
+
entry_predicate, entry_params = _codex_cache_account_predicate(account_key)
|
|
4757
|
+
total_count = 0
|
|
4758
|
+
max_rowid = None
|
|
4759
|
+
per_model: list[tuple] = []
|
|
4760
|
+
for model in models:
|
|
4761
|
+
row = cache_conn.execute(
|
|
4762
|
+
"SELECT COUNT(*), MAX(rowid), TOTAL(input_tokens), "
|
|
4763
|
+
" TOTAL(cached_input_tokens), TOTAL(output_tokens), "
|
|
4764
|
+
" TOTAL(reasoning_output_tokens), TOTAL(total_tokens) "
|
|
4765
|
+
" FROM codex_session_entries "
|
|
4766
|
+
" WHERE model=? AND timestamp_utc>=? AND timestamp_utc<=? "
|
|
4767
|
+
" AND +source_root_key=? " + entry_predicate,
|
|
4768
|
+
(model, query_start, query_end, source_root_key, *entry_params),
|
|
4769
|
+
).fetchone()
|
|
4770
|
+
count = int(row[0] or 0)
|
|
4771
|
+
if not count:
|
|
4772
|
+
continue
|
|
4773
|
+
total_count += count
|
|
4774
|
+
max_rowid = row[1] if max_rowid is None else max(max_rowid, row[1])
|
|
4775
|
+
per_model.append((model, count, *(float(v) for v in row[2:])))
|
|
4776
|
+
return (total_count, max_rowid, tuple(per_model))
|
|
4777
|
+
|
|
4778
|
+
|
|
4677
4779
|
def codex_quota_breakdown(
|
|
4678
4780
|
identity: QuotaWindowIdentity,
|
|
4679
4781
|
resets_at: str | dt.datetime,
|
|
@@ -4747,18 +4849,8 @@ def codex_quota_breakdown(
|
|
|
4747
4849
|
if owns_cache:
|
|
4748
4850
|
cache.close()
|
|
4749
4851
|
return ()
|
|
4750
|
-
|
|
4751
|
-
|
|
4752
|
-
# deliberately one second wider and let the physical-tuple comparison
|
|
4753
|
-
# below enforce the exact inclusive endpoint. This preserves same-second
|
|
4754
|
-
# path/offset ordering without relying on mixed-spelling text equality.
|
|
4755
|
-
query_start = (
|
|
4756
|
-
start[0] - dt.timedelta(seconds=1)
|
|
4757
|
-
).astimezone(UTC).strftime("%Y-%m-%dT%H:%M:%S.%fZ")
|
|
4758
|
-
query_end = (
|
|
4759
|
-
_parse_utc(str(milestones[-1][1]), "captured_at_utc")
|
|
4760
|
-
+ dt.timedelta(seconds=1)
|
|
4761
|
-
).astimezone(UTC).strftime("%Y-%m-%dT%H:%M:%S.%fZ")
|
|
4852
|
+
query_start, query_end = codex_entry_selection_bounds(
|
|
4853
|
+
start[0], milestones[-1][1])
|
|
4762
4854
|
try:
|
|
4763
4855
|
entries = []
|
|
4764
4856
|
# Cost read: strict, always. See the docstring above.
|