Files
DECNET/decnet/realism/planner.py
anti f57c621117 feat(realism): scaffold decnet/realism/ library
Empty subpackage skeleton for the realism migration: ContentClass enum
(file/email/canary content categories), Plan dataclass (frozen, with
edit-action invariant), in_work_hours window check (wrap-around
supported, fail-open on parse error), and sample_mtime for backdated
file timestamps that snap into a persona's active hours.

Stage 1 of the orchestrator+canary realism unification — no
production caller wired yet; planner.pick is a stub returning None
until stage 3.
2026-04-27 15:55:21 -04:00

54 lines
1.9 KiB
Python

"""Realism planner — picks the next ``(decky, persona, class, action)`` tuple.
Stage-1 stub: the public signature is in place so the orchestrator
worker (stage 3) can import it, but the body returns ``None`` ("nothing
to do this tick") until stage 3 wires the synthetic_files table and
naming/body generators.
The eventual policy lives entirely in :func:`pick`; downstream
consumers should not branch on ``ContentClass`` themselves — let the
planner decide weights and rate-limits in one place.
"""
from __future__ import annotations
import secrets
from datetime import datetime
from typing import Any, Optional, Sequence
from decnet.realism.taxonomy import Plan
def pick(
deckies: Sequence[dict[str, Any]],
now: datetime,
*,
repo: Any = None,
rand: Optional[secrets.SystemRandom] = None,
) -> Optional[Plan]:
"""Return the next :class:`Plan` for the orchestrator's tick.
Stage-1 stub returns ``None`` unconditionally so the orchestrator
can import this function before the real implementation lands. The
full policy (diurnal gate, action distribution 60/30/10
create/edit/leave, content-class weights, canary rate-limit) lands
in stage 3 of the realism migration.
Parameters
----------
deckies :
Output of :meth:`BaseRepository.list_running_deckies`. Each
entry must carry ``uuid``, ``name``, ``services``,
``email_personas`` (topology-pool JSON or list).
now :
Tick timestamp. Injected so tests don't need to monkey-patch
:func:`datetime.utcnow`.
repo :
:class:`BaseRepository` for synthetic_files lookup (edit
action). Optional in stage 1; required from stage 3 onward.
rand :
RNG for sampling. Defaults to a fresh
:class:`secrets.SystemRandom`.
"""
_ = (deckies, now, repo, rand) # silence unused-arg until stage 3
return None