cctally 1.97.0 → 1.99.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.
@@ -14,11 +14,13 @@ import secrets
14
14
  import sqlite3
15
15
  import sys
16
16
  import time
17
- from dataclasses import dataclass
17
+ from dataclasses import dataclass, replace
18
18
  from typing import Callable, Iterable, Mapping, NoReturn, Sequence
19
19
 
20
20
  import _cctally_core
21
21
  import _lib_accounts
22
+ import _lib_codex_window_attribution as _wa
23
+ import _lib_quota
22
24
  from _cctally_core import _command_as_of, eprint
23
25
  from _lib_quota import (
24
26
  CODEX_RESET_ANCHOR_TOLERANCE_SECONDS,
@@ -538,10 +540,15 @@ def codex_physical_mutation_seq(conn: sqlite3.Connection) -> int:
538
540
  return 0
539
541
 
540
542
 
541
- def load_codex_quota_projection_certificate(
543
+ def _codex_quota_projection_certificate_payload(
542
544
  conn: sqlite3.Connection,
543
- ) -> tuple[int, dict[str, str]] | None:
544
- """Read the post-reconciliation physical-signature certificate in O(1)."""
545
+ ) -> "dict | None":
546
+ """The stored certificate as written, with no revision gate applied.
547
+
548
+ Separate from the reader below because the reconcile needs to know WHY a
549
+ certificate is not usable: an attribution-stale one has to widen the pass to
550
+ the attribution's own groups, while an absent one is an ordinary full pass.
551
+ """
545
552
  try:
546
553
  row = conn.execute(
547
554
  "SELECT value FROM cache_meta WHERE key=?",
@@ -550,6 +557,46 @@ def load_codex_quota_projection_certificate(
550
557
  if row is None:
551
558
  return None
552
559
  payload = json.loads(str(row[0]))
560
+ except (sqlite3.Error, TypeError, ValueError, json.JSONDecodeError):
561
+ return None
562
+ return payload if isinstance(payload, dict) else None
563
+
564
+
565
+ def _certificate_attribution_revision(payload: "Mapping[str, object] | None") -> int:
566
+ """The attribution revision a stored certificate was computed against.
567
+
568
+ A certificate written before #500 carries no such member and reads as ``0``,
569
+ which is also the revision of a store where nothing has ever been asserted —
570
+ so an install with no attributions keeps its existing certificate and its
571
+ existing short-circuit unchanged.
572
+ """
573
+ if not payload:
574
+ return 0
575
+ try:
576
+ return int(payload.get("attributionRevision", 0))
577
+ except (TypeError, ValueError):
578
+ return 0
579
+
580
+
581
+ def load_codex_quota_projection_certificate(
582
+ conn: sqlite3.Connection,
583
+ ) -> tuple[int, dict[str, str]] | None:
584
+ """Read the post-reconciliation physical-signature certificate in O(1).
585
+
586
+ Also gated on the ATTRIBUTION REVISION (#500 spec §8.3). This design writes
587
+ nothing to ``quota_window_snapshots``, so an operator attribution fires no
588
+ trigger and appears in no change-ledger entry; left alone, every consumer of
589
+ this certificate would read a confident no-op and the attribution would never
590
+ reach ``quota_window_blocks`` until some unrelated future ingest happened to
591
+ dirty the same group. Returning ``None`` when the stored revision is not the
592
+ live one puts every consumer — the reconcile short-circuit, the dashboard
593
+ source coherence check, the deferred cache-sync gate — on the fail-safe side
594
+ of that question at once.
595
+ """
596
+ payload = _codex_quota_projection_certificate_payload(conn)
597
+ if payload is None:
598
+ return None
599
+ try:
553
600
  if (
554
601
  int(payload["interpretationVersion"])
555
602
  != _CODEX_QUOTA_INTERPRETATION_VERSION
@@ -560,10 +607,14 @@ def load_codex_quota_projection_certificate(
560
607
  str(root_key): str(signature)
561
608
  for root_key, signature in dict(payload["signatures"]).items()
562
609
  }
563
- except (sqlite3.Error, TypeError, ValueError, KeyError, json.JSONDecodeError):
610
+ except (sqlite3.Error, TypeError, ValueError, KeyError):
564
611
  return None
565
612
  if sequence < 0 or any(len(signature) != 64 for signature in signatures.values()):
566
613
  return None
614
+ if _certificate_attribution_revision(payload) != (
615
+ _cache_module().codex_window_attribution_revision(conn)
616
+ ):
617
+ return None
567
618
  return sequence, signatures
568
619
 
569
620
 
@@ -572,6 +623,7 @@ def _store_codex_quota_projection_certificate(
572
623
  sequence: int,
573
624
  signatures: Mapping[str, str],
574
625
  prune_ledger_through: "int | None" = None,
626
+ attribution_revision: "int | None" = None,
575
627
  ) -> None:
576
628
  """Stamp exact validated signatures only if cache physical state is unchanged.
577
629
 
@@ -592,6 +644,17 @@ def _store_codex_quota_projection_certificate(
592
644
  The prune runs even when the certificate itself is declined: a sequence that
593
645
  advanced mid-pass means new evidence landed, not that the old entries are
594
646
  unconsumed.
647
+
648
+ ``attribution_revision`` (#500 §8.3) is the SEMANTIC twin of ``sequence``
649
+ and is gated the same way: the caller passes the revision its pass actually
650
+ computed against, and a live revision that no longer equals it declines the
651
+ stamp. Reading the live value here instead would certify a projection built
652
+ from observations that never saw the assertion — and it needs no concurrency
653
+ to happen, because the pass's OWN ingest cycle materializes a pending
654
+ ``codex_window_attribution`` op after the observations are loaded. That is
655
+ §8.5's ``recordedPending`` state, and the certificate would poison every
656
+ later reconcile with a confident no-op. ``None`` means no gate, for callers
657
+ that are not a projection pass.
595
658
  """
596
659
  path = _cctally_core.CACHE_DB_PATH
597
660
  if not path.exists():
@@ -611,10 +674,21 @@ def _store_codex_quota_projection_certificate(
611
674
  if codex_physical_mutation_seq(conn) != sequence:
612
675
  conn.commit()
613
676
  return
677
+ live_revision = _cache_module().codex_window_attribution_revision(
678
+ conn)
679
+ if (
680
+ attribution_revision is not None
681
+ and live_revision != int(attribution_revision)
682
+ ):
683
+ conn.commit()
684
+ return
614
685
  payload = json.dumps({
615
686
  "interpretationVersion": _CODEX_QUOTA_INTERPRETATION_VERSION,
616
687
  "sequence": sequence,
617
688
  "signatures": dict(sorted(signatures.items())),
689
+ # #500 §8.3: the semantic revision this projection was computed
690
+ # against — the caller's, verified equal to the live one above.
691
+ "attributionRevision": live_revision,
618
692
  }, sort_keys=True, separators=(",", ":"))
619
693
  conn.execute(
620
694
  "INSERT INTO cache_meta(key, value) VALUES (?, ?) "
@@ -1110,6 +1184,640 @@ def _iter_shard_rows(conn, shards):
1110
1184
  yield from conn.execute(shard_sql, shard_params)
1111
1185
 
1112
1186
 
1187
+ #: Every ``quota_window_snapshots`` column that must be present and non-blank
1188
+ #: before ``load_codex_quota_observations`` will interpret the row.
1189
+ #:
1190
+ #: Named once because TWO populations have to agree on it: the loader's own, and
1191
+ #: the #500 attribution evidence pass's. A row one of them keeps and the other
1192
+ #: drops is a silent divergence in BOTH directions — an evidence row the loader
1193
+ #: discarded can name an account no loaded observation carries, turning a group
1194
+ #: the fold sees as cleanly unattributed into a suppressed one.
1195
+ #:
1196
+ #: One divergence between those two populations is KNOWN and is not on this
1197
+ #: list, because it is not about a required column. Both sides derive the group
1198
+ #: anchor as ``COALESCE(canonical_resets_at_utc, resets_at_utc)``, but SQL
1199
+ #: ``COALESCE`` only replaces NULL, while the loader's per-row interpretation
1200
+ #: treats ``''`` as absent too (``in (None, "")``) and falls back to the raw
1201
+ #: reset. So a row storing an EMPTY canonical anchor is kept by the loader and
1202
+ #: dropped by the evidence pass, which discards one witness for that group. The
1203
+ #: append path never writes ``''`` — this shape comes from a hand-repaired row —
1204
+ #: and the effect is one-directional (a narrower witness set can only make an
1205
+ #: assertion dormant, never make it claim a group it does not own), so it is
1206
+ #: recorded here rather than repaired. It predates #500.
1207
+ _CODEX_QUOTA_REQUIRED_TEXT = (
1208
+ "source", "source_root_key", "source_path", "captured_at_utc",
1209
+ "observed_slot", "logical_limit_key", "resets_at_utc",
1210
+ )
1211
+
1212
+
1213
+ def _codex_quota_required_text_present(values: Iterable[object]) -> bool:
1214
+ """True iff every required text value is present and not blank."""
1215
+ return not any(
1216
+ value is None or not str(value).strip() for value in values)
1217
+
1218
+
1219
+ # --------------------------------------------------------------------------
1220
+ # #500 §6.4 — the fold-time operator attribution overlay
1221
+ # --------------------------------------------------------------------------
1222
+ #
1223
+ # The operator's assertions live in the append-only journal and are indexed into
1224
+ # cache.db's `codex_window_attributions` (#500 Task 1). This is where they are
1225
+ # APPLIED: immediately before the continuity fold, so an attributed group is
1226
+ # genuinely identified by the time `adopt_unidentified_observations`,
1227
+ # `build_blocks` and the spend-adoption pass see it. Nothing is written back to
1228
+ # `quota_window_snapshots`, which stays raw pre-fold provider evidence.
1229
+ #
1230
+ # Resolution and application are separate phases and are NOT interchangeable
1231
+ # (spec §6.4.1). Witness matching is population-dependent, and several callers
1232
+ # deliberately hand the loader a reduced population — the dashboard bounds by
1233
+ # recent days and a row cap, doctor asks for the latest row per identity. If
1234
+ # matching ran against the reduced set, a component a later observation bridged
1235
+ # could present a subset carrying none of the assertion's original witnesses and
1236
+ # the attribution would vanish from the dashboard alone. So resolution always
1237
+ # reads its own COMPLETE evidence for the roots in play, and only application
1238
+ # touches the caller's rows.
1239
+
1240
+
1241
+ def _cache_module():
1242
+ """`_cctally_cache`, imported lazily.
1243
+
1244
+ That module imports THIS one inside its own functions for the same reason:
1245
+ the cache leg reads quota observations and the quota leg reads the cache's
1246
+ derived attribution index, so a module-level import either way is a cycle.
1247
+ """
1248
+ import _cctally_cache
1249
+
1250
+ return _cctally_cache
1251
+
1252
+
1253
+ def _codex_quota_instant_is_valid(value: object) -> bool:
1254
+ """``_parse_utc`` succeeds on ``value``, without paying for the conversion.
1255
+
1256
+ The evidence pass asks this question about every row's capture and reset
1257
+ only to agree with the loader on which rows exist, and never uses the
1258
+ resulting datetime — while ``astimezone`` is the expensive half of
1259
+ ``_parse_utc``.
1260
+
1261
+ Same acceptance set, and the last branch is what makes that true rather than
1262
+ approximately true. ``_parse_utc`` ends in ``astimezone(UTC)``, which raises
1263
+ ``OverflowError`` when shifting the instant leaves the representable range —
1264
+ a year-9999 instant with a negative offset, or a year-1 instant with a
1265
+ positive one. Skipping the conversion outright would accept a row the loader
1266
+ rejects, so it is performed on exactly the two years where it can fail, and
1267
+ nowhere else.
1268
+ """
1269
+ try:
1270
+ parsed = dt.datetime.fromisoformat(str(value).replace("Z", "+00:00"))
1271
+ except (TypeError, ValueError):
1272
+ return False
1273
+ if parsed.tzinfo is None or parsed.utcoffset() is None:
1274
+ return False
1275
+ if parsed.year in (dt.MINYEAR, dt.MAXYEAR):
1276
+ try:
1277
+ parsed.astimezone(UTC)
1278
+ except (OverflowError, OSError, ValueError):
1279
+ return False
1280
+ return True
1281
+
1282
+
1283
+ def _codex_attribution_witness(value: object) -> str:
1284
+ """One spelling for one reset instant, applied to BOTH sides of the binding.
1285
+
1286
+ The cache retains whichever spelling the provider sent and the journal
1287
+ payload carries whichever spelling the command read, so a `Z` witness and a
1288
+ `+00:00` group member are the same instant and must intersect. This is the
1289
+ same fail-open normalizer the loading-unit key uses.
1290
+ """
1291
+ return _ledger.normalize_reset(value)
1292
+
1293
+
1294
+ def _codex_attribution_table_present(conn: sqlite3.Connection) -> bool:
1295
+ """Whether this cache carries the derived index at all.
1296
+
1297
+ A cache too old to have it degrades to "no assertions", exactly as every
1298
+ other column probe in this loader degrades. The fail-LOUD requirement of
1299
+ §6.2 is about the rebuild's publication gate, which is where a partial index
1300
+ would be certified as complete; a read against a pre-#500 cache has no
1301
+ assertion to under-apply.
1302
+ """
1303
+ try:
1304
+ return bool(conn.execute(
1305
+ "SELECT 1 FROM sqlite_master "
1306
+ " WHERE type='table' AND name='codex_window_attributions' LIMIT 1"
1307
+ ).fetchone())
1308
+ except sqlite3.DatabaseError:
1309
+ return False
1310
+
1311
+
1312
+ def _codex_attribution_axis_shards(
1313
+ assertions: "Sequence[Mapping[str, object]]",
1314
+ ) -> "dict[tuple, set[str]]":
1315
+ """Assertions grouped by their four normalized axes, witnesses unioned.
1316
+
1317
+ The shard, not the assertion, is the unit both evidence passes are issued
1318
+ per — because the kernel binds on ``group.axes == assertion.axes`` and every
1319
+ assertion sharing one axis combination therefore reaches the same candidate
1320
+ groups. One query per combination is what keeps the pass proportional to the
1321
+ axes in play instead of to the number of assertions.
1322
+ """
1323
+ shards: "dict[tuple, set[str]]" = {}
1324
+ for assertion in assertions:
1325
+ try:
1326
+ axes = (
1327
+ str(assertion["source_root_key"]),
1328
+ str(assertion["logical_limit_key"]),
1329
+ str(assertion["observed_slot"]),
1330
+ int(assertion["window_minutes"]),
1331
+ )
1332
+ witnesses = {
1333
+ str(witness) for witness in assertion["raw_resets_at_utc"]}
1334
+ except (KeyError, TypeError, ValueError):
1335
+ continue
1336
+ if not all(str(member).strip() for member in axes[:3]) or not witnesses:
1337
+ continue
1338
+ shards.setdefault(axes, set()).update(witnesses)
1339
+ return shards
1340
+
1341
+
1342
+ def _codex_attribution_stored_limit_keys(logical_limit_key: str) -> "list[str]":
1343
+ """Every spelling ``quota_window_snapshots`` can hold for one axis key.
1344
+
1345
+ Two closures, because the stored key and the INTERPRETED key are not the
1346
+ same value. The snap closure covers the weekly jitter that lives in the key
1347
+ as well as in the column, and the model-pool strip covers the read-path
1348
+ rewrite: a row the interpretation moves INTO a model-scoped bucket is stored
1349
+ under the ordinary key, so an axis key carrying a ``modelPool`` member has to
1350
+ ask for the stripped spellings too or its own members become unreachable.
1351
+ For an ordinary key ``strip_model_pool`` is the identity and this is exactly
1352
+ the three snap spellings.
1353
+ """
1354
+ return sorted(
1355
+ set(codex_snap_equivalent_limit_keys(logical_limit_key))
1356
+ | set(codex_snap_equivalent_limit_keys(
1357
+ _ledger.strip_model_pool(logical_limit_key)))
1358
+ )
1359
+
1360
+
1361
+ def _load_codex_window_group_evidence(
1362
+ conn: sqlite3.Connection, assertions: "Sequence[Mapping[str, object]]",
1363
+ ) -> "tuple[_wa.WindowGroup, ...]":
1364
+ """Complete current evidence for every group a stored witness can reach.
1365
+
1366
+ Two indexed passes rather than one interpretation of all history, and the
1367
+ two are exactly equivalent to a full read for RESOLUTION's purposes:
1368
+
1369
+ * Pass 1 finds the canonical anchors of every group holding a row whose RAW
1370
+ reset is one of the stored witnesses. The kernel binds on an intersection
1371
+ against those witnesses, so a group holding none of them cannot match and
1372
+ its absence here changes no verdict — the assertion is dormant either way.
1373
+ * Pass 2 loads the COMPLETE membership of exactly those groups. Every member
1374
+ of a group shares its axes and its canonical anchor by definition of the
1375
+ physical window key, so the shard is a superset of the group and the
1376
+ identified accounts, the model-pool verdict and the full witness set are
1377
+ all read over the whole population.
1378
+
1379
+ BOTH passes are sharded on the assertion's four axes, and that is the whole
1380
+ performance story. ``idx_qws_physical_group`` is ``(source_root_key,
1381
+ logical_limit_key, observed_slot, window_minutes, unixepoch(COALESCE(
1382
+ canonical_resets_at_utc, resets_at_utc))) WHERE source='codex'``, and SQLite
1383
+ cannot skip an interior member: a pass constraining only the root falls back
1384
+ to ``idx_quota_window_source_root`` and reads the root's whole history per
1385
+ query. Measured read-only on the maintainer's 267,163-row store, 63
1386
+ assertions over 2 axis combinations resolving 57 groups:
1387
+
1388
+ ============================================== ========= =========
1389
+ pass root-only sharded
1390
+ ============================================== ========= =========
1391
+ 1 (one query, or one per axis combination) 63.9 ms 43.8 ms
1392
+ 2 (one query per group) 3609.7 ms 119.2 ms
1393
+ whole call, SQL and interpretation together 4443.5 ms 453.8 ms
1394
+ ============================================== ========= =========
1395
+
1396
+ Pass 2 is where the plan actually changes, and it is the dominant cost. It
1397
+ moves from ``SEARCH ... USING INDEX idx_quota_window_source_root
1398
+ (source_root_key=?)`` at 63.3 ms per group to ``SEARCH ... USING INDEX
1399
+ idx_qws_physical_group (source_root_key=? AND logical_limit_key=? AND
1400
+ observed_slot=? AND window_minutes=? AND <expr>=?)`` at 2.1 ms per group.
1401
+ Pass 1 cannot constrain the fifth member at all — it matches RAW resets
1402
+ while the index holds the coalesced anchor — so it seeks the four-member
1403
+ prefix and scans that range; its gain is modest and, on a store where every
1404
+ axis combination is asserted at once, it can cost slightly more than one
1405
+ root-wide query. That is accepted: pass 1 is under 2% of the call, and
1406
+ pairing the axes with each anchor is what lets pass 2 seek all five members.
1407
+
1408
+ This runs three times per ``sync_codex_cache`` and once per dashboard tick
1409
+ and per ``codex quota``, inside both cache flocks.
1410
+
1411
+ Interpretation matches ``load_codex_quota_observations`` member for member —
1412
+ the ``window_minutes`` snap, the limit-key snap, the model-pool rewrite, and
1413
+ the row-validity predicate — because the group key produced here has to equal
1414
+ ``_lib_quota._physical_window_key`` of the observations it will own, and the
1415
+ accounts read here have to be the accounts those observations carry.
1416
+
1417
+ A row whose ``canonical_resets_at_utc`` is NULL is NOT lost: the anchor
1418
+ expression coalesces onto the raw reset, and ``QuotaObservation`` fills
1419
+ ``canonical_resets_at`` from ``resets_at`` under exactly the same rule
1420
+ (``bin/_lib_quota.py`` ``__post_init__``), so both sides key such a row on
1421
+ its own raw reset and they agree. Cache migration 032 backfills the column
1422
+ for ``source='codex'`` anyway.
1423
+ """
1424
+ shards = _codex_attribution_axis_shards(assertions)
1425
+ if not shards:
1426
+ return ()
1427
+ columns = {
1428
+ str(row[1]) for row in conn.execute(
1429
+ "PRAGMA table_info(quota_window_snapshots)")
1430
+ }
1431
+ if not {"source", "source_root_key", "resets_at_utc"} <= columns:
1432
+ return ()
1433
+ has_anchor = "canonical_resets_at_utc" in columns
1434
+ has_account = "account_key" in columns
1435
+ has_model = "observed_model" in columns
1436
+ anchor_expr = (
1437
+ "COALESCE(canonical_resets_at_utc, resets_at_utc)"
1438
+ if has_anchor else "resets_at_utc"
1439
+ )
1440
+ account_expr = "account_key" if has_account else "NULL"
1441
+ model_expr = "observed_model" if has_model else "NULL"
1442
+ # The seven required-text columns first, in `_CODEX_QUOTA_REQUIRED_TEXT`
1443
+ # order, so the shared predicate can be applied to `row[:7]` verbatim.
1444
+ pass_two_select = (
1445
+ "SELECT source, source_root_key, source_path, captured_at_utc,"
1446
+ " observed_slot, logical_limit_key, resets_at_utc,"
1447
+ " window_minutes, limit_id, limit_name, used_percent,"
1448
+ " line_offset,"
1449
+ f" {model_expr} AS observed_model,"
1450
+ f" {account_expr} AS account_key,"
1451
+ f" {anchor_expr} AS anchor"
1452
+ " FROM quota_window_snapshots"
1453
+ )
1454
+
1455
+ buckets: "dict[tuple, dict]" = {}
1456
+ # Per-CALL memos. Every one of these is a pure function of a value drawn
1457
+ # from a tiny domain — at most a handful of stored limit-key spellings, one
1458
+ # anchor spelling per group, a few distinct raw resets, one or two models —
1459
+ # evaluated once per ROW over a population that is ~1,700 rows per group on
1460
+ # the maintainer's store. Interpreting each row independently made the
1461
+ # Python half of this pass cost more than the (now indexed) SQL half.
1462
+ snapped_keys: "dict[str, str]" = {}
1463
+ pools: "dict[object, object]" = {}
1464
+ instants: "dict[str, object]" = {}
1465
+ valid_instants: "dict[str, bool]" = {}
1466
+ witness_texts: "dict[str, str]" = {}
1467
+ model_scoped: "dict[tuple, bool]" = {}
1468
+ for axes, shard_witnesses in sorted(shards.items()):
1469
+ root_key, limit_key, slot, window_minutes = axes
1470
+ # Rows are STORED under whichever length and key spelling the provider
1471
+ # sent, so the filter enumerates every equivalent rather than snapping
1472
+ # in SQL — which it could not do and still seek the index.
1473
+ limit_keys = _codex_attribution_stored_limit_keys(limit_key)
1474
+ minutes = sorted({
1475
+ int(value)
1476
+ for value in codex_snap_equivalent_window_minutes(window_minutes)
1477
+ })
1478
+ witnesses = sorted(shard_witnesses)
1479
+ axis_clause = (
1480
+ " WHERE source='codex' AND source_root_key = ?"
1481
+ " AND logical_limit_key IN ("
1482
+ + ",".join("?" * len(limit_keys)) + ")"
1483
+ " AND observed_slot = ?"
1484
+ " AND window_minutes IN (" + ",".join("?" * len(minutes)) + ")"
1485
+ )
1486
+ axis_params = (root_key, *limit_keys, slot, *minutes)
1487
+ anchors: "set[str]" = set()
1488
+ pass_one = (
1489
+ f"SELECT DISTINCT {anchor_expr} AS anchor"
1490
+ " FROM quota_window_snapshots"
1491
+ + axis_clause
1492
+ + " AND unixepoch(resets_at_utc) IN ("
1493
+ + ",".join("unixepoch(?)" for _ in witnesses) + ")"
1494
+ )
1495
+ for row in conn.execute(pass_one, (*axis_params, *witnesses)):
1496
+ if row[0] is None or not str(row[0]).strip():
1497
+ continue
1498
+ anchors.add(str(row[0]))
1499
+ if not anchors:
1500
+ continue
1501
+ # ONE SHARD PER GROUP, for the reason the loader states at its own group
1502
+ # filter: an OR over the equality gives up and scans, while each group
1503
+ # as its own query seeks all five members of `idx_qws_physical_group`.
1504
+ pass_two = (
1505
+ pass_two_select + axis_clause
1506
+ + f" AND unixepoch({anchor_expr}) = unixepoch(?)"
1507
+ )
1508
+ for anchor_text in sorted(anchors):
1509
+ for row in conn.execute(pass_two, (*axis_params, anchor_text)):
1510
+ if not _codex_quota_required_text_present(row[:7]):
1511
+ continue
1512
+ if row[14] is None or not str(row[14]).strip():
1513
+ continue
1514
+ stored_key = str(row[5])
1515
+ anchor_value = str(row[14])
1516
+ capture_text = str(row[3])
1517
+ reset_text = str(row[6])
1518
+ try:
1519
+ snapped_minutes = snap_codex_window_minutes(int(row[7]))
1520
+ logical_limit_key = snapped_keys.get(stored_key)
1521
+ if logical_limit_key is None:
1522
+ logical_limit_key = snapped_keys[stored_key] = (
1523
+ snap_window_minutes(stored_key))
1524
+ model = row[12]
1525
+ if model not in pools:
1526
+ pools[model] = codex_model_scoped_quota_pool(model)
1527
+ if pools[model] is not None:
1528
+ logical_limit_key = _codex_logical_limit_key(
1529
+ str(row[1]), row[8], str(row[4]), snapped_minutes,
1530
+ str(model),
1531
+ )
1532
+ anchor = instants.get(anchor_value)
1533
+ if anchor is None:
1534
+ anchor = instants[anchor_value] = _parse_utc(
1535
+ anchor_value, "canonical_resets_at_utc")
1536
+ used_percent = float(row[10])
1537
+ line_offset = int(row[11])
1538
+ except (TypeError, ValueError, OverflowError):
1539
+ # The loader skips a malformed physical row window-by-window
1540
+ # rather than suppressing unrelated valid windows; so does
1541
+ # this.
1542
+ continue
1543
+ # The rest of the loader's per-row contract, which
1544
+ # `QuotaObservation.__post_init__` enforces there and which has
1545
+ # to be enforced here or the two populations disagree.
1546
+ for text in (capture_text, reset_text):
1547
+ if text not in valid_instants:
1548
+ valid_instants[text] = _codex_quota_instant_is_valid(
1549
+ text)
1550
+ if (
1551
+ not valid_instants[capture_text]
1552
+ or not valid_instants[reset_text]
1553
+ or not 0 <= used_percent <= 100
1554
+ or line_offset < 0
1555
+ or not str(row[2]).startswith("/")
1556
+ ):
1557
+ continue
1558
+ key = ("codex", str(row[1]), logical_limit_key, str(row[4]),
1559
+ snapped_minutes, anchor)
1560
+ bucket = buckets.get(key)
1561
+ if bucket is None:
1562
+ bucket = buckets[key] = {
1563
+ "root": str(row[1]),
1564
+ "limit_key": logical_limit_key,
1565
+ "slot": str(row[4]),
1566
+ "minutes": snapped_minutes,
1567
+ "witnesses": set(),
1568
+ "accounts": set(),
1569
+ "model_scoped": False,
1570
+ }
1571
+ witness = witness_texts.get(reset_text)
1572
+ if witness is None:
1573
+ witness = witness_texts[reset_text] = (
1574
+ _codex_attribution_witness(reset_text))
1575
+ bucket["witnesses"].add(witness)
1576
+ account = row[13]
1577
+ if account not in (None, "", _lib_accounts.UNATTRIBUTED):
1578
+ bucket["accounts"].add(str(account))
1579
+ # `limit_name` is compare=False on the identity, so the label can
1580
+ # differ across one group's observations; ANY Spark evidence
1581
+ # demotes the whole group out of account weekly quota (#373),
1582
+ # matching the spend fold. That direction only ever withholds an
1583
+ # attribution.
1584
+ scope_key = (logical_limit_key, row[9])
1585
+ if scope_key not in model_scoped:
1586
+ model_scoped[scope_key] = is_model_scoped_codex_quota(
1587
+ logical_limit_key, row[9])
1588
+ if model_scoped[scope_key]:
1589
+ bucket["model_scoped"] = True
1590
+ return tuple(
1591
+ _wa.WindowGroup(
1592
+ group_key=key,
1593
+ source_root_key=bucket["root"],
1594
+ logical_limit_key=bucket["limit_key"],
1595
+ observed_slot=bucket["slot"],
1596
+ window_minutes=bucket["minutes"],
1597
+ raw_resets_at_utc=frozenset(bucket["witnesses"]),
1598
+ identified_accounts=frozenset(bucket["accounts"]),
1599
+ model_scoped=bucket["model_scoped"],
1600
+ )
1601
+ for key, bucket in sorted(buckets.items(), key=lambda item: str(item[0]))
1602
+ )
1603
+
1604
+
1605
+ def resolve_codex_window_attributions(
1606
+ conn: sqlite3.Connection,
1607
+ *,
1608
+ source_root_keys: "Iterable[str] | None" = None,
1609
+ include_retracted: bool = False,
1610
+ ) -> "tuple[tuple[_wa.AssertionResolution, ...], Mapping[tuple, str]]":
1611
+ """``resolve_codex_window_attributions_with_evidence`` without the groups."""
1612
+ resolutions, ownership, _groups = (
1613
+ resolve_codex_window_attributions_with_evidence(
1614
+ conn, source_root_keys=source_root_keys,
1615
+ include_retracted=include_retracted))
1616
+ return resolutions, ownership
1617
+
1618
+
1619
+ def resolve_codex_window_attributions_with_evidence(
1620
+ conn: sqlite3.Connection,
1621
+ *,
1622
+ source_root_keys: "Iterable[str] | None" = None,
1623
+ include_retracted: bool = False,
1624
+ ) -> "tuple[tuple[_wa.AssertionResolution, ...], Mapping[tuple, str], tuple[_wa.WindowGroup, ...]]":
1625
+ """Resolve every recorded assertion against COMPLETE current evidence.
1626
+
1627
+ Returns the loaded GROUPS alongside the resolutions and the ownership map,
1628
+ because one caller needs a question the resolutions cannot answer: the §7.1
1629
+ spend reconciliation has to know every account the current world can
1630
+ JUSTIFY for a group, not only the account a resolved assertion supplies. A
1631
+ group's own ``identified_accounts`` is that justification — the fold adopts
1632
+ every unattributed member into it — and a resolution carries it only for
1633
+ ``SUPPRESSED_NATIVE``, so reading it from the groups covers the split and
1634
+ dormant shapes as well. The evidence is loaded once either way; this only
1635
+ stops it being discarded.
1636
+
1637
+ The seam the overlay, ``account attribute``'s preview and the
1638
+ ``accounts.codex_window_attribution`` doctor leg all read: it returns a
1639
+ resolution for EVERY assertion, including the dormant, split and suppressed
1640
+ ones that apply nothing, plus the ownership map only the resolved ones
1641
+ populate.
1642
+
1643
+ ``source_root_keys`` bounds which ASSERTIONS are loaded. It never bounds the
1644
+ evidence they are resolved against — that read derives its own roots from
1645
+ the assertions and is deliberately independent of any presentation bound.
1646
+
1647
+ ``include_retracted`` additionally returns the tombstoned records so the
1648
+ §7.1 spend reconciliation can see the groups an assertion used to own. Their
1649
+ resolutions are reported, but they never enter the ownership map.
1650
+ """
1651
+ if not _codex_attribution_table_present(conn):
1652
+ return (), {}, ()
1653
+ assertions = _cache_module().load_active_window_attributions(
1654
+ conn, source_root_keys=source_root_keys)
1655
+ retracted: "tuple[Mapping[str, object], ...]" = ()
1656
+ if include_retracted:
1657
+ retracted = _cache_module().load_active_window_attributions(
1658
+ conn, source_root_keys=source_root_keys, retracted_only=True)
1659
+ if not assertions and not retracted:
1660
+ return (), {}, ()
1661
+ groups = _load_codex_window_group_evidence(conn, (*assertions, *retracted))
1662
+ resolutions, ownership = _wa.resolve_window_attributions(
1663
+ [
1664
+ _wa.WindowAssertion(
1665
+ op_id=str(record["op_id"]),
1666
+ account_key=str(record["account_key"]),
1667
+ source_root_key=str(record["source_root_key"]),
1668
+ logical_limit_key=str(record["logical_limit_key"]),
1669
+ observed_slot=str(record["observed_slot"]),
1670
+ window_minutes=int(record["window_minutes"]),
1671
+ raw_resets_at_utc=frozenset(
1672
+ _codex_attribution_witness(value)
1673
+ for value in record["raw_resets_at_utc"]
1674
+ ),
1675
+ )
1676
+ for record in assertions
1677
+ ],
1678
+ groups,
1679
+ )
1680
+ if not include_retracted:
1681
+ return resolutions, ownership, groups
1682
+ # Retracted records are resolved SEPARATELY, against the same evidence, so a
1683
+ # tombstone can never claim a group or join a conflict. Their only purpose
1684
+ # here is to name the range whose spend rows may still be stamped.
1685
+ tombstoned, _ignored = _wa.resolve_window_attributions(
1686
+ [
1687
+ _wa.WindowAssertion(
1688
+ op_id=str(record["op_id"]),
1689
+ account_key=str(record["account_key"]),
1690
+ source_root_key=str(record["source_root_key"]),
1691
+ logical_limit_key=str(record["logical_limit_key"]),
1692
+ observed_slot=str(record["observed_slot"]),
1693
+ window_minutes=int(record["window_minutes"]),
1694
+ raw_resets_at_utc=frozenset(
1695
+ _codex_attribution_witness(value)
1696
+ for value in record["raw_resets_at_utc"]
1697
+ ),
1698
+ )
1699
+ for record in retracted
1700
+ ],
1701
+ groups,
1702
+ )
1703
+ return (*resolutions, *tombstoned), ownership, groups
1704
+
1705
+
1706
+ def codex_attribution_projection_scope(
1707
+ conn: sqlite3.Connection,
1708
+ ) -> "dict[str, frozenset] | None":
1709
+ """The dirty units an attribution change makes the projection owe.
1710
+
1711
+ Returns the same ``{"raw_groups", "units"}`` shape ``_resolve_pass_scope``
1712
+ returns for a ledger-derived scope, so the two are unioned rather than
1713
+ special-cased, or ``None`` when this store has no attribution records at all.
1714
+
1715
+ Three of §8.3's four points live here.
1716
+
1717
+ **Snap expansion.** ``_apply_quota_projection_rows`` requires the loaded
1718
+ observations to carry the COMPLETE current membership of every dirty unit,
1719
+ and the loader's targeted filter matches RAW stored coordinates. One minute
1720
+ of weekly jitter lives in both the limit key and the column, so two raw
1721
+ groups can interpret into one window and asking only for the un-snapped
1722
+ spelling would hand the fold a partial population. This inherits the ledger's
1723
+ own helper rather than re-deriving the closure.
1724
+
1725
+ **Prior units, not only current ones.** A retraction, a newly dormant
1726
+ assertion and a component split all change which unit a group's rows belong
1727
+ to, so the sweep set carries every unit a record named AT ASSERTION TIME
1728
+ alongside every unit its current resolution names. Without the first half the
1729
+ obsolete blocks survive as exactly the duplicated window this work removes.
1730
+
1731
+ **Suppressed and dormant records still count.** A record that resolves to
1732
+ nothing is precisely the one whose previously-materialized rows have to be
1733
+ swept, so the scope is built from every record — active, retracted,
1734
+ suppressed, split — and not from the ownership map.
1735
+ """
1736
+ if not _codex_attribution_table_present(conn):
1737
+ return None
1738
+ cache = _cache_module()
1739
+ records = (
1740
+ *cache.load_active_window_attributions(conn),
1741
+ *cache.load_active_window_attributions(conn, retracted_only=True),
1742
+ )
1743
+ if not records:
1744
+ return None
1745
+ raw: "set[tuple]" = set()
1746
+ units: "set[str]" = set()
1747
+ for record in records:
1748
+ anchor = _ledger.normalize_reset(record["canonical_resets_at_utc"])
1749
+ group = (
1750
+ str(record["source_root_key"]),
1751
+ str(record["logical_limit_key"]),
1752
+ str(record["observed_slot"]),
1753
+ int(record["window_minutes"]),
1754
+ anchor,
1755
+ )
1756
+ raw.add(group)
1757
+ units.add(_ledger.physical_group_key_text(
1758
+ _ledger.loading_unit_from_raw(group)))
1759
+ resolutions, _ownership = resolve_codex_window_attributions(
1760
+ conn, include_retracted=True)
1761
+ for resolution in resolutions:
1762
+ group_key = resolution.group_key
1763
+ if group_key is None:
1764
+ continue
1765
+ # A resolution's group key is the INTERPRETED one, so its unit is taken
1766
+ # through `loading_unit_from_identity` — the half that strips a
1767
+ # `modelPool` member. `loading_unit_from_raw` applies the length snap
1768
+ # only, so a SUPPRESSED_MODEL_SCOPED resolution fed through it would
1769
+ # produce a unit string no block ever wrote, and the sweep would look for
1770
+ # a key nothing stamped. The raw-coordinate filter below is a different
1771
+ # question and keeps the raw helper: the loader matches STORED columns,
1772
+ # and the stored row is what carries the un-stripped key.
1773
+ raw.add((
1774
+ str(group_key[1]), str(group_key[2]), str(group_key[3]),
1775
+ int(group_key[4]), _ledger.normalize_reset(_utc_iso(group_key[5])),
1776
+ ))
1777
+ units.add(_ledger.physical_group_key_text(
1778
+ _ledger.loading_unit_from_identity(
1779
+ source_root_key=str(group_key[1]),
1780
+ logical_limit_key=str(group_key[2]),
1781
+ observed_slot=str(group_key[3]),
1782
+ window_minutes=int(group_key[4]),
1783
+ canonical_reset_iso=_utc_iso(group_key[5]),
1784
+ )))
1785
+ return {
1786
+ "raw_groups": _ledger.snap_equivalent_raw_groups(raw),
1787
+ "units": frozenset(units),
1788
+ }
1789
+
1790
+
1791
+ def _apply_codex_window_attribution_overlay(
1792
+ conn: sqlite3.Connection,
1793
+ observations: "list[QuotaObservation]",
1794
+ *,
1795
+ source_root_keys: "set[str] | None",
1796
+ ) -> "list[QuotaObservation]":
1797
+ """Stamp resolved ownership onto this load's currently-unattributed rows.
1798
+
1799
+ The table-presence probe lives in the resolver, so this is one extra
1800
+ `sqlite_master` read and one indexed read of an empty table on a store that
1801
+ has never asserted anything, and nothing else.
1802
+ """
1803
+ if not observations:
1804
+ return observations
1805
+ _resolutions, ownership = resolve_codex_window_attributions(
1806
+ conn, source_root_keys=source_root_keys)
1807
+ if not ownership:
1808
+ return observations
1809
+ return list(_wa.apply_resolution(
1810
+ ownership,
1811
+ observations,
1812
+ _lib_quota._physical_window_key,
1813
+ lambda observation: observation.identity.account_key,
1814
+ lambda observation, account: replace(
1815
+ observation,
1816
+ identity=replace(observation.identity, account_key=account),
1817
+ ),
1818
+ ))
1819
+
1820
+
1113
1821
  def load_codex_quota_observations(
1114
1822
  *,
1115
1823
  source_root_keys: Iterable[str] | None = None,
@@ -1120,6 +1828,7 @@ def load_codex_quota_observations(
1120
1828
  physical_signatures: dict[str, str] | None = None,
1121
1829
  canonical_resets_between: "tuple[dt.datetime, dt.datetime] | None" = None,
1122
1830
  physical_groups: "Iterable[tuple[str, str, str, int, str]] | None" = None,
1831
+ latest_per_identity: bool = False,
1123
1832
  ) -> tuple[QuotaObservation, ...]:
1124
1833
  """Load only valid root-qualified S1 physical quota rows.
1125
1834
 
@@ -1173,6 +1882,39 @@ def load_codex_quota_observations(
1173
1882
  the account over the population) happens below, in Python, exactly as it
1174
1883
  does on the unbounded path — so the caller is responsible for widening a
1175
1884
  dirty group to every raw spelling that snaps onto it before asking for it.
1885
+
1886
+ ``latest_per_identity`` (#566 §5.1 item 5) returns exactly the latest
1887
+ physical observation of each interpreted identity over the SAME all-history
1888
+ population, without materializing one Python object per retained row. It is
1889
+ a work bound, not a scope bound: no time range, no root filter and no row
1890
+ cap is introduced, so a caller that only needs each window's most recent
1891
+ capture — ``doctor`` — reads the same identities, the same latest captures
1892
+ and therefore the same verdict as the full load, on a store where the full
1893
+ load meant interpreting 266,337 rows to answer a question about 608 of them.
1894
+
1895
+ SQL narrows to the rows that can possibly win, and Python still decides. The
1896
+ partition is the RAW spelling of every column the interpretation reads
1897
+ (root, limit key, slot, window minutes, limit id and name, observed model,
1898
+ account key, and the coalesced reset anchor), which is strictly FINER than
1899
+ the interpreted identity — snapping and the model-pool rewrite only ever
1900
+ merge raw partitions, never split one — and the maximum over a set equals
1901
+ the maximum of its parts' maxima, so narrowing to per-partition winners
1902
+ cannot change the answer. Two consequences are load-bearing rather than
1903
+ incidental: the account key is a partition member, so every (physical
1904
+ window, identified account) pair still contributes a row and the
1905
+ window-account continuity fold below sees the same identified-account set it
1906
+ sees on the full population; and the cut keeps EVERY row tied at the
1907
+ partition's maximum whole-second capture rather than one row per partition,
1908
+ because SQL compares seconds while ``physical_order_key`` compares full
1909
+ datetimes and then breaks ties on the reset anchor and physical position.
1910
+
1911
+ The residual difference is a malformed row. Rows whose required text is
1912
+ blank, or whose capture or reset instant SQLite cannot read as a time, are
1913
+ excluded in SQL exactly as the loop below excludes them; a row that survives
1914
+ those predicates but still fails a Python parse can, on this path, hide an
1915
+ older valid capture of the same window that the full load would have
1916
+ reported. That trade is confined to a store already carrying corrupt quota
1917
+ rows, and it is the only behavioural difference between the two paths.
1176
1918
  """
1177
1919
  for name, value in (
1178
1920
  ("captured_at_or_after", captured_at_or_after), ("active_at", active_at),
@@ -1200,6 +1942,20 @@ def load_codex_quota_observations(
1200
1942
  if max_rows is not None:
1201
1943
  if not isinstance(max_rows, int) or isinstance(max_rows, bool) or max_rows <= 0:
1202
1944
  raise ValueError("max_rows must be a positive integer or None")
1945
+ if latest_per_identity and (
1946
+ max_rows is not None
1947
+ or physical_signatures is not None
1948
+ or physical_groups is not None
1949
+ or captured_at_or_after is not None
1950
+ or active_at is not None
1951
+ or canonical_resets_between is not None
1952
+ ):
1953
+ # Every one of these either bounds the population or accumulates over
1954
+ # it, and the reduction below already discards the rows a bound would
1955
+ # act on. Refuse the combination rather than return a set whose meaning
1956
+ # depends on which narrowing ran first.
1957
+ raise ValueError(
1958
+ "latest_per_identity cannot be combined with a population bound")
1203
1959
  group_filter: tuple[tuple[object, ...], ...] | None = None
1204
1960
  if physical_groups is not None:
1205
1961
  # Neither combination has a coherent meaning, and both would fail
@@ -1273,16 +2029,19 @@ def load_codex_quota_observations(
1273
2029
  "quota_window_snapshots.observed_model AS observed_model"
1274
2030
  if has_observed_model else "NULL AS observed_model"
1275
2031
  )
1276
- sql = """
1277
- SELECT source, source_root_key, source_path, line_offset,
2032
+ select_list = """source, source_root_key, source_path, line_offset,
1278
2033
  captured_at_utc, observed_slot, logical_limit_key, limit_id,
1279
2034
  limit_name, window_minutes, used_percent, resets_at_utc,
1280
2035
  plan_type, individual_limit_json, reached_type,
1281
- {model_expr}, {account_expr}, {anchor_expr}
2036
+ {model_expr}, {account_expr}, {anchor_expr}""".format(
2037
+ model_expr=model_expr, account_expr=account_expr,
2038
+ anchor_expr=anchor_expr,
2039
+ )
2040
+ sql = f"""
2041
+ SELECT {select_list}
1282
2042
  FROM quota_window_snapshots
1283
2043
  WHERE source='codex' AND source_root_key IS NOT NULL
1284
- """.format(model_expr=model_expr, account_expr=account_expr,
1285
- anchor_expr=anchor_expr)
2044
+ """
1286
2045
  params: list[object] = []
1287
2046
  if requested is not None:
1288
2047
  if not requested:
@@ -1354,6 +2113,52 @@ def load_codex_quota_observations(
1354
2113
  "COALESCE(canonical_resets_at_utc, resets_at_utc)"
1355
2114
  if has_anchor else "resets_at_utc"
1356
2115
  )
2116
+ if latest_per_identity:
2117
+ # Every column the per-row interpretation reads, in its RAW
2118
+ # spelling. Partitioning on the raw columns is strictly finer than
2119
+ # the interpreted identity, which is what makes the per-partition
2120
+ # maximum a safe candidate set (see the docstring).
2121
+ partition_by = ", ".join((
2122
+ "source_root_key",
2123
+ "logical_limit_key",
2124
+ "observed_slot",
2125
+ "window_minutes",
2126
+ "limit_id",
2127
+ "limit_name",
2128
+ "observed_model" if has_observed_model else "NULL",
2129
+ "account_key" if has_account else "NULL",
2130
+ reset_group_expr,
2131
+ ))
2132
+ # The same validity predicates the interpretation loop applies,
2133
+ # restricted to the ones SQL can state. A row SQLite cannot read as
2134
+ # a time can never win its partition, which matters because the
2135
+ # window maximum ignores NULLs.
2136
+ required_not_blank = " AND ".join(
2137
+ f"trim(coalesce({column}, '')) <> ''"
2138
+ for column in _CODEX_QUOTA_REQUIRED_TEXT
2139
+ )
2140
+ # The root filter is the only optional clause that can still be in
2141
+ # play here, because every other bound is refused above, so the
2142
+ # inner query is rebuilt rather than surgically edited.
2143
+ root_clause = (
2144
+ " AND source_root_key IN ("
2145
+ + ",".join("?" for _ in requested) + ")"
2146
+ if requested is not None else ""
2147
+ )
2148
+ sql = (
2149
+ f"SELECT * FROM (SELECT {select_list},"
2150
+ " MAX(unixepoch(captured_at_utc)) OVER"
2151
+ f" (PARTITION BY {partition_by}) AS _group_latest_capture"
2152
+ " FROM quota_window_snapshots WHERE"
2153
+ " source='codex' AND source_root_key IS NOT NULL"
2154
+ f" AND {required_not_blank}"
2155
+ " AND unixepoch(captured_at_utc) IS NOT NULL"
2156
+ " AND unixepoch(resets_at_utc) IS NOT NULL"
2157
+ f"{root_clause}"
2158
+ ") WHERE unixepoch(captured_at_utc) = _group_latest_capture"
2159
+ " ORDER BY source_root_key, captured_at_utc, resets_at_utc,"
2160
+ " source_path, line_offset"
2161
+ )
1357
2162
  shards: list[tuple[str, tuple[object, ...]]] = []
1358
2163
  if group_filter is None:
1359
2164
  shards.append((sql, tuple(params)))
@@ -1371,11 +2176,9 @@ def load_codex_quota_observations(
1371
2176
  result: list[QuotaObservation] = []
1372
2177
  signature_tuples: dict[str, dict[str, list[tuple[object, ...]]]] = {}
1373
2178
  for row in _iter_shard_rows(conn, shards):
1374
- required_text = (
1375
- "source", "source_root_key", "source_path", "captured_at_utc",
1376
- "observed_slot", "logical_limit_key", "resets_at_utc",
1377
- )
1378
- if any(row[name] is None or not str(row[name]).strip() for name in required_text):
2179
+ if not _codex_quota_required_text_present(
2180
+ row[name] for name in _CODEX_QUOTA_REQUIRED_TEXT
2181
+ ):
1379
2182
  continue
1380
2183
  try:
1381
2184
  # #416 spec §4.3: snap a jittered `window_minutes` (the stray
@@ -1467,6 +2270,19 @@ def load_codex_quota_observations(
1467
2270
  observation.source_path,
1468
2271
  observation.line_offset,
1469
2272
  ))
2273
+ # Operator attribution overlay (#500 spec §6.4), immediately before the
2274
+ # fold. Ordered here and nowhere else: the fold then finds nothing left
2275
+ # to adopt in an attributed group, `build_blocks` carries the account
2276
+ # into `quota_window_blocks`, and the spend-adoption pass sees a
2277
+ # claiming window that identifies exactly one account — all three axes
2278
+ # from ONE insertion point, with no new adoption logic anywhere.
2279
+ #
2280
+ # Ordered AFTER the physical signatures too, which are computed from the
2281
+ # physical tuple alone and are therefore account-independent, so the
2282
+ # certificate a bounded read stamps does not depend on whether an
2283
+ # assertion happened to apply.
2284
+ result = _apply_codex_window_attribution_overlay(
2285
+ conn, result, source_root_keys=requested)
1470
2286
  # Window-account continuity fold (#341 spec §2): adopt unidentified
1471
2287
  # observations into a same-physical-window identified account (exactly
1472
2288
  # one). Physical signatures above are account-independent (computed from
@@ -1474,6 +2290,23 @@ def load_codex_quota_observations(
1474
2290
  # recursion path below re-fetches + re-folds. Idempotent for an
1475
2291
  # already-identified set — a single-account cache is a no-op.
1476
2292
  result = list(adopt_unidentified_observations(result))
2293
+ if latest_per_identity:
2294
+ # Python decides the winner, using the same total order every other
2295
+ # caller uses. SQL only removed rows that could not have won.
2296
+ latest: dict[QuotaWindowIdentity, QuotaObservation] = {}
2297
+ for observation in result:
2298
+ held = latest.get(observation.identity)
2299
+ if held is None or physical_order_key(
2300
+ observation,
2301
+ ) > physical_order_key(held):
2302
+ latest[observation.identity] = observation
2303
+ result = sorted(latest.values(), key=lambda observation: (
2304
+ observation.identity.source_root_key,
2305
+ observation.captured_at,
2306
+ observation.resets_at,
2307
+ observation.source_path,
2308
+ observation.line_offset,
2309
+ ))
1477
2310
  if physical_signatures is not None:
1478
2311
  physical_signatures.clear()
1479
2312
  roots = requested if requested is not None else set(signature_tuples)
@@ -2806,6 +3639,21 @@ def reconcile_codex_quota_projection(
2806
3639
  physical_sequence = codex_physical_mutation_seq(cache)
2807
3640
  certificate = load_codex_quota_projection_certificate(cache)
2808
3641
  ledger_high = _ledger_max_seq(cache)
3642
+ # #500 §8.3. An attribution change fires no `quota_window_snapshots`
3643
+ # trigger and writes no ledger entry, so the change ledger cannot
3644
+ # see it and the certificate reader above has already declined a
3645
+ # certificate computed against a different revision. What is left is
3646
+ # naming the groups the pass now owes, which is only worth reading
3647
+ # when the revision actually moved.
3648
+ attribution_revision = (
3649
+ _cache_module().codex_window_attribution_revision(cache))
3650
+ attribution_stale = _certificate_attribution_revision(
3651
+ _codex_quota_projection_certificate_payload(cache)
3652
+ ) != attribution_revision
3653
+ attribution_scope = (
3654
+ codex_attribution_projection_scope(cache)
3655
+ if attribution_stale else None
3656
+ )
2809
3657
  finally:
2810
3658
  cache.commit()
2811
3659
  # ONE stats read decides the whole shape of the pass: whether the
@@ -2924,6 +3772,22 @@ def reconcile_codex_quota_projection(
2924
3772
  stale_reverse_map=stale_reverse_map,
2925
3773
  verification_due=verification_due,
2926
3774
  )
3775
+ if dirty_units is not None and attribution_scope:
3776
+ # Union, never replace: the ledger's own dirty set is still owed.
3777
+ # A bounded pass that then exceeds the incremental ceiling falls
3778
+ # back to whole history exactly as `_resolve_pass_scope` would,
3779
+ # because N indexed seeks stop beating one scan at the same point
3780
+ # however the units were arrived at.
3781
+ merged_units = (
3782
+ frozenset(dirty_units["units"]) | attribution_scope["units"])
3783
+ if len(merged_units) > _MAX_INCREMENTAL_UNITS:
3784
+ dirty_units = None
3785
+ else:
3786
+ dirty_units = {
3787
+ "raw_groups": frozenset(dirty_units["raw_groups"])
3788
+ | attribution_scope["raw_groups"],
3789
+ "units": merged_units,
3790
+ }
2927
3791
  # ``None`` means the genuine whole-history path. A set means complete
2928
3792
  # histories for only those roots — axis 2 and epoch-1007 axis 4 can both
2929
3793
  # be satisfied without scanning unrelated roots.
@@ -3202,9 +4066,15 @@ def reconcile_codex_quota_projection(
3202
4066
  # cache write this function makes, and folding it in avoids adding a second
3203
4067
  # unflocked mutator.
3204
4068
  if holder["signatures"] is not None:
4069
+ # `attribution_revision` is the value read at the top of the pass, and
4070
+ # passing it is what makes the certificate bind THIS pass's inputs: the
4071
+ # ingest cycle above can materialize a pending attribution op, and a
4072
+ # certificate stamped at the post-ingest revision would certify a
4073
+ # projection built from pre-ingest observations (#500 §8.3).
3205
4074
  _store_codex_quota_projection_certificate(
3206
4075
  sequence=physical_sequence, signatures=holder["signatures"],
3207
4076
  prune_ledger_through=watermark_target,
4077
+ attribution_revision=attribution_revision,
3208
4078
  )
3209
4079
  return holder["result"]
3210
4080
 
@@ -3266,7 +4136,7 @@ def _codex_cache_account_predicate(
3266
4136
  dollars are these" — widening it IS attribution, which D1 forbids, and it
3267
4137
  puts one row in two scopes.
3268
4138
 
3269
- FOUR stamping mechanisms exist and must never be conflated: the
4139
+ FIVE stamping mechanisms exist and must never be conflated: the
3270
4140
  quota-observation fold (``adopt_unidentified_observations``, per physical-
3271
4141
  window group, landing post-fold in ``quota_window_blocks`` /
3272
4142
  ``quota_percent_milestones`` and NEVER written back to
@@ -3276,7 +4146,16 @@ def _codex_cache_account_predicate(
3276
4146
  spec — ``_lib_codex_account_adoption`` +
3277
4147
  ``_cctally_cache.apply_codex_window_spend_adoption``, which stamps that same
3278
4148
  ``codex_session_entries.account_key`` column at ingest from the window's
3279
- single identified account); and the stats ``accounts`` registry.
4149
+ single identified account); OPERATOR ATTRIBUTION (#500 —
4150
+ ``_lib_codex_window_attribution`` + ``_apply_codex_window_attribution_overlay``,
4151
+ which makes a group identified at FOLD time from a journal-recorded
4152
+ assertion and therefore reaches both the percentage and the spend axis
4153
+ through the two mechanisms above rather than beside them); and the stats
4154
+ ``accounts`` registry.
4155
+
4156
+ The rule below is unchanged by that fifth entry, and deliberately so:
4157
+ operator attribution feeds the fold, so every read already scoped by the
4158
+ fold's answer stays scoped the same way and no predicate flavour moves.
3280
4159
 
3281
4160
  So ``codex_session_entries.account_key`` now carries window-derived
3282
4161
  attribution IN ADDITION to per-file decisions, and that is precisely what