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.
- package/CHANGELOG.md +21 -1
- package/README.md +4 -2
- package/bin/_cctally_cache.py +44 -4
- package/bin/_cctally_core.py +56 -7
- package/bin/_cctally_dashboard.py +71 -14
- package/bin/_cctally_dashboard_conversation.py +8 -4
- package/bin/_cctally_db.py +111 -11
- package/bin/_cctally_journal.py +1102 -102
- package/bin/_cctally_parser.py +20 -0
- package/bin/_cctally_quota.py +2 -2
- package/bin/_cctally_statusline.py +6 -6
- package/bin/_cctally_store.py +783 -67
- package/bin/_cctally_tui.py +54 -6
- package/bin/_lib_codex_conversation_query.py +30 -5
- package/bin/_lib_codex_find_projection.py +147 -0
- package/bin/_lib_conversation_dispatch.py +15 -1
- package/bin/_lib_conversation_query.py +62 -2
- package/bin/_lib_journal_router.py +234 -0
- package/bin/_lib_stats_publish.py +243 -0
- package/bin/cctally +12 -3
- package/dashboard/static/assets/{index-BEzzJtUd.js → index-Dat-mza6.js} +51 -51
- package/dashboard/static/dashboard.html +1 -1
- package/package.json +3 -1
package/bin/_cctally_parser.py
CHANGED
|
@@ -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
|
)
|
package/bin/_cctally_quota.py
CHANGED
|
@@ -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
|
|
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
|
|
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().
|
|
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().
|
|
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().
|
|
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.
|
|
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.
|
|
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().
|
|
1727
|
+
except _cctally().StatsRebuildDeferred:
|
|
1728
1728
|
return None
|
|
1729
1729
|
except Exception:
|
|
1730
1730
|
return None
|