You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Added workflow fan-out / map-join (docs): a step with a for_each list compiles to one parallel task per item (<workflow>/<step>#<item>),
and any dependency on that step expands to a join over every expanded task — a map
(the parallel tasks) and a join (a downstream step waiting on all of them) out of
the plain dependency primitive. Fan-out composes with conditional edges (the
condition carries onto every join edge) and with capability routing; expansion is
bounded to 64 tasks per step and is a pure authoring-time rewrite, so the board and
driver see only the expanded graph of ordinary tasks. 100% line+branch covered.
Added conditional (branching) workflow edges (docs): a
dependency may now be written as {"step": "test", "on": "done"} to wait for a
specific terminal outcome (done or cancelled) rather than mere completion, so
a workflow can branch on result (run one step on success, another on failure). The
condition is enforced by the driver, not the board — the board still sees a plain depends_on edge; the driver classifies a task whose conditional edge can never be
met as skipped and retires it on the board (cancels it), keeping the graph
moving. derive_state gains a skipped bucket and the run loop cancels skipped
branches. Unconditional edges keep their meaning (any terminal status satisfies).
100% line+branch covered.
Added synapse workflow run (docs), the autonomous live
loop around the planner: it connects to the hub, posts a compiled workflow's
tasks once, then on every board reading re-derives the state and routes the ready
steps by writing each task's suggested_owner. Routing is advisory (workers stay
free to choose), idempotent (a task already advising the chosen agent is not
re-written), resumable (it routes from the live board, so a restarted driver
continues), and bounded by both --max-in-flight and --deadline. The decision
logic is the pure planner; run adds only the connect-post-read-assign shell
(core/workflow_run.py). 100% covered.
Added the workflow driver's planning core (core/workflow_driver.py) and a synapse workflow plan command: given a compiled workflow and a board snapshot,
it buckets tasks into done/in-flight/ready/blocked (readiness recomputed from
dependencies) and plans which ready tasks to hand to which capable agents,
bounded by --max-in-flight and one task per agent per round. A pure,
deterministic function over the workflow and the board — the autonomous live
loop wraps it. 100% covered.
Added a declarative workflow layer (core/workflow.py, docs):
a workflow is a plain JSON artifact (a name and steps with depends_on edges)
that compiles to ordinary blackboard tasks, so the board's existing ready/blocked
derivation executes it — no new runtime, no new dependency. Validation rejects
duplicate ids, dangling deps, self-dependencies, and cycles before anything is
posted; compilation namespaces task ids by workflow and emits them in dependency
order. New synapse workflow validate and synapse workflow compile [--json]
offline authoring commands. This is the first slice of the declarative
orchestration layer; a workflow driver follows.