Epic: Ting workflows — cards, definitions, a minimal executor, and code gates #1

Open
opened 2026-09-06 07:43:37 +00:00 by larandar · 7 comments
Owner

Why

Ruling 10 (Larandar, 2026-09-06, Ting/contracts openspec/changes/establish-console-ux-contract/adversarial-review-2026-09-05.md §Rulings), reached after surveying the open formats and DSH's own primitive: DSH has no declarative workflow — dsh-workflow runs a model-written JavaScript script in the foreground of a session — so everything Dispatch renders and every gate a swarm passes is ting's to define. Ruling 2 makes Dispatch a pure "start a workflow" renderer of what the workflow declares; ruling 3 makes the UI faithful to emitted state only. This epic is the definition and execution layer those rulings presuppose.

The four layers

  1. Agents = A2A Agent Cards. One card per seat (queen, vinculum, drone, probe, resistance): name · description · version · supported_interfaces · capabilities.extensions · default_input_modes/output_modes · skills[{id, name, description, tags, examples, input_modes, output_modes}] · security_*. Source persisted as YAML (or TOML) beside the preset's skills/, served as JSON at /.well-known/agent-card.json. No system prompt or model in the card (spec); prose stays in SKILL.md, composition in preset.yml. Ting extension URIs (ting/seat, ting/authority) carry seat identity and declared authority read-only.
  2. Workflow = Open Workflow Specification DSL 1.0 (CNCF, ex Serverless Workflow) — the deployment layer. Each step binds a card (call: http to its interface, or a catalogued use.functions seat template), a model route (a step field: the "machine type"), inputs (the workflow's input schema — what Dispatch renders; file parts by media type), authority, and a gate. Reuse: use.functions (seat and gate templates), use.catalogs (a versioned library functions/<name>/<version>/function.yaml), run.workflow (sub-workflows such as the landing gate), use.extensions (cross-cutting law before/after tasks: log every forge write, refuse a step whose authority is read-only, emit the ruling event before mutation).
  3. Executor = ting's own, Rust, deliberately small. Parse and validate the definition with the spec's own Rust SDK (serverless-workflow-core / -builders / -io, Apache-2.0, DSL 1.0.x, currently 1.0.0-alpha6, parse/validate/build only — pinned and asserted per law 9), provision what each agent step needs (card, model route, inputs as A2A parts, authority) and start it through ting-a2a's message/send on a context, evaluate gates, and emit run state (workflow/*-shaped events) that the UI renders as emitted — never a second, inferred state. No general engine: no Synapse/SonataFlow, no background scheduler beyond what a run needs, no journaling in the first cut.
  4. Code gates = OpenSpec + Datalog. A gate is an OpenSpec requirement/scenario evaluated as Datalog rules over the run's facts (forge state, session events, test results, roster claims); the executor evaluates them and exposes them to agents as callable checks, so a landing gate is a computed verdict, not a queen's narration.

Deliverables (sessions)

  • S1 Cards. Card schema for the five seats as YAML; a just/nu recipe that composes and serves the JSON card; ting extension URIs specified as an OpenSpec capability in Ting/contracts (contracts.ting.agent-card); SKILL.md and preset.yml reference the card, not the reverse.
  • S2 Definitions and catalog. The swarm and grooming workflows written in OWS DSL 1.0 with ting conventions (step metadata for model/authority, input schema with file parts); a ting catalog repo layout with functions/<seat>/<version>/function.yaml and the landing-gate sub-workflow; conventions specified as contracts.ting.workflow-definition.
  • S3 Executor. Rust crate: parse/validate → provision → start steps over ting-a2a → evaluate gates → emit run events; a --dump that proves composition (law 4) and a boot plus a route probe that proves mounting; where it runs (host plugin vs sidecar) decided in its design.
  • S4 Gates. OpenSpec→Datalog mapping (which scenario forms become which rules; fact sources), the embedded Datalog engine choice, the gate call surface for agents (tool or skill), the landing gate of the swarm charter as the first real gate.
  • S5 Console integration. Dispatch renders the workflow input schema (swarm/ting-dsh#115); run state from the executor shown as emitted (ruling 3); trajectory shows workflow/* events as rows; Focus shows the gate verdicts.

Not in scope

  • A general workflow engine (Synapse/SonataFlow parity), journaling/resume, token-budget accounting across children — DSH's own dsh-workflow limits are not this epic's to lift.
  • Any authority model inside Dispatch (ruling 2).
  • Replacing DSH's subagent tool as the queen's way to brief a member — S3 starts contexts through ting-a2a; how a step's agent is spawned inside DSH stays with the swarm charter.

Open questions (to rule)

  1. Catalog location: Ting/contracts beside the specs, or this repo.
  2. Executor placement: DSH host plugin (@ting/… bundle calling a Rust binary) vs a sidecar service with its own route.
  3. Datalog engine (Rust-embedded candidates: crepe, ascent, datafrog) and whether gates may run run.script steps or are the only code.
  4. Card source format: YAML vs TOML.
  5. Whether one card per seat or one card per preset with seats as skills — the roster wire (Member.id, role, landed) implies per-seat identity.

swarm/ting-dsh#72 (vocabulary: workflow / run), #73 (a2a-purity), #74 (swarm-workflow spec), #58, #96, #115; Ting/contracts establish-console-ux-contract deltas 868afbc; rulings 2, 3, 4, 10 in adversarial-review-2026-09-05.md.

## Why Ruling 10 (Larandar, 2026-09-06, `Ting/contracts` `openspec/changes/establish-console-ux-contract/adversarial-review-2026-09-05.md` §Rulings), reached after surveying the open formats and DSH's own primitive: DSH has no declarative workflow — `dsh-workflow` runs a model-written JavaScript script in the foreground of a session — so everything Dispatch renders and every gate a swarm passes is ting's to define. Ruling 2 makes Dispatch a pure "start a workflow" renderer of what the workflow declares; ruling 3 makes the UI faithful to emitted state only. This epic is the definition and execution layer those rulings presuppose. ## The four layers 1. **Agents = A2A Agent Cards.** One card per seat (queen, vinculum, drone, probe, resistance): `name · description · version · supported_interfaces · capabilities.extensions · default_input_modes/output_modes · skills[{id, name, description, tags, examples, input_modes, output_modes}] · security_*`. Source persisted as YAML (or TOML) beside the preset's `skills/`, served as JSON at `/.well-known/agent-card.json`. No system prompt or model in the card (spec); prose stays in `SKILL.md`, composition in `preset.yml`. Ting extension URIs (`ting/seat`, `ting/authority`) carry seat identity and declared authority read-only. 2. **Workflow = Open Workflow Specification DSL 1.0** (CNCF, ex Serverless Workflow) — the deployment layer. Each step binds a card (`call: http` to its interface, or a catalogued `use.functions` seat template), a model route (a step field: the "machine type"), inputs (the workflow's `input` schema — what Dispatch renders; file parts by media type), authority, and a gate. Reuse: `use.functions` (seat and gate templates), `use.catalogs` (a versioned library `functions/<name>/<version>/function.yaml`), `run.workflow` (sub-workflows such as the landing gate), `use.extensions` (cross-cutting law before/after tasks: log every forge write, refuse a step whose authority is read-only, emit the ruling event before mutation). 3. **Executor = ting's own, Rust, deliberately small.** Parse and validate the definition with the spec's own Rust SDK (`serverless-workflow-core` / `-builders` / `-io`, Apache-2.0, DSL 1.0.x, currently `1.0.0-alpha6`, parse/validate/build only — pinned and asserted per law 9), provision what each agent step needs (card, model route, inputs as A2A parts, authority) and start it through `ting-a2a`'s `message/send` on a context, evaluate gates, and **emit** run state (`workflow/*`-shaped events) that the UI renders as emitted — never a second, inferred state. No general engine: no Synapse/SonataFlow, no background scheduler beyond what a run needs, no journaling in the first cut. 4. **Code gates = OpenSpec + Datalog.** A gate is an OpenSpec requirement/scenario evaluated as Datalog rules over the run's facts (forge state, session events, test results, roster claims); the executor evaluates them and exposes them to agents as callable checks, so a landing gate is a computed verdict, not a queen's narration. ## Deliverables (sessions) - **S1 Cards.** Card schema for the five seats as YAML; a `just`/nu recipe that composes and serves the JSON card; ting extension URIs specified as an OpenSpec capability in `Ting/contracts` (`contracts.ting.agent-card`); `SKILL.md` and `preset.yml` reference the card, not the reverse. - **S2 Definitions and catalog.** The `swarm` and `grooming` workflows written in OWS DSL 1.0 with ting conventions (step metadata for model/authority, input schema with file parts); a `ting` catalog repo layout with `functions/<seat>/<version>/function.yaml` and the landing-gate sub-workflow; conventions specified as `contracts.ting.workflow-definition`. - **S3 Executor.** Rust crate: parse/validate → provision → start steps over `ting-a2a` → evaluate gates → emit run events; a `--dump` that proves composition (law 4) and a boot plus a route probe that proves mounting; where it runs (host plugin vs sidecar) decided in its design. - **S4 Gates.** OpenSpec→Datalog mapping (which scenario forms become which rules; fact sources), the embedded Datalog engine choice, the gate call surface for agents (tool or skill), the landing gate of the swarm charter as the first real gate. - **S5 Console integration.** Dispatch renders the workflow `input` schema (swarm/ting-dsh#115); run state from the executor shown as emitted (ruling 3); trajectory shows `workflow/*` events as rows; Focus shows the gate verdicts. ## Not in scope - A general workflow engine (Synapse/SonataFlow parity), journaling/resume, token-budget accounting across children — DSH's own `dsh-workflow` limits are not this epic's to lift. - Any authority model inside Dispatch (ruling 2). - Replacing DSH's `subagent` tool as the queen's way to brief a member — S3 starts contexts through `ting-a2a`; how a step's agent is spawned inside DSH stays with the swarm charter. ## Open questions (to rule) 1. Catalog location: `Ting/contracts` beside the specs, or this repo. 2. Executor placement: DSH host plugin (`@ting/…` bundle calling a Rust binary) vs a sidecar service with its own route. 3. Datalog engine (Rust-embedded candidates: crepe, ascent, datafrog) and whether gates may run `run.script` steps or are the only code. 4. Card source format: YAML vs TOML. 5. Whether one card per seat or one card per preset with seats as skills — the roster wire (`Member.id`, `role`, `landed`) implies per-seat identity. ## Related swarm/ting-dsh#72 (vocabulary: workflow / run), #73 (a2a-purity), #74 (swarm-workflow spec), #58, #96, #115; `Ting/contracts` `establish-console-ux-contract` deltas `868afbc`; rulings 2, 3, 4, 10 in `adversarial-review-2026-09-05.md`.
Author
Owner

Ruling — repository layout (Larandar, 2026-09-06)

Open question 1 is closed: the catalog lives here, not in Ting/contracts.

  • catalog/ — the public, reusable parts: the versioned function library (functions/<name>/<version>/function.yaml), seat and gate templates, sub-workflows such as the landing gate, and the agent cards' YAML sources.
  • executor/ — the Rust crate that is the executor (parse/validate on the spec's Rust SDK, provision, start steps over ting-a2a, evaluate gates, emit run state).
  • sandboxing/ — maybe later; reserved for whatever isolation a step's code gate or script needs.

Consequences: S1 and S2 deliver into catalog/, S3 into executor/; Ting/contracts keeps only the OpenSpec capabilities that describe them (contracts.ting.agent-card, contracts.ting.workflow-definition).

## Ruling — repository layout (Larandar, 2026-09-06) Open question 1 is closed: the catalog lives **here**, not in `Ting/contracts`. - `catalog/` — the public, reusable parts: the versioned function library (`functions/<name>/<version>/function.yaml`), seat and gate templates, sub-workflows such as the landing gate, and the agent cards' YAML sources. - `executor/` — the Rust crate that is the executor (parse/validate on the spec's Rust SDK, provision, start steps over `ting-a2a`, evaluate gates, emit run state). - `sandboxing/` — maybe later; reserved for whatever isolation a step's code gate or script needs. Consequences: S1 and S2 deliver into `catalog/`, S3 into `executor/`; `Ting/contracts` keeps only the OpenSpec capabilities that describe them (`contracts.ting.agent-card`, `contracts.ting.workflow-definition`).
Author
Owner

Ruling — card and definition source format (Larandar, 2026-09-06)

Open question 4 is closed: YAML, "since everything else is" — presets (preset.yml, *.cordis.yml), the Open Workflow Spec definitions, and now the agent cards' sources under catalog/. Cards are composed to JSON only at serve time (/.well-known/agent-card.json); no TOML anywhere in this repository.

## Ruling — card and definition source format (Larandar, 2026-09-06) Open question 4 is closed: **YAML**, "since everything else is" — presets (`preset.yml`, `*.cordis.yml`), the Open Workflow Spec definitions, and now the agent cards' sources under `catalog/`. Cards are composed to JSON only at serve time (`/.well-known/agent-card.json`); no TOML anywhere in this repository.
Author
Owner

Ruling — where cards live, and how many (Larandar, 2026-09-06)

Amends the layout ruling above (comment 17090) on one point and closes open question 5.

  • Cards are workflow-local by default. An agent card's YAML source sits beside the workflow definition that binds it (the "final workflow"), not in catalog/. A card is promoted into catalog/ only when a second workflow reuses it — the same rule the DSL applies to use.catalogs: nothing is shared until something shares it.
  • One card per seat kind, never per instance. A card is the seat's "image" (drone, probe, …); twenty running drones are twenty contexts/tasks on that one card, not twenty cards. The per-instance facts — identity (sa-<uuid>, Member.id), count, addressing — are runtime and workflow-step properties: the roster wire, the spawning step's ting/seat extension params, task_id/context_id on the shared interface, and parallel over N in the definition. The card never changes per run.
## Ruling — where cards live, and how many (Larandar, 2026-09-06) Amends the layout ruling above (comment 17090) on one point and closes open question 5. - **Cards are workflow-local by default.** An agent card's YAML source sits beside the workflow definition that binds it (the "final workflow"), not in `catalog/`. A card is promoted into `catalog/` only when a second workflow reuses it — the same rule the DSL applies to `use.catalogs`: nothing is shared until something shares it. - **One card per seat kind, never per instance.** A card is the seat's "image" (drone, probe, …); twenty running drones are twenty contexts/tasks on that one card, not twenty cards. The per-instance facts — identity (`sa-<uuid>`, `Member.id`), count, addressing — are runtime and workflow-step properties: the roster wire, the spawning step's `ting/seat` extension params, `task_id`/`context_id` on the shared interface, and `parallel` over N in the definition. The card never changes per run.
Author
Owner

Ruling — cards live in larandar/agents.lar (Larandar, 2026-09-06)

Supersedes the "where cards live" half of comment 17106; the "one card per seat kind" half stands.

  • Agent cards are defined in larandar/agents.lar, the roster. Each persona's own folder carries that persona's personal card (YAML, per the format ruling); a sibling folder holds the generic agent cards plus the preset that non-persona seats (drone, probe, …) instantiate.
  • Ting/workflows therefore holds no card sources: a workflow definition binds a card by reference (the card's id and the interface URL it is served at), and catalog/ keeps only the reusable workflow parts — seat/gate function templates and sub-workflows — none of which is a card.
  • S1 ("Cards") moves out of this epic's deliverables into agents.lar; what stays here is the reference convention a step uses to name a card, specified with contracts.ting.workflow-definition.
## Ruling — cards live in `larandar/agents.lar` (Larandar, 2026-09-06) Supersedes the "where cards live" half of comment 17106; the "one card per seat kind" half stands. - **Agent cards are defined in `larandar/agents.lar`, the roster.** Each persona's own folder carries that persona's personal card (YAML, per the format ruling); a sibling folder holds the **generic agent cards plus the preset** that non-persona seats (drone, probe, …) instantiate. - `Ting/workflows` therefore holds no card sources: a workflow definition binds a card by reference (the card's id and the interface URL it is served at), and `catalog/` keeps only the reusable workflow parts — seat/gate function templates and sub-workflows — none of which is a card. - S1 ("Cards") moves out of this epic's deliverables into `agents.lar`; what stays here is the reference convention a step uses to name a card, specified with `contracts.ting.workflow-definition`.
Author
Owner

Ruling — the sibling folder is seats/ (Larandar, 2026-09-06)

Completes comment 17107: in larandar/agents.lar, personal cards sit in agents/<persona>/, and the generic seat cards plus their preset sit in seats/ beside agents/. The card work is filed there (larandar/agents.lar#6).

## Ruling — the sibling folder is `seats/` (Larandar, 2026-09-06) Completes comment 17107: in `larandar/agents.lar`, personal cards sit in `agents/<persona>/`, and the generic seat cards plus their preset sit in **`seats/`** beside `agents/`. The card work is filed there (larandar/agents.lar#6).
Author
Owner

Ruling (Larandar, 2026-09-10, swarm/ting-dsh#115): "dispatch -> interface for the executor that will run using dsh as harness". The console'"'"'s Dispatch is the interface to this executor; the executor runs using dsh as the harness (seat sessions, tools, A2A mount). Interface the console needs from here: a catalog listing (definitions with their input schema and declared effects), a start call returning the run identity, and run state on the wire the console reads. swarm/ting-dsh#115 renders it; #27 / #32 there bind the seats.

Ruling (Larandar, 2026-09-10, swarm/ting-dsh#115): "dispatch -> interface for the executor that will run using dsh as harness". The console'"'"'s Dispatch is the interface to this executor; the executor runs using dsh as the harness (seat sessions, tools, A2A mount). Interface the console needs from here: a catalog listing (definitions with their `input` schema and declared effects), a start call returning the run identity, and run state on the wire the console reads. swarm/ting-dsh#115 renders it; #27 / #32 there bind the seats.
Author
Owner

Audit 2026-09-19/20, G34. Folded owner rulings from comments 17106-17114: cards live in larandar/agents.lar; personal cards sit under agents//; generic cards and their preset live in seats/; there is one card per seat kind, not per seat instance; and Ting/workflows holds no card sources. S1 Cards is removed as a workflows deliverable. Questions 2-3 remain the frontier: executor/catalog ownership and the remaining executor/catalog boundary. This preserves the repository layout ruling while recording the later card-source rulings.

<!-- larandar:groom:v1 --> Audit 2026-09-19/20, G34. Folded owner rulings from comments 17106-17114: cards live in larandar/agents.lar; personal cards sit under agents/<persona>/; generic cards and their preset live in seats/; there is one card per seat kind, not per seat instance; and Ting/workflows holds no card sources. S1 Cards is removed as a workflows deliverable. Questions 2-3 remain the frontier: executor/catalog ownership and the remaining executor/catalog boundary. This preserves the repository layout ruling while recording the later card-source rulings.
Sign in to join this conversation.
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Reference
Ting/workflows#1
No description provided.