cctally 1.116.1 → 1.117.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 +47 -0
- package/README.md +4 -6
- package/bin/_cctally_account.py +57 -3
- package/bin/_cctally_cache.py +5720 -885
- package/bin/_cctally_claude_attribution.py +997 -0
- package/bin/_cctally_completion.py +101 -28
- package/bin/_cctally_core.py +235 -12
- package/bin/_cctally_dashboard.py +263 -17
- package/bin/_cctally_dashboard_conversation.py +107 -21
- package/bin/_cctally_dashboard_envelope.py +44 -0
- package/bin/_cctally_db.py +928 -80
- package/bin/_cctally_diagnosis_sources.py +78 -13
- package/bin/_cctally_doctor.py +211 -86
- package/bin/_cctally_five_hour.py +446 -22
- package/bin/_cctally_forecast.py +302 -6
- package/bin/_cctally_journal.py +2418 -158
- package/bin/_cctally_milestone_history.py +379 -91
- package/bin/_cctally_oauth_samples.py +185 -7
- package/bin/_cctally_parser.py +38 -0
- package/bin/_cctally_project.py +34 -8
- package/bin/_cctally_quarantine.py +821 -343
- package/bin/_cctally_quota.py +69 -4
- package/bin/_cctally_quota_calibration.py +677 -3
- package/bin/_cctally_quota_model.py +927 -127
- package/bin/_cctally_record.py +922 -445
- package/bin/_cctally_rederive.py +119 -15
- package/bin/_cctally_statusline.py +1048 -176
- package/bin/_cctally_store.py +544 -110
- package/bin/_cctally_tui.py +455 -42
- package/bin/_cctally_update.py +77 -14
- package/bin/_lib_account_protocol.py +227 -19
- package/bin/_lib_claude_attribution.py +421 -0
- package/bin/_lib_clone_copy.py +30 -0
- package/bin/_lib_codex_conversation_query.py +45 -9
- package/bin/_lib_codex_conversation_watch.py +72 -13
- package/bin/_lib_codex_rollout_container.py +234 -19
- package/bin/_lib_codex_worker_lifecycle.py +374 -0
- package/bin/_lib_credit.py +22 -13
- package/bin/_lib_dashboard_sources.py +257 -18
- package/bin/_lib_detector_access_registry.py +1335 -166
- package/bin/_lib_doctor.py +276 -92
- package/bin/_lib_ingest_frontier.py +269 -36
- package/bin/_lib_journal.py +273 -22
- package/bin/_lib_jsonl.py +12 -0
- package/bin/_lib_meter_rate_change.py +72 -0
- package/bin/_lib_outcome_quarantine.py +917 -554
- package/bin/_lib_provider_activity.py +24 -6
- package/bin/_lib_quota_calibration.py +57 -3
- package/bin/_lib_quota_copy.py +7 -2
- package/bin/_lib_quota_lineage.py +613 -0
- package/bin/_lib_quota_model.py +464 -33
- package/bin/_lib_rate_change_delivery.py +16 -0
- package/bin/_lib_reclaim_planner.py +6 -4
- package/bin/_lib_rederive.py +2046 -21
- package/bin/_lib_selector_state.py +131 -3
- package/bin/_lib_snapshot_cache.py +8 -0
- package/bin/_lib_stale_proof.py +113 -4
- package/bin/_lib_statusline.py +72 -3
- package/bin/_lib_statusline_candidates.py +246 -42
- package/bin/_lib_tick_stats.py +10 -5
- package/bin/_lib_write_io.py +419 -6
- package/bin/cctally +28 -11
- package/dashboard/static/assets/{ConversationsView-Dflb_myA.js → ConversationsView-oqNsWzWV.js} +1 -1
- package/dashboard/static/assets/{DoctorModal-DFX5CfIs.js → DoctorModal-B0DnU9d9.js} +1 -1
- package/dashboard/static/assets/ModalRoot-CYua2wP_.js +1 -0
- package/dashboard/static/assets/{ProjectsDrillPanel-C3PJy1xx.js → ProjectsDrillPanel-DSxXQSa-.js} +1 -1
- package/dashboard/static/assets/{SourceDetailModal-BczsWKhD.js → SourceDetailModal-BleDpQqG.js} +1 -1
- package/dashboard/static/assets/{UpdateModal-Os-Lo5cs.js → UpdateModal-CMqaAkSK.js} +1 -1
- package/dashboard/static/assets/{index-CYZ3NLqF.js → index-BjQV-0-D.js} +3 -3
- package/dashboard/static/assets/index-D34eYhAc.css +1 -0
- package/dashboard/static/assets/{outlineNavigation-k-zIif6W.js → outlineNavigation-CO-VWBm7.js} +1 -1
- package/dashboard/static/assets/{useKeymap-CW7Up0Ay.js → useKeymap-CUgEnnua.js} +1 -1
- package/dashboard/static/dashboard.html +3 -3
- package/package.json +5 -1
- package/dashboard/static/assets/ModalRoot-HlxoagIa.js +0 -1
- package/dashboard/static/assets/index-BKITk1CT.css +0 -1
|
@@ -627,15 +627,23 @@ def _witness(status, instant, reason, total, examined, digest) -> ActivityWitnes
|
|
|
627
627
|
files_total=total, files_examined=examined, digest=digest)
|
|
628
628
|
|
|
629
629
|
|
|
630
|
-
def capture_activity(transcript_path: str | None, *, cache_path: pathlib.Path
|
|
630
|
+
def capture_activity(transcript_path: str | None, *, cache_path: pathlib.Path,
|
|
631
|
+
seed_path: pathlib.Path | None = None) -> ActivityWitness:
|
|
631
632
|
"""Capture one arrival's provider-activity evidence (spec 4.1). Called
|
|
632
633
|
once per arrival, before the intake commit and outside the intake
|
|
633
634
|
critical section; never raises for anything a transcript or the cache
|
|
634
|
-
can contain.
|
|
635
|
+
can contain.
|
|
636
|
+
|
|
637
|
+
``seed_path`` is the starting state of an absent cache (#1019 C4): the
|
|
638
|
+
same contributor's document in a previous spool, read without its lock
|
|
639
|
+
and never written. Its records are keyed by file incarnation, so a seed
|
|
640
|
+
is as valid as a document this arrival would write; an unreadable or
|
|
641
|
+
invalid seed is an ordinary first arrival."""
|
|
635
642
|
if not isinstance(transcript_path, str) or not transcript_path:
|
|
636
643
|
return _witness("unknown", None, "no-transcript-path", 0, 0, _digest([], True, True))
|
|
637
644
|
try:
|
|
638
|
-
return _capture_locked(transcript_path, pathlib.Path(cache_path)
|
|
645
|
+
return _capture_locked(transcript_path, pathlib.Path(cache_path),
|
|
646
|
+
None if seed_path is None else pathlib.Path(seed_path))
|
|
639
647
|
except Exception:
|
|
640
648
|
# Every transcript and cache condition is classified above; anything
|
|
641
649
|
# else is still an explicit, eligible unknown capture, never a
|
|
@@ -643,18 +651,28 @@ def capture_activity(transcript_path: str | None, *, cache_path: pathlib.Path) -
|
|
|
643
651
|
return _witness("unknown", None, "unreadable", 0, 0, _digest([], False, False))
|
|
644
652
|
|
|
645
653
|
|
|
646
|
-
def _capture_locked(transcript_path: str, cache_path: pathlib.Path
|
|
654
|
+
def _capture_locked(transcript_path: str, cache_path: pathlib.Path,
|
|
655
|
+
seed_path: pathlib.Path | None) -> ActivityWitness:
|
|
647
656
|
lock = _lock_cache(cache_path)
|
|
648
657
|
try:
|
|
658
|
+
seeded = False
|
|
649
659
|
if lock is None:
|
|
650
660
|
cache, cache_valid, contended = _Cache(), True, True
|
|
651
661
|
else:
|
|
652
|
-
|
|
662
|
+
contended = False
|
|
663
|
+
# Under the lock no other arrival writes this cache, so an absent
|
|
664
|
+
# document stays absent until this arrival stores one.
|
|
665
|
+
seeded = seed_path is not None and not os.path.lexists(cache_path)
|
|
666
|
+
if seeded:
|
|
667
|
+
seed, seed_valid = _load_cache(seed_path)
|
|
668
|
+
cache, cache_valid = (seed if seed_valid else _Cache()), True
|
|
669
|
+
else:
|
|
670
|
+
cache, cache_valid = _load_cache(cache_path)
|
|
653
671
|
before = None if contended else _cache_document(cache)
|
|
654
672
|
result = _capture(transcript_path, cache, cache_valid=cache_valid)
|
|
655
673
|
if lock is not None:
|
|
656
674
|
after = _cache_document(cache)
|
|
657
|
-
if after != before or not cache_valid:
|
|
675
|
+
if after != before or not cache_valid or seeded:
|
|
658
676
|
_store_cache(cache_path, after)
|
|
659
677
|
return result
|
|
660
678
|
finally:
|
|
@@ -48,6 +48,16 @@ class RegimeRejection(str, enum.Enum):
|
|
|
48
48
|
#: gate. The mark is S1 stating that the regime must not be used to
|
|
49
49
|
#: predict, so it is refused here rather than applied.
|
|
50
50
|
DETECTION_ONLY = "calibration-detection-only"
|
|
51
|
+
#: #1015 spec 5.4: the open regime was fitted before a reviewed
|
|
52
|
+
#: correction to its inputs was materialized (its lineage assesses
|
|
53
|
+
#: `tainted`, or a sweep already annotated it). Wire code
|
|
54
|
+
#: `recalibration-needed`.
|
|
55
|
+
RECALIBRATION_NEEDED = "recalibration-needed"
|
|
56
|
+
#: #1015 spec 5.4: the regime's correction lineage could not be read
|
|
57
|
+
#: (no published facts, a missing projection, a read error) or holds an
|
|
58
|
+
#: unresolved reference. Never an unverified calibrated number; the wire
|
|
59
|
+
#: states `unavailable`.
|
|
60
|
+
LINEAGE_UNAVAILABLE = "calibration-lineage-unavailable"
|
|
51
61
|
|
|
52
62
|
|
|
53
63
|
#: The qualification S1 writes onto a successor fit that is below its
|
|
@@ -96,6 +106,12 @@ class ValidatedRegime:
|
|
|
96
106
|
#: member of `qm.COEFFICIENT_ERAS` (#978).
|
|
97
107
|
coefficient_era: str
|
|
98
108
|
qualifications: tuple = ()
|
|
109
|
+
#: The fit-weighted family composition of the days the regime's fit was
|
|
110
|
+
#: taken over (#991 spec 4.5), the reference the evidence-bounded family
|
|
111
|
+
#: test measures a consumer population against. None when the stored
|
|
112
|
+
#: record carries no valid one, which disables that test for the regime
|
|
113
|
+
#: and leaves the radius rule alone deciding.
|
|
114
|
+
fit_family_shares: "dict | None" = None
|
|
99
115
|
|
|
100
116
|
|
|
101
117
|
@dataclasses.dataclass(frozen=True)
|
|
@@ -162,6 +178,36 @@ def _shares(value) -> "dict | None":
|
|
|
162
178
|
return out
|
|
163
179
|
|
|
164
180
|
|
|
181
|
+
def _fit_reference_shares(value) -> "dict | None":
|
|
182
|
+
"""A stored `fitFamilyShares`, or None when it is unusable (#991).
|
|
183
|
+
|
|
184
|
+
Stricter than `_shares`, which accepts `{}`, negative shares and any sum
|
|
185
|
+
and stays as it is for the TV references: a non-empty dict of string keys
|
|
186
|
+
and finite, non-negative numbers whose `math.fsum` is within 1e-9 of 1,
|
|
187
|
+
returned exactly as stored, never renormalized or rounded. Anything else
|
|
188
|
+
is None, not a rejection, because the regime's fit and its TV references
|
|
189
|
+
remain usable.
|
|
190
|
+
"""
|
|
191
|
+
if not isinstance(value, dict) or not value:
|
|
192
|
+
return None
|
|
193
|
+
out = {}
|
|
194
|
+
for name, share in value.items():
|
|
195
|
+
if not isinstance(name, str) or isinstance(share, bool) \
|
|
196
|
+
or not isinstance(share, (int, float)) \
|
|
197
|
+
or not _finite(share) or share < 0.0:
|
|
198
|
+
return None
|
|
199
|
+
out[name] = float(share)
|
|
200
|
+
try:
|
|
201
|
+
total = math.fsum(out[k] for k in sorted(out))
|
|
202
|
+
except OverflowError:
|
|
203
|
+
# Finite shares whose sum leaves the float range are no
|
|
204
|
+
# distribution; raising would take the whole calibration with it.
|
|
205
|
+
return None
|
|
206
|
+
if abs(total - 1.0) > 1e-9:
|
|
207
|
+
return None
|
|
208
|
+
return out
|
|
209
|
+
|
|
210
|
+
|
|
165
211
|
def _optional_radius(value):
|
|
166
212
|
"""`(ok, radius)` — a radius is absent, or a finite non-negative float."""
|
|
167
213
|
if value is None:
|
|
@@ -272,6 +318,7 @@ def validate_regime(raw, *, account_key, expected_fingerprint,
|
|
|
272
318
|
class_radius=class_radius,
|
|
273
319
|
coefficient_era=era.id,
|
|
274
320
|
qualifications=marks,
|
|
321
|
+
fit_family_shares=_fit_reference_shares(raw.get("fitFamilyShares")),
|
|
275
322
|
)
|
|
276
323
|
|
|
277
324
|
|
|
@@ -338,9 +385,16 @@ def apply_regime(regime: ValidatedRegime, entries, *, interval
|
|
|
338
385
|
if aggregated is None:
|
|
339
386
|
return ApplyRejection.EMPTY_POPULATION
|
|
340
387
|
family_shares, class_shares = aggregated
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
388
|
+
# #991 spec 4.6: the same evaluator as the forecast probe, against the
|
|
389
|
+
# regime's OWN fit-weighted family composition and era.
|
|
390
|
+
support = qm.evaluate_prediction_support(
|
|
391
|
+
family_shares, class_shares,
|
|
392
|
+
family_centre=regime.family_shares,
|
|
393
|
+
family_radius=regime.family_radius,
|
|
394
|
+
class_centre=regime.class_shares,
|
|
395
|
+
class_radius=regime.class_radius,
|
|
396
|
+
fit_family_shares=regime.fit_family_shares, era=era)
|
|
397
|
+
if not support.supported:
|
|
344
398
|
return ApplyRejection.UNSUPPORTED_COMPOSITION
|
|
345
399
|
|
|
346
400
|
units = population_units(entries, era=era)
|
package/bin/_lib_quota_copy.py
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
"""#661 S2 Task D1 — the ONE cause-code copy table (spec section 8).
|
|
2
2
|
|
|
3
|
-
S1 publishes fifteen withheld-figure codes in `EVIDENCE_CODES
|
|
3
|
+
S1 publishes fifteen withheld-figure codes in `EVIDENCE_CODES`, and #1015
|
|
4
|
+
adds a sixteenth, `recalibration-needed`. Section 8
|
|
4
5
|
renders them through one table in two registers, and this module is that
|
|
5
6
|
table.
|
|
6
7
|
|
|
@@ -27,7 +28,7 @@ matters because a dashboard tab can outlive a server restart through
|
|
|
27
28
|
`execvp` and will meet an older server's envelope.
|
|
28
29
|
|
|
29
30
|
Pure: no I/O, no clock, no store. The cause vocabulary is the closed
|
|
30
|
-
|
|
31
|
+
16-member `EVIDENCE_CODES` union, and the separate basis vocabulary names
|
|
31
32
|
which measurement produced a projection. They share this rendering boundary
|
|
32
33
|
but never one semantic union: a basis is not a withholding cause.
|
|
33
34
|
"""
|
|
@@ -79,6 +80,10 @@ _LONG_FORM: dict = {
|
|
|
79
80
|
"the stored calibration came from a newer cctally than this one",
|
|
80
81
|
"unavailable":
|
|
81
82
|
"no usable calibration could be read for this account",
|
|
83
|
+
# --- #1015: the stored calibration's own refusal (U3, spec 2) ---
|
|
84
|
+
"recalibration-needed":
|
|
85
|
+
"the stored calibration was fitted before a correction to its "
|
|
86
|
+
"inputs; run cctally quota to recalibrate",
|
|
82
87
|
}
|
|
83
88
|
|
|
84
89
|
#: Projection-basis copy in the same two registers, deliberately separate
|