feat(memory,jobs): replies and curator runs go to daily files

This commit is contained in:
hh committed 2026-10-13 01:23:20 +02:00
1 parent 0273f29589
commit dea793dbd7
6 files changed
+47 -16

No files matched your search

+15 -8
View File
@@ -3,8 +3,9 @@
Крон дёргает детерминированный код, модель судит: здесь собирается брифинг
для служебного тёрна `beaver-curator` - новые реплики Бобра целиком и имена
файлов, изменившихся с прошлого прогона. Время прошлого прогона куратор
сам пишет первой строкой `мета/бобер/куратор.md`; нет ничего нового -
брифинга нет и джоб не спавнится.
сам пишет первой строкой `мета/бобер/куратор.md`, запись о прогоне - в файл
дня `мета/бобер/куратор/YYYY-MM-DD.md`; нет ничего нового - брифинга нет и
джоб не спавнится.
"""
from __future__ import annotations
@@ -46,13 +47,16 @@ def last_run(journal: Path, *, default: datetime) -> datetime:
def new_replies(replies_dir: Path, since: datetime, tz: str) -> list[str]:
"""Строки `реплики/YYYY-MM.md` позже ``since`` (время в строках локальное)."""
"""Строки `реплики/YYYY-MM-DD.md` позже ``since`` (время в строках локальное)."""
zone = ZoneInfo(tz)
local_since = since.astimezone(zone).replace(tzinfo=None)
out: list[str] = []
if not replies_dir.exists():
return out
for path in sorted(replies_dir.glob("????-??.md"))[-2:]:
first = f"{local_since:%Y-%m-%d}.md"
for path in sorted(replies_dir.glob("????-??-??.md")):
if path.name < first:
continue
for line in path.read_text(encoding="utf-8", errors="ignore").splitlines():
m = REPLY_RE.match(line)
if not m:
@@ -91,6 +95,7 @@ def briefing(
*,
vault: Path,
journal: Path,
runs: Path,
replies_dir: Path,
watched: list[Watched],
tz: str,
@@ -111,12 +116,14 @@ def briefing(
if not replies and not changed:
return None
zone = ZoneInfo(tz)
local = now.astimezone(zone)
head = (
f"Прогон куратора {now.astimezone(zone):%Y-%m-%d %H:%M} ({tz}); прошлый - "
f"Прогон куратора {local:%Y-%m-%d %H:%M} ({tz}); прошлый - "
f"{since.astimezone(zone):%Y-%m-%d %H:%M}. Ниже - что изменилось с тех пор; "
"остальное читай сам по слоям. В конце обнови первую строку "
f"`{journal.relative_to(vault)}`: `последний прогон: "
f"{now.astimezone(zone).isoformat(timespec='seconds')}`."
"остальное читай сам по слоям. В конце запись о прогоне - в "
f"`{(runs / f'{local:%Y-%m-%d}.md').relative_to(vault)}`, а в "
f"`{journal.relative_to(vault)}` только первая строка: `последний прогон: "
f"{local.isoformat(timespec='seconds')}`."
)
parts = [head]
if replies: