Tick and entries
harness.runtime.tick
Section titled “harness.runtime.tick”Observe, judge the rules and deliver one worker command per control period.
The tick exists while an execution or a rule on time needs it, and not otherwise: nothing is driven by time unless a unit asks for it. Single-resource executions take turns and receive the receipts for their own commands. With channels, executions advance concurrently, merging their inputs with what units hold before local admission. Delayed actions retain their admission and attribution until delivery. The worker shield judges every delivered command.
driving
Section titled “driving”def driving(profile) -> tupleHow an environment says it can be driven: (the most commands a second it takes, None:
as fast as it answers; the time one step of it lasts, None: its time is the wall’s).
From the profile’s max_hz and step_seconds; a profile that still names a clock
is read as what that mode meant: steps (or none), each step lasts 1 / control_hz;
wall, at most control_hz commands a second; events, neither.
delay_ticks
Section titled “delay_ticks”def delay_ticks(reaction_delay_ms, hz) -> intThe control periods a decision waits before it is sent: reaction_delay_ms
rounded up to whole periods of hz.
Preempted
Section titled “Preempted”class Preempted(Exception) __init__(by=None, priority=0)Raised in an execution’s steps where they wait for a step’s reply: the unit by, of
priority, takes the embodiment.
class Tick __init__(session)The tick of one kernel session (see the module docstring): run(steps) runs an
execution on it, judge() has the rules judged, stop() ends it. ticks counts the
steps it sent. bound: the most commands a second the environment takes (its periods
are paced then), step_seconds: the time one step of it lasts (driving()).
def judge()Have the rules judged: one was set, what they read changed, or a rule’s program ended. Nothing where no rule is judged (no rule, no tick).
def stop(timeout=5.0)Stop ticking; a program entry still running ends with an error.
on_thread
Section titled “on_thread”def on_thread() -> boolWhether the caller runs on the tick (a controller, a guard).
def run(steps)Run the execution on the tick and return its trace, or raise its error.
steps: its generator, or a function that makes it. Without channels the
embodiment is held by priority: the execution of the unit of highest priority
advances (the oldest among equals), and it ends a lower unit’s execution where
that is: with PREEMPTED and what it had done, and the model is told at once
(_preempt). The unit that took the embodiment holds it until it ends: what lower
units start meanwhile waits, and goes on then. A unit that said restart=True has
its execution started again then instead (its trace counts the restarts).
Where the environment pauses (its profile says “pauses”), the lower execution
does not end: the environment holds what it was doing, and it goes on from there
when the higher unit has ended (_pause, _resume).
def hold(unit) -> Noneunit said with what priority it holds the embodiment (at_priority): it holds it
with that from now until it ends, between its executions too.
def known(names) -> listnames (a name or a list) as channel names of the embodiment (ValueError for
one it does not declare).
conflicts
Section titled “conflicts”def conflicts(entry, names, *, claiming=False) -> dict{channel: id of the entry that has it} for the channels of names that entry
cannot use now: another entry drives or holds it, or claimed it (a claim of an
entry above entry leaves it to the entries below).
def claim(entry, names) -> dictentry claims the channels names until it releases them or ends: {channel:
holder id} of those it cannot have (then it claims none), else {}.
release
Section titled “release”def release(entry, names=None) -> Noneentry lets go of the channels names (None: all it has): its claims, and the
keys and buttons it holds down on them, which go up at the next period.
let_go
Section titled “let_go”def let_go(entries) -> NoneThe keys and buttons entries hold down go up at the next period; their claims
stay (a guard stopped what they do, runtime/execution/session.py).
def board() -> dictWho has each channel now: {channel: {“entry”, “how”: claimed, driving or holding}}, None where nobody does (it is at its default).
Refused
Section titled “Refused”class Refused(Exception) __init__(reason: dict)A command the session cannot take apart into its channels’ periods (an input of no
channel, a command it does not know): its reason, as a shield’s.
harness.runtime.execution.entries
Section titled “harness.runtime.execution.entries”Units of a kernel session, and bounded ClosedLoop executions.
A session has one model (the root entry) and the units it started: every program the model writes, every function a program spawns, every sub-agent. A unit has its own output, events and pictures (its box) and its own result. What a unit starts belongs to the model, not to the unit: it outlives the program that started it and ends with the model. An event goes through the handlers; one nobody answers reaches the model, and so does every unit’s end.
current_entry
Section titled “current_entry”def current_entry()The entry executing on this thread, or None outside every unit.
class Box __init__()What one unit gathered for the model: its output (a writer the kernel gives it, whose recent(chars) is what was printed last), the pictures it showed and looked at, and the events of its executions.
Cancelled
Section titled “Cancelled”class Cancelled(BaseException)Raised in an entry’s code when the entry was cancelled; a BaseException so that the broad excepts of a program do not keep it running.
class Entry __init__(tree, identifier, name, kind, parent, claims=(), agent=None)One unit of a session (see the module docstring): its id, name, kind (“root”
for the model, “program” for code, “agent” for a sub-agent), the model it belongs to
(parent), its claims, its status (running, done, failed, cancelled) and, once
ended, what its function returned (result) or why it failed (error). cell is the
number of the model’s program it is (None for spawned code), rule the name of the rule
whose program it is (the rules that program sets live with it), priority what it holds
the embodiment with and restart whether an execution of it that a higher unit ended
is started again (runtime/tick.py; default: it ends with PREEMPTED), box what it gathered,
outcome how its code ended ({“status”: ok, error, escalated, episode_ended, finished
or cancelled, …}), raised the exception of an error.
running
Section titled “running”def running() -> boolWhether it has not ended yet.
def rank() -> floatWhat it holds the environment with now: its priority, or the one the code it runs in the environment asks for, whichever is higher.
lineage
Section titled “lineage”def lineage() -> listThis entry and the entries above it, up to the root.
def state() -> dictThe entry as a program and the model see it.
def wait(timeout=None)Wait until this entry has ended, at most timeout seconds (None: as long as it
takes). Returns what its
function returned (a sub-agent: its report); raises its failure (an Escalation
with an ENTRY_FAILED event), which this wait then handles; returns None when it
was cancelled or is still running at the timeout (status says which).
output
Section titled “output”def output(chars=2000) -> strWhat this unit has printed so far: the last chars characters (at most 30000),
while it runs or after it ended. Reading takes nothing away: its result still has
the whole output when it ends. “” for a unit that printed nothing (a sub-agent
prints nothing here: its report is its result).
def send(message)Send this entry a message, which its code reads with receive() (a sub-agent: the answer to its question, or more to do).
cancel
Section titled “cancel”def cancel(timeout=5.0)Stop this unit: the execution it runs ends at its next step, a wait or receive it is in raises, and code that does not reach the harness is interrupted where it is after a moment. What it started goes on (it is the model’s). Returns its state.
receive
Section titled “receive”def receive(timeout=None)The oldest message sent to this entry, waiting at most timeout seconds for one
(None: as long as it takes); None when none came.
class Tree __init__(session)The units of one kernel session (see the module docstring). on_end(entry, handled)
is called once for every unit that ended (the kernel tells the model,
runtime/execution/kernel.py); new_output(entry) gives a new unit the writer of its output.
current
Section titled “current”def current() -> EntryThe entry the calling code belongs to (the root outside every other).
acting
Section titled “acting”def acting(entry)Code inside belongs to entry (the tick steps an entry’s execution, a handler
of an entry runs).
def get(identifier) -> EntryThe entry identifier (the root when there is none).
def under(entry) -> listentry and every entry below it (those it started, those they started, …).
def check(entry=None) -> NoneRaise in the code of entry (default: the caller’s) what it must stop for: its
cancellation, or the user’s pause.
interruption
Section titled “interruption”def interruption(entry, take=True)What entry’s code must stop for now (see check), or None: every unit of the
model stops while the user has paused it (runtime/execution/control.py).
def spawn(fn, name=None, claims=None, *, cell=None, rule=None, priority=None, restart=False, quiet=False, until=None) -> EntryRun fn() as a new unit of the model (see the module docstring); cell: it is the
model’s program of that number; rule: it is the program of that rule; priority:
its own (default: that of the unit that starts it); restart True: an execution of
it that a unit of higher priority ends is started again when that unit is over
(default: it ends there with PREEMPTED).
def until(condition) -> NoneThe unit this code runs in is for condition: a function of the view that holds
when its work is done. It is judged when the unit ends, and the end says whether it
held.
at_priority
Section titled “at_priority”def at_priority(priority) -> '_Priority'with at_priority(priority): the unit this code runs in holds the embodiment
with priority for the block, between its executions too (runtime/tick.py hold),
and with what it held it before from the block’s end on. A unit of higher priority
still takes it (a reflex whose place is priority or above); one of lower priority
waits, and is judged again when the block ends. Its own ends stay: it is cancelled,
its calls reach their time, a reflex that ends what runs holds, the episode ends.
def claim(names) -> boolThe caller’s entry claims the channels names (see the module docstring): True;
False when one is another entry’s and a handler took the CHANNEL_CONFLICT event,
which otherwise escalates.
release
Section titled “release”def release(names=None) -> NoneThe caller’s entry lets go of the channels names (None: all it has): its
claims, and the keys and buttons it holds down on them.
channels
Section titled “channels”def channels() -> dictWho has each channel now ({channel: {“entry”, “how”}}, None: nobody); {} when the embodiment declares none.
adopt_agent
Section titled “adopt_agent”def adopt_agent(agent, task) -> EntryThe unit of a sub-agent the model’s code started (delegate).
agent_runs
Section titled “agent_runs”def agent_runs(agent) -> boolWhether a unit of sub-agent agent has not ended.
agent_ended
Section titled “agent_ended”def agent_ended(agent, report, *, cancelled=False) -> NoneA turn of a sub-agent ended (the conversation tells the kernel, runtime/execution/kernel.py): so does its entry, failed unless the turn ended with an answer.
record_event
Section titled “record_event”def record_event(trace, entry=None)raise_event
Section titled “raise_event”def raise_event(entry, trace, *, notice=False) -> NoneDeliver an independent event without waiting for its handlers on the tick.
handle
Section titled “handle”def handle(entry, trace) -> boolOffer trace’s event to the tree of reflexes (runtime/reactive/tree.py answer): a
node that answers its kind, and whose turn it is, starts its program as a unit, and
the event is answered.
running
Section titled “running”def running() -> listThe units that have not ended, oldest first (the model aside).
def close(timeout=2.0) -> NoneThe session closes: the model ends, and every unit with it.
Result
Section titled “Result”class Result(dict)What a closed loop did: {“ok”, “reason”, “tries”, “seconds”, “detail”}; true when ok.
class Stop(Exception)Raised in a step: the loop ends here with this reason (no more tries).
ClosedLoop
Section titled “ClosedLoop”class ClosedLoop __init__(*args, **kwargs)Confirm, do, check, retry, give the reason: one bounded execution, in any action
scenario; a skill the model writes is one, and so is every execution of the session’s
skills (runtime/execution/session.py Execution). A subclass fills in confirm() (before each try:
True, or the reason not to act), do(), check() (after it: True, or why not) and
recover(reason) (between tries); a step may raise Stop(reason). Called with the skill’s
parameters (on self), it runs at most tries times and max_seconds long and returns a
Result; an exception of catches in a step is its reason (the episode’s end, finish()
and PASS_ON always end the program). A step may fill in detail. Each try’s end is
report()ed: a skill_step record, news for the model while the program runs.
confirm
Section titled “confirm”def confirm()def do()def check()recover
Section titled “recover”def recover(reason)report
Section titled “report”def report(number: int, what: str, ok: bool, seconds: float, reason) -> Nonedef run() -> Result