diff --git a/.env.example b/.env.example index 806bea0..75ef3bb 100644 --- a/.env.example +++ b/.env.example @@ -111,6 +111,14 @@ VIBEGRAM_REPO= # Токен GitHub с доступом к репе (приватная); пусто - публичная VIBEGRAM_REPO_TOKEN= +### Досуг (ежечасный тик мастера, с S13) ###################################### + +# Час активного окна (12:00-03:59) и четыре часа тихого (04:00-11:59) будят +# мастера инжектом без задания. Повседневный выключатель - строка `досуг: выкл` +# в `мета/бобер/досуг.md`; здесь - рубильник: `off` снимает джоб совсем. +# Пусто = включено. +LEISURE= + ### Порты хоста и внешний адрес ############################################### PORT_GATEWAY=62990 diff --git a/README.md b/README.md index 1bb266f..feea80e 100644 --- a/README.md +++ b/README.md @@ -163,6 +163,47 @@ pieces live in `beaver_agent/`, one concern per module: and seeds, the vault watcher, the curator briefing - `jobs/` - crons and webhooks, one file per job +## Leisure: the hourly tick (`beaver_agent/jobs/leisure.py`) + +The master gets an inject with no task in it every hour: what time it is, +what kind of hour this is, and what is left of the day's plan. The active +window (12:00-03:59) ticks every hour; the quiet one (04:00-11:59, the hours +the owner has never once written in) ticks only in the four hours the plan +names - twenty ticks a day. + +The day runs noon to noon and the first tick of it is the planning one: the +model lays the remaining hours out into *mine* (leisure only, the owner's +business stays out) and *mixed*, and writes them to `мета/бобер/досуг.md`: + +```markdown +досуг: вкл +сутки: 2026-09-08 +тихие часы: 04, 06, 08, 10 +мои часы: 13, 15, 18, 21, 00, 02, 06 +``` + +**The model writes that file, the job only reads it**, so they cannot +overwrite each other; how many leisure slots are spent follows from the plan +and the clock, so there is no state to keep. No plan for the day (a restart, +a fresh day, a broken file) is not an error: the job falls back to defaults +and says so in the inject. Fewer than seven leisure hours in the plan are +topped up to seven by the job - the guarantee is the mechanism's, not the +model's. + +A tick lands as `wake` and starts a turn once the master is idle; a busy +master or a message less than five minutes old moves it five minutes on, +up to three times, so it never cuts into a live exchange. If a `schedule` +inject of the model's own is due later in the same hour, the tick goes in +as `normal` instead and rides into that turn with it - one turn, both +reasons, neither swallowed. The cron sits at `:07`, not `:00`, because +rotation is on the hour and a tick waiting in the queue counts as a busy +master. + +Nothing of this reaches Telegram by itself: a turn started by an inject +publishes no reply, so the only voice in it is the `say` tool. +Switches: `досуг: выкл` as the first line of the file for every day, and +`LEISURE=off` in `.env` to drop the job entirely. + ## Policy (`beaver_agent/policy.py`) `bypassPermissions` everywhere; the boundary is `PreToolUse` rules declared