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.
Files changed (60) hide show
  1. package/CHANGELOG.md +46 -0
  2. package/README.md +7 -3
  3. package/bin/_cctally_cache.py +2783 -175
  4. package/bin/_cctally_completion.py +106 -33
  5. package/bin/_cctally_core.py +69 -4
  6. package/bin/_cctally_dashboard.py +227 -23
  7. package/bin/_cctally_dashboard_conversation.py +5 -1
  8. package/bin/_cctally_dashboard_envelope.py +60 -19
  9. package/bin/_cctally_dashboard_sources.py +23 -1
  10. package/bin/_cctally_db.py +193 -153
  11. package/bin/_cctally_diagnosis_sources.py +63 -7
  12. package/bin/_cctally_doctor.py +865 -93
  13. package/bin/_cctally_five_hour.py +124 -54
  14. package/bin/_cctally_forecast.py +301 -7
  15. package/bin/_cctally_journal.py +186 -18
  16. package/bin/_cctally_milestone_history.py +1193 -108
  17. package/bin/_cctally_oauth_samples.py +286 -15
  18. package/bin/_cctally_parser.py +2 -2
  19. package/bin/_cctally_quota.py +104 -12
  20. package/bin/_cctally_record.py +153 -29
  21. package/bin/_cctally_rederive.py +608 -68
  22. package/bin/_cctally_statusline.py +108 -81
  23. package/bin/_cctally_store.py +179 -38
  24. package/bin/_cctally_tui.py +1210 -170
  25. package/bin/_cctally_update.py +32 -13
  26. package/bin/_lib_codex_conversation_query.py +52 -14
  27. package/bin/_lib_codex_drain_admission.py +224 -6
  28. package/bin/_lib_codex_metadata.py +39 -0
  29. package/bin/_lib_conversation_anon.py +15 -8
  30. package/bin/_lib_conversation_dispatch.py +7 -0
  31. package/bin/_lib_conversation_query.py +289 -70
  32. package/bin/_lib_dashboard_sources.py +131 -9
  33. package/bin/_lib_detector_access_registry.py +497 -26
  34. package/bin/_lib_doctor.py +85 -20
  35. package/bin/_lib_doctor_scan_index.py +321 -0
  36. package/bin/_lib_ingest_frontier.py +20 -1
  37. package/bin/_lib_oauth_samples.py +23 -7
  38. package/bin/_lib_pricing.py +146 -16
  39. package/bin/_lib_quota.py +19 -0
  40. package/bin/_lib_quota_model.py +29 -11
  41. package/bin/_lib_rederive.py +11 -6
  42. package/bin/_lib_retained_records.py +516 -0
  43. package/bin/_lib_snapshot_cache.py +18 -0
  44. package/bin/_lib_stale_proof.py +272 -43
  45. package/bin/_lib_stats_content_revision.py +831 -0
  46. package/bin/_lib_tick_stats.py +10 -5
  47. package/bin/_lib_write_io.py +12 -5
  48. package/bin/cctally +8 -1
  49. package/dashboard/static/assets/ConversationsView-D4Iv4ku0.js +72 -0
  50. package/dashboard/static/assets/{DoctorModal-BqmXbnhn.js → DoctorModal-D4QSq6uz.js} +1 -1
  51. package/dashboard/static/assets/ModalRoot-C9F5dhZi.js +1 -0
  52. package/dashboard/static/assets/{ProjectsDrillPanel-B-HZkDnT.js → ProjectsDrillPanel-WxAdRDMt.js} +1 -1
  53. package/dashboard/static/assets/{SourceDetailModal-QhJkHB7i.js → SourceDetailModal-NyyEfXmc.js} +1 -1
  54. package/dashboard/static/assets/{UpdateModal-CkXEIQcK.js → UpdateModal-CFLq9pT1.js} +1 -1
  55. package/dashboard/static/assets/{index-HKS1s56o.js → index-BKTWH9JE.js} +2 -2
  56. package/dashboard/static/assets/{outlineNavigation-BNGaNPCp.js → outlineNavigation-BnGUwCS3.js} +3 -3
  57. package/dashboard/static/dashboard.html +1 -1
  58. package/package.json +4 -1
  59. package/dashboard/static/assets/ConversationsView-Dcfn8T6f.js +0 -72
  60. 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
- for record in prefix.slots:
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
- self.slots: list = [] # selector slots, one per decoded record
935
+ # selector slots, one per decoded record
936
+ self.slots = _journal._new_retained_records()
933
937
  self.evidence: list = [] # protocol-resolution prefix evidence
934
- self.window: list = [] # window records (placeholders kept)
935
- self.coordinates: list = [] # parallel to `window`
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.append(None)
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.append({**placeholder, "quarantine": {
1015
- "record": record, "segment": segment, "offset": offset}})
1016
- out.coordinates.append((segment, offset))
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
- out.slots.append(
1036
- record if t in _lib_journal_router.RETAINED_RECORD_TYPES else None)
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
- out.window.append(record)
1039
- out.coordinates.append((segment, offset))
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
- out = copy.deepcopy(record)
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(record, cutover_claude),
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
- out = {index for index, record in enumerate(prefix.window)
1213
- if _is_legacy_input(record)
1214
- and _SNAPSHOT_ID_PREFIX + str(record.get("id")) in legacy}
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 (0 <= index < len(prefix.window)
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
- for record in prefix.slots:
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
- events_a, _ = _replay(
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, _ = _replay(
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
 
@@ -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
- STATS_INDEX_EPOCH = 1023
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 TEXT PRIMARY KEY,
2883
- account_key TEXT NOT NULL,
2884
- captured_at_utc TEXT NOT NULL
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