cctally 1.117.0 → 1.118.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 +46 -0
- package/README.md +7 -3
- package/bin/_cctally_cache.py +2783 -175
- package/bin/_cctally_completion.py +106 -33
- package/bin/_cctally_core.py +69 -4
- package/bin/_cctally_dashboard.py +227 -23
- package/bin/_cctally_dashboard_conversation.py +5 -1
- package/bin/_cctally_dashboard_envelope.py +60 -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 +124 -54
- package/bin/_cctally_forecast.py +301 -7
- package/bin/_cctally_journal.py +186 -18
- package/bin/_cctally_milestone_history.py +1193 -108
- 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 +1210 -170
- 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 +131 -9
- 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_quota_model.py +29 -11
- package/bin/_lib_rederive.py +11 -6
- package/bin/_lib_retained_records.py +516 -0
- package/bin/_lib_snapshot_cache.py +18 -0
- package/bin/_lib_stale_proof.py +272 -43
- package/bin/_lib_stats_content_revision.py +831 -0
- package/bin/_lib_tick_stats.py +10 -5
- package/bin/_lib_write_io.py +12 -5
- package/bin/cctally +8 -1
- package/dashboard/static/assets/ConversationsView-D4Iv4ku0.js +72 -0
- package/dashboard/static/assets/{DoctorModal-BqmXbnhn.js → DoctorModal-D4QSq6uz.js} +1 -1
- package/dashboard/static/assets/ModalRoot-C9F5dhZi.js +1 -0
- package/dashboard/static/assets/{ProjectsDrillPanel-B-HZkDnT.js → ProjectsDrillPanel-WxAdRDMt.js} +1 -1
- package/dashboard/static/assets/{SourceDetailModal-QhJkHB7i.js → SourceDetailModal-NyyEfXmc.js} +1 -1
- package/dashboard/static/assets/{UpdateModal-CkXEIQcK.js → UpdateModal-CFLq9pT1.js} +1 -1
- package/dashboard/static/assets/{index-HKS1s56o.js → index-BKTWH9JE.js} +2 -2
- package/dashboard/static/assets/{outlineNavigation-BNGaNPCp.js → outlineNavigation-BnGUwCS3.js} +3 -3
- package/dashboard/static/dashboard.html +1 -1
- package/package.json +4 -1
- package/dashboard/static/assets/ConversationsView-Dcfn8T6f.js +0 -72
- package/dashboard/static/assets/ModalRoot-Ck3WJK2V.js +0 -1
|
@@ -867,10 +867,7 @@ def _apply_owed_outputs(base, start, output_end, boundary) -> frozenset:
|
|
|
867
867
|
{"lines": 0, "bytes": 0, "decodes": 0}, boundary=boundary)
|
|
868
868
|
elif prefix.cutover_claude is None:
|
|
869
869
|
prefix.cutover_claude = _lib_accounts.UNATTRIBUTED
|
|
870
|
-
|
|
871
|
-
if record is not None:
|
|
872
|
-
_journal._normalize_legacy_account_stamp(
|
|
873
|
-
record, prefix.cutover_claude)
|
|
870
|
+
_install_window_normalizer(prefix, prefix.cutover_claude)
|
|
874
871
|
selection = _lib_journal.resolve_effective_events(
|
|
875
872
|
prefix.slots, protocol_prefix_evidence=tuple(prefix.evidence))
|
|
876
873
|
owed: dict = {}
|
|
@@ -926,13 +923,22 @@ def _apply_owed_outputs(base, start, output_end, boundary) -> frozenset:
|
|
|
926
923
|
# --------------------------------------------------------------------------
|
|
927
924
|
|
|
928
925
|
class _Prefix:
|
|
929
|
-
"""One pass over the journal through the round's target.
|
|
926
|
+
"""One pass over the journal through the round's target.
|
|
927
|
+
|
|
928
|
+
#1004 spec D4: `slots` and `window` are `RetainedRecords` (each record a
|
|
929
|
+
reader retains decoded is a streamed slot, re-read and digest-checked on
|
|
930
|
+
access), and `coordinates` is the window's `LineCoordinates` starts view,
|
|
931
|
+
parallel to `window`. With `MATERIALIZE_FOR_TESTS` they are today's
|
|
932
|
+
lists (a test switch)."""
|
|
930
933
|
|
|
931
934
|
def __init__(self):
|
|
932
|
-
|
|
935
|
+
# selector slots, one per decoded record
|
|
936
|
+
self.slots = _journal._new_retained_records()
|
|
933
937
|
self.evidence: list = [] # protocol-resolution prefix evidence
|
|
934
|
-
|
|
935
|
-
self.
|
|
938
|
+
# window records (placeholders kept)
|
|
939
|
+
self.window = _journal._new_retained_records()
|
|
940
|
+
# parallel to `window`: each position's `(segment, offset)`
|
|
941
|
+
self.coordinates = self.window.coordinates.starts()
|
|
936
942
|
self.excluded_revisions: dict = {}
|
|
937
943
|
self.inert_revisions: dict = {}
|
|
938
944
|
self.begin_at: dict = {}
|
|
@@ -976,6 +982,8 @@ def _window_omits(record) -> bool:
|
|
|
976
982
|
|
|
977
983
|
|
|
978
984
|
def _read_prefix(start, target, boundary) -> _Prefix:
|
|
985
|
+
import _lib_retained_records
|
|
986
|
+
materialize = _lib_retained_records.MATERIALIZE_FOR_TESTS
|
|
979
987
|
out = _Prefix()
|
|
980
988
|
segments = _journal.list_segments()
|
|
981
989
|
hasher = _journal._new_prefix_hasher()
|
|
@@ -1007,13 +1015,13 @@ def _read_prefix(start, target, boundary) -> _Prefix:
|
|
|
1007
1015
|
# compacted before anything holds a reference to it.
|
|
1008
1016
|
record = _lib_journal.compact_retained(record)
|
|
1009
1017
|
if not admitted:
|
|
1010
|
-
out.slots.
|
|
1018
|
+
out.slots.append_retained(None, segment, offset, len(raw))
|
|
1011
1019
|
if record.get("t") in ("evt", "correction"):
|
|
1012
1020
|
_bump(out.excluded_revisions, record)
|
|
1013
1021
|
if in_window:
|
|
1014
|
-
out.window.
|
|
1015
|
-
"record": record, "segment": segment, "offset": offset}}
|
|
1016
|
-
|
|
1022
|
+
out.window.append_retained({**placeholder, "quarantine": {
|
|
1023
|
+
"record": record, "segment": segment, "offset": offset}},
|
|
1024
|
+
segment, offset, len(raw))
|
|
1017
1025
|
prior["hw"] = end
|
|
1018
1026
|
continue
|
|
1019
1027
|
if t == "op":
|
|
@@ -1032,15 +1040,59 @@ def _read_prefix(start, target, boundary) -> _Prefix:
|
|
|
1032
1040
|
out.begin_at.setdefault(record.get("id"), record.get("at"))
|
|
1033
1041
|
out.begins.setdefault(record.get("id"), []).append(record)
|
|
1034
1042
|
out.batch_family.setdefault(record.get("id"), record.get("family"))
|
|
1035
|
-
|
|
1036
|
-
|
|
1043
|
+
if t in _lib_journal_router.RETAINED_RECORD_TYPES:
|
|
1044
|
+
if materialize:
|
|
1045
|
+
out.slots.append_retained(record, segment, offset, len(raw))
|
|
1046
|
+
else:
|
|
1047
|
+
out.slots.append_streamed(raw, segment, offset, len(raw))
|
|
1048
|
+
else:
|
|
1049
|
+
out.slots.append_retained(None, segment, offset, len(raw))
|
|
1037
1050
|
if in_window and not omitted:
|
|
1038
|
-
|
|
1039
|
-
|
|
1051
|
+
if materialize:
|
|
1052
|
+
out.window.append_retained(record, segment, offset, len(raw))
|
|
1053
|
+
else:
|
|
1054
|
+
out.window.append_streamed(raw, segment, offset, len(raw))
|
|
1040
1055
|
prior["hw"] = end
|
|
1056
|
+
if materialize:
|
|
1057
|
+
# Every slot is a retained object here, so this decodes nothing; a
|
|
1058
|
+
# record both lists keep is one shared object, as before.
|
|
1059
|
+
slots, window = out.slots, out.window
|
|
1060
|
+
out.slots, out.window = list(slots), list(window)
|
|
1061
|
+
out.coordinates = list(window.coordinates.starts())
|
|
1062
|
+
slots.close()
|
|
1063
|
+
window.close()
|
|
1041
1064
|
return out
|
|
1042
1065
|
|
|
1043
1066
|
|
|
1067
|
+
def _install_window_normalizer(prefix: _Prefix, cutover_claude) -> None:
|
|
1068
|
+
"""#1004 spec D4: normalize the prefix's retained records under the
|
|
1069
|
+
resolved ``cutover_claude`` at decode time, on both `slots` and `window`,
|
|
1070
|
+
replacing the in-place loop both `_apply_owed_outputs` and
|
|
1071
|
+
`_complete_window` ran before any consumer read a record.
|
|
1072
|
+
|
|
1073
|
+
The loop normalized the selector slots, which are the retained decision
|
|
1074
|
+
records (`RETAINED_RECORD_TYPES`), and with them the very same objects
|
|
1075
|
+
the window shares; a window observation was normalized only in each
|
|
1076
|
+
replay's private copy (`_normalized_copy`). The hook keeps exactly that
|
|
1077
|
+
scope on both sequences. Normalization is idempotent and a pure function
|
|
1078
|
+
of the record and the cutover, so every decode yields an equal record."""
|
|
1079
|
+
if isinstance(prefix.slots, list):
|
|
1080
|
+
# MATERIALIZE_FOR_TESTS: today's lists and today's loop.
|
|
1081
|
+
for record in prefix.slots:
|
|
1082
|
+
if record is not None:
|
|
1083
|
+
_journal._normalize_legacy_account_stamp(
|
|
1084
|
+
record, cutover_claude)
|
|
1085
|
+
return
|
|
1086
|
+
retained_types = _lib_journal_router.RETAINED_RECORD_TYPES
|
|
1087
|
+
|
|
1088
|
+
def normalize(record) -> None:
|
|
1089
|
+
if record.get("t") in retained_types:
|
|
1090
|
+
_journal._normalize_legacy_account_stamp(record, cutover_claude)
|
|
1091
|
+
|
|
1092
|
+
prefix.slots.set_normalizer(normalize)
|
|
1093
|
+
prefix.window.set_normalizer(normalize)
|
|
1094
|
+
|
|
1095
|
+
|
|
1044
1096
|
def _held_observation_ids(slots) -> frozenset:
|
|
1045
1097
|
"""The observations a retained reviewed weekly decision holds (latest
|
|
1046
1098
|
decision per observation wins, as the rederive planner reads them)."""
|
|
@@ -1110,17 +1162,32 @@ def _no_cache_read_adapters():
|
|
|
1110
1162
|
setattr(cctally, name, value)
|
|
1111
1163
|
|
|
1112
1164
|
|
|
1113
|
-
def _normalized_copy(record, cutover_claude):
|
|
1165
|
+
def _normalized_copy(record, cutover_claude, *, fresh=False):
|
|
1114
1166
|
"""One window record as a replay sees it: a private deep copy, its legacy
|
|
1115
1167
|
account stamp normalized under ``cutover_claude`` (an excluded placeholder
|
|
1116
1168
|
is only copied). Reads only this record and the journal-wide cutover
|
|
1117
|
-
value (#997 spec D5).
|
|
1118
|
-
|
|
1169
|
+
value (#997 spec D5).
|
|
1170
|
+
|
|
1171
|
+
``fresh`` (#1004 spec D4): ``record`` is a streamed slot's own decode,
|
|
1172
|
+
already private, so it is normalized in place and returned without the
|
|
1173
|
+
copy (the copy of a private dict equals it)."""
|
|
1174
|
+
out = record if fresh else copy.deepcopy(record)
|
|
1119
1175
|
if out.get("t") != _lib_account_protocol.EXCLUDED_PLACEHOLDER_TYPE:
|
|
1120
1176
|
_journal._normalize_legacy_account_stamp(out, cutover_claude)
|
|
1121
1177
|
return out
|
|
1122
1178
|
|
|
1123
1179
|
|
|
1180
|
+
def _retained_window_ids(window) -> "frozenset | None":
|
|
1181
|
+
"""The identities of the window's retained objects (its placeholders),
|
|
1182
|
+
or None for a list window, all of whose records are retained. A retained
|
|
1183
|
+
object lives as long as the window, so no fresh decode offered while
|
|
1184
|
+
the window is alive can share its id."""
|
|
1185
|
+
if isinstance(window, list):
|
|
1186
|
+
return None
|
|
1187
|
+
return frozenset(id(window.slot(i)) for i in range(len(window))
|
|
1188
|
+
if not window.is_streamed(i))
|
|
1189
|
+
|
|
1190
|
+
|
|
1124
1191
|
def _replay(base, tmp, name, prefix, held_ids, cache_conn, *, retention,
|
|
1125
1192
|
skip=frozenset()):
|
|
1126
1193
|
"""One scratch replay of the window from the predecessor state, the
|
|
@@ -1132,6 +1199,7 @@ def _replay(base, tmp, name, prefix, held_ids, cache_conn, *, retention,
|
|
|
1132
1199
|
copy_path = tmp / name
|
|
1133
1200
|
shutil.copyfile(base, copy_path)
|
|
1134
1201
|
cutover_claude = prefix.cutover_claude
|
|
1202
|
+
retained = _retained_window_ids(prefix.window)
|
|
1135
1203
|
by_input: dict = {}
|
|
1136
1204
|
conn = _cctally_core.open_db(_target_path=str(copy_path))
|
|
1137
1205
|
try:
|
|
@@ -1143,7 +1211,9 @@ def _replay(base, tmp, name, prefix, held_ids, cache_conn, *, retention,
|
|
|
1143
1211
|
# offered, never the whole window up front.
|
|
1144
1212
|
events = _cctally_rederive.replay_scratch_records(
|
|
1145
1213
|
conn, prefix.window, cache_conn, fold=fold, held_ids=held_ids,
|
|
1146
|
-
prepare=lambda record: _normalized_copy(
|
|
1214
|
+
prepare=lambda record: _normalized_copy(
|
|
1215
|
+
record, cutover_claude,
|
|
1216
|
+
fresh=retained is not None and id(record) not in retained),
|
|
1147
1217
|
coordinates=prefix.coordinates, skip_indexes=skip,
|
|
1148
1218
|
on_input=lambda index, derived: by_input.__setitem__(
|
|
1149
1219
|
index, list(derived)),
|
|
@@ -1209,12 +1279,15 @@ def _legacy_decided_inputs(prefix, by_input=None) -> frozenset:
|
|
|
1209
1279
|
previous-release reading closed at that second, and treating that retry
|
|
1210
1280
|
as the reading's own history left the reading's decision unjournaled."""
|
|
1211
1281
|
legacy = prefix.legacy_origin_ids
|
|
1212
|
-
|
|
1213
|
-
|
|
1214
|
-
|
|
1282
|
+
# One pass (#1004 D4: each access decodes a streamed record, so the
|
|
1283
|
+
# legacy inputs are found once rather than by a lookup per input).
|
|
1284
|
+
legacy_inputs = {index: record.get("id")
|
|
1285
|
+
for index, record in enumerate(prefix.window)
|
|
1286
|
+
if _is_legacy_input(record)}
|
|
1287
|
+
out = {index for index, record_id in legacy_inputs.items()
|
|
1288
|
+
if _SNAPSHOT_ID_PREFIX + str(record_id) in legacy}
|
|
1215
1289
|
for index, derived in (by_input or {}).items():
|
|
1216
|
-
if not
|
|
1217
|
-
and _is_legacy_input(prefix.window[index])):
|
|
1290
|
+
if index not in legacy_inputs:
|
|
1218
1291
|
continue
|
|
1219
1292
|
if any(event["id"] in legacy for event in derived
|
|
1220
1293
|
if _lib_rederive._is_owned_event(event)):
|
|
@@ -1253,10 +1326,7 @@ def _complete_window(base, tmp, start, target, boundary, round_index, *,
|
|
|
1253
1326
|
{"lines": 0, "bytes": 0, "decodes": 0}, boundary=boundary)
|
|
1254
1327
|
elif prefix.cutover_claude is None:
|
|
1255
1328
|
prefix.cutover_claude = _lib_accounts.UNATTRIBUTED
|
|
1256
|
-
|
|
1257
|
-
if record is not None:
|
|
1258
|
-
_journal._normalize_legacy_account_stamp(
|
|
1259
|
-
record, prefix.cutover_claude)
|
|
1329
|
+
_install_window_normalizer(prefix, prefix.cutover_claude)
|
|
1260
1330
|
accumulators: dict = {}
|
|
1261
1331
|
selection = _lib_journal.resolve_effective_events(
|
|
1262
1332
|
prefix.slots, protocol_prefix_evidence=tuple(prefix.evidence),
|
|
@@ -1290,20 +1360,23 @@ def _complete_window(base, tmp, start, target, boundary, round_index, *,
|
|
|
1290
1360
|
return False
|
|
1291
1361
|
_lib_rebuild_progress.phase(
|
|
1292
1362
|
"completion:replay-without", round=round_index)
|
|
1293
|
-
|
|
1363
|
+
# #1004: only the events are kept. A discarded `by_input` bound to a
|
|
1364
|
+
# local would stay alive through the next replay (≈ 24 MB at 195 k
|
|
1365
|
+
# inputs, measured by T11's residual census).
|
|
1366
|
+
events_a = _replay(
|
|
1294
1367
|
base, tmp, f"without-{round_index}.db", prefix, held_ids,
|
|
1295
1368
|
cache_conn, skip=gap,
|
|
1296
|
-
retention=_retention(effective, prefix, owed, legacy=legacy))
|
|
1369
|
+
retention=_retention(effective, prefix, owed, legacy=legacy))[0]
|
|
1297
1370
|
reference: dict = {}
|
|
1298
1371
|
for event in events_a:
|
|
1299
1372
|
reference.setdefault(
|
|
1300
1373
|
event["id"], _lib_journal.event_content_hash(event))
|
|
1301
1374
|
_lib_rebuild_progress.phase(
|
|
1302
1375
|
"completion:replay-with", round=round_index)
|
|
1303
|
-
events_b
|
|
1376
|
+
events_b = _replay(
|
|
1304
1377
|
base, tmp, f"with-{round_index}.db", prefix, held_ids, cache_conn,
|
|
1305
1378
|
retention=_retention(effective, prefix, owed, legacy=legacy,
|
|
1306
|
-
reference=reference))
|
|
1379
|
+
reference=reference))[0]
|
|
1307
1380
|
with_gap = _owned_by_id(events_b)
|
|
1308
1381
|
without_gap = _owned_by_id(events_a)
|
|
1309
1382
|
|
package/bin/_cctally_core.py
CHANGED
|
@@ -599,7 +599,16 @@ _init_paths_from_env()
|
|
|
599
599
|
# `outcome_quarantine_episodes`, `outcome_quarantine_bounds` and
|
|
600
600
|
# `outcome_quarantine_axis_state`, so an index built without them is not
|
|
601
601
|
# current. No numbered migration; `DERIVATION_FRONTIER_EPOCH` is unchanged.
|
|
602
|
-
|
|
602
|
+
# 1023 -> 1024 (#1018 twin spec 5.1): current-week freshness from confirming
|
|
603
|
+
# weekly readings. `claude_weekly_observation_index` gains `weekly_percent`,
|
|
604
|
+
# `weekly_resets_at_utc`, `weekly_reading_genuine` and
|
|
605
|
+
# `weekly_freshness_eligible`, and the partial covering index
|
|
606
|
+
# `idx_claude_weekly_observation_index_freshness` serves the confirmation
|
|
607
|
+
# lookup, so an index built without them is not current. The index
|
|
608
|
+
# population and `captured_at_utc` are unchanged. No numbered migration;
|
|
609
|
+
# `DERIVATION_FRONTIER_EPOCH` is unchanged.
|
|
610
|
+
# Bump checklist (partners, regenerate commands, tripwires): tests/test_stats_index_epoch_pin.py.
|
|
611
|
+
STATS_INDEX_EPOCH = 1024
|
|
603
612
|
LEGACY_STATS_HEAD = 13
|
|
604
613
|
|
|
605
614
|
|
|
@@ -1071,6 +1080,16 @@ _STATS_INGEST_LOCK_HELD = contextvars.ContextVar(
|
|
|
1071
1080
|
_STATS_INTERRUPTED_RECOVERY_SUPPRESSED = contextvars.ContextVar(
|
|
1072
1081
|
"cctally_stats_interrupted_recovery_suppressed", default=0
|
|
1073
1082
|
)
|
|
1083
|
+
#: #1005: the active diagnostic maintenance-wait allowance, or None outside a
|
|
1084
|
+
#: `_cctally_store.bounded_diagnostic_waits` scope. The value is a mutable
|
|
1085
|
+
#: record with one attribute, `remaining_s`, shared by every nested scope and
|
|
1086
|
+
#: charged by `_cctally_store.diagnostic_flock`. Kept here for the same reason
|
|
1087
|
+
#: as the two above: a store-owned ContextVar would be replaced by an empty one
|
|
1088
|
+
#: when `load_script()` reloads the siblings, and a scope entered before the
|
|
1089
|
+
#: reload would silently stop bounding.
|
|
1090
|
+
_STATS_DIAGNOSTIC_WAIT_ALLOWANCE = contextvars.ContextVar(
|
|
1091
|
+
"cctally_stats_diagnostic_wait_allowance", default=None
|
|
1092
|
+
)
|
|
1074
1093
|
|
|
1075
1094
|
|
|
1076
1095
|
def note_stats_maintenance_acquired() -> None:
|
|
@@ -2413,6 +2432,10 @@ def open_db(*, _target_path=None) -> sqlite3.Connection:
|
|
|
2413
2432
|
conn, _STATS_MIGRATIONS, "stats.db"
|
|
2414
2433
|
)
|
|
2415
2434
|
_reconcile_incomplete_quota_projection(conn)
|
|
2435
|
+
# #1050 §4.3: a `current` store costs two reads and no lock; an
|
|
2436
|
+
# index published by an older binary (or never installed) gets
|
|
2437
|
+
# its content-revision objects here, without an epoch bump.
|
|
2438
|
+
_ensure_stats_content_revision(conn, live=_target_path is None)
|
|
2416
2439
|
return conn
|
|
2417
2440
|
if _target_path is None:
|
|
2418
2441
|
if _uv > LEGACY_STATS_HEAD:
|
|
@@ -2474,6 +2497,7 @@ def open_db(*, _target_path=None) -> sqlite3.Connection:
|
|
|
2474
2497
|
_reconcile_durable_applied_migration_errors(
|
|
2475
2498
|
conn, _STATS_MIGRATIONS, "stats.db"
|
|
2476
2499
|
)
|
|
2500
|
+
_ensure_stats_content_revision(conn, live=_target_path is None)
|
|
2477
2501
|
return conn
|
|
2478
2502
|
# PR-3: everything below is pending schema, migration or cutover work;
|
|
2479
2503
|
# it sorts under FILE, and the writer temp store is selected again
|
|
@@ -2876,12 +2900,25 @@ def open_db(*, _target_path=None) -> sqlite3.Connection:
|
|
|
2876
2900
|
# credit detection, never pruned. `account_key` is the account live
|
|
2877
2901
|
# ingest reads after the cutover-aware legacy normalization;
|
|
2878
2902
|
# `captured_at_utc` is canonical full-precision UTC.
|
|
2903
|
+
#
|
|
2904
|
+
# #1018 twin epoch 1024 (spec 5.1): the record's raw weekly value, its
|
|
2905
|
+
# nearest-hour normalized reset (the second-precision spelling of
|
|
2906
|
+
# `claude_oauth_samples.weekly_resets_at_utc`, used only for
|
|
2907
|
+
# equality), whether it is a genuine weekly reading for this row's
|
|
2908
|
+
# account, and whether it may confirm a displayed weekly value
|
|
2909
|
+
# (genuine, both values present, captured strictly before the reset,
|
|
2910
|
+
# not held by the effective reviewed decision). The partial index
|
|
2911
|
+
# covers the one confirmation lookup.
|
|
2879
2912
|
conn.execute(
|
|
2880
2913
|
"""
|
|
2881
2914
|
CREATE TABLE IF NOT EXISTS claude_weekly_observation_index (
|
|
2882
|
-
observation_id
|
|
2883
|
-
account_key
|
|
2884
|
-
captured_at_utc
|
|
2915
|
+
observation_id TEXT PRIMARY KEY,
|
|
2916
|
+
account_key TEXT NOT NULL,
|
|
2917
|
+
captured_at_utc TEXT NOT NULL,
|
|
2918
|
+
weekly_percent REAL,
|
|
2919
|
+
weekly_resets_at_utc TEXT,
|
|
2920
|
+
weekly_reading_genuine INTEGER NOT NULL DEFAULT 0,
|
|
2921
|
+
weekly_freshness_eligible INTEGER NOT NULL DEFAULT 0
|
|
2885
2922
|
)
|
|
2886
2923
|
"""
|
|
2887
2924
|
)
|
|
@@ -2889,6 +2926,13 @@ def open_db(*, _target_path=None) -> sqlite3.Connection:
|
|
|
2889
2926
|
"CREATE INDEX IF NOT EXISTS idx_claude_weekly_observation_index_window "
|
|
2890
2927
|
"ON claude_weekly_observation_index (account_key, captured_at_utc)"
|
|
2891
2928
|
)
|
|
2929
|
+
conn.execute(
|
|
2930
|
+
"CREATE INDEX IF NOT EXISTS "
|
|
2931
|
+
"idx_claude_weekly_observation_index_freshness "
|
|
2932
|
+
"ON claude_weekly_observation_index "
|
|
2933
|
+
"(account_key, weekly_resets_at_utc, weekly_percent, "
|
|
2934
|
+
"captured_at_utc DESC) WHERE weekly_freshness_eligible = 1"
|
|
2935
|
+
)
|
|
2892
2936
|
# Every decision of every reviewed weekly op (not only the latest),
|
|
2893
2937
|
# with the DECODED disposition: a `weekly_axis_retractions` member is
|
|
2894
2938
|
# `retract`. Idempotent under the primary key.
|
|
@@ -3903,10 +3947,31 @@ def open_db(*, _target_path=None) -> sqlite3.Connection:
|
|
|
3903
3947
|
except Exception:
|
|
3904
3948
|
pass
|
|
3905
3949
|
raise
|
|
3950
|
+
# #1050 §4.3: the fresh, scratch and cutover schema apply install
|
|
3951
|
+
# the content-revision objects once the store is at the epoch, so
|
|
3952
|
+
# a scratch replay is tracked from its first row and is published
|
|
3953
|
+
# with them. After the cutover rather than before it: the
|
|
3954
|
+
# cutover's `journal_id` stamping is bookkeeping, and tracking it
|
|
3955
|
+
# would only cost one trigger per legacy row. A legacy store that
|
|
3956
|
+
# a deferred migration keeps below the epoch is not installed.
|
|
3957
|
+
if conn.execute(
|
|
3958
|
+
"PRAGMA user_version"
|
|
3959
|
+
).fetchone()[0] == STATS_INDEX_EPOCH:
|
|
3960
|
+
_ensure_stats_content_revision(
|
|
3961
|
+
conn, live=_target_path is None)
|
|
3906
3962
|
_cctally_store.apply_writer_temp_store(conn)
|
|
3907
3963
|
return conn
|
|
3908
3964
|
|
|
3909
3965
|
|
|
3966
|
+
def _ensure_stats_content_revision(conn, *, live: bool) -> str:
|
|
3967
|
+
"""#1050: install or repair stats.db's content-revision objects (the pure
|
|
3968
|
+
kernel `_lib_stats_content_revision`, a proven leaf). A `current` store is
|
|
3969
|
+
two reads; contention leaves the store as it is for the next open."""
|
|
3970
|
+
import _lib_stats_content_revision
|
|
3971
|
+
return _lib_stats_content_revision.ensure_stats_content_revision(
|
|
3972
|
+
conn, live=live)
|
|
3973
|
+
|
|
3974
|
+
|
|
3910
3975
|
# === WeekRef cluster ================================================
|
|
3911
3976
|
|
|
3912
3977
|
|