ãµãŒããããéããŠããéã«ã1æ¬ã ãæ¬ç©ã®ãªã¯ãšã¹ããéã â åªå ãããŒããšSKIPPEDèšé²ã®èœãšã穎
ååãã²ãŒããæ¢ããã®ã¯1è¡ã§ãã£ãŠãããå
šäœã§ã¯ãªãè©±ãæžããŸãããä»åã¯åãclaude-quota-guard.pyã®äžã§ãããµãŒããããéãããŸãŸåŸ©æ§ã確ãããclaim_priority_probeãšrun_jobã®å®è£
ã§ãããã¯ã©ãŒã¿åŸ©æ§ãæ€ç¥ãããå
šéšåå®è¡ãããquota-catchup.pyåŽã®è©±ãããåæ®µãšããŠããã®catchupãèªã¿ã«ããSKIPPEDããŒã«ãŒãã©ãäœãããŠããããå
ã«èŠãŠãããŸãã
å°ãããšïŒãµãŒãããã¯å šãžã§ããäžåŸã«æ¢ããããæçš¿ç³»ã¯åŸ ãŠãªã
claude-quota-guard.pyã¯ã¯ã©ãŒã¿äžéãæ€ç¥ãããšopen_untilãŸã§EXIT_CIRCUIT_OPENïŒ75ïŒãè¿ããã¬ãŒã察象ã®15æ¬ãã¹ãŠãäžåŸã«æ¢ããŸããã³ãŒãäžã®ã³ã¡ã³ãã«ããªãããã ãã§ã¯è¶³ããªãã£ãããæžããŠãããŸãã
# ðŽ 2026-08-21: circuit ãéããšå
šãžã§ããäžåŸã§æ¢ãŸããããæ¶è²»ã®å€§åãå ãã
# è¿ä¿¡/ãšã³ã²ãŒãžç³»ãã¯ã©ãŒã¿ã䜿ãåã£ãå·»ãæ·»ãã§ãæçš¿ããŸã§åæ¢ããŠããã
# 宿ž¬(launchd.log 环èš): xpilot.autopost 㯠231å®è¡/308ã¹ãããïŒå®è¡ç43%ã§ã
# threadspilot.engage(64%) ããåªå
床ãäœãæ±ãã«ãªã£ãŠãããæçš¿ã¯ãã®æé垯ãéããš
# äºåºŠãšåãŸããªãã®ã§ã--priority ãä»ãããžã§ãã ã㯠circuit ãéããŠããŠã
# ãã®ééã§1åã ã詊è¡ãèš±ãã詊è¡ãéãã°ã¯ã©ãŒã¿ååŸ©ã®æ©ææ€ç¥ã«ããªã
# (åŸæ¥ã¯ open_until ãŸã§ç²ç®çã«åŸ
ã€ã ãã ã£ã)ã
ïŒclaude-quota-guard.py:18-24ïŒ
äžåŸã«æ¢ãããšãæ¶è²»éã®å€§ãããšã³ã²ãŒãžç³»ã«å·»ãæ·»ããé£ã£ãŠæçš¿ç³»(xpilot.autopost)ãå®è¡ç43%ãŸã§èœã¡ãŠããããšãã宿ž¬ã§ãããããopen_untilã¯ãäžéæããããŒã¹ããresetæå»ããã6æécooldownãã®ã©ã¡ããã§æ±ºãŸãïŒrecord_claude_resultïŒã®ã§ãå®éã®ã¯ã©ãŒã¿ãããããæ©ãæ»ã£ãŠããŠãããµãŒãããã¯åŸåã«ãã®æå»ãŸã§éãããŸãŸã§ããæçš¿ã®ããã«ããã®æé垯ãéããšäºåºŠãšåãŸããªãããžã§ãã«ãšã£ãŠãããã¯ç¡èŠã§ããŸããã
èšèšïŒ--priorityãžã§ãã ãã«30å1åã®è©Šè¡æš©ãæž¡ã
察çã¯ããµãŒããããéããŠããŠããåªå
ãžã§ãã«ã ãäžå®ééã§1åãæ¬ç©ã®ãªã¯ãšã¹ããéããããšã§ããåŒã³åºãåŽã¯run_jobã«ã³ãã³ããæž¡ããšãã«--priorityãä»ããŸãã
def run_job(label: str, command: list[str], priority: bool = False) -> int:
if not command:
print("claude quota guard: --job requires a command after --", file=sys.stderr)
return 2
status = circuit_status()
probe_claimed = False
if status["is_open"]:
if not (priority and claim_priority_probe()):
print(
"CLAUDE_QUOTA_JOB_SKIPPED "
f"job={label} reason={status['reason']} remaining={status['remaining_seconds']}s ts={now()}",
file=sys.stderr,
)
return 0
probe_claimed = True
print(
"CLAUDE_QUOTA_JOB_PRIORITY_PROBE "
f"job={label} reason={status['reason']} remaining={status['remaining_seconds']}s ts={now()}",
file=sys.stderr,
)
ïŒclaude-quota-guard.py:471-490ïŒ
priorityãç«ã£ãŠããŠããå®éã«è©Šè¡ã§ãããã©ããã¯claim_priority_probe()ãæ¡ã£ãŠããŸãã
def claim_priority_probe() -> bool:
"""circuit ãéããŠããéãåªå
ãžã§ãã«è©Šè¡æš©ã1ã€æž¡ãã
ééã¯å
šåªå
ãžã§ãã§å
±æãã(=1æ¬ã䜿ã£ããæ¬¡ã®æ ãŸã§ä»ãåŸ
ã€)ãäžéã«æ¬åœã«
éããŠããéã«äœæ¬ãå©ããŠãã¯ã©ãŒã¿ã¯æ»ããªããããå©ãåæ°èªäœãçµãã
"""
if PRIORITY_PROBE_INTERVAL <= 0:
return False
with locked_state() as state:
last = int(state.get("last_priority_probe") or 0)
current = now()
if current - last < PRIORITY_PROBE_INTERVAL:
return False
state["last_priority_probe"] = current
return True
ïŒclaude-quota-guard.py:454-468ãPRIORITY_PROBE_INTERVALã¯claude-quota-guard.py:25ã§æ¢å®1800ç§ïŒ
last_priority_probeã¯locked_state()ïŒfcntl.flockã§æä»ããJSONæ°žç¶ç¶æ
ïŒã«èŒã£ãŠãã1åã®ã¿ã€ã ã¹ã¿ã³ãã§ãããžã§ãåäœã§ã¯ãªããµãŒãããåäœã§ãã®å€ãæã€ã®ããã€ã³ãã§ãã誰ã詊è¡ããããã¯åãããæåŸã«èª°ãã詊è¡ããŠãã30åçµã£ãããã ããèŠãŸãã
è©Šè¡æš©ãåŸãåŽã¯ãsubprocess.runããåããã»ã¹ã®ç°å¢å€æ°ã«CLAUDE_QUOTA_PRIORITY_PROBE=1ãæž¡ããŸãã
guard = str(Path(__file__).resolve())
env = os.environ.copy()
env["CLAUDE_AUTOMATION_GUARD"] = "1"
env["CLAUDE"] = guard
env["CLAUDE_BIN"] = guard
if probe_claimed:
# å
åŽã® run_claude ã«ããããŒããšããŠèµ°ã£ãŠãããããšãäŒãã(ãããç¡ããš circuit ã§å³ 75 ã«ãªã)
env["CLAUDE_QUOTA_PRIORITY_PROBE"] = "1"
ïŒclaude-quota-guard.py:491-498ïŒ
ãã®ãã©ã°ãåãåãåŽãrun_claudeã§ãããžã§ãã³ãã³ãã®å
éšã§claudeæ¬äœãå©ããšããguardèªèº«ãçµç±ããããã«PATHãå·®ãæ¿ããããŠããã®ã§ãåããã»ã¹ã®äžã§ããäžæ®µcircuit_status()ã®ãã§ãã¯ãèµ°ããŸãã
def run_claude(arguments: list[str]) -> int:
status = circuit_status()
if status["is_open"]:
# run_job ãåªå
ãããŒãã claim ããåããã»ã¹ã ã㯠circuit ãçŽ éãããŠå® claude ãå©ãã
# çµæã¯ record_claude_result ã«å
¥ãã®ã§ãäžéæãªã circuit ãå»¶ã³ãæåãªãéããã
if os.environ.get("CLAUDE_QUOTA_PRIORITY_PROBE") != "1":
print(
"CLAUDE_QUOTA_CIRCUIT_OPEN "
f"reason={status['reason']} remaining={status['remaining_seconds']}s",
file=sys.stderr,
)
return EXIT_CIRCUIT_OPEN
print(
"CLAUDE_QUOTA_PRIORITY_PROBE_PASS "
f"reason={status['reason']} remaining={status['remaining_seconds']}s",
file=sys.stderr,
)
ïŒclaude-quota-guard.py:416-432ïŒ
ç°å¢å€æ°ãäŒæããå¿ãããšãrun_jobåŽã§è©Šè¡æš©ãåŸãŠããå
åŽã®run_claudeãããäžåºŠcircuitãèŠãŠå³EXIT_CIRCUIT_OPENãè¿ãã ãã«ãªããŸããäºæ®µæ§ãã®ã²ãŒããäž¡æ¹éãããã®1è¡ãenv["CLAUDE_QUOTA_PRIORITY_PROBE"] = "1"ã§ãã
ãããŠå®éã«å©ããçµæã¯ããã€ãéãrecord_claude_resultã«å
¥ããŸããäžéæããŸã è¿ã£ãŠããã°open_untilãå»¶ã³ãæåããã°circuitãéããŸãã詊è¡ã倱æããŠãæåããŠãããã®1åã®çµæããã®ãŸãŸãµãŒãããã®æ¬¡ã®ç¶æ
ãæ±ºãããšããæå³ã§ãããã¯ã1æ¬ã ãéãæ¬ç©ã®ãªã¯ãšã¹ããã§ãã
èžãã èœãšã穎1ïŒ30å1æ¬ã¯ãå šåªå ãžã§ãã®å ±æã«ãŠã³ã¿ã
claim_priority_probeã®docstringã«ããéããPRIORITY_PROBE_INTERVALã¯ãžã§ãåäœã§ã¯ãªãå
šäœã§å
±æã§ãã--priorityãä»ãããžã§ããåã30åã®æ ã«è€æ°ã¹ã±ãžã¥ãŒã«ãããŠããŠããæåã®1æ¬ãclaim_priority_probe()ãéããç¬éã«last_priority_probeãæŽæ°ãããã®ã§ãåŸç¶ã¯priority and claim_priority_probe()ã®æç¹ã§Falseã«ãªããå®ã¯ã©ã€ã¢ã³ãã1åãå©ããã«SKIPPEDãžèœã¡ãŸãã
ããã¯çã£ãæåã§ããäžéã«æ¬åœã«éããŠããéã¯äœæ¬å©ããŠãã¯ã©ãŒã¿ã¯æ»ããªãã®ã§ã詊è¡åæ°èªäœãçµãèšèšã«ãªã£ãŠããŸãããã ãéçšäžã¯ãåªå ãžã§ããè€æ°ãããããšãã£ãŠããããããç¬ç«ã«30åããã®æ©äŒãæã€ããã§ã¯ãªããããšãå¿ãããšãããªããã®ãžã§ãã ã埩æ§ç¢ºèªã®æ©äŒãåã£ãŠããªããã ãããã§1æ¬ããããŸãã
èžãã èœãšã穎2ïŒãããŒãã空æ¯ããããšãé»ã£ãŠRAN exitâ 0ãšããŠæ®ã
ãããä»åã®äž»é¡ã§ããrun_jobã¯subprocess.runã®åŸããããŒãã空æ¯ããããã©ãããèŠãŠããŒã«ãŒãåºãåããŸãã
try:
result = subprocess.run(command, env=env, check=False)
except OSError as exc:
print(f"claude quota guard job={label}: {exc}", file=sys.stderr)
return 127
if probe_claimed and result.returncode != 0 and circuit_status()["is_open"]:
# åªå
ãããŒããäžéã®ãŸãŸç©ºæ¯ããããRAN exitâ 0 ã®ãŸãŸæ®ããš quota-catchup.py
# ïŒææ°ããŒã«ãŒ=SKIPPED ã ããåå®è¡ïŒããæŒãã埩垰åŸãåœæ¥åãæ¬ çªã«ãªã
# ïŒ2026-09-13ã16 ã® note2-daily / codex-note-funnel 宿ž¬ïŒãSKIPPED ãšããŠèšé²ããã
print(
"CLAUDE_QUOTA_JOB_SKIPPED "
f"job={label} reason=priority-probe-quota exit={result.returncode} ts={now()}",
file=sys.stderr,
)
return result.returncode
print(
f"CLAUDE_QUOTA_JOB_RAN job={label} exit={result.returncode} ts={now()}",
file=sys.stderr,
)
return result.returncode
ïŒclaude-quota-guard.py:499-518ïŒ
ãã®åå²ãå
¥ããåã¯ããããŒããè©Šè¡æš©ãåŸãŠå®éã«åããã»ã¹ãèµ·åããæç¹ã§ã詊è¡ããããšããäºå®ã ããèŠãŠãæ«å°Ÿã®CLAUDE_QUOTA_JOB_RANãçŽ éãã§åºããŠããŸããããããŒãããŸãäžéã«åœãã£ãŠexitâ 0ã§çµãã£ãŠãããã°ã«æ®ãã®ã¯CLAUDE_QUOTA_JOB_RAN job=... exit=1ã§ãã
åé¡ã¯ããã®RANããŒã«ãŒãquota-catchup.pyã«ãšã£ãŠãããæžãã æ±ããã«ãªãããšã§ããquota-catchup.pyãåå®è¡åè£ãçµãlatest_job_markerã¯ããæžãããŠããŸãã
def latest_job_marker(paths: list[Path], label: str) -> Optional[Tuple[str, int]]:
"""Return the newest timestamped skip/run marker for one launchd label."""
marker_pattern = re.compile(
r"CLAUDE_QUOTA_JOB_(SKIPPED|RAN)\s+job="
+ re.escape(label)
+ r"(?=\s|$).*\bts=(\d+)(?=\s|$)"
)
...
def latest_marker_is_today_skip(paths: list[Path], label: str, today: datetime.date) -> bool:
marker = latest_job_marker(paths, label)
if marker is None:
return False
marker_type, timestamp = marker
return marker_type == "SKIPPED" and datetime.fromtimestamp(timestamp).astimezone().date() == today
ïŒquota-catchup.py:160-193ïŒ
èŠãŠã®éãããã®å€å®ã¯ããŒã«ãŒã®çš®é¡ïŒSKIPPEDãRANãïŒããèŠãŠããããRANåŽã®exitã³ãŒãã¯äžåãã§ãã¯ããŠããŸããããããŒãã空æ¯ãããŠexit=1ã§çµãã£ãŠããæåŸã«åºããã°ãCLAUDE_QUOTA_JOB_RANã§ããéãlatest_marker_is_today_skipã¯Falseãè¿ããfind_candidatesã®åå®è¡å¯Ÿè±¡ããéãã«å€ããŸãã
ãã®çµæããµãŒããããæ¬åœã«éããåŸãããã®ãžã§ãã¯ã仿¥ã¯ããRANæžã¿ããšãã誀ã£ãèšé²ã®ãŸãŸã次ã®ã¹ã±ãžã¥ãŒã«æå»ïŒç¿æãªã©ïŒãŸã§æŸçœ®ãããŸããå®éã«note2-dailyãšcodex-note-funnelã2026-09-13ã16ã®éããã®çµè·¯ã§åœæ¥åãæ¬ çªã«ãªã£ããšã³ã¡ã³ãã«å®æž¬ãæ®ã£ãŠããŸãã
çŽãæ¹ã¯ã·ã³ãã«ã§ãããããŒããcircuit openäžã«ç©ºæ¯ãããããšããæ¡ä»¶ïŒprobe_claimed and result.returncode != 0 and circuit_status()["is_open"]ïŒãå
ã«å€å®ãããã®å Žåã ãCLAUDE_QUOTA_JOB_RANã§ã¯ãªãCLAUDE_QUOTA_JOB_SKIPPED reason=priority-probe-quotaãåºããŸãã颿°ã®æ»ãå€èªäœã¯result.returncodeã®ãŸãŸå€ããŠããŸãããlaunchdåŽã®LastExitStatusã«ã¯å®éã®å€±æãæ£ããèšé²ããã€ã€ãquota-catchup.pyãèŠããã°ããŒã«ãŒã ããããŸã å詊è¡ãã¹ããã®ãã«ä»ãæ¿ããããšããåãåãã§ãã
exit codeãšåå®è¡ãã¹ããã©ããã¯å¥ã®è»žã§ããä»åã®ãã°ã¯ããã®2ã€ããRANãšãã1ã€ã®ããŒã«ãŒãã«æŒã蟌ããŠããããã«ãquota-catchup.pyåŽãexitâ 0ã®ã±ãŒã¹ãæ³å®ããŠããªãã£ãããšã§èµ·ããŸããããã°ããŒã«ãŒãèšèšãããšãã¯ããå®éã«äœãèµ·ãããããšãåŸç¶ããããæ¬¡ã«äœããã¹ããããåãæååã«çžä¹ããããªãã»ããå®å šã§ãã
ãŸãšã
- ãµãŒãããã¯äžåŸã«æ¢ããããæçš¿ç³»ã®ããã«æ©äŒãéããšåãè¿ããªããžã§ãã¯
--priorityã§30åã«1åã ãè©Šè¡æš©ãæãŠã - è©Šè¡æš©ã¯
claim_priority_probeãlocked_stateã®last_priority_probeã§ç®¡çãããžã§ãåäœã§ã¯ãªãå šåªå ãžã§ãã§å ±æãããè€æ°ã®åªå ãžã§ããåãæ ã«éãªã£ãŠãæ©äŒã¯1å - è©Šè¡æš©ãåŸãåããã»ã¹ã«ã¯
CLAUDE_QUOTA_PRIORITY_PROBE=1ãæž¡ãå¿ èŠããããæž¡ãå¿ãããšå åŽã®run_claudeãäºæ®µç®ã®circuitãã§ãã¯ã§å³åº§ã«åŒŸã - ãããŒãã空æ¯ãããã
CLAUDE_QUOTA_JOB_RAN exitâ 0ã§ã¯ãªãCLAUDE_QUOTA_JOB_SKIPPED reason=priority-probe-quotaãšããŠèšé²ãããquota-catchup.pyã®åå®è¡å€å®ã¯ããŒã«ãŒã®çš®é¡ããèŠãŠããããexitã³ãŒãã¯èŠãŠããªããã - ãã°ããŒã«ãŒã¯ãå®éã«äœãèµ·ãããããšãåŸç¶ããããäœããã¹ããããåããŠèšèšãã
次åã¯ããã®SKIPPEDããŒã«ãŒãquota-catchup.pyãã©ãæŸã£ãŠåŸ©æ§åŸã«ã©ãã ãåå®è¡ãããæ±ºããŠããããæžããŸãã
LilyïŒ@bokuwalilyïŒâ å人éçºè ãClaude Code ã§èªåååºç€ãçµã¿ãªãããiOSã¢ããªãWebãµãŒãã¹ãéç£ããŠããŸã
- AIã§ãå¯ãŠãŠãåãä»çµã¿ããäœã£ãŠæ120äžã«ãã話㯠noteã®ææèšäº ã«ð°
- OSS: github.com/bokuwalily ð
- ææ°æ å ±ã»ãåãåãã㯠X @bokuwalily ãžð
- AIå°å ¥ã»èªååã®çžè«ãšå®è£ ãã³ãã¬7æ¬ã®é åžã¯ å ¬åŒLINE ããð¬
çããã® â€ïž ãã·ã§ã¢ãå±ã¿ã«ãªããŸãïŒ