feat(config,policy): skill sets per kind, master without vault skills, attachments in the vault, crons in local tz

This commit is contained in:
hh
2026-09-01 23:13:29 +02:00
parent 43d0d43f9d
commit f7844a5411
4 changed files with 89 additions and 20 deletions
+30 -7
View File
@@ -6,7 +6,7 @@ from typing import Any
from zoneinfo import ZoneInfo
from beaver_gateway.agents.base import BaseAgent, ExposedMcp
from beaver_gateway.agents.claude import ClaudeAgent, ClaudeOptions, Prompts
from beaver_gateway.agents.claude import ClaudeAgent, ClaudeOptions, Prompts, SkillSets
from beaver_gateway.agents.raycast import RaycastAgent, RemoteTool, UserPreferences
from beaver_gateway.core.conversations import (
ConversationTexts,
@@ -27,7 +27,7 @@ from beaver_gateway.frontends.api import ApiFrontend
from beaver_gateway.frontends.base import Frontend
from beaver_gateway.frontends.markdown import MarkdownFrontend
from beaver_gateway.frontends.mcp_server import McpServerFrontend
from beaver_gateway.frontends.telegram import TelegramFrontend
from beaver_gateway.frontends.telegram import Attachments, TelegramFrontend
from beaver_gateway.mcp.types import HttpMcp, McpServer, McpServerT
from curator import Watched, briefing
@@ -42,6 +42,7 @@ from policy import (
TRIAGE_DISALLOWED,
Zones,
bash_zones,
forbid_skills,
requires_skill,
skill_tracker,
vault_zones,
@@ -127,9 +128,23 @@ CURATOR_PROMPTS = Prompts(
)
QUICK_PROMPT = assemble((*VOICE, PROFILE, overlay("quick", "быстрый")))
# §4.3: наборы скиллов = папки = плагины. Глубокие грузят общие + vault.
# §4.3: наборы скиллов = папки = плагины. Глубокие грузят общие + vault;
# мастер - без vault (firefly, beaver durden - только в ветке и в глубоком);
# форк и джоб диспетчера - без скиллов вовсе.
DEEP_SKILLS = (SKILLS / "общие", SKILLS / "vault")
DISPATCHER_SKILLS = (SKILLS / "общие", SKILLS / "диспетчер", SKILLS / "vault")
DISPATCHER_SKILLS = SkillSets(
master=(SKILLS / "общие", SKILLS / "диспетчер"),
branch=(SKILLS / "общие", SKILLS / "диспетчер", SKILLS / "vault"),
fork=(),
job=(),
)
# Мастер не становится Дерденом: без набора скилл и так не найдётся, правило -
# ради внятного отказа («открой ветку»).
MASTER_FORBIDDEN_SKILLS = (
tuple(p.name for p in sorted((SKILLS / "vault").iterdir()) if p.is_dir())
if (SKILLS / "vault").exists()
else ()
)
# §3.7 (решение h, 2026-08-30): vault - дом диспетчера. Создавать, править,
@@ -290,7 +305,10 @@ def dispatcher(name: str, model: str, effort: str | None = None) -> ClaudeAgent:
skill_sets=DISPATCHER_SKILLS,
gateway_tools=("read_conversation", "spawn", "say", "schedule"),
options=ClaudeOptions(effort=effort, disallowed_tools=DISPATCHER_DISALLOWED),
policy=VAULT_POLICY,
policy=(
*VAULT_POLICY,
forbid_skills(MASTER_FORBIDDEN_SKILLS, kinds=("master",)),
),
# §4.4: t3code и вайбграм - руки диспетчера (мастер, ветки), глубоким
# не даются: наружу и в код ходит только он.
expose_mcps=(*CLAUDE_MCPS, *t3code_exposed, *vibegram_exposed),
@@ -409,6 +427,11 @@ TELEGRAM = (
user_id=int(os.environ["TELEGRAM_USER_ID"]),
master_agent="beaver-dispatcher",
branch_agent="beaver-dispatcher",
# §3.8: вложения - входящая папка в зоне агента, по дням; что стоит
# хранить, он переносит к заметке сам, остальное сметается через месяц.
attachments=Attachments(
mode="vault", dir=BEAVER / "вложения", keep_days=30, tz=TZ
),
)
if os.environ.get("TELEGRAM_BOT_TOKEN")
else None
@@ -850,9 +873,9 @@ jobs = [
Job("вайбграм", vibegram, cron="*/10 * * * *", critical=False),
Job("закрытие", close_idle, cron="20 4 * * *", critical=False),
Job("память", memory, cron="30 4 * * 0", critical=False),
# крон в UTC контейнера: 02/10/14/18/22 по Варшаве летом;
# кроны считаются в Gateway.tz (Варшава), не в UTC контейнера;
# руками - POST /api/jobs/куратор/run
Job("куратор", curate, cron="0 0,8,12,16,20 * * *", critical=False),
Job("куратор", curate, cron="0 2,8,12,16,20 * * *", critical=False),
Job("deploy", deploy, webhook=True),
# алерты идут пачками (тревога и отбой подряд) - схлопывать нельзя
Job("komodo", komodo_alert, webhook=True, dedupe=False),