ð¢ exit 0 ãåãã€ã â èªå·±ç· åã§æ¢ãŸã£ãèªååã¯3æ¥ã¹ããªãŒã¯ã§æ€ç¥ãã
æ10äžã®å¯æ¥ããå§ããŠæãæã¡ã§æ60äžãŸã§äŒžã°ããäŒç€Ÿéœåã§äžå€ã«ããŠãŒãã«ãªããå幎ã§Claude Codeã®èªåŸå®è¡ç°å¢ãäžããçµã¿çŽããŠä»ã¯æå120äžã§ãããã®é£èŒã¯ããã®éçšã§èžãã ç©ŽãšæŸã£ãèšèšãæžãèšããã®ã§ãã
ãªããã®ä»çµã¿ãå¹ãã®ã
2026幎8æã®è©±ã§ããIGã®ãšã³ã²ãŒãžãžã§ãïŒig_engage.pyïŒãæ¯æ¥ exit 124 ã§çµãã£ãŠããŸããã
exit 124 㯠SIGKILL ã§ããlaunchd ããžã§ãã匷å¶çµäºãããšãã®ã³ãŒãã§ããbrowser-slot.sh å
ã®Perlã¹ãŒããŒãã€ã¶ãŒããèšå®ã¿ã€ã ã¢ãŠããéããç¬éã« alarm $timeout; ... exit 124 if $timed_out; ãå©ãæ§é ã«ãªã£ãŠããŠããã¬ãŒã ã¯ãŒã¯å
šäœã®ãã¿ã€ã ã¢ãŠãããã exit 124 ã§çµããããšããèšèšã«åŸã£ãŠããŸãã
ãã°ãæããšæ¯æ¥åãã§ãããTIMEOUT: killed after 2400sã
ã³ãŒãã¯1è¡ãå£ããŠããŸããã§ãããlikes ã®äžéã¯62ãfollows ã¯24ãunfollows ã¯15ãåèšæå€§101ã¢ã¯ã·ã§ã³ãã¢ã¯ã·ã§ã³éã®åŸ æ©ã¯ã©ã³ãã ã§æå°20ç§ã»æå€§60ç§ãå¹³å40ç§ãèµ·åæã«ã©ã³ãã ãžãã¿ãŒæå€§900ç§ãã©ã®æ°åãåç¬ã§èŠãã°ãŸãšãã§ãã
ãã ããæãç®ãäžåºŠãããŠããŸããã§ããã
101ã¢ã¯ã·ã§ã³ à 平å40ç§ = 4,040ç§
+ èµ·åãžãã¿ãŒæå€§ 900ç§
ââââââââââââââââââââââââ
æå€§æèŠæé 4,940ç§
å®è¡æ ïŒBROWSER_SLOT_TIMEOUT_SECïŒ 2,400ç§
4,940 ÷ 2,400 â 1.7åãèšå®å€ã¯ã©ããæ£ãããçµã¿åããã ããç Žç¶»ããŠããŸãããã³ãŒãã¬ãã¥ãŒã§ã¯çµ¶å¯Ÿã«èŠã€ãããªãé¡ã®åé¡ã§ããã©ã®è¡ãèªãã§ããæ£ããããšå€æãããŸãã
SIGKILLã®å®å®³ã¯ããäžã€ãããŸãããPlaywright ã® finally: ctx.close() ãéããªããããChromium ããã»ã¹ãå€å
åããŠç©ã¿äžããç¶ããŸãã~/.cache/lily-browser-slots/slot.log ã«ã¯æ¯æ result=timeout:2400s ã䞊ãã§ããŸããããæ¬åœã®åœ±é¿ã¯ããã§ã¯ãªãããã·ã³å
šäœã®ããŒããé倩äºã«äžãã£ãŠããæ¹ã§ããã
ä¿®æ£ã®æ¹åã¯ãcapsãäžãããã§ã¯ãããŸããã§ããã caps ã¯ãã®ãŸãŸãšã³ã²ãŒãžã¡ã³ãæœçã®äžéã§ããäžããã°æé·æœçãçž®ã¿ãŸããå€ããã¹ãã¯å®è¡æéã®äœ¿ãæ¹ã§ããããSIGKILLãããåã«èªåããæ¢ãŸã£ãŠ exit 0 ã§è¿ãããäžéã«å°éããªããŸãŸçµãããããã«ãã¹ã¯ãªããèªèº«ãç· åãèšç®ããŠããã®åã«èµ°è¡ãæã¡åãèšèšã«å€ããŸããã
ããã§æ°ããåé¡ãçãŸããŸãã
exit 0 ã¯åãã€ããŸãã
ig_engage.py ã¯æ¯æ¥ç·ã§çµããããã«ãªããŸãããlaunchd ã¯ãžã§ããæåãããšèšé²ããŸããããã·ã¥ããŒãã®ã¹ããŒã¿ã¹ã¯åé¡ãªããã§ãå®éã«ã¯ã101ã¢ã¯ã·ã§ã³äž60ããçµãã£ãŠããªãæ¥ããããŸããäºç®ãåããããæã¡åã£ãã®ã«ããã°äžã¯ãæ£åžžçµäºãã§ãã
ããããµã€ã¬ã³ããµã¯ã»ã¹ã§ããèªååãæ£ããåããŠããããã«èŠããããææã¯ååã§éãã«æ¢ãŸã£ãŠããç¶æ ã宿å®è¡ã®æãã¯ããã«ãããŸããæäœæ¥ãªããããã仿¥å°ãªããªããšæ°ã¥ããŸããèªååã¯æ°ã¥ãããŠãããŸãããæ¯æ¥ exit 0 ãè¿ã£ãŠããããã誰ãçããŸããããã©ããŒæ°ã䌞ã³ãªããŠããã¢ã«ãŽãªãºã ããªããšæããŸããå®éã¯ãæ¯æ¥40ã¢ã¯ã·ã§ã³ã§æ¢ãŸã£ãŠããã ãã§ãã
æã¡åããæ£åžžçµäºã«ããç¬éã«ããéãã«æ¢ãŸãä»çµã¿ãéãã«ç£èŠãããä»çµã¿ãå¿ èŠã«ãªããŸãã
ããã¯äœæ¥ã®è©±ã§ã¯ãããŸãããç°å¢ã®åé¡ã§ãã
èªååã®æ¬è³ªçãªäŸ¡å€ã¯ãå¯ãŠããéãåããããšã§ããã§ããå¯ãŠããéãåããŠãããµããã«ãªã£ãç¬éããã®äŸ¡å€ã¯æ¶ããŸãããããæ°ã¥ããªããŸãŸæ¶ããŸãã
èªè ã®çãããèšå®ããèªååã仿¥ãæ£åžžçµäºããŠãããšããŠââããã¯ãæ³å®ã©ããã®ææãåºããæ£åžžçµäºãã§ããããããããšããéäžã§æã¡åã£ãæ£åžžçµäºãã§ãããããexit code ã ãã§ã¯åºå¥ãã€ããŸããã
ãã®åºå¥ãã€ããä»çµã¿ãšããŠèšèšããã®ããã3æ¥é£ç¶æã¡åãã§1æ¥1åã ãã¢ã©ãŒãããšããéŸå€ã§ãã
1æ¥ã§ã¯é³ŽãããŸããã
éãæ¥ã¯1åã®æã¡åãã§çµããããšããããŸãã忥ã«ãã©ãã¯ãŒãæ¥å¢ããŠãšã³ã²ãŒãžãå¢ãããAPIãéãã£ããå¥ã®ãžã§ããšæ ãç«¶åããââåçºã®çç±ã¯ãããã§ããããŸãã1æ¥ã§é³Žãããšãæ¬åœã«åé¡ã«ãªãåã«çŒå°å¹Žã«ãªããŸããéç¥ãæ¯æ¥æ¥ããšã人éã¯èªãŸãªããªããŸãã
æ¯æ¥ã¯é³ŽãããŸããã
3æ¥é£ç¶ã§æã¡åããèµ·ããŠããã°ãããã¯æ§é åé¡ã§ããcapsãšå®è¡æéã®ãã©ã³ã¹ãæåžžçã«ãããŠããŸããã§ããã®äºå®ãæ¯æ¥ã¢ã©ãŒãã«ããŠãæå³ããããŸãããããŸãæ¥ããã«ãªãã ãã§ã察åŠããæ°ã«ãªããªãã
3æ¥é£ç¶ãšããéŸå€ã¯ãåçºãã€ãºã®å€ãã«ããã1æ¥1åãšããé »åºŠã¯ã察åŠã§ããéãã«åãŸã£ãŠããŸãããã®2ã€ã®å€±æã®éã«ãã¡ããã©è¯ãç¹ããããŸãã
å šäœã®æµã
æ§é ãã²ãšã€ã®å³ã§ç€ºããŸãã
launchd ã ig_engage.py ãèµ·å
â
âŒ
compute_budget()
âââââââââââââââââââââââââââââââââââââââââââââââ
â 1. IG_ENGAGE_BUDGET_SECïŒç°å¢å€æ°ïŒãèªã â
â 2. ãªããã° BROWSER_SLOT_TIMEOUT_SEC ãèªã â â 2,400ç§
â 3. ã©ã¡ãããªããã° 0ïŒå
šå€å®ãç¡å¹åïŒ â
â deadline = START_TS + budget - 120ç§ â â BUDGET_MARGIN_S
âââââââââââââââââââââââââââââââââââââââââââââââ
â
âŒ
èµ·åãžãã¿ãŒïŒã©ã³ãã åŸ
æ©ïŒ
âââââââââââââââââââââââââââââââââââââââââ
â wait = min(900, (deadline - now) à 0.2) â â æ®äºç®ã®20%ã§ã¯ã©ã³ã
âââââââââââââââââââââââââââââââââââââââââ
â
âŒ
ã¢ã¯ã·ã§ã³ã«ãŒãïŒlikes â follows â unfollowsïŒ
ââââââââââââââââââââââââââââââââââââââââââââââââââââââââ
â ã«ãŒãå
é : if blocked["hit"] or over_budget(): break â â æ¢åå€å®ã«çžä¹ãïŒ4ç®æïŒ
â â
â over_budget() ã®å
èš³: â
â æ®äºç® < action_min_s(20ç§) â True â
â deadline ãéããŠãã â True â
â â
â action_sleep() ã§åŸ
æ©ãããšã: â
â sleepæéãæ®äºç®å
ã«åãã â
ââââââââââââââââââââââââââââââââââââââââââââââââââââââââ
â
âŒ
return 0 â exit 124 ã®ä»£ããã« "æ£åžžçµäº"
ïŒãããã¯æ€ç¥ã»ãã°ã€ã³åãã® exit 1 çµè·¯ã¯äžåè§ŠããªãïŒ
â
âŒ
state/engage_budget.json ãæŽæ°
âââââââââââââââââââââââââââââââââââââââââââ
â { â
â "streak": N, // é£ç¶æã¡åãåæ° â
â "last_date": "YYYY-MM-DD", â
â "last_alert_date": "YYYY-MM-DD" â
â } â
âââââââââââââââââââââââââââââââââââââââââââ
â
âââ 仿¥ãæã¡åãã ã£ãå Žå
â streak += 1
â streak ⥠3 ã〠last_alert_date â today
â â
â alerts ãžéç¥ïŒ1æ¥1åã ãïŒ
â "capsãå®è¡æéã«å¯ŸããŠé倧ïŒäºç®å°éã§ã®æã¡åãã
â Næ¥é£ç¶ïŒlikes XX/62, follows XX/24, unfollows XX/15ïŒ"
â
âââ æã¡åããªãã ã£ãå Žå
streak = 0 ã«ãªã»ãã
ã³ãŒãã®å€æŽéã¯æ³åããå°ãªãã§ããæ°ããå¶åŸ¡æ§é ãã¯ã©ã¹ã¯äœã£ãŠããŸãããæ¢åã® if blocked["hit"]: ãšããå€å®ã4ç®æãããããããã« or over_budget() ã远å ããã ãã§ããæã¡åãæã®åŠç㯠return 0 ã®1è¡ãæ°æ©èœã®æ¢å®å€ã¯ãäœãããªãåŽãã«çœ®ããšããã«ãŒã«ã©ãããcompute_budget() ãäºç®ãåããªãïŒå€ã 0 ãŸãã¯æªèšå®ïŒãšã㯠deadline = None ã«ããŠå
šå€å®ãç¡å¹åããæ¢åã®æåã1ããªãå€ããŸããã ç°å¢å€æ°ãæ¶ããç¬éã«ãžã§ããæ¢ãŸãäœãã«ããªãããšããã®ãååã§ãã
èµ·åãžãã¿ãŒã®ã¯ã©ã³ãã min(900, (deadline - now) à 0.2) ã«ãªã£ãŠããçç±ãç®è¡ã§ããå
ã® start_jitter_max_s=900 ããã®ãŸãŸäœ¿ããšãæ®äºç®2,400ç§ã®ãã¡æå€§900ç§ããžãã¿ãŒã§æ¶ããŸããæ¯çã«ããŠ37.5%ãã¢ã¯ã·ã§ã³åã®åŸ
æ©ã ãã§äºç®ã®4å²è¿ããé£ã¶èšç®ã§ããæ®äºç®ã®20%ãšããäžéãèšããããšã§ãjitterãé·ããªã£ãŠãã¢ã¯ã·ã§ã³æ¬äœã®æéã確ä¿ãããŸãã2,400ç§ã®20%ã¯480ç§ãªã®ã§ãå
ã®900ç§ããçãããã€çãäºç®ã®ãšãã»ã©jitterãçããªããŸãã
browser-slot.sh ã BROWSER_SLOT_TIMEOUT_SEC ãã¿ã€ã ã¢ãŠãèšå®ãšããŠæž¡ããPerlã¹ãŒããŒãã€ã¶ãŒãæéè¶
éæã« exit 124 ãè¿ãæ§é ã¯å€ãããŸãããig_engage.py ãèªåããç· ååã«çµããã°ãã¹ãŒããŒãã€ã¶ãŒã¯ exit $? >> 8ïŒ=exit 0ïŒãè¿ããŸããexit 124 ããã°ã«åºãªããªã£ãæç¹ã§ãå€åŽã®ãã¬ãŒã ã¯ãŒã¯èгç¹ã§ã¯ãæ£åžžåäœããŠãããã«ãªããŸãã
ã ããããå åŽã®ã¹ããªãŒã¯ç£èŠãèŠããŸããå€ããèŠãŠç·ãªã®ã«ãäžã§ã¯æ¯æ¥40ã¢ã¯ã·ã§ã³ã§æ¢ãŸã£ãŠããââãã®å·®ãæ€ç¥ã§ããã®ã¯ããžã§ãèªèº«ãèªåã®ããã©ãŒãã³ã¹ãèšé²ããŠãããšãã ãã§ãã
å®è£ ã®è©³çް
browser-slot.sh ãå€åŽã®ç· åãäœã
ãŸãå
šäœã®å€æ ãæŽçããŸããig_engage.py ã¯çŽæ¥ launchd ããèµ·åãããã®ã§ã¯ãªããbrowser-slot.sh ãçµç±ããŠèµ·åãããŸãããã® shell ã¹ã¯ãªããããäœåãŸã§äžŠåã§ Chromium ãåãããããå¶åŸ¡ããã¹ããã管çå±€ã§ãã
ã¹ã¯ãªããã®äžæ žã¯ Perl ã§æžãããã¹ãŒããŒãã€ã¶ãŒã§ããbash ãã¢ããã¥ã¡ã³ãã§åã蟌ãŸããŠããŠãå®è¡æã« perl -e ã§å±éãããŸãã
my $timed_out = 0;
local $SIG{ALRM} = sub { $timed_out = 1; stop_tree(); };
alarm $timeout;
while (waitpid($child, 0) == -1) {
next if $!{EINTR};
exit 1;
}
alarm 0;
exit 124 if $timed_out;
exit $? >> 8;
alarm $timeout ã§ã¿ã€ããŒãã»ããããåããã»ã¹ãçµäºãããŸã§ waitpid ã§åŸ
ã¡ãŸããã¿ã€ã ã¢ãŠããæ¥ããš SIGALRM ã§ $timed_out = 1 ãã»ãããããstop_tree() ãèµ°ããŸããstop_tree() 㯠/bin/ps -axo pid=,ppid= ã§ããã»ã¹ããªãŒãæ§ç¯ããåå«å
šå¡ã« TERM â KILL ã®é ã§éä¿¡ããŸãã
sub stop_tree {
return if $stopping++;
my @pids = descendants($child);
kill "TERM", reverse(@pids), $child;
select undef, undef, undef, 1;
kill "KILL", grep { kill 0, $_ } reverse(@pids), $child;
}
ãããéèŠã§ããkill "KILL" ã¯ããã»ã¹ã« SIGKILL ãéããŸããPlaywright ã async with browser.new_context() as ctx: ã® finally ãããã¯ã§ ctx.close() ãåŒãã§ããŠããSIGKILL ã«ã¯æããŸãããfinally ã¯å®è¡ããããChromium ããã»ã¹ãå€å
ãšããŠæ®ããŸãã
browser-slot.sh ã®æ«å°Ÿã§ã¯ exit code ã«ãã£ãŠ RESULT ãåããŸãã
if [ "$status" -eq 124 ]; then
echo "TIMEOUT: killed after ${TIMEOUT_SEC}s"
RESULT="timeout:${TIMEOUT_SEC}s"
else
RESULT="exit:$status"
fi
ã€ãŸã ig_engage.py ãèªåãã exit 0 ã§çµãã£ãå Žåã$? >> 8 㯠0 ã«ãªããbash åŽã®ã¹ããŒã¿ã¹ã 0 ã§ããRESULT 㯠exit:0 ãšããŠãã°ã«èšé²ãããŸããã¹ãŒããŒãã€ã¶ãŒã® exit 124 ã«å°éããªãéããã¿ã€ã ã¢ãŠããšã¯èšé²ãããŸãããããããå
åŽããå
ã«æ¢ãŸããèšèšã®å¹æã§ãã
deadline ã®ç®åºãš compute_budget()
Python åŽã®å®è£
㯠compute_budget() ãšãã颿°ããå§ãŸããŸããç°å¢å€æ°ã®èªã¿åãé åºã¯3段éã«ãªã£ãŠããŸãã
def compute_budget() -> float | None:
for key in ("IG_ENGAGE_BUDGET_SEC", "BROWSER_SLOT_TIMEOUT_SEC"):
val = os.environ.get(key, "")
if val.strip().isdigit() and int(val) > 0:
return float(val)
return None
IG_ENGAGE_BUDGET_SEC ãå
ã«èªãçç±ã¯ããžã§ãåºæã®äºç®ã BROWSER_SLOT_TIMEOUT_SEC ãšåãé¢ããããã«ããããã§ããã¹ãããåŽã®ã¿ã€ã ã¢ãŠããå€ããã«ããšã³ã²ãŒãžãžã§ãã ãäºç®ãçµãããå Žé¢ããããŸããäž¡æ¹ãªããã° None ãè¿ããŸãã
åŒã³åºãåŽã§ã¯ deadline ãããæ±ºããŸãã
BUDGET_MARGIN_S = 120 # ã¹ãŒããŒãã€ã¶ãŒãSIGKILLãéãåã«ç¢ºå®ã«çµããããã®äœè£
budget = compute_budget()
if budget is not None:
deadline = START_TS + budget - BUDGET_MARGIN_S
else:
deadline = None # å
šå€å®ãç¡å¹å
BUDGET_MARGIN_S = 120 ãšãã120ç§ã®äœè£ã¯ãã¹ãŒããŒãã€ã¶ãŒã® alarm $timeout ã鳎ãããå
ã« Python åŽã return 0 ãŸã§å°éããããã®ãããã¡ã§ããæåŸã®ã¢ã¯ã·ã§ã³ãçµãã£ãŠãã engage_budget.json ãæžããŠã¢ã©ãŒããéããŸã§ã®æéãèŠèŸŒãã§ããŸãã
deadline ã None ã®ãšããç¶ã over_budget() ã¯åžžã« False ãè¿ããŸããã€ãŸãç°å¢å€æ°ãæ¶ããç¬éãã¹ã¯ãªããã¯ç¡å¶éã«åãã®ã§ã¯ãªããã¹ãŒããŒãã€ã¶ãŒä»»ãã®ä»¥åã®ç¶æ
ã«æ»ããŸããæ°æ©èœã®æ¢å®å€ã¯ãäœãããªãåŽãã«çœ®ããšããååã§ãã
over_budget() ã¯æ¢åã®å€å®ç¹ã«çžä¹ããã
ig_engage.py ã®ã¢ã¯ã·ã§ã³ã«ãŒãã«ã¯4ç®æã®äžæå€å®ããããŸãããããšããšã¯ãããã¯æ€ç¥ã ããç®çã§ããã
# 倿ŽåïŒãããã¯æ€ç¥ã®ã¿ïŒ
if blocked["hit"]:
break
# 倿ŽåŸïŒäºç®ãã§ãã¯ãçžä¹ãïŒ
if blocked["hit"] or over_budget():
break
ãã®4ç®æã« or over_budget() ã远å ããã ãã§ããæ°ãã if ãããã¯ãã¯ã©ã¹ãäœã£ãŠããŸãããover_budget() ã®äžèº«ã¯ããã§ãã
def over_budget() -> bool:
if deadline is None:
return False
now = time.time()
if now >= deadline:
return True
remaining = deadline - now
return remaining < ACTION_MIN_S # 20ç§
ãæ®ã20ç§æªæºãªãæã¡åãããšããå€å®ãå
¥ã£ãŠããŸãã20ç§ã¯ action_min_s ã®å€ã§ããæ¬¡ã®ã¢ã¯ã·ã§ã³ãå§ããŠãéäžã§ã¹ãŒããŒãã€ã¶ãŒã«æã¡åãããå¯èœæ§ãé«ãããšããèšç®ã§ããäžéå端ã«å§ãããããä»ã®æç¹ã§ return 0 ããŠèšé²ãæ®ãæ¹ãè¯ãã
ã¢ã¯ã·ã§ã³éã®åŸ
æ© action_sleep() ãäºç®å
ã«åããŸãã
def action_sleep(min_s: float, max_s: float) -> None:
if deadline is not None:
remaining = deadline - time.time()
max_s = min(max_s, remaining - ACTION_MIN_S)
if max_s <= 0:
return # åŸ
ããã«å³è¿ã
time.sleep(random.uniform(min_s, min(min_s, max_s)))
ãæ®äºç®ããæ¬¡ã®ã¢ã¯ã·ã§ã³1ååïŒ20ç§ïŒãåŒããå€ããåŸ
æ©ã®äžéã§ããæ®ãã20ç§ãäžåã£ãŠããã°ã¹ãªãŒãããå³è¿ããŸããæ¬¡ã® over_budget() ãã§ãã¯ã§æã¡åãããŸãã
ãžãã¿ãŒã¯ã©ã³ãã®ç®è¡
èµ·åãžãã¿ãŒã®ã³ãŒãã¯1è¡ã§ãã
wait = min(START_JITTER_MAX_S, (deadline - time.time()) * 0.2)
START_JITTER_MAX_S ã¯ããšããš 900 ç§ã§ãããå
ã®èšèšã§ã¯ãèµ·åæå»ã忣ãããããã©ã³ãã æå€§900ç§åŸ
ã€ããšããæå³ã§ããããããäºç® 2,400 ç§ã«å¯ŸããŠæå€§ 900 ç§ã®ãžãã¿ãŒã¯ 37.5% ã§ãã4å²è¿ããåŸ
æ©ã ãã§æ¶ããŸãã
æ®äºç®ã®20%ãšããäžéãèšããããšã§ãäºç®ãé·ããã°ãžãã¿ãŒãé·ãïŒåæ£å¹æãç¶æïŒãäºç®ãçããã°ãžãã¿ãŒãçããªããŸãïŒã¢ã¯ã·ã§ã³æéãé£ããªãïŒã2,400ç§ã®20%ã¯480ç§ãªã®ã§ãå ã®900ç§ããã¯çãã
å®éã«èšç®ããŠã¿ãŸãã
deadline = START_TS + 2400 - 120 = START_TS + 2280ç§
èµ·åçŽåŸã®æ®äºç® â 2280ç§
20% = 456ç§
min(900, 456) = 456ç§
ããã§èµ·åãžãã¿ãŒã¯æå€§456ç§ã«åãŸããŸããæ®ãã®1,824ç§ã§ã¢ã¯ã·ã§ã³ãåŠçããŸãã101ã¢ã¯ã·ã§ã³Ãå¹³å40ç§=4,040ç§ã«ã¯å±ããŸãããã2,280ç§ã§ã¯72ã¢ã¯ã·ã§ã³çžåœã§ããå šéã¯åŠçã§ããªããã®ã®ãSIGKILLãªãã§æ£åžžçµäºã§ããŸãã
ã¹ããªãŒã¯ç®¡çã®å®è£
state/engage_budget.json ã®æ§é ã¯ã·ã³ãã«ã§ãã
{
"streak": 2,
"last_date": "2026-08-14",
"last_alert_date": "2026-08-12"
}
ãžã§ãçµäºæã«ãã®ãã¡ã€ã«ãæŽæ°ããŸããæã¡åããèµ·ãããã©ããã¯ãå®è¡ããã¢ã¯ã·ã§ã³æ°ãš caps ã®æ¯èŒã§å€å®ããŸãã
was_truncated = (
likes_done < LIKES_CAP or
follows_done < FOLLOWS_CAP or
unfollows_done < UNFOLLOWS_CAP
) and budget_hit # äžéå°éã§æã¡åã£ãå Žåã®ã¿
budget_hit ãã©ã°ãå¥ã«æã€ã®ã¯ãããããã¯æ€ç¥ã§æ¢ãŸã£ããå Žåãšãäºç®åãã§æ¢ãŸã£ããå Žåãåºå¥ããããã§ãããããã¯æ€ç¥ã«ããäžæã¯ã¹ããªãŒã¯ã«å ç®ããŸããããããŸã§ãcaps à delays ã®æãç®ãæ ã«åãŸã£ãŠããªãããšããæ§é åé¡ãæ°ãããã
ã¢ã©ãŒãæ¡ä»¶ã¯2ã€ã® and ã§ãã
today = datetime.date.today().isoformat()
if streak >= 3 and state.get("last_alert_date") != today:
send_alert(
f"capsãå®è¡æéã«å¯ŸããŠé倧ïŒäºç®å°éã§ã®æã¡åãã{streak}æ¥é£ç¶\n"
f"likes {likes_done}/{LIKES_CAP}, "
f"follows {follows_done}/{FOLLOWS_CAP}, "
f"unfollows {unfollows_done}/{UNFOLLOWS_CAP}"
)
state["last_alert_date"] = today
last_alert_date != today ãšããæ¡ä»¶ãã1æ¥1åã ãããå®çŸããŠããŸããstreak >= 3 ãæºãããæ¥ã«éç¥ãé£ã³ããã®æ¥äžã«äœåºŠãžã§ããèµ°ã£ãŠã last_alert_date ã仿¥ä»ãã«ãªã£ãŠããã®ã§éè€ããŸãããç¿æ¥ã streak ã 3 以äžãç¶æããŠããã°ããŸã1éé£ã³ãŸãã
ç§ãè©°ãŸã£ã話
èšèšãšããŠãæ£ãããå®è£ ããåãããŠã¿ããšå¥ã®åé¡ãçã¿åºããšããçµéšã3åãããŸããã
è©°ãŸãâ ãTypeError ã§å šã¢ã¯ã·ã§ã³ãæ¢ãŸã£ã
deadline=None ã®ãšã over_budget() 㯠False ãè¿ãããšããèšèšã¯æ£ããã£ãã§ããåé¡ã¯ action_sleep() ã®æ¹ã§ããã
# ãã°ã®ãã£ãç
def action_sleep(min_s, max_s):
remaining = deadline - time.time() # deadline ã None â TypeError
max_s = min(max_s, remaining - ACTION_MIN_S)
...
deadline ã None ãã§ãã¯ããã«åç
§ããŠããŸãããçç¶ã¯ããžã§ããèµ·åçŽåŸã«æ»ã¬ãexit code 1ãã§ããBROWSER_SLOT_TIMEOUT_SEC ãèšå®ãããŠããªãéçºç°å¢ã§ã®ã¿çºçããã®ã§ãæ¬çªã§ã¯1é±éæ°ã¥ããŸããã§ããã
# slot.log ã§ç¢ºèªãããã°
2026-08-09T06:01:03+0900 label=ig-engage group=engage result=exit:1
2026-08-10T06:01:14+0900 label=ig-engage group=engage result=exit:1
result=exit:1 ã¯ãããã¯æ€ç¥ãšåºå¥ãã€ããŸããããã°ã®èŠãç®ã¯ãããã¯ãšåãã§ãããããçºèŠãé
ãããåå ã§ããã
çŽãæ¹ã¯åçŽã§ããaction_sleep() ã®å
é ã«ã¬ãŒããå
¥ããŸããã
def action_sleep(min_s, max_s):
if deadline is None:
time.sleep(random.uniform(min_s, max_s))
return
remaining = deadline - time.time()
...
åŠãã ããšã¯ãdeadline=None ãç¡å¹åãšããŠèšèšãããªããdeadline ãåç
§ããå
šç®æã« None ãã§ãã¯ãèŠããã§ããåœããåã§ãããover_budget() ã ãçŽã㊠action_sleep() ãèŠèœãšãã®ã¯ååèµ·ããŸãã
è©°ãŸãâ¡ãèµ·åãžãã¿ãŒã§äºç®ãå šéšäœ¿ãåã£ãŠãã
ã¯ã©ã³ããå ¥ããåã®è©±ã§ããäºç®2,400ç§ã«å¯ŸããŠèµ·åãžãã¿ãŒãæå€§900ç§ã§ããããžãã¿ãŒãé·ãåŒãããæ¥ã¯ãèµ·ååŸã«æ®äºç®ã1,500ç§ãããªããeven that was not the issue.
å®éã®åé¡ã¯ãover_budget() ã®ãã§ãã¯ããåã«ãžãã¿ãŒãèµ°ããšããé åºã§ããããžãã¿ãŒã§900ç§åŸ
ã¡ãªããããã®éã« deadline ãéããŠããæ¥ããããŸããããžãã¿ãŒçµäºæç¹ã§æ®äºç®ããã€ãã¹ã«ãªã£ãŠãããæåã® over_budget() ãã§ãã¯ã§å³æã¡åãã0ã¢ã¯ã·ã§ã³ã§ return 0 ããŸããã
# state/engage_budget.json ã確èª
{"streak": 1, "last_date": "2026-08-05", "last_alert_date": null}
# ãã ã likes_done=0, follows_done=0 ãšããç¶æ³
likes ã 0 ãªã®ã«æã¡åãã®ã¹ããªãŒã¯ãç©ãŸãããã¢ã©ãŒãã¯ãŸã æ¥ãªããã§ã1æ¥åã®åŠçãå®å šã«ã¹ããããããŠããŸããã
ã¯ã©ã³ããå ¥ããåã«ããã¹ãã ã£ãããšã¯ããžãã¿ãŒãäºç®ããåŒããšããæèãæåããæã€ããšã§ãããããžãã¿ãŒã»åŸ æ©ã»ã¢ã¯ã·ã§ã³æéãã®å šéšãè¶³ãåãããŠãå®è¡æ ã«åãŸãããã§ãã¯ãããéšåæé©ã®ç©ã¿éãã§å šäœãå£ããŸãã
è©°ãŸãâ¢ã3æ¥é£ç¶ã§é³Žãã¯ãã®éç¥ãæ¥ãªãã£ã
ã¹ããªãŒã¯ã3ãè¶ ããŠãéç¥ãæ¥ãªãæ¥ããããŸããããã°ãæããš streak ãæ¯æ¥ãªã»ãããããŠããŸããã
// ææ
{"streak": 1, "last_date": "2026-08-11"}
// ç«æ
{"streak": 1, "last_date": "2026-08-12"} // â ç©ã¿äžãã£ãŠããªã
åå 㯠last_date ã®æŽæ°ããžãã¯ã§ãããåæå®è£
ã§ã¯ã仿¥æã¡åããèµ·ãããããã仿¥ã®æ¥ä»ã last_date ãšäžèŽãããã§å€å®ãããŠããŸããã
# ãã°ã®ãã£ãç
today = datetime.date.today().isoformat()
if was_truncated:
if state.get("last_date") == today:
pass # 仿¥ã¯æ¢ã«ã«ãŠã³ãæžã¿
else:
state["streak"] = state.get("streak", 0) + 1
state["last_date"] = today
äžèŠæ£ããããã«èŠããŸããã§ã else ãã©ã³ãã§ last_date ã仿¥ã«æŽæ°ãããšããåæ¥ã® last_date ãæšæ¥ä»¥å€ã®ã±ãŒã¹ãæ³å®ããŠããŸããã§ããããžã§ãã2æ¥éã¹ããããããïŒã¹ãããç«¶åã§ skip:global-limit ã«ãªã£ãïŒåŸã«åéãããšãstreak ã忥ãŸã§æ»ãããªã»ãããããŸãã
æ£ããã¯ã忥ãæã¡åãã ã£ãããã streak ã®ç¶ç¶æ¡ä»¶ã«ããããšã§ãã
today = datetime.date.today()
yesterday = (today - datetime.timedelta(days=1)).isoformat()
today_str = today.isoformat()
if was_truncated:
if state.get("last_date") == yesterday:
state["streak"] = state.get("streak", 0) + 1
elif state.get("last_date") != today_str:
state["streak"] = 1 # é£ç¶ãéåããã1ããåã¹ã¿ãŒã
state["last_date"] = today_str
else:
state["streak"] = 0
state["last_date"] = today_str
ãæšæ¥ãæã¡åãããªãç¶ç¶ããæšæ¥ä»¥å€ã®æ¥ã«æã¡åãèšé²ãããããªã streak ã1ã«ãªã»ããããšããå€å®ã§ããããã§2æ¥ã¹ãããåŸã«åéããŠããé£ç¶ã«ãŠã³ãã誀ã£ãŠç¶ç¶ãããªããªããŸãã
ãã®ä¿®æ£ãå ¥ããŠãã1é±éåŸãåããŠã¢ã©ãŒããé£ãã§ããŸããããcapsãå®è¡æéã«å¯ŸããŠé倧ïŒäºç®å°éã§ã®æã¡åãã3æ¥é£ç¶ïŒlikes 58/62, follows 18/24, unfollows 10/15ïŒããéç¥ãæ¥ãŠåããŠããé£ç¶3æ¥ãšããæå³ã§ã®ãã©ã³ã¹åŽ©ããã確èªã§ããŸããã
å ±éãã倱æã®å
3ã€ã®è©°ãŸãã«å ±éããåããããŸãã
å®è£ ããã©ãããã¯æ£ãããããæ¥ç¶éšåããæããŠããã
deadline=None 㯠over_budget() ã§ã¯åãã action_sleep() ã§ã¯åããªããã¯ã©ã³ãã¯ã¢ã¯ã·ã§ã³æéã«ã¯å¹ãããžãã¿ãŒã«ã¯å¹ããªããlast_date ã®æŽæ°ã¯ã«ãŠã³ãç¶ç¶ã«ã¯äœ¿ãããé£ç¶æ§ã®å®çŸ©ãç·©ããã©ã®ç®æãåç¬ã§èªãã°ãæ£ãããããã«èŠããŸããåé¡ã¯è€æ°ã®éšåãã€ãªããå¢ç®ã«ãããŸãã
èªååã®æãã¯ããã§ããæ¥ç¶éšåã®ãã°ã¯ãå®è¡ãæåããŠããïŒexit 0ïŒã®ã§çºèŠãé ããŸãããã°ãèŠãŠããæ£åžžãã«èŠããŸããæ°åãæç³»åã§äžŠã¹ãŠãå¢ããã¹ããã®ãå¢ããŠããªãããšæ°ã¥ããŸã§ãéãã«ééã£ããŸãŸåãç¶ããŸãã
ã¹ããªãŒã¯ç£èŠãäœã£ãã®ã¯ããããããéãã«åããŠãããäžèº«ã¯ååããªç¶æ ãæ°åãšããŠå¯èŠåããããã§ããããã ãç£èŠã³ãŒãèªäœãè©°ãŸããŸããç£èŠã®ç£èŠãŸã§äœãæ°ã«ã¯ãªããªãã®ã§ãç£èŠã³ãŒãã¯ãã·ã³ãã«ã«ãããžãã¯ãäžç®ã§ãããè¡æ°ã«ããšããæ¹éã§æžããŠããŸããè€éãªç£èŠã³ãŒãã¯ããèªäœããã°ã®æž©åºã«ãªããŸãã
ã€ãŸãããã€ã³ã
åç¯ã§ deadline=None åç
§æŒãã»ãžãã¿ãŒäºç®è¶
éã»streak ã® last_date ãã°ã®3ä»¶ã詳述ããŸãããããã§ã¯ããããå«ããåãçªã§åºãå
šå€±æãéçŽããŸãã
-
caps à delays ã®ç©ãäžåºŠãèšç®ããªãã£ããlikes 62ïŒfollows 24ïŒunfollows 15 = æå€§101ã¢ã¯ã·ã§ã³ãå¹³ååŸ æ©40ç§ã101 à 40 = 4,040ç§ãå®è¡æ
BROWSER_SLOT_TIMEOUT_SEC=2400ã®1.7åãã³ãŒãã®1è¡ãééã£ãŠããªããã©ã®èšå®å€ãåç¬ã§èŠãã°ãŸãšããç©ã ããç Žç¶»ããŠããŸããã -
äžéããåç®å€Ã0.8ãã§åã£ããå®çžŸã«å±ããªãã£ããClaudeã¯ã©ãŒã¿æ¯æžã§2026幎8æ13æ¥ã«æçš¿0æ¬ã«ãªã£ããšããå šã¬ãŒã³ãäžåŸ2å²ã«ããããŸãããããã
x-autoreplyã®å®çžŸã¯63ã93ãäžéã¯150ã§ãã150Ã0.8=120ã§ã¯å®çžŸ93ã«å±ããŸãããåããããã«èŠããŠäœãåããŠããŸããã§ãããæ£ããäžéã¯å®çžŸÃ0.8ã§çœ®ãå¿ èŠããããŸããig-autoreplyã¯OPEN_POLICY ? InfinityããããŠ160ïŒå®çžŸ200ã®8å²ïŒã«å€ããŸãããäžéããå®è¡ãçžãå€ãã§ã¯ãªããå®è¡ã®èšè¿°ãã«ãããªã£ãŠããªãå Žé¢ããããŸãã -
SIGKILLã§Chromiumãå€å åãããã·ã³ããŒããé倩äºã«ãªã£ãã
~/.cache/lily-browser-slots/slot.logã«ã¯æ¯æresult=timeout:2400sã䞊ãã§ããŸããããããæ¬åœã®è¢«å®³ã¯ããã§ã¯ãããŸããã§ãããPlaywright ã®finally: ctx.close()ã¯SIGKILLã«æããŸãããå€å Chromiumãç©ã¿äžããç¶ããŠãã·ã³å šäœãäžèª¿ã«ãªããŸãããæéäºç®ã®è¶ éããç¡é¢ä¿ã«èŠããã·ã¹ãã é害ãšããŠçŸããå žåã§ãã -
SLOT_MAXãæã蟌ã¿ã§çµãã30%ã®ãžã§ããã¹ããããããã
browser-slot.shã®ã³ã¡ã³ãã«ãã®èšé²ãæ®ã£ãŠããŸãã# 宿ž¬(2026-08-09): Chromeç³»ãžã§ã9åã§åèš0.7GBãswapæ¯æžã®äž»ç¯ã¯ dasd(47GB)/ # ComfyUI(12GB)/iii(3.5GB)ã§ãã£ãŠãã©ãŠã¶ãžã§ãã§ã¯ãªãã£ããäžé3ã¯éå°ã«å³ãã # 1æ¥ã§92åã®skip(å šäœã®30%)ãåºããŠããã®ã§5ã«ç·©ããã SLOT_MAX="${BROWSER_SLOT_MAX:-6}"swapæ¯æžã®åå ããã©ãŠã¶ãžã§ããšæã蟌ãã§
SLOT_MAX=3ã«çµã£ããã1æ¥92åã»å šäœã®30%ãã¹ããããããŠããŸããã宿ž¬ãããäž»ç¯ã¯dasdïŒ47GBïŒãšComfyUIïŒ12GBïŒã§ãChromeã¯0.7GBãã䜿ã£ãŠããŸããã§ããã -
æçš¿ãžã§ããå šã¹ãããå æäžã«9åã¹ããããããæéåž¯ã®æ ãæ¶ããã
browser-slot.shãåœæã®çµç·¯ãèšé²ããŠããŸãã# 2026-08-15: æã®7æ¬åætimeoutã§æ 6ãæ»ãã runã«å æãããæçš¿ã¬ãŒã³(xpilot.autopost # ç)ã global-limit ã§9åskipãããããã/ãã©ããŒã¯1åèœã¡ãŠãç¿åã§åãè¿ãããã # æçš¿ã¯ãã®æéåž¯ã®æ ãæ¶ãããšäºåºŠãšåãŸããªãã SLOT_RESERVED_GROUPS="${BROWSER_SLOT_RESERVED_GROUPS:-post}" SLOT_RESERVE_COUNT="${BROWSER_SLOT_RESERVE:-1}"ããããã¯ç¿æ¥åãè¿ãããæçš¿ã®9ææ ã¯9æãéãããæ¶ããããšããåªå 床ã®å·®ããå šã¹ãããããã©ããã«æ±ãèšèšã«åãããŠããŸããã
-
Discord 2000åäžéã§æ¥æ¬¡ã¬ããŒããäžžããšèœã¡ãã
lily-line-funnel/scripts/pdca.mjsã®sendDiscordReportãã¬ããŒãå šæã1åã®POSTã§éã£ãŠããŸãããã¬ããŒããé·ãæ¥ã¯éç¥ãã®ãã®ãæ¶ããŸãã倱æããŠããã®ã«å€±æãã°ããªããµã€ã¬ã³ããªç¶æ ã§ããçŽãæ¹ã¯è¡åäœãã£ã³ã¯åå²ãšãæåæ°ã«ãŠã³ãã[...s].lengthïŒãµãã²ãŒããã¢å¯Ÿå¿ïŒã«ããããšãDiscordéä¿¡ãšã©ãŒã®æ¬æã¯å é 800åã§åã£ãŠãã°ã¯å šæã®ãŸãŸæ®ãæ§æã«ããããšã§ãã -
Chrome screenshotã®é«ãããèªåfitãããªãã£ããã³ãŒãå ã³ã¡ã³ãã«ãé«ãã¯èªåïŒã³ã³ãã³ãfitïŒã«ãããã倧ããwindowããšãããŸããã誀ãã§ããã
--headless=new --screenshotã¯ãŠã£ã³ããŠãµã€ãºããã®ãŸãŸæ®ããŸããã³ã³ãã³ããçããŠãæå®ãµã€ãºã®äœçœãçãŸãããnoteçšã®è¡šç»åãåžžã«1760Ã4000pxïŒäžã«å·šå€§ãªçœäœçœïŒã®ãŸãŸå ¬éãããŠããŸãããçŽãæ¹ã¯2ãã¹åã1ãã¹ç®ã§--dump-domããscrollHeightãèªã¿ã2ãã¹ç®ã§ãã®é«ããæå®ããŠæ®åœ±ããŸãããã ã1ãã¹ç®ã®ãŠã£ã³ããŠé«ãã¯200ã«ããå¿ èŠããããŸãã2000ã®ãŸãŸã§ã¯scrollHeightã2000æªæºã«ãªããåããã°ãæ®ããŸããçµæã¯ 1760Ã4000 â 1760Ã1178 ã«ãªããŸããã -
imagegen ã®åºå寞æ³ãæå®ã©ãããšä¿¡ããŠãããã4:5瞊 1024Ã1280ããšæç€ºããŠãå®éã®åºå㯠1122Ã1402 ã 1003Ã1568 ã§è¿ããŸããçæããŒã«ã®ã¢ã¹ãã¯ãæ¯æå®ã¯ä¿èšŒã§ã¯ãããŸãããã¬ãŒã³ã«ãã£ãŠ
sipsæ£èŠåãããããªãã£ããã®äžçµ±äžãæ®ããAI portraits ã®ä»äžãããã¬ãŒã³éã§ãã©ãã©ã«ãªããŸãããçæåŸã«æ¯ååŒ·å¶æ£èŠåããŠå®å¯žã確èªããã®ãæ£è§£ã§ãã -
ãåŸéã¯äžéãäŸçµŠããããã°ããå€å¥ã§ããªãã£ãããã©ããŒæ°ã䌞ã³ãªãåå ã®èª¿æ»ã§ããäžéã«éããŠæ¢ãŸã£ãŠããã®ãããåè£ãæ¯æžããŠåŠçã§ããªãã®ããããã°ãèªãã§ãå€å¥ã§ããªãç¶æ ããããŸããã
æ¥æ¬¡äžéã«å°éããŠæã¡åã: ig-autoreply 160/160ã®1è¡ãæã¡åãæã«åºåããã ãã§ããã¢ã«ãŽãªãºã ããªããšãã誀解ã«ããèª¿æ»æéãæ¶ããŸãã -
result=exit:1ããšã©ãŒã®çš®é¡ãæããŠãããªãã£ããdeadline=Noneæã®TypeErrorããããã¯æ€ç¥ã«ããäžæããã°ã€ã³åãã«ããäžæããã¹ãŠåãexit:1ã§èšé²ãããŠããŸãããåç¯ã§è©³è¿°ãããšããã§ããexit codeãåããªã®ã«åå ãç°ãªããšãã調æ»ã¯ãã°ä»¥å€ã®æããããæ¢ãããšããå§ãŸããŸãã
ãã¹ããã©ã¯ãã£ã¹
1. caps à delays à jitter ã®ç©ãå ã«èšç®ãã
èšå®å€ãæžããããšãææªã±ãŒã¹ã®æèŠæéïŒæå€§caps à æå€§delay + jitteräžéïŒãåºã㊠BROWSER_SLOT_TIMEOUT_SEC ãšæ¯ã¹ãŠãã ããããcapsãæ£ããããdelaysãæ£ãããã¯å¥ã
ã®ç¢ºèªã§ããçµã¿åãããåããŠç Žç¶»ããŸããä»å㯠101 à 60 + 900 = 6,960ç§ > 2,400ç§ãå®è¡åã«èšç®ã§ããçãã§ãã
2. ç· åã¯ãcapsãäžãããã§ã¯ãªããèªåããå ã«æ¢ãŸããã§è§£æ±ºãã
capsã¯æé·æœçã®äžéã§ããäžããã°æœçã®å¹æãçž®ã¿ãŸããcompute_budget() ã§ç· åãèšç®ããŠãç· ååã« return 0 ããèšèšã«å€ããæ¹ãææã®æå€±ãå°ãªããSIGKILLãåããåŽãããèªãæ¢ãŸãåŽã«ç«å Žãå€ããå®è£
ã§ãã
3. æ°æ©èœã®æ¢å®å€ã¯ãäœãããªãåŽãã«çœ®ã
def compute_budget() -> float | None:
for key in ("IG_ENGAGE_BUDGET_SEC", "BROWSER_SLOT_TIMEOUT_SEC"):
val = os.environ.get(key, "")
if val.strip().isdigit() and int(val) > 0:
return float(val)
return None # å
šå€å®ãç¡å¹å
deadline = None ã®ãšã over_budget() ã¯åžžã« False ãè¿ããŸããç°å¢å€æ°ãæ¶ããç¬éã以åã®åäœã«æ»ããŸããç°å¢å€æ°ãæ¶ããç¬éã«ãžã§ããæ¢ãŸãäœãã«ããªãããåºæ¬ååã§ãã
4. æ¢åã®å€å®ç¹ã«çžä¹ãããŠãæ°ããå¶åŸ¡æ§é ãäœããªã
# 倿Žå
if blocked["hit"]:
break
# 倿ŽåŸïŒ4ç®æã«è¿œå ããã ãïŒ
if blocked["hit"] or over_budget():
break
æ°ããã¯ã©ã¹ã if ãããã¯ãäœããŸããã倿Žéãå°ããã»ã©æ¢åã®æåãå£ããªã¹ã¯ãäžãããŸããä»åã®äž»èŠãªããžãã¯å€æŽã¯ã4ç®æãžã® or over_budget() ã®è¿œå ãš return 0 ã®1è¡ã§ãã
5. jitterãäºç®ããå·®ãåŒããæ®äºç®ã®20%ã§ã¯ã©ã³ããã
wait = min(START_JITTER_MAX_S, (deadline - time.time()) * 0.2)
äºç®2,400ç§ã«å¯ŸããŠæå€§900ç§ã®jitterã¯37.5%ã§ããæ®äºç®ã®20%ïŒ480ç§ïŒã§ã¯ã©ã³ãããããšã§ãäºç®ãçãã»ã©jitterãçããªããŸãã2,400ç§ã®20%ã¯480ç§ãªã®ã§å ã®900ç§ããçãããã€äºç®ãåãããã»ã©jitterãèªåçã«çž®ã¿ãŸãããžãã¿ãŒã®åŸã«äºç®ãæ®ã£ãŠããã確èªããªãå®è£ ã¯ã0ã¢ã¯ã·ã§ã³ã§æ£åžžçµäºããŸãã
6. æã¡åããšãã®ä»ã®ãšã©ãŒããã©ã°ã§åºå¥ãã
was_truncated = (
likes_done < LIKES_CAP or
follows_done < FOLLOWS_CAP or
unfollows_done < UNFOLLOWS_CAP
) and budget_hit
budget_hit ãã©ã°ãå¥ã«æã€ããšã§ããããã¯æ€ç¥ã«ããäžæãšäºç®åãã«ããäžæãåé¢ããŸããã¹ããªãŒã¯ã¯ãcapsãšå®è¡æéã®ãã¹ããããã ããæ°ããŸãããããã¯ãããæ¥ã¯ã¹ããªãŒã¯ãå ç®ããŸããã
7. äžéã¯ãåç®å€Ã0.8ãã§ã¯ãªããå®çžŸÃ0.8ãã«çœ®ã
| ã¬ãŒã³ | å®çžŸ/æ¥ | æ§äžé | æ°äžéïŒå®çžŸÃ0.8ïŒ |
|---|---|---|---|
| x-autoreply | 63ã93 | 150 | 75 |
| ig-autoreplyïŒDMïŒ | 200 | Infinity | 160 |
| x-outbound | 120 | 120 | 96 |
| threads-engage out | 47ã50 | 50 | 40 |
å®çžŸ93ã«å¯ŸããŠäžé150ã0.8åãã120ã¯ãå®çžŸã«å±ããŸããããŸãå®çžŸã枬ãããã®äžã«äžéã眮ãé åºãæ£ãããäžéãå®çžŸãäžåã£ãŠããªããªããããã¯äžéã§ã¯ãªãåãªãæ°åã§ãã
8. éèŠãªãžã§ãçšã®äºçŽæ ãã¹ããã管çã«çµã¿èŸŒã
SLOT_RESERVED_GROUPS="${BROWSER_SLOT_RESERVED_GROUPS:-post}"
SLOT_RESERVE_COUNT="${BROWSER_SLOT_RESERVE:-1}"
ãæçš¿ã¯ä»æ¥ã®æéåž¯ãæ¶ãããšäºåºŠãšåãŸããªããããããã¯ç¿æ¥åãè¿ããããšããåªå
床ã®å·®ãã¹ãããèšèšã«åæ ããŸããå
šã¹ãããããã©ããã«æ±ããšãéèŠãªãžã§ããéåŒãããŸããengageç³»ïŒãããã»ãã©ããŒïŒã¯ effective_max = SLOT_MAX - SLOT_RESERVE_COUNT ã®å®å¹äžéã§åãããpost系㯠SLOT_MAX ãŸã§äœ¿ããŸãã
9. ãåšã®ãµã€ãºãã¯å¿ ãæãç®ããçµæã§ç®¡çãã
Discord 2000åã»Chrome scrollHeightã»imagegen åºå寞æ³ââãããããæå®ããå€ãåºããåæã§å®è£ ãããšå£ããŸããå¶çŽã¯ãæžããæ°åãã§ã¯ãªããåºãŠããæ°åã®ææªã±ãŒã¹ãã§æã€å¿ èŠããããŸããéä¿¡åã«ãã£ã³ã¯åå²ãæ®åœ±åã«ãµã€ãºèšæž¬ãçæåŸã«åŒ·å¶æ£èŠåãå·¥çšã«çµã¿èŸŒãããšã§ããæå®ãšå®éã®ä¹é¢ããåŸã«ãªã£ãŠçºèŠãããã°ãé²ããŸãã
10. ã¢ã©ãŒãã¯ã3æ¥é£ç¶ + 1æ¥1åãã®éŸå€ã§èšèšãã
1æ¥ã§é³Žãããšåçºãã€ãºã§èªãŸããªããªããŸããæ¯æ¥é³ŽãããšããŸãæ¥ããã«ãªããŸãã3æ¥é£ç¶ã¯ãåçºã®éãæ¥ã®å€ãã«ããæçã®é£ç¶ã§ãã1æ¥1åã¯ã人éã察åŠã§ããéãã§ããlast_alert_date != today ã®æ¡ä»¶1ã€ã§ã忥äžã®éè€éç¥ãé²ããŸãã
today = datetime.date.today().isoformat()
if streak >= 3 and state.get("last_alert_date") != today:
send_alert(
f"capsãå®è¡æéã«å¯ŸããŠé倧ïŒäºç®å°éã§ã®æã¡åãã{streak}æ¥é£ç¶\n"
f"likes {likes_done}/{LIKES_CAP}, "
f"follows {follows_done}/{FOLLOWS_CAP}, "
f"unfollows {unfollows_done}/{UNFOLLOWS_CAP}"
)
state["last_alert_date"] = today
11. streakã«ãŠã³ãã¯ã忥ãæã¡åããã§ç¶ç¶æ¡ä»¶ãå®çŸ©ãã
ãlast_dateã仿¥ããã§å€å®ãããšã2æ¥ã¹ãããåŸã®åéã§streakãæ£ããç©ãŸããŸããããlast_dateãæšæ¥ãããç¶ç¶æ¡ä»¶ã«ããããšã§ãã¹ãããããŸããã§ãé£ç¶æ§ãæ£ããå®çŸ©ãããŸãã
yesterday = (today - datetime.timedelta(days=1)).isoformat()
if was_truncated:
if state.get("last_date") == yesterday:
state["streak"] = state.get("streak", 0) + 1
elif state.get("last_date") != today_str:
state["streak"] = 1 # é£ç¶ãéåãã
state["last_date"] = today_str
else:
state["streak"] = 0
state["last_date"] = today_str
12. ãåŸéã¯äžéãäŸçµŠãããæã¡åãæã®1è¡ã§æ®ã
æ¥æ¬¡äžéã«å°éããŠæã¡åã: ig-autoreply 160/160
ãã®1è¡ãããã ãã§ãããã©ããŒæ°ã䌞ã³ãªãåå ã¯äžéãäŸçµŠäžè¶³ããã®èª¿æ»ã2åã§çµãããŸãããªããšããã°ã2æéæã£ãŠãå€å¥ã§ããŸãããåŠçãæ¢ãŸã£ãçç±ã¯ãæ¢ãŸã£ãæç¹ã§æžãåºããŠãã ããã
13. SLOT_MAXã¯å®æž¬å€ããæ±ºããã³ã¡ã³ãã«æ ¹æ ãæ®ã
browser-slot.sh ã®ã³ã¡ã³ãã¯èšæž¬ããæ°å€ãšãã®å€ææ ¹æ ãæžããŠããŸãããChromeç³»9åã§0.7GBã»äž»ç¯ã¯dasd47GBããšãã宿ž¬ããæ¬¡åã®èª¿æ»ã2åã§çµããããŸããèšå®å€ã«ã³ã¡ã³ãããªããšããæ¬¡ã®æ
åœè
ïŒæªæ¥ã®èªåïŒã¯åã調æ»ãäžããå§ããŸãã
ãŸãšã
èªååããéãã«åããŠãããäžèº«ã¯ååãã«ãªã£ãŠããæéãããã·ã¥ããŒãã¯åé¡ãªããlaunchdã¯æåãèšé²ããæ¯æ exit 0 ãè¿ã£ãŠããŠããŸããã
åé¡ã®æ§é ã¯åçŽã§ããcapsãšå®è¡æéãå¥ã ã®å Žæã«æžããŠãäžåºŠãæãç®ããªãã£ãããã®çµæãæ¯æ¥SIGKILLãããChromiumãå€å åãããã·ã³å šäœãäžèª¿ã«ãªããŸãããDiscord ã®2000åãChrome ã® scrollHeightãimagegen ã®åºå寞æ³ãåãåã§ããã³ãŒãã®ã©ã®è¡ãèªãã§ããæ£ããããçµã¿åããã ããç Žç¶»ããŠããããã®ãã°ã¯ã³ãŒãã¬ãã¥ãŒã§ã¯èŠã€ãããŸãããèšå®å€ã©ããã®ç©ãåºãç¿æ £ã ããé²ããŸãã
ä¿®æ£ã¯å€æŽéãå°ãªãæ¹ãæ£ããå®è£
ã§ããcompute_budget() ã§ç· åãèšç®ããover_budget() ãæ¢åã®4ç®æã®å€å®ç¹ã«çžä¹ãããreturn 0 ã§èªåããæ¢ãŸããã³ã¢ã®ããžãã¯å€æŽã¯2æ¡ã®è¡æ°ã§çµãããŸããã
ãã ããèªåããæ¢ãŸã£ãŠ exit 0 ã«ããããéžãã ç¬éããéãã«æ¢ãŸãä»çµã¿ãéãã«ç£èŠããã責任ãçãŸããŸãã3æ¥é£ç¶+1æ¥1åã¢ã©ãŒããšããèšèšã¯ããã®è²¬ä»»ãæããæå°ã®æ§é ã§ãã1æ¥ã§ã¯é³Žãããªããæ¯æ¥ã鳎ãããªããšããéŸå€ã®éã«ããç¹ããçŒå°å¹Žãé¿ããªããæ§é åé¡ãæ€ç¥ã§ããå¯äžã®å Žæã§ããã
exit 0 ãä¿¡ããããexit 0 ã®äžèº«ã確èªãããââãã®å·®ããæå120äžãç¶æããèªåŸç°å¢ãšãéãã«æ¢ãŸãç¶ããç°å¢ã®åå²ç¹ã§ãã
ä»çµã¿ã®å šäœåã»æ120äžã®å èš³ã»30æ¥æé ã¯æænoteã«ãŸãšããŠããŸãã ð Claude CodeèªåŸç°å¢ã§ãå®éã©ã皌ãã â ä»çµã¿ã»å®äŸã»å§ãæ¹ã»ãµããŒã
LilyïŒ@bokuwalilyïŒâ å人éçºè ãClaude Code ã§èªåååºç€ãçµã¿ãªãããiOSã¢ããªãWebãµãŒãã¹ãéç£ããŠããŸã
- AIã§ãå¯ãŠãŠãåãä»çµã¿ããäœã£ãŠæ120äžã«ãã話㯠noteã®ææèšäº ã«ð°
- OSS: github.com/bokuwalily ð
- ææ°æ å ±ã»ãåãåãã㯠X @bokuwalily ãžð
- AIå°å ¥ã»èªååã®çžè«ãšå®è£ ãã³ãã¬7æ¬ã®é åžã¯ å ¬åŒLINE ããð¬
çããã® â€ïž ãã·ã§ã¢ãå±ã¿ã«ãªããŸãïŒ