claude-multiacc 2.0.20 → 2.0.21
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/CLAUDE_ACCS_TASK.md +10 -5
- package/README.md +45 -18
- package/bin/claude +113 -59
- package/bin/claude-accounts +4 -1
- package/bin/codex +178 -43
- package/bin/codex-accounts +4 -1
- package/docs/ACCOUNT_OPERATIONS.md +7 -4
- package/docs/TRACK_PROMPT.md +76 -0
- package/docs/UNIFIED_SELECTOR.md +40 -7
- package/lib/__pycache__/audit.cpython-312.pyc +0 -0
- package/lib/__pycache__/keychain.cpython-312.pyc +0 -0
- package/lib/__pycache__/selector_policy.cpython-312.pyc +0 -0
- package/lib/__pycache__/selector_primitives.cpython-312.pyc +0 -0
- package/lib/selector_policy.py +42 -7
- package/lib/selector_primitives.py +25 -16
- package/package.json +1 -1
- package/tests/run-tests.sh +331 -35
- package/tests/test_selector.py +104 -2
package/tests/test_selector.py
CHANGED
|
@@ -52,9 +52,10 @@ class SelectorTests(unittest.TestCase):
|
|
|
52
52
|
self.assertEqual(
|
|
53
53
|
response["candidate_snapshot_digest"],
|
|
54
54
|
"e8ef0b4bc7b95e76231ee6da79616d92bd9251c1c991845c8c0524fcbfb6593a")
|
|
55
|
+
# Recomputed 2026-09-03: the proof input grew by session_gate.
|
|
55
56
|
self.assertEqual(
|
|
56
57
|
response["selection_digest"],
|
|
57
|
-
"
|
|
58
|
+
"1239440c286d579f4326b4dd633072f51435709a0459cba4f9d671b8cefeb646")
|
|
58
59
|
|
|
59
60
|
def test_unicode_and_active_reservation_proof(self):
|
|
60
61
|
busy = {"active_expires_at": "2026-08-25T09:00:00.000001Z", "last_selected_at": None}
|
|
@@ -66,9 +67,10 @@ class SelectorTests(unittest.TestCase):
|
|
|
66
67
|
self.assertEqual(
|
|
67
68
|
response["candidate_snapshot_digest"],
|
|
68
69
|
"29e8e7d1a611f38ee0be43622102b33875e7ff75ff9024aa43d16151575071d4")
|
|
70
|
+
# Recomputed 2026-09-03: the proof input grew by session_gate.
|
|
69
71
|
self.assertEqual(
|
|
70
72
|
response["selection_digest"],
|
|
71
|
-
"
|
|
73
|
+
"646f38c209df65af94a4ee25e47579d4794902161f902e94030da23ca49d07ff")
|
|
72
74
|
|
|
73
75
|
def test_both_chooses_each_provider_and_survives_provider_loss(self):
|
|
74
76
|
codex = select(_request([
|
|
@@ -308,5 +310,105 @@ class HeadroomBandTests(unittest.TestCase):
|
|
|
308
310
|
self.assertEqual(select(_request(pool))["headroom_band"], "30")
|
|
309
311
|
|
|
310
312
|
|
|
313
|
+
class SessionGateTests(unittest.TestCase):
|
|
314
|
+
"""The session (5h) bucket is the FIRST cut; the weekly band ranks the survivors.
|
|
315
|
+
|
|
316
|
+
Operator, 2026-09-03: "among accounts where high session limits it must choose
|
|
317
|
+
randomly from ones where highest weekly limits." A nearly-spent 5h bucket is
|
|
318
|
+
about to reject the launch whatever the weekly headroom says, so it disqualifies
|
|
319
|
+
the account outright — it is no longer a tie-break, and it no longer shrinks the
|
|
320
|
+
band through min(weekly, session).
|
|
321
|
+
"""
|
|
322
|
+
|
|
323
|
+
def _pool(self, *specs) -> list[dict]:
|
|
324
|
+
# spec: (account_id, weekly_pct, session_pct) — distinct runner ids keep the
|
|
325
|
+
# identities unique without touching the account names the assertions read.
|
|
326
|
+
return [_candidate(runner_id=3 + index, account_id=name,
|
|
327
|
+
weekly_pct=weekly, session_pct=session)
|
|
328
|
+
for index, (name, weekly, session) in enumerate(specs)]
|
|
329
|
+
|
|
330
|
+
def _winners(self, pool: list[dict], **patch) -> set[str]:
|
|
331
|
+
return {select(_request(pool, reservation_key=f"launch-{index}", **patch))["account_id"]
|
|
332
|
+
for index in range(40)}
|
|
333
|
+
|
|
334
|
+
def test_spent_session_loses_to_a_worse_weekly_account(self):
|
|
335
|
+
# 10w/85s vs 70w/20s -> ALWAYS the 70w account. This reverses the pre-gate
|
|
336
|
+
# behaviour, where the session-heavy account stayed in the band on its
|
|
337
|
+
# weekly headroom alone.
|
|
338
|
+
pool = self._pool(("session-spent", 10, 85), ("session-free", 70, 20))
|
|
339
|
+
response = select(_request(pool))
|
|
340
|
+
self.assertEqual(response["account_id"], "session-free")
|
|
341
|
+
self.assertEqual((response["session_ok_count"], response["band_count"]), (1, 1))
|
|
342
|
+
self.assertEqual(self._winners(pool), {"session-free"})
|
|
343
|
+
|
|
344
|
+
def test_weekly_decides_when_both_clear_the_gate(self):
|
|
345
|
+
# 10w/45s vs 70w/20s -> always the 10w account: session only acts through the
|
|
346
|
+
# gate, never as a tie-break inside the band.
|
|
347
|
+
pool = self._pool(("best-weekly", 10, 45), ("session-free", 70, 20))
|
|
348
|
+
response = select(_request(pool))
|
|
349
|
+
self.assertEqual(response["account_id"], "best-weekly")
|
|
350
|
+
self.assertEqual((response["session_ok_count"], response["band_count"]), (2, 1))
|
|
351
|
+
self.assertEqual(self._winners(pool), {"best-weekly"})
|
|
352
|
+
|
|
353
|
+
def test_gate_steps_aside_when_nobody_clears_it(self):
|
|
354
|
+
# 10w/85s vs 70w/60s -> the gate compares, it never empties the pool, so the
|
|
355
|
+
# weekly band ranks everyone exactly as it did before the gate existed.
|
|
356
|
+
pool = self._pool(("best-weekly", 10, 85), ("other", 70, 60))
|
|
357
|
+
response = select(_request(pool))
|
|
358
|
+
self.assertEqual(response["account_id"], "best-weekly")
|
|
359
|
+
self.assertEqual(response["session_ok_count"], 0)
|
|
360
|
+
self.assertEqual((response["band_floor"], response["band_count"]), ("60", 1))
|
|
361
|
+
|
|
362
|
+
def test_gate_of_one_hundred_disables_it(self):
|
|
363
|
+
pool = self._pool(("best-weekly", 10, 85), ("session-free", 70, 20))
|
|
364
|
+
response = select(_request(pool, session_gate=100))
|
|
365
|
+
self.assertEqual(response["account_id"], "best-weekly")
|
|
366
|
+
self.assertEqual((response["session_gate"], response["session_ok_count"]), ("100", 2))
|
|
367
|
+
self.assertEqual(self._winners(pool, session_gate=100), {"best-weekly"})
|
|
368
|
+
|
|
369
|
+
def test_unknown_quota_never_clears_the_gate(self):
|
|
370
|
+
# A row with no telemetry has no session reading, so it cannot be evidence of
|
|
371
|
+
# room: it stays out of the gated set and out of the weekly band, and the
|
|
372
|
+
# floor is computed from the known row alone.
|
|
373
|
+
pool = [_candidate(account_id="blind", weekly_pct=None, session_pct=None),
|
|
374
|
+
_candidate(runner_id=4, account_id="heavy", weekly_pct=0, session_pct=90)]
|
|
375
|
+
response = select(_request(pool))
|
|
376
|
+
self.assertEqual(response["account_id"], "heavy")
|
|
377
|
+
self.assertEqual(response["session_ok_count"], 0)
|
|
378
|
+
self.assertEqual((response["band_floor"], response["band_count"]), ("70", 1))
|
|
379
|
+
|
|
380
|
+
def test_gate_is_validated_exactly_like_the_band(self):
|
|
381
|
+
pool = self._pool(("a", 0, 0), ("b", 40, 0))
|
|
382
|
+
narrow = select(_request(pool, session_gate="0"))
|
|
383
|
+
self.assertTrue(narrow["ok"])
|
|
384
|
+
self.assertEqual(narrow["session_gate"], "0")
|
|
385
|
+
for bad in ("abc", True, [], "1e5", None):
|
|
386
|
+
refusal = select(_request(pool, session_gate=bad))
|
|
387
|
+
self.assertFalse(refusal["ok"], bad)
|
|
388
|
+
self.assertEqual(refusal["error_detail"], {"field": "session_gate"}, bad)
|
|
389
|
+
|
|
390
|
+
def test_gate_participates_in_the_selection_proof(self):
|
|
391
|
+
# Same pool, same winner, different gate -> a different proof: a policy input
|
|
392
|
+
# that can change the winner has to be inside the digest.
|
|
393
|
+
pool = self._pool(("a", 0, 40), ("b", 20, 40))
|
|
394
|
+
tight = select(_request(pool, session_gate="10"))
|
|
395
|
+
loose = select(_request(pool, session_gate="90"))
|
|
396
|
+
self.assertNotEqual(tight["selection_digest"], loose["selection_digest"])
|
|
397
|
+
# An omitted gate is the documented default, and says so in the response.
|
|
398
|
+
self.assertEqual(select(_request(pool))["session_gate"], "50")
|
|
399
|
+
|
|
400
|
+
def test_band_measures_weekly_not_the_minimum_of_weekly_and_session(self):
|
|
401
|
+
# 0w/45s vs 40w/0s with band 30: on min(weekly, session) the 0w account's
|
|
402
|
+
# effective headroom (55) is below the other's (60) and both used to band
|
|
403
|
+
# together. On weekly remaining the 0w account IS the leader and the 40w
|
|
404
|
+
# account (60) falls outside the 70-point floor.
|
|
405
|
+
pool = self._pool(("empty-weekly", 0, 45), ("empty-session", 40, 0))
|
|
406
|
+
response = select(_request(pool))
|
|
407
|
+
self.assertEqual(response["account_id"], "empty-weekly")
|
|
408
|
+
self.assertEqual((response["band_floor"], response["band_count"]), ("70", 1))
|
|
409
|
+
self.assertEqual(response["session_ok_count"], 2)
|
|
410
|
+
self.assertEqual(self._winners(pool), {"empty-weekly"})
|
|
411
|
+
|
|
412
|
+
|
|
311
413
|
if __name__ == "__main__":
|
|
312
414
|
unittest.main()
|