Docket v0.1.1 Roadmap — Composability and Ergonomics

Copy Markdown View Source

The current development tree includes the schema, reducer, graph-editing, telemetry, and TenantFair operations work summarized below. The remaining sections describe open work only. Module documentation defines the implemented API.

Implemented outcomes

Schema and reducer support

  • Schemas support strings, floats, integers, booleans, maps, objects, enums, and lists.
  • Numeric, string, and list constraints are enforced. Objects may opt into unknown keys with open: true.
  • Schema shorthand accepts primitive atoms and type tuples throughout graph construction.
  • Reducers fold the prior committed value with deterministically ordered writes. Built-ins are last_value, first_value, append, merge, sum, and union.
  • Accumulating reducers provide natural initial values and reducer-aware write validation. List writes to append and union concatenate their elements.

See Docket.Schema, Docket.Reducer, and the reducer rationale.

Inline graph fields

Docket.Graph.put_node/4 and put_node!/4 accept inputs: and fields: declarations that materialize ordinary graph fields. Identical declarations are idempotent, conflicting declarations fail, and deleting a node does not delete shared fields.

Event telemetry

Every committed Docket.Event with a public telemetry mapping emits after the commit. This gives live instrumentation a direct event stream without requiring checkpoint parsing. Delivery remains best effort; retained events are the durable source.

See Docket.Telemetry and the telemetry guide.

TenantFair operations

The TenantFair claim policy includes versioned administration of the persisted default and per-owner overrides, aggregate admission counts, telemetry, and regression tooling. Weighted service, borrowing, reclaim, and alternate schedulers are separate proposals in the future roadmap.

Open work

Graph modules and a static DSL

A static graph module could expose a declarative frontend while preserving the existing graph document as the only canonical representation:

defmodule MyApp.Graphs.SupportReply do
  use Docket.Graph, id: "support-reply"

  input :customer_message, :string, required: true
  field :messages, {:list, :map}, reducer: :append
  node :draft, MyApp.Nodes.LLM, config: %{}
  chain [:start, :draft, :finish]
  output :draft_response
end

An implementation would need to:

  • expand through the public graph-editing and schema APIs;
  • preserve an authored %Docket.Graph{} for publication and serialization;
  • validate static definitions at compile time; and
  • establish compile dependencies on referenced node modules so schema changes recompile dependent graph modules.

Runtime-created, UI-built, and stored graphs would remain ordinary graph documents using the existing compiler and runtime cache.

Subgraph composition

The first candidate is build-time inlining:

Docket.Graph.compose!(parent, "triage", child_graph,
  inputs: %{"message" => "customer_message"},
  outputs: %{"result" => "triage_result"}
)

Inlining would namespace child nodes, fields, and edges; map its inputs and outputs to parent fields; and produce one flat graph document covered by one hash. The design still needs stable namespacing, collision diagnostics, rewriting rules for field references in guards and configuration, and a decision on provenance metadata.

A runtime subgraph node referencing an independently versioned child graph is deferred. It would require nested run, checkpoint, interrupt, and recovery semantics rather than only a graph-document transformation.

Detached node completion

Vehicles do not refresh claims. In-process node attempts run under the runtime-owned hard deadline, and token/sequence fencing rejects a stale commit after claim recovery. Work durably owned by an external system should park the run and return through an interrupt or another serialized signal.

{:await, term()} is reserved by the executor contract and currently becomes a permanent node failure. Supporting detached completion would require:

  • a durable task state that records stable task and attempt identity without trying to checkpoint an in-flight process;
  • a serialized result mutation fenced on that exact detached task and attempt;
  • a mandatory durable deadline and recovery path;
  • a supervised home for local completions after the vehicle exits; and
  • unchanged replay and external-effect idempotency rules for late or rejected results.

The completion protocol must release the vehicle and claim while ensuring that stale, duplicate, and superseded results cannot advance the run.

Additional extension points

Custom reducer or guard behaviours remain possible, but they would make host modules part of durable graph semantics and move determinism obligations to the host. They should be added only for requirements that the built-in reducers and guard expressions cannot represent. Retry/backoff strategy customization is also deferred pending a concrete integration need.