cctally 1.92.0 → 1.92.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.
@@ -3382,6 +3382,25 @@ def _build_stats_epoch_rebuild_parser(subparsers, name, *, help_text, xref=None)
3382
3382
  )
3383
3383
  worker.set_defaults(func=c.cmd_stats_epoch_rebuild_internal)
3384
3384
 
3385
+ def _build_stats_corruption_heal_parser(subparsers, name, *, help_text, xref=None):
3386
+ """Build the #496 S3 detached stats corruption-heal worker parser."""
3387
+ c = _cctally()
3388
+ worker = subparsers.add_parser(
3389
+ name,
3390
+ help=help_text,
3391
+ formatter_class=CLIHelpFormatter,
3392
+ description=textwrap.dedent(
3393
+ """\
3394
+ Internal subcommand: rebuild a corrupt stats index from the
3395
+ journal under its own maintenance-exclusive hold. Spawned by
3396
+ the classifier-gated corruption heal so no statusline render
3397
+ and no dashboard start blocks on the rebuild. Always returns
3398
+ 0; failures are logged and remain retryable.
3399
+ """
3400
+ ),
3401
+ )
3402
+ worker.set_defaults(func=c.cmd_stats_corruption_heal_internal)
3403
+
3385
3404
  def _build_codex_replay_drain_parser(subparsers, name, *, help_text, xref=None):
3386
3405
  """Build the `_codex-replay-drain` parser (public #5 §4)."""
3387
3406
  c = _cctally()
@@ -3484,6 +3503,7 @@ _REGISTRATION = (
3484
3503
  _Reg('_telemetry-beat', _build_telemetry_beat_parser, argparse.SUPPRESS, None, None),
3485
3504
  _Reg('_codex-quota-verify', _build_codex_quota_verify_parser, argparse.SUPPRESS, None, None),
3486
3505
  _Reg('_stats-epoch-rebuild', _build_stats_epoch_rebuild_parser, argparse.SUPPRESS, None, None),
3506
+ _Reg('_stats-corruption-heal', _build_stats_corruption_heal_parser, argparse.SUPPRESS, None, None),
3487
3507
  _Reg('_codex-replay-drain', _build_codex_replay_drain_parser, argparse.SUPPRESS, None, None),
3488
3508
  _Reg('repair-symlinks', _build_repair_symlinks_parser, argparse.SUPPRESS, None, None),
3489
3509
  )
@@ -717,7 +717,7 @@ def _blocks_missing_reverse_map(stats_conn: sqlite3.Connection) -> bool:
717
717
 
718
718
  A scoped sweep matches on ``physical_group_key``, so a NULL there would
719
719
  silently escape it and the stale block would survive indefinitely. The
720
- epoch rebuild (1005 introduced the column; current epoch 1007) stamps every row, and
720
+ epoch rebuild (1005 introduced the column; current epoch 1008) stamps every row, and
721
721
  this is the guard that turns the
722
722
  one shape it cannot reach — a block written by an older binary against an
723
723
  already-current index — into a full pass rather than a missed one.
@@ -2129,7 +2129,7 @@ def _apply_quota_projection_rows(
2129
2129
  schedule_boundary = min(stored_schedule.values(), default=None)
2130
2130
  # A scalar-only boundary is a legacy/fail-safe state with unknown ownership.
2131
2131
  # Keep the prior behavior until a qualifying whole-history pass can retire
2132
- # it; epoch-1007 indexes normally never enter this branch.
2132
+ # it; current-epoch indexes normally never enter this branch.
2133
2133
  legacy_boundary = stored_boundary if not stored_next_evaluation_by_root else None
2134
2134
  boundary = (
2135
2135
  None if schedule_boundary is None
@@ -771,7 +771,7 @@ def _read_db_projection_stable(*, attempts: int = 3) -> "_candidates.DbProjectio
771
771
  before = _db_file_fingerprint()
772
772
  try:
773
773
  projection = _read_db_projection_once()
774
- except _cctally().StatsEpochRebuildDeferred:
774
+ except _cctally().StatsRebuildDeferred:
775
775
  return _candidates.DbProjection(None, None, db_files=before)
776
776
  after = _db_file_fingerprint()
777
777
  if before == after and after["main"] is not None:
@@ -1012,7 +1012,7 @@ def _authoritative_record_usage(
1012
1012
 
1013
1013
  try:
1014
1014
  rc = _cctally().cmd_record_usage(args)
1015
- except _cctally().StatsEpochRebuildDeferred as exc:
1015
+ except _cctally().StatsRebuildDeferred as exc:
1016
1016
  return _AuthoritativeRecordResult("record_failed", str(exc))
1017
1017
  except Exception as exc:
1018
1018
  return _AuthoritativeRecordResult("record_failed", str(exc))
@@ -1172,7 +1172,7 @@ def _statusline_reduce_and_publish() -> "_candidates.ReductionDecision | None":
1172
1172
  record_rc = _cctally().cmd_record_usage(
1173
1173
  args, ingest_mode="opportunistic"
1174
1174
  )
1175
- except _cctally().StatsEpochRebuildDeferred:
1175
+ except _cctally().StatsRebuildDeferred:
1176
1176
  return decision
1177
1177
  if record_rc != 0:
1178
1178
  return decision
@@ -1597,7 +1597,7 @@ def _build_statusline_injections(warn_once):
1597
1597
  range_start - c.BLOCK_DURATION, now + c.BLOCK_DURATION,
1598
1598
  )
1599
1599
  )
1600
- except c.StatsEpochRebuildDeferred:
1600
+ except c.StatsRebuildDeferred:
1601
1601
  recorded_windows, block_start_overrides, canonical_intervals = (
1602
1602
  [], {}, {},
1603
1603
  )
@@ -1637,7 +1637,7 @@ def _build_statusline_injections(warn_once):
1637
1637
  _acct_params = () if _sl_account is None else (_sl_account,)
1638
1638
  try:
1639
1639
  conn = open_db()
1640
- except c.StatsEpochRebuildDeferred:
1640
+ except c.StatsRebuildDeferred:
1641
1641
  return (None, None)
1642
1642
  except Exception:
1643
1643
  return (None, None)
@@ -1724,7 +1724,7 @@ def _build_statusline_injections(warn_once):
1724
1724
  def _db_latest_rate_limits():
1725
1725
  try:
1726
1726
  conn = open_db()
1727
- except _cctally().StatsEpochRebuildDeferred:
1727
+ except _cctally().StatsRebuildDeferred:
1728
1728
  return None
1729
1729
  except Exception:
1730
1730
  return None