relay-flow 0.2.6-alpha → 0.2.7-alpha

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -1,36 +1,160 @@
1
1
  # relay-flow
2
2
 
3
- Durable, graph-based agent workflow runner. A ticket is the unit of work; a workflow YAML declares nodes and routes; a durable engine (go-workflows + SQLite) drives progression, waits, retries, and recovery. The task system (Jira and Beads built-ins) supplies parent tickets and mailbox subtasks; the runner (Orca built-in) owns worktrees and terminals; the harness (OpenCode and Pi built-ins) owns agent sessions and report semantics. All three are pluggable.
3
+ Durable, graph-based agent workflow runner. A ticket is the unit of work; a workflow YAML declares nodes and routes; a durable executor drives progression, waits, retries, and recovery. Task systems (Jira and Beads), runners (Orca and Herdr), harnesses (OpenCode and Pi), and durable executors (go-workflows and Temporal) are selectable independently.
4
4
 
5
5
  This is a ground-up rewrite. The previous per-workflow, in-memory daemon is gone. There is no migration path and no compatibility layer.
6
6
 
7
7
  ---
8
8
 
9
- ## Setup
9
+ ## Quick start
10
10
 
11
- ### Prerequisites
11
+ ### 1. Install relay-flow
12
12
 
13
- | Tool | Why |
14
- |---|---|
15
- | [opencode](https://opencode.ai) | Agents run in opencode sessions (harness) |
16
- | [Orca](https://github.com/Necmttn/orca) CLI + app | Worktrees + terminals (runner) |
17
- | `bd` CLI | Beads task-system access (required when `taskPlugin: beads`) |
18
- | Dolt | External/server-backed Beads only |
19
- | Jira API token | Jira REST API v3 access (required when `taskPlugin: jira`) |
20
- | Go 1.24+ | Build the CLI |
13
+ Install the latest released CLI with Homebrew:
21
14
 
22
- ### Install
15
+ ```sh
16
+ brew install rajpopat27/tap/relay-flow
17
+ ```
18
+
19
+ ### 2. Install the harness extension
20
+
21
+ Choose the harness that will run your agent sessions. Both commands install the
22
+ same `relay-flow-plugin` package with host-specific entrypoints.
23
+
24
+ **OpenCode**
25
+
26
+ ```sh
27
+ opencode plugin relay-flow-plugin@0.2.7-alpha
28
+ ```
29
+
30
+ **Pi**
31
+
32
+ ```sh
33
+ pi install npm:relay-flow-plugin@0.2.7-alpha
34
+ ```
35
+
36
+ Pi loads the package's `pi.ts` extension from its manifest. Do not add
37
+ `-e`/`--extension` to relay-flow's Pi launch command.
38
+
39
+ ### 3. Initialize relay-flow
40
+
41
+ Choose one task system, runner, harness, and durable executor. This example
42
+ uses Jira, Orca, OpenCode, and the default embedded executor:
23
43
 
24
44
  ```sh
25
- go install github.com/rajpopat27/relay-flow/cmd/relay-flow@latest
45
+ relay-flow init \
46
+ --task-plugin jira \
47
+ --runner-plugin orca \
48
+ --harness-plugin opencode
26
49
  ```
27
50
 
51
+ The default executor is `goworkflows` with SQLite. To use Temporal instead,
52
+ add `--executor-plugin temporal`, `--temporal-address <host:port>`, and
53
+ `--temporal-namespace <name>` to the command.
54
+
55
+ ### 4. Authenticate the task system
56
+
57
+ For Jira, authenticate the selected task plugin:
58
+
59
+ ```sh
60
+ relay-flow task auth
61
+ ```
62
+
63
+ For Beads, skip this command and initialize/authenticate the Beads workspace
64
+ with `bd` and, when needed, Dolt. See [Beads task system](#beads-task-system)
65
+ below.
66
+
67
+ ### 5. Start the server
68
+
69
+ ```sh
70
+ relay-flow serve --background
71
+ ```
72
+
73
+ ### 6. Register a repository
74
+
75
+ The repository must already exist in the selected runner. For Orca:
76
+
77
+ ```sh
78
+ orca repo add --path /work/payments
79
+ relay-flow repo register
80
+ ```
81
+
82
+ For Herdr, register the repository path directly; relay-flow creates ticket
83
+ worktrees lazily. The interactive registration asks for the task-system values
84
+ required by the selected task plugin.
85
+
86
+ ### 7. Submit a workflow
87
+
88
+ ```sh
89
+ relay-flow workflow submit --file examples/minimal-jira-task-workflow.yaml
90
+ relay-flow workflow list
91
+ ```
92
+
93
+ Replace the example workflow with
94
+ `examples/minimal-beads-task-workflow.yaml` when using Beads. The workflow's
95
+ `repos` value must match the name used during repository registration.
96
+
97
+ ## Supported plugins
98
+
99
+ Each category is a replaceable boundary. Select one plugin from each category
100
+ at initialization; the workflow YAML and core orchestration do not change when
101
+ you switch an implementation.
102
+
103
+ | Category | Supported plugins | Owns |
104
+ |---|---|---|
105
+ | Task system | `jira`, `beads` | Parent tickets, mailbox subtasks, task state, labels, comments, and task configuration |
106
+ | Runner | `orca`, `herdr` | Ticket worktrees, environments, terminals, process liveness, and cleanup |
107
+ | Harness | `opencode`, `pi` | Agent launch commands, sessions, prompts, report parsing, nudges, and resume behavior |
108
+ | Durable executor | `goworkflows`, `temporal` | Graph progression, waits, retries, recovery, and durable execution state |
109
+
110
+ The default durable executor is `goworkflows`, which stores execution state in
111
+ SQLite. `temporal` uses an external Temporal server and is selected with the
112
+ Temporal address and namespace during `init`.
113
+
114
+ The plugin composition is explicit:
115
+
116
+ ```text
117
+ Task system (Jira or Beads)
118
+
119
+
120
+ Durable executor (go-workflows or Temporal)
121
+
122
+
123
+ Runner (Orca or Herdr)
124
+
125
+
126
+ Harness (OpenCode or Pi)
127
+
128
+
129
+ relay-flow report transport
130
+ ```
131
+
132
+ The equivalent non-interactive selection is:
133
+
134
+ ```sh
135
+ relay-flow init \
136
+ --task-plugin <jira|beads> \
137
+ --runner-plugin <orca|herdr> \
138
+ --harness-plugin <opencode|pi> \
139
+ --executor-plugin <goworkflows|temporal>
140
+ ```
141
+
142
+ `--executor-plugin` defaults to `goworkflows`. Jira requires Jira credentials;
143
+ Beads requires the `bd` CLI and a configured workspace. Orca requires its CLI
144
+ and app; Herdr requires its CLI/server. OpenCode and Pi each require their
145
+ corresponding agent runtime. These integrations remain behind their small
146
+ contracts, so task-system fields do not leak into runners or harnesses.
147
+
148
+ ## Detailed setup
149
+
150
+ ### Harness configuration
151
+
28
152
  OpenCode plugin configuration uses both entrypoints. The server entrypoint is listed in `opencode.json`:
29
153
 
30
154
  ```json
31
155
  {
32
156
  "$schema": "https://opencode.ai/config.json",
33
- "plugin": ["relay-flow-plugin"]
157
+ "plugin": ["relay-flow-plugin@0.2.7-alpha"]
34
158
  }
35
159
  ```
36
160
 
@@ -39,7 +163,7 @@ The native HITL approval entrypoint is listed in `.opencode/tui.json`:
39
163
  ```json
40
164
  {
41
165
  "$schema": "https://opencode.ai/tui.json",
42
- "plugin": ["relay-flow-plugin"]
166
+ "plugin": ["relay-flow-plugin@0.2.7-alpha"]
43
167
  }
44
168
  ```
45
169
 
@@ -55,7 +179,7 @@ Pi plugin: install the same published package manually in Pi's global package
55
179
  settings before starting a Pi harness session:
56
180
 
57
181
  ```sh
58
- pi install npm:relay-flow-plugin@<version>
182
+ pi install npm:relay-flow-plugin@0.2.7-alpha
59
183
  ```
60
184
 
61
185
  Relay-flow does not install or configure the package automatically. Pi resolves
@@ -71,14 +195,14 @@ structured report, applies the agent/HITL nudge policy, and delivers
71
195
  `reportId` comes from the harness session/message identity; `nodeVisitID` is
72
196
  internal and is never part of either plugin payload.
73
197
 
74
- ### One-time machine setup
198
+ ### Machine setup details
75
199
 
76
200
  ```sh
77
201
  relay-flow init
78
202
  relay-flow task auth
79
203
  ```
80
204
 
81
- `init` only selects the task system, runner, and harness (singleton options are automatic), writes machine config, and initializes SQLite. `task auth` delegates authentication to that selected task plug-in. Jira prompts for its site, email, and masked API token, validates `/myself`, and owns the system-wide `credentials.yaml`; for scripts, pass `task auth --site`, `--email`, and `--token`. A normal init rerun refuses existing state. `relay-flow init --force` updates safe stopped instances while preserving durable and repo state.
205
+ `init` selects the task system, runner, harness, and durable executor (singleton options are automatic), writes machine config, and initializes the selected execution backend. `task auth` delegates authentication to that selected task plug-in. Jira prompts for its site, email, and masked API token, validates `/myself`, and owns the system-wide `credentials.yaml`; for scripts, pass `task auth --site`, `--email`, and `--token`. A normal init rerun refuses existing state. `relay-flow init --force` updates safe stopped instances while preserving durable and repo state.
82
206
 
83
207
  For Beads, select the plugin explicitly when scripting setup:
84
208
 
@@ -135,7 +259,7 @@ Shows a multi-select titled `Select repositories`; use Space to select Orca repo
135
259
 
136
260
  Each Jira poll uses REST v3 enhanced search and requests linked-issue status with the candidate fields. Tickets with any unfinished inward `Blocks` issue are filtered before routing; no per-ticket blocker lookup is made.
137
261
 
138
- For scripts, use `relay-flow repo register --name <name> --path <path> --set project=<project>`. Component is always derived from `--name` and cannot be overridden. Registration is rejected while another repo already holds the same canonical task scope.
262
+ For scripted Jira registration, use `relay-flow repo register --name <name> --path <path> --set project=<project>`. Component is always derived from `--name` and cannot be overridden. Registration is rejected while another repo already holds the same canonical task scope.
139
263
 
140
264
  ### Beads task system
141
265
 
@@ -229,10 +353,7 @@ Workflows live at `~/.relay-flow/workflows/<name>.yaml` after submit. Replacemen
229
353
 
230
354
  Use [`examples/config-reference.yaml`](examples/config-reference.yaml) for the complete machine configuration, [`examples/workflow-reference.yaml`](examples/workflow-reference.yaml) for the complete workflow schema, or the provider-specific minimal workflows [`examples/minimal-jira-task-workflow.yaml`](examples/minimal-jira-task-workflow.yaml) and [`examples/minimal-beads-task-workflow.yaml`](examples/minimal-beads-task-workflow.yaml). Runtime node agents should follow [`docs/agent-instructions.md`](docs/agent-instructions.md). The existing [`examples/default-story-workflow.yaml`](examples/default-story-workflow.yaml) remains a more detailed Jira Story example, while [`examples/beads-workflow.yaml`](examples/beads-workflow.yaml) shows the Beads lifecycle shape. Replace the repo name and uncomment only the optional fields you need.
231
355
 
232
- Task, runner, and harness plugins are selected machine-wide. A single relay-flow
233
- configuration cannot run Jira and Beads simultaneously; use separate
234
- `RELAY_FLOW_HOME` directories or machine configurations when both providers are
235
- needed.
356
+ Task, runner, harness, and durable executor plugins are selected machine-wide. A single relay-flow configuration cannot run Jira and Beads simultaneously; use separate `RELAY_FLOW_HOME` directories or machine configurations when both providers are needed.
236
357
 
237
358
  ### Run
238
359
 
@@ -262,6 +383,8 @@ cleanupRunnerOnEnd: false # optional; when true the runner tears down at
262
383
  taskConfig: # optional; adapter-owned; merged root → repo → workflow → node
263
384
  filters:
264
385
  parentStatuses: [To Do]
386
+ labels: ["workflow:true"]
387
+ assignees: ["currentUser()"] # Jira resolves this to the authenticated email.
265
388
 
266
389
  nodes:
267
390
  start:
@@ -271,20 +394,43 @@ nodes:
271
394
  onSuccess: [{ target: coding }]
272
395
 
273
396
  coding:
274
- type: agent # or hitl
275
- agent: build # opencode agent
397
+ type: agent
398
+ agent: build
276
399
  description: | # becomes the mailbox description and launch prompt
277
- Implement the ticket.
400
+ Implement the ticket in the current worktree.
401
+ nudgePrompt: |
402
+ Continue working on {{ticket}}. Read the parent {{taskSystem}} ticket
403
+ {{ticket}} and your assigned ticket {{mailbox}} to understand the requirements. Read
404
+ the latest feedback, address the requested changes, and work on the next
405
+ bounded task slice. Return the complete report. Valid choices are:
406
+ {{nextSteps}}.
278
407
  onSuccess: [{ target: reviewing, when: "work complete" }]
279
408
  onFailure: [{ target: coding, when: "retry" }]
280
- nudgePrompt: "Check edge cases for {{ticket}} before reporting." # optional custom instructions
281
409
 
282
410
  reviewing:
411
+ type: agent
412
+ agent: plan
413
+ description: Review the completed implementation and report required changes.
414
+ nudgePrompt: |
415
+ Review {{ticket}}. Read the parent {{taskSystem}} ticket {{ticket}} and
416
+ your assigned ticket {{mailbox}} to understand the requirements. Re-check the
417
+ implementation and latest coding feedback, then return the complete
418
+ report. Valid choices are:
419
+ {{nextSteps}}.
420
+ onSuccess: [{ target: humanReview, when: "ready for human review" }]
421
+ onFailure: [{ target: coding, when: "changes required" }]
422
+
423
+ humanReview:
283
424
  type: hitl
284
- agent: build
285
- description: Human review.
286
- onSuccess: [{ target: end }]
287
- onFailure: [{ target: coding }]
425
+ agent: plan
426
+ description: Approve the reviewed implementation or request changes.
427
+ nudgePrompt: |
428
+ Review the completed work for {{ticket}} with the human. Read the parent
429
+ {{taskSystem}} ticket {{ticket}} and your assigned ticket {{mailbox}} to
430
+ understand the requirements. Return the complete report. Valid choices are:
431
+ {{nextSteps}}.
432
+ onSuccess: [{ target: end, when: "approved" }]
433
+ onFailure: [{ target: coding, when: "changes requested" }]
288
434
 
289
435
  end: {}
290
436
  ```
@@ -468,7 +614,7 @@ tickets are not reopened automatically.
468
614
  ## Architecture
469
615
 
470
616
  - **Task system** owns parent tickets, mailbox subtasks, task state, labels, comments, and adapter config. The parent ticket is the unit of work.
471
- - **Durable workflow engine** (go-workflows + SQLite) owns graph progression, waits, reports, retries, and recovery. No custom state machine.
617
+ - **Durable workflow engine** (`goworkflows` + SQLite or `temporal`) owns graph progression, waits, reports, retries, and recovery. No custom state machine.
472
618
  - **Mailbox subtask** is one agent/HITL node's scratch space; its description defines the node's work and its comments hold the node's summary plus selected incoming feedback.
473
619
  - **Harness** owns agent launch, session/report behavior, parsing, nudging, and resume semantics.
474
620
  - **Runner** owns ticket worktrees/environments, terminals, liveness, and execution of harness commands.
@@ -11,10 +11,11 @@ taskConfig:
11
11
  - To Do
12
12
  issueTypes:
13
13
  - Story
14
- # labels:
15
- # - coding
16
- # assignees:
17
- # - owner@example.com
14
+ labels:
15
+ - "workflow:true"
16
+ assignees:
17
+ - currentUser()
18
+ # Jira resolves currentUser() to the authenticated Jira email.
18
19
  # assignee: default-node-owner@example.com
19
20
  # project: PAY
20
21
  # component: api
@@ -28,48 +29,62 @@ nodes:
28
29
  transitionTo:
29
30
  parentStatus: In Progress
30
31
  onSuccess:
31
- - target: implement
32
+ - target: coding
32
33
  when: The parent story is ready for implementation
33
34
 
34
- implement:
35
+ coding:
35
36
  type: agent
36
37
  agent: build
37
- description: Implement the parent story and verify the changes.
38
- # nudgePrompt: "Finish {{node}} for {{ticket}} and choose one of: {{nextSteps}}"
38
+ description: Implement the parent story in the current ticket worktree.
39
+ nudgePrompt: |
40
+ Continue working on {{ticket}}. Read the parent {{taskSystem}} ticket
41
+ {{ticket}} and your assigned ticket {{mailbox}} to understand the requirements. Read
42
+ the latest feedback, address the requested changes, and work on the next
43
+ bounded task slice. Return the complete report. Valid choices are:
44
+ {{nextSteps}}.
39
45
  taskConfig:
40
46
  # assignee: developer@example.com
41
47
  transitionTo:
42
48
  taskStatus: In Progress
43
49
  # parentStatus: In Progress
44
50
  onSuccess:
45
- - target: review
51
+ - target: reviewing
46
52
  when: Implementation and verification are complete
47
53
  onFailure:
48
- - target: implement
54
+ - target: coding
49
55
  when: Implementation needs another pass
50
56
 
51
- review:
57
+ reviewing:
52
58
  type: agent
53
59
  agent: plan
54
- description: Review the implementation for correctness, regressions, and missing tests.
55
- # nudgePrompt: "Complete the review for {{ticket}}. Valid routes: {{nextSteps}}"
60
+ description: Review the completed implementation and report required changes.
61
+ nudgePrompt: |
62
+ Review {{ticket}}. Read the parent {{taskSystem}} ticket {{ticket}} and
63
+ your assigned ticket {{mailbox}} to understand the requirements. Re-check the
64
+ implementation and latest coding feedback, then return the complete
65
+ report. Valid choices are:
66
+ {{nextSteps}}.
56
67
  taskConfig:
57
68
  # assignee: reviewer@example.com
58
69
  transitionTo:
59
70
  taskStatus: In Progress
60
71
  # parentStatus: In Review
61
72
  onSuccess:
62
- - target: prReview
73
+ - target: humanReview
63
74
  when: The changes are ready for human approval
64
75
  onFailure:
65
- - target: implement
76
+ - target: coding
66
77
  when: Code changes are required
67
78
 
68
- prReview:
79
+ humanReview:
69
80
  type: hitl
70
81
  agent: plan
71
- description: Discuss the pull request with the human and obtain approval.
72
- # nudgePrompt: "Review {{ticket}} with the human. Valid routes: {{nextSteps}}"
82
+ description: Approve the reviewed implementation or request changes.
83
+ nudgePrompt: |
84
+ Review the completed work for {{ticket}} with the human. Read the parent
85
+ {{taskSystem}} ticket {{ticket}} and your assigned ticket {{mailbox}} to
86
+ understand the requirements. Return the complete report. Valid choices are:
87
+ {{nextSteps}}.
73
88
  taskConfig:
74
89
  # assignee: human-reviewer@example.com
75
90
  transitionTo:
@@ -79,7 +94,7 @@ nodes:
79
94
  - target: end
80
95
  when: The human approves the review
81
96
  onFailure:
82
- - target: implement
97
+ - target: coding
83
98
  when: The human requests code changes
84
99
 
85
100
  end:
@@ -14,7 +14,7 @@ import (
14
14
  "github.com/rajpopat27/relay-flow/internal/workflow"
15
15
  )
16
16
 
17
- const configuredPlugin = "relay-flow-plugin@0.2.6-alpha"
17
+ const configuredPlugin = "relay-flow-plugin@0.2.7-alpha"
18
18
 
19
19
  func TestBuildCommandArgv(t *testing.T) {
20
20
  t.Setenv("RELAY_FLOW_HOME", "/var/lib/relay-flow-test")
@@ -10,7 +10,7 @@ import (
10
10
  "github.com/rajpopat27/relay-flow/internal/config"
11
11
  )
12
12
 
13
- const relayFlowPlugin = "relay-flow-plugin@0.2.6-alpha"
13
+ const relayFlowPlugin = "relay-flow-plugin@0.2.7-alpha"
14
14
 
15
15
  type jsoncToken struct {
16
16
  kind byte
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "relay-flow",
3
- "version": "0.2.6-alpha",
3
+ "version": "0.2.7-alpha",
4
4
  "description": "Graph-based agent workflow engine — tracker-agnostic, pluggable runners",
5
5
  "bin": {
6
6
  "relay-flow": "./bin/relay-flow.js",