relay-flow 0.2.0-alpha → 0.2.2-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 +171 -26
- package/cmd/relay-flow/beads_composition_test.go +451 -0
- package/cmd/relay-flow/commands_test.go +593 -15
- package/cmd/relay-flow/main.go +356 -119
- package/cmd/relay-flow/scenario_test.go +246 -35
- package/cmd/relay-flow/serve.go +5 -2
- package/examples/beads-workflow.yaml +74 -0
- package/examples/default-story-workflow.yaml +88 -0
- package/go.mod +2 -1
- package/go.sum +2 -0
- package/internal/config/config.go +13 -2
- package/internal/config/merge_test.go +18 -0
- package/internal/execution/goworkflows/activities.go +136 -87
- package/internal/execution/goworkflows/end_feedback_test.go +124 -0
- package/internal/execution/goworkflows/engine.go +41 -8
- package/internal/execution/goworkflows/engine_test.go +100 -22
- package/internal/execution/goworkflows/fakes_test.go +63 -25
- package/internal/execution/goworkflows/interpreter.go +45 -30
- package/internal/execution/goworkflows/mailbox_test.go +85 -0
- package/internal/execution/goworkflows/node_runtime_integration_test.go +12 -6
- package/internal/execution/goworkflows/node_runtime_test.go +72 -23
- package/internal/execution/goworkflows/recovery_test.go +7 -7
- package/internal/execution/goworkflows/report_contract_fixture_test.go +31 -0
- package/internal/execution/goworkflows/retry_log_test.go +11 -11
- package/internal/harness/contract_test.go +15 -0
- package/internal/harness/factory.go +25 -3
- package/internal/harness/harness.go +30 -4
- package/internal/harness/opencode/opencode.go +125 -10
- package/internal/harness/opencode/opencode_test.go +183 -0
- package/internal/harness/opencode/repo_setup.go +361 -0
- package/internal/harness/plugin_selection_test.go +5 -5
- package/internal/paths/paths.go +18 -16
- package/internal/recover/recover.go +11 -6
- package/internal/repo/repo.go +13 -0
- package/internal/repo/service.go +10 -0
- package/internal/repo/service_test.go +55 -6
- package/internal/router/router.go +3 -2
- package/internal/router/router_test.go +87 -0
- package/internal/run/manager.go +14 -1
- package/internal/run/run.go +6 -4
- package/internal/run/run_manager_test.go +21 -1
- package/internal/runner/contract_test.go +64 -26
- package/internal/runner/orca/orca.go +30 -54
- package/internal/runner/orca/orca_test.go +143 -4
- package/internal/runner/orca/orcacli/orcacli.go +5 -0
- package/internal/runner/orca/orcacli/orcacli_test.go +3 -0
- package/internal/runner/orca/orcacli/testdata/strict-orca.sh +2 -0
- package/internal/runner/runner.go +15 -8
- package/internal/task/auth_test.go +48 -0
- package/internal/task/beads/bdcli/bdcli.go +323 -0
- package/internal/task/beads/bdcli/bdcli_test.go +297 -0
- package/internal/task/beads/bdcli/testdata/array.json +1 -0
- package/internal/task/beads/bdcli/testdata/children.json +1 -0
- package/internal/task/beads/bdcli/testdata/claimed.json +1 -0
- package/internal/task/beads/bdcli/testdata/commented.json +1 -0
- package/internal/task/beads/bdcli/testdata/comments.json +1 -0
- package/internal/task/beads/bdcli/testdata/created.json +1 -0
- package/internal/task/beads/bdcli/testdata/object.json +1 -0
- package/internal/task/beads/bdcli/testdata/ready.json +1 -0
- package/internal/task/beads/bdcli/testdata/show.json +1 -0
- package/internal/task/beads/bdcli/testdata/strict-bd.sh +149 -0
- package/internal/task/beads/bdcli/testdata/updated.json +1 -0
- package/internal/task/beads/beads.go +840 -0
- package/internal/task/beads/beads_test.go +609 -0
- package/internal/task/beads/comments_test.go +242 -0
- package/internal/task/beads/config_compatibility_test.go +163 -0
- package/internal/task/beads/lifecycle_inheritance_test.go +168 -0
- package/internal/task/beads/repo_composition_test.go +232 -0
- package/internal/task/beads/runtime_config_test.go +81 -0
- package/internal/task/beads/status_compatibility_test.go +233 -0
- package/internal/task/beads/status_test.go +257 -0
- package/internal/task/beads/testdata/strict-bd-repo.sh +27 -0
- package/internal/task/beads/validation_test.go +110 -0
- package/internal/task/contract_test.go +12 -0
- package/internal/task/factory.go +52 -3
- package/internal/task/jira/auth.go +209 -0
- package/internal/task/jira/auth_test.go +160 -0
- package/internal/task/jira/effects_test.go +39 -0
- package/internal/task/jira/filters_test.go +96 -16
- package/internal/task/jira/helpers_test.go +29 -19
- package/internal/task/jira/jira.go +263 -90
- package/internal/task/jira/lifecycle_inheritance_test.go +172 -0
- package/internal/task/jira/normalize.go +32 -14
- package/internal/task/jira/rest/adf.go +165 -0
- package/internal/task/jira/rest/adf_test.go +60 -0
- package/internal/task/jira/rest/client.go +573 -0
- package/internal/task/jira/rest/client_test.go +381 -0
- package/internal/task/jira/templates_test.go +118 -0
- package/internal/task/jira/transition_defaults_test.go +22 -18
- package/internal/task/jira/validation_test.go +1 -1
- package/internal/task/task.go +32 -0
- package/internal/workflow/report_test.go +45 -0
- package/internal/workflow/workflow.go +9 -6
- package/internal/workflow/workflow_test.go +14 -12
- package/package.json +2 -1
- package/internal/task/jira/acli/acli.go +0 -306
- package/internal/task/jira/acli/acli_test.go +0 -208
- package/internal/task/jira/acli/testdata/acli_comments.json +0 -55
- package/internal/task/jira/acli/testdata/search_invalid_assignee.txt +0 -1
- package/internal/task/jira/acli/testdata/search_invalid_status.txt +0 -1
- /package/internal/task/{jira/acli/testdata/search_success.json → beads/bdcli/testdata/empty.json} +0 -0
- /package/internal/task/jira/testdata/{acli_search.json → jira_search_issues.json} +0 -0
package/README.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
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 built-
|
|
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 built-in) owns agent sessions and report semantics. All three are pluggable.
|
|
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
|
|
|
@@ -14,7 +14,9 @@ This is a ground-up rewrite. The previous per-workflow, in-memory daemon is gone
|
|
|
14
14
|
|---|---|
|
|
15
15
|
| [opencode](https://opencode.ai) | Agents run in opencode sessions (harness) |
|
|
16
16
|
| [Orca](https://github.com/Necmttn/orca) CLI + app | Worktrees + terminals (runner) |
|
|
17
|
-
|
|
|
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`) |
|
|
18
20
|
| Go 1.24+ | Build the CLI |
|
|
19
21
|
|
|
20
22
|
### Install
|
|
@@ -32,20 +34,30 @@ OpenCode plugin: add `"relay-flow-plugin"` to the `plugin` array in your repo's
|
|
|
32
34
|
}
|
|
33
35
|
```
|
|
34
36
|
|
|
35
|
-
The plugin is the report-path half of the harness contract: it parses the agent's structured report, applies the agent/HITL nudge policy, and delivers `{runId, node, reportId, report}` via `relay-flow report` with retry.
|
|
37
|
+
The plugin is the report-path half of the harness contract: it registers each emitted harness session with `{runId, node, sessionId}`, parses the agent's structured report, applies the agent/HITL nudge policy, and delivers `{runId, node, reportId, report}` via `relay-flow report` with retry. `reportId` comes from the harness session/message identity; `nodeVisitID` is internal and is never part of either plugin payload.
|
|
36
38
|
|
|
37
39
|
### One-time machine setup
|
|
38
40
|
|
|
39
41
|
```sh
|
|
40
42
|
relay-flow init
|
|
43
|
+
relay-flow task auth
|
|
41
44
|
```
|
|
42
45
|
|
|
43
|
-
|
|
46
|
+
`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.
|
|
47
|
+
|
|
48
|
+
For Beads, select the plugin explicitly when scripting setup:
|
|
49
|
+
|
|
50
|
+
```sh
|
|
51
|
+
relay-flow init --task-plugin beads --runner-plugin orca --harness-plugin opencode
|
|
52
|
+
```
|
|
53
|
+
|
|
54
|
+
Beads authentication is owned by the Beads workspace and its `bd`/Dolt configuration. `relay-flow task auth` is a no-op for Beads and does not create relay-flow credentials; do not add a Jira token to a Beads-only installation.
|
|
44
55
|
|
|
45
56
|
The full machine layout is fixed under `~/.relay-flow` (0700):
|
|
46
57
|
|
|
47
58
|
```
|
|
48
59
|
config.yaml 0600 machine config
|
|
60
|
+
credentials.yaml 0600 selected task plug-in credentials
|
|
49
61
|
state.db 0600 durable execution (SQLite)
|
|
50
62
|
server.sock 0600 CLI ↔ server
|
|
51
63
|
server.lock 0600 single-process flock
|
|
@@ -56,11 +68,104 @@ workflows/<name>.yaml 0644 submitted workflow definitions
|
|
|
56
68
|
|
|
57
69
|
### Register a repo
|
|
58
70
|
|
|
71
|
+
`repo register` and `workflow submit` are server-backed commands: start the
|
|
72
|
+
server first, otherwise they fail with `dial unix ~/.relay-flow/server.sock:
|
|
73
|
+
connect: no such file or directory`.
|
|
74
|
+
|
|
75
|
+
```sh
|
|
76
|
+
relay-flow serve --background
|
|
77
|
+
```
|
|
78
|
+
|
|
79
|
+
The repo must already exist in the runner. For the Orca runner, add it first
|
|
80
|
+
and keep the names aligned — the runner resolves a repo by path **and** display
|
|
81
|
+
name, so `--name` must equal the Orca display name (Orca derives it from the
|
|
82
|
+
directory name):
|
|
83
|
+
|
|
84
|
+
```sh
|
|
85
|
+
orca repo add --path /work/payments # displayName becomes "payments"
|
|
86
|
+
```
|
|
87
|
+
|
|
59
88
|
```sh
|
|
60
89
|
relay-flow repo register
|
|
61
90
|
```
|
|
62
91
|
|
|
63
|
-
|
|
92
|
+
Shows a multi-select titled `Select repositories`; use Space to select Orca repos and Enter to confirm. Enter the Jira project once. Each repo is registered sequentially with its Orca name/path and a Jira component derived from that repo name. Earlier registrations remain if a later one fails.
|
|
93
|
+
|
|
94
|
+
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.
|
|
95
|
+
|
|
96
|
+
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.
|
|
97
|
+
|
|
98
|
+
### Beads task system
|
|
99
|
+
|
|
100
|
+
Beads uses the local `bd` CLI and supports both an embedded workspace and a workspace backed by an externally managed Dolt server. Install and verify the tools before registering a Beads repo:
|
|
101
|
+
|
|
102
|
+
```sh
|
|
103
|
+
bd --version
|
|
104
|
+
# Required only for server-backed workspaces:
|
|
105
|
+
dolt version
|
|
106
|
+
```
|
|
107
|
+
|
|
108
|
+
Initialize the Beads workspace before `repo register`; relay-flow never initializes a workspace, runs migrations, or starts `bd serve`.
|
|
109
|
+
|
|
110
|
+
For a local workspace, keep the workspace beside the code repository and use its `.beads` directory as `beadsDir`:
|
|
111
|
+
|
|
112
|
+
```sh
|
|
113
|
+
cd /work/payments
|
|
114
|
+
bd init --prefix payments
|
|
115
|
+
# code repository: /work/payments
|
|
116
|
+
# Beads workspace: /work/payments/.beads
|
|
117
|
+
```
|
|
118
|
+
|
|
119
|
+
For a server-backed workspace, an operator starts and manages Dolt separately, then initializes Beads with external-server metadata. The exact server host, port, credentials, and data directory belong to that Beads/Dolt deployment; relay-flow does not manage their lifecycle:
|
|
120
|
+
|
|
121
|
+
```sh
|
|
122
|
+
# Run this from the externally managed Beads/Dolt environment, not from relay-flow.
|
|
123
|
+
BEADS_DOLT_SERVER_TLS=0 \
|
|
124
|
+
BEADS_DOLT_PASSWORD= \
|
|
125
|
+
bd init \
|
|
126
|
+
--server \
|
|
127
|
+
--external \
|
|
128
|
+
--server-host 127.0.0.1 \
|
|
129
|
+
--server-port 13307 \
|
|
130
|
+
--server-user root \
|
|
131
|
+
--prefix payments \
|
|
132
|
+
--non-interactive \
|
|
133
|
+
--skip-hooks \
|
|
134
|
+
--skip-agents
|
|
135
|
+
# Example external workspace: /var/lib/beads/payments/.beads
|
|
136
|
+
```
|
|
137
|
+
|
|
138
|
+
Register the code repository and its Beads workspace separately. `beadsDir` is required for every Beads repo, must name an existing directory, and is the task scope used to reject duplicate workspace registration:
|
|
139
|
+
|
|
140
|
+
```sh
|
|
141
|
+
# Local/embedded workspace
|
|
142
|
+
relay-flow repo register \
|
|
143
|
+
--name payments \
|
|
144
|
+
--path /work/payments \
|
|
145
|
+
--set beadsDir=/work/payments/.beads
|
|
146
|
+
|
|
147
|
+
# External/server-backed workspace
|
|
148
|
+
relay-flow repo register \
|
|
149
|
+
--name payments \
|
|
150
|
+
--path /work/payments \
|
|
151
|
+
--set beadsDir=/var/lib/beads/payments/.beads
|
|
152
|
+
```
|
|
153
|
+
|
|
154
|
+
The registered `--path` remains the code/runner repository. Every `bd` command runs with that path as its working directory and the configured `beadsDir` as `BEADS_DIR`, even when unrelated Beads selector variables exist in the relay-flow environment. Two repos may register different canonical `beadsDir` values; a second repo pointing at the same workspace is rejected. A Beads prefix such as `payments-...` is optional and only makes issue IDs recognizable—it is not a component, workspace selector, poller selector, or database isolation mechanism.
|
|
155
|
+
|
|
156
|
+
Beads workflow filters are structured and evaluated in relay-flow. For example, `examples/beads-workflow.yaml` uses the Beads status and issue-type fields:
|
|
157
|
+
|
|
158
|
+
```yaml
|
|
159
|
+
taskConfig:
|
|
160
|
+
filters:
|
|
161
|
+
parentStatuses: [open]
|
|
162
|
+
issueTypes: [epic]
|
|
163
|
+
labels: [relay-ready]
|
|
164
|
+
```
|
|
165
|
+
|
|
166
|
+
The supported Beads status names are `open`, `in_progress`, `blocked`, `deferred`, `hooked`, and `closed`. The claimed-parent poll uses the canonical active set `open,in_progress,blocked,deferred`; it intentionally does not substitute `hooked` for `deferred`. Omitted lifecycle settings move the parent to `in_progress` at `start`, a work-node mailbox to `in_progress`, and the parent to `closed` at `end` — the same shape as Jira, with Beads-native values. Relay-flow creates one Repo Poller per registered repo, not one poller per workflow. Each poll reads ready top-level parents and relay-owned active parents, deduplicates them, and never routes mailbox children. Claims are permanent `wf:<workflow>` labels.
|
|
167
|
+
|
|
168
|
+
Beads does not need relay-flow credentials or a Beads-specific poller. In server mode, leave Dolt and Beads server setup running outside relay-flow and point each repo at its own `beadsDir`.
|
|
64
169
|
|
|
65
170
|
### Submit a workflow
|
|
66
171
|
|
|
@@ -70,14 +175,22 @@ relay-flow workflow submit --file <path>
|
|
|
70
175
|
|
|
71
176
|
Workflows live at `~/.relay-flow/workflows/<name>.yaml` after submit. Replacement and removal are rejected while any run of that workflow is active.
|
|
72
177
|
|
|
178
|
+
Use [`examples/default-story-workflow.yaml`](examples/default-story-workflow.yaml) as a fully annotated Jira-oriented starting point, or [`examples/beads-workflow.yaml`](examples/beads-workflow.yaml) for the Beads filter and lifecycle shape. Replace the repo name and uncomment only the optional fields you need.
|
|
179
|
+
|
|
73
180
|
### Run
|
|
74
181
|
|
|
182
|
+
The server must already be running for `repo register` and `workflow submit`;
|
|
183
|
+
the same process polls repos and drives runs.
|
|
184
|
+
|
|
75
185
|
```sh
|
|
76
186
|
relay-flow serve # normal start; requires an initialized database
|
|
187
|
+
relay-flow serve --background # detached; returns after the server is ready
|
|
77
188
|
relay-flow serve --recover # explicit destructive rebuild from the task system
|
|
78
189
|
relay-flow stop
|
|
79
190
|
```
|
|
80
191
|
|
|
192
|
+
`--background` preserves `--debug` and `--recover`, logs to `~/.relay-flow/server.log`, and remains stoppable with `relay-flow stop`. Plain `serve` remains foreground and blocking.
|
|
193
|
+
|
|
81
194
|
`serve --recover` treats ALL SQLite execution state as gone, closes surviving run-owned terminals (preserving worktrees and code), resets Jira parent+mailbox state, and starts every labeled parent in a fresh deterministic run from `start` with fresh `nodeVisitID`s. Recovery never runs automatically; database loss is never inferred.
|
|
82
195
|
|
|
83
196
|
---
|
|
@@ -90,13 +203,14 @@ repos: [payments] # one or more registered repos, unique
|
|
|
90
203
|
cleanupRunnerOnEnd: false # optional; when true the runner tears down at end
|
|
91
204
|
|
|
92
205
|
taskConfig: # optional; adapter-owned; merged root → repo → workflow → node
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
work: { mailbox: "In Progress" }
|
|
96
|
-
end: { parent: "Done" }
|
|
206
|
+
filters:
|
|
207
|
+
parentStatuses: [To Do]
|
|
97
208
|
|
|
98
209
|
nodes:
|
|
99
210
|
start:
|
|
211
|
+
taskConfig: # transitionTo belongs on a node: it applies to
|
|
212
|
+
transitionTo: # the lifecycle point the node represents
|
|
213
|
+
parentStatus: In Progress
|
|
100
214
|
onSuccess: [{ target: coding }]
|
|
101
215
|
|
|
102
216
|
coding:
|
|
@@ -129,7 +243,9 @@ Rules enforced at submit:
|
|
|
129
243
|
|
|
130
244
|
### Task-config merge
|
|
131
245
|
|
|
132
|
-
`taskConfig` may appear at root, repo, workflow, and node scopes. The adapter merges in that order: maps merge recursively, later scalar/list replaces, omitted keys inherit, explicit YAML `null` is rejected. The merged values decode against one adapter-owned typed config at use time.
|
|
246
|
+
`taskConfig` may appear at root, repo, workflow, and node scopes. The adapter merges in that order: maps merge recursively, later scalar/list replaces, omitted keys inherit, explicit YAML `null` is rejected. The merged values decode against one adapter-owned typed config at use time. Adapter lifecycle defaults sit underneath all four scopes, so the effective precedence is `adapter default < root < repo < workflow < node`.
|
|
247
|
+
|
|
248
|
+
`transitionTo` describes one lifecycle point, so configure it on a node. A `transitionTo` set at root, repo, or workflow scope applies to **every** lifecycle point that reads it — including `end`, where a `parentStatus` other than the closing status stops the parent from being closed.
|
|
133
249
|
|
|
134
250
|
### Jira transition defaults
|
|
135
251
|
|
|
@@ -139,33 +255,61 @@ Omitted transitions default to:
|
|
|
139
255
|
- work node: mailbox → `In Progress` (parent unchanged)
|
|
140
256
|
- `end`: parent → `Done`
|
|
141
257
|
|
|
258
|
+
### Beads transition defaults
|
|
259
|
+
|
|
260
|
+
Beads follows the same lifecycle shape with Beads-native values:
|
|
261
|
+
|
|
262
|
+
- `start`: parent → `in_progress`
|
|
263
|
+
- work node: mailbox → `in_progress` (parent unchanged)
|
|
264
|
+
- `end`: parent → `closed`
|
|
265
|
+
|
|
266
|
+
A parent moved to `in_progress` stays visible to the claimed-parent poll, which reads `open,in_progress,blocked,deferred`. Entering a node reuses that node's mailbox: a fresh mailbox moves `open → in_progress` and a revisited one moves `closed → in_progress`. Beads reads the issue before every status write, so an already-applied status is a no-op and a status relay-flow did not set (for example a human marking an issue `blocked`) blocks the transition and retries instead of being overwritten.
|
|
267
|
+
|
|
268
|
+
### Shared task configuration and provider status values
|
|
269
|
+
|
|
270
|
+
Beads and Jira use the shared `filters`, `templates`, optional top-level
|
|
271
|
+
`assignee`, and `transitionTo` field names. `transitionTo` uses
|
|
272
|
+
`parentStatus` for the parent issue and `taskStatus` for a mailbox. In both
|
|
273
|
+
adapters `assignee` is the default assignee filter when `filters.assignees` is
|
|
274
|
+
absent, and an `assignee` in effect for a node also assigns that node's
|
|
275
|
+
mailbox. Beads requires the repo-only `taskConfig.beadsDir` shown above; Jira
|
|
276
|
+
instead uses its repo `project` and `component` keys. `project` and
|
|
277
|
+
`component` are not Beads fields, and a Beads issue prefix is not a component
|
|
278
|
+
or workspace selector. Beads status values remain native (`open`,
|
|
279
|
+
`in_progress`, `blocked`, `deferred`, `hooked`, `closed`), while Jira values
|
|
280
|
+
remain native (`In Progress`, `Done`, and so on); relay-flow does not
|
|
281
|
+
translate arbitrary values between providers. Beads rejects workflow/node-level
|
|
282
|
+
template overrides because the fixed task text rendering contract has no
|
|
283
|
+
lower-scope input.
|
|
284
|
+
|
|
142
285
|
---
|
|
143
286
|
|
|
144
287
|
## Structured node report
|
|
145
288
|
|
|
146
|
-
Every visit (agent or HITL)
|
|
289
|
+
Every visit (agent or HITL) submits one report with the same fixed labels:
|
|
147
290
|
|
|
148
291
|
```
|
|
149
292
|
STATUS: success | failure
|
|
150
293
|
NEXT STEP: <one configured route for that status>
|
|
151
294
|
|
|
152
|
-
SUMMARY
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
295
|
+
SUMMARY:
|
|
296
|
+
COMPLETED: ...
|
|
297
|
+
COMMITS: <commit IDs or None>
|
|
298
|
+
NOT COMPLETED: ... | None
|
|
299
|
+
ISSUES DISCOVERED: ... | None
|
|
300
|
+
VERIFICATION: ...
|
|
301
|
+
NOTES: ... | None
|
|
302
|
+
|
|
303
|
+
FEEDBACK:
|
|
304
|
+
REASON FOR NEXT STEP: ...
|
|
305
|
+
REQUIRED ACTIONS: ...
|
|
306
|
+
RELEVANT CONTEXT: ...
|
|
307
|
+
EXPECTED RESULT: ...
|
|
164
308
|
```
|
|
165
309
|
|
|
166
|
-
`None` is the literal marker for an intentionally empty section. When `NEXT STEP` is `end`, every FEEDBACK field must be `None` and no feedback comment is written.
|
|
310
|
+
The labels above are fixed; configurable templates do not change the parsed report contract. The plugin submits one `report` object containing both lower-camel `summary` and `feedback` objects. Relay-flow validates that complete shape once, renders `summaryReport` through the task system's summary-comment template on the current mailbox, and renders `feedbackReport` through its feedback-comment template on only the selected next mailbox. `None` is the literal marker for an intentionally empty section. When `NEXT STEP` is `end`, every FEEDBACK field must be `None` and no feedback comment is written.
|
|
167
311
|
|
|
168
|
-
The plugin delivers
|
|
312
|
+
The plugin delivers `{runId, node, reportId, report}` as one JSON object via `relay-flow report` stdin with the shared backoff (initial 2s, factor 2, jitter 0.2, max 5m) until acknowledged. It derives `reportId` from the harness session/message identity. Duplicate/stale reports are acked safely with no repeated graph effects. Invalid agent output is nudged; invalid HITL output stays silent.
|
|
169
313
|
|
|
170
314
|
---
|
|
171
315
|
|
|
@@ -183,7 +327,8 @@ The plugin delivers the report as one JSON object via `relay-flow report` stdin
|
|
|
183
327
|
- `runID` is deterministic from `repo/workflow/ticket`.
|
|
184
328
|
- `nodeVisitID` is generated once per node entry as a durable replay-safe side effect; it changes on revisit and on fresh runs after `--recover`.
|
|
185
329
|
- Terminal titles are stable `<ticket>:<node>` — they never carry `nodeVisitID`, workflow, or agent.
|
|
186
|
-
-
|
|
330
|
+
- Runtime registration is exactly `{runId, node, sessionId}`; normal execution persists that session ID and uses it to resume the harness session.
|
|
331
|
+
- Reports are exactly `{runId, node, reportId, report}`; `reportId` is derived from harness session/message identity and `nodeVisitID` stays internal.
|
|
187
332
|
|
|
188
333
|
### Poll cycle
|
|
189
334
|
|