@nanobpm/nano-workforce 0.48.1 → 0.49.0

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.
@@ -7,10 +7,11 @@
7
7
  "id": "nav",
8
8
  "props": {
9
9
  "variant": "bar",
10
+ "sticky": true,
10
11
  "title": "Nano Workforce",
11
12
  "items": [
12
13
  { "label": "Convergence", "page": "home" },
13
- { "label": "Epic", "page": "epic" }
14
+ { "label": "Epics", "page": "epic" }
14
15
  ]
15
16
  }
16
17
  },
@@ -23,7 +24,7 @@
23
24
  "type": "text",
24
25
  "id": "subtitle",
25
26
  "props": {
26
- "text": "Hand an issue to the fleet to plan and implement it, then track each plan's review trace, wave state, merge-exclusion graph, coordination notes, and trial-merge gate results.",
27
+ "text": "Hand an issue to the fleet to plan and implement it, then open an epic to track its review trace, wave state, merge-exclusion graph, coordination notes, and trial-merge gate results.",
27
28
  "variant": "sub"
28
29
  }
29
30
  },
@@ -44,7 +45,7 @@
44
45
  "type": "dataGrid",
45
46
  "id": "epic-plans",
46
47
  "props": {
47
- "title": "Plans",
48
+ "title": "Epics",
48
49
  "rowKey": "plan_key",
49
50
  "refreshMs": 5000,
50
51
  "data": {
@@ -66,241 +67,13 @@
66
67
  { "label": "All", "filter": [] }
67
68
  ],
68
69
  "columns": [
69
- { "field": "plan_key", "header": "Issue", "linkField": "issue_url" },
70
+ { "field": "plan_key", "header": "Epic", "link": { "kind": "page", "page": "epic-detail", "keyField": "plan_key" } },
70
71
  { "field": "status", "header": "Status", "link": { "kind": "processExplorer", "keyField": "process_key" } },
72
+ { "field": "wave_label", "header": "Wave" },
71
73
  { "field": "task_count", "header": "Tasks" },
72
- { "field": "open_task_id", "header": "Open escalation" },
73
- { "field": "open_plan_round", "header": "Plan escalation round" },
74
+ { "field": "open_plan_findings", "header": "Attention", "badge": { "tone": "danger", "label": "!" } },
75
+ { "field": "issue_number", "header": "Issue", "linkField": "issue_url" },
74
76
  { "field": "updated_at", "header": "Updated" }
75
- ],
76
- "rowActions": [
77
- {
78
- "label": "Proceed with plan",
79
- "confirm": "Dispatch the current unapproved plan as a human override?",
80
- "showWhenField": "open_plan_escalation_id",
81
- "action": {
82
- "path": "/app/api/actions/message",
83
- "body": {
84
- "name": "plan-escalation-answered",
85
- "correlationKey": "{{row.plan_key}}",
86
- "variables": { "directive": "proceed", "note": "Proceed override from the plans page." }
87
- }
88
- }
89
- }
90
- ],
91
- "detail": {
92
- "linkField": "issue_url",
93
- "fields": [
94
- { "field": "repo", "label": "Repository" },
95
- { "field": "issue_number", "label": "Issue number" },
96
- { "field": "base_branch", "label": "Base branch (blank = repo default)" },
97
- { "field": "outcome", "label": "Outcome" },
98
- { "field": "open_plan_findings", "label": "Open plan-review findings" },
99
- { "field": "open_task_question", "label": "Open escalation question" }
100
- ],
101
- "form": {
102
- "showWhenField": "open_plan_escalation_id",
103
- "title": "Answer the open plan-review escalation",
104
- "promptField": "open_plan_findings",
105
- "inputKey": "note",
106
- "inputLabel": "Revision directive note for the planner",
107
- "submitLabel": "Revise plan",
108
- "action": {
109
- "path": "/app/api/actions/message",
110
- "body": {
111
- "name": "plan-escalation-answered",
112
- "correlationKey": "{{row.plan_key}}",
113
- "variables": { "directive": "revise", "note": "{{form.note}}" }
114
- }
115
- }
116
- }
117
- }
118
- }
119
- },
120
- {
121
- "type": "dataGrid",
122
- "id": "plan-reviews",
123
- "props": {
124
- "title": "Plan review trace",
125
- "refreshMs": 5000,
126
- "data": {
127
- "kind": "datasource",
128
- "source": "app",
129
- "table": "plan_reviews",
130
- "orderBy": { "field": "round", "dir": "asc" }
131
- },
132
- "columns": [
133
- { "field": "plan_key", "header": "Plan" },
134
- { "field": "round", "header": "Round" },
135
- { "field": "epoch", "header": "Epoch" },
136
- { "field": "approved", "header": "Approved? (1/0)" },
137
- { "field": "findings", "header": "Reviewer findings" },
138
- { "field": "created_at", "header": "Recorded" }
139
- ]
140
- }
141
- },
142
- {
143
- "type": "dataGrid",
144
- "id": "plan-review-escalations",
145
- "props": {
146
- "title": "Plan-review escalations",
147
- "rowKey": "id",
148
- "refreshMs": 5000,
149
- "data": {
150
- "kind": "datasource",
151
- "source": "app",
152
- "table": "plan_review_escalations",
153
- "orderBy": { "field": "id", "dir": "desc" }
154
- },
155
- "columns": [
156
- { "field": "plan_key", "header": "Plan" },
157
- { "field": "epoch", "header": "Epoch" },
158
- { "field": "round", "header": "Round" },
159
- { "field": "findings", "header": "Findings" },
160
- { "field": "status", "header": "Status" },
161
- { "field": "directive", "header": "Directive" },
162
- { "field": "note", "header": "Human note" },
163
- { "field": "asked_at", "header": "Asked" },
164
- { "field": "answered_at", "header": "Answered" }
165
- ]
166
- }
167
- },
168
- {
169
- "type": "dataGrid",
170
- "id": "wave-state",
171
- "props": {
172
- "title": "Wave state",
173
- "rowKey": "id",
174
- "refreshMs": 5000,
175
- "data": {
176
- "kind": "datasource",
177
- "source": "app",
178
- "table": "plan_tasks",
179
- "orderBy": { "field": "wave", "dir": "asc" },
180
- "filter": [
181
- { "field": "status", "in": ["pending", "opened", "escalated", "waiting-for-lane", "blocked"] }
182
- ]
183
- },
184
- "tabs": [
185
- {
186
- "label": "Active",
187
- "filter": [
188
- { "field": "status", "in": ["pending", "opened", "escalated", "waiting-for-lane", "blocked"] }
189
- ]
190
- },
191
- {
192
- "label": "Skipped",
193
- "filter": [{ "field": "status", "in": ["skipped"] }]
194
- },
195
- { "label": "All", "filter": [] }
196
- ],
197
- "columns": [
198
- { "field": "plan_key", "header": "Plan" },
199
- { "field": "wave", "header": "Wave" },
200
- { "field": "task_id", "header": "Task" },
201
- { "field": "title", "header": "Title" },
202
- { "field": "status", "header": "Status" },
203
- { "field": "pr_key", "header": "PR" },
204
- { "field": "summary", "header": "Summary" },
205
- { "field": "updated_at", "header": "Updated" }
206
- ],
207
- "detail": {
208
- "fields": [
209
- { "field": "open_question", "label": "Open question" },
210
- { "field": "answer", "label": "Answer" },
211
- { "field": "draft_pr_key", "label": "Draft PR" },
212
- { "field": "prompt", "label": "Prompt" }
213
- ]
214
- }
215
- }
216
- },
217
- {
218
- "type": "dataGrid",
219
- "id": "merge-exclusions",
220
- "props": {
221
- "title": "Conflict graph / who blocks whom",
222
- "rowKey": "id",
223
- "refreshMs": 5000,
224
- "data": {
225
- "kind": "datasource",
226
- "source": "app",
227
- "table": "plan_merge_exclusions",
228
- "orderBy": { "field": "id", "dir": "asc" }
229
- },
230
- "columns": [
231
- { "field": "plan_key", "header": "Plan" },
232
- { "field": "task_a", "header": "Task A" },
233
- { "field": "task_b", "header": "Task B" },
234
- { "field": "files", "header": "Shared files" },
235
- { "field": "source", "header": "Source" },
236
- { "field": "updated_at", "header": "Updated" }
237
- ]
238
- }
239
- },
240
- {
241
- "type": "dataGrid",
242
- "id": "coordination-notes",
243
- "props": {
244
- "title": "Coordination notes",
245
- "rowKey": "id",
246
- "refreshMs": 5000,
247
- "data": {
248
- "kind": "datasource",
249
- "source": "app",
250
- "table": "plan_blackboard",
251
- "orderBy": { "field": "id", "dir": "asc" }
252
- },
253
- "columns": [
254
- { "field": "plan_key", "header": "Plan" },
255
- { "field": "wave", "header": "Wave" },
256
- { "field": "author_task", "header": "Agent" },
257
- { "field": "kind", "header": "Kind" },
258
- { "field": "files", "header": "Files" },
259
- { "field": "body", "header": "Note" },
260
- { "field": "created_at", "header": "Posted" }
261
- ]
262
- }
263
- },
264
- {
265
- "type": "dataGrid",
266
- "id": "trial-merge-results",
267
- "props": {
268
- "title": "Trial-merge results",
269
- "rowKey": "id",
270
- "refreshMs": 5000,
271
- "data": {
272
- "kind": "datasource",
273
- "source": "app",
274
- "table": "plan_trial_merges",
275
- "orderBy": { "field": "created_at", "dir": "desc" },
276
- "filter": [
277
- { "field": "result", "in": ["merge-conflict", "suite-failed"] },
278
- { "field": "resolved", "in": [0] }
279
- ]
280
- },
281
- "tabs": [
282
- {
283
- "label": "Needs attention",
284
- "filter": [
285
- { "field": "result", "in": ["merge-conflict", "suite-failed"] },
286
- { "field": "resolved", "in": [0] }
287
- ]
288
- },
289
- {
290
- "label": "Clean",
291
- "filter": [{ "field": "result", "in": ["clean"] }]
292
- },
293
- { "label": "All", "filter": [] }
294
- ],
295
- "columns": [
296
- { "field": "plan_key", "header": "Plan" },
297
- { "field": "wave", "header": "Wave" },
298
- { "field": "result", "header": "Result" },
299
- { "field": "heads", "header": "Heads" },
300
- { "field": "conflicts", "header": "Conflicts" },
301
- { "field": "failing", "header": "Failing" },
302
- { "field": "summary", "header": "Summary" },
303
- { "field": "created_at", "header": "Recorded" }
304
77
  ]
305
78
  }
306
79
  }
@@ -9,15 +9,25 @@
9
9
  "variant": "bar",
10
10
  "title": "Nano Workforce",
11
11
  "items": [
12
- { "label": "Convergence", "page": "home" },
13
- { "label": "Epic", "page": "epic" }
14
- ]
12
+ {
13
+ "label": "Convergence",
14
+ "page": "home"
15
+ },
16
+ {
17
+ "label": "Epics",
18
+ "page": "epic"
19
+ }
20
+ ],
21
+ "sticky": true
15
22
  }
16
23
  },
17
24
  {
18
25
  "type": "text",
19
26
  "id": "title",
20
- "props": { "text": "PR Review Convergence", "variant": "heading" }
27
+ "props": {
28
+ "text": "PR Review Convergence",
29
+ "variant": "heading"
30
+ }
21
31
  },
22
32
  {
23
33
  "type": "text",
@@ -31,13 +41,13 @@
31
41
  "type": "button",
32
42
  "id": "agent-instructions",
33
43
  "props": {
34
- "label": "🤖 Agent Instructions",
44
+ "label": "\ud83e\udd16 Agent Instructions",
35
45
  "variant": "ghost",
36
46
  "modal": {
37
47
  "title": "Point your agent at Nano Workforce",
38
48
  "description": "Copy this prompt and paste it into your coding agent (Copilot, Claude, etc.). It tells the agent to read this workforce's live operator guide, then help you drive and debug it.",
39
49
  "copyLabel": "Copy prompt",
40
- "copyText": "You are helping me operate a running Nano Workforce instance a durable orchestration app that drives pull requests to review convergence against an automated reviewer, merges them, and can take a whole issue and plan \u2192 implement \u2192 converge it across a fleet of coding agents.\n\nFirst, fetch and read its live operator guide. It tells you how to submit PRs and epics for convergence (including whether to go all the way to merge or stop at review consensus), how to find engine instances and relate them to PRs via the Nano/Camunda-8 REST API, how to inspect the models and prompts, and how to help me untangle escalations:\n\n curl -sS {{appBase}}app/api/agent\n\nIf this instance is secured with a shared secret (NANO_PR_WEBHOOK_SECRET), add its value as an x-hook-secret header, otherwise the request returns 401:\n\n curl -sS -H \"x-hook-secret: <secret>\" {{appBase}}app/api/agent\n\nThen follow that guide to help me drive and debug this workforce. If you find a bug or a stuck process, the guide explains how to raise an issue or a PR against nanobpm/nano-workforce."
50
+ "copyText": "You are helping me operate a running Nano Workforce instance \u2014 a durable orchestration app that drives pull requests to review convergence against an automated reviewer, merges them, and can take a whole issue and plan \u2192 implement \u2192 converge it across a fleet of coding agents.\n\nFirst, fetch and read its live operator guide. It tells you how to submit PRs and epics for convergence (including whether to go all the way to merge or stop at review consensus), how to find engine instances and relate them to PRs via the Nano/Camunda-8 REST API, how to inspect the models and prompts, and how to help me untangle escalations:\n\n curl -sS {{appBase}}app/api/agent\n\nIf this instance is secured with a shared secret (NANO_PR_WEBHOOK_SECRET), add its value as an x-hook-secret header, otherwise the request returns 401:\n\n curl -sS -H \"x-hook-secret: <secret>\" {{appBase}}app/api/agent\n\nThen follow that guide to help me drive and debug this workforce. If you find a bug or a stuck process, the guide explains how to raise an issue or a PR against nanobpm/nano-workforce."
41
51
  }
42
52
  }
43
53
  },
@@ -47,11 +57,26 @@
47
57
  "props": {
48
58
  "title": "Submit a pull request",
49
59
  "submitLabel": "Start review",
50
- "action": { "path": "/app/api/actions/start/convergence-loop", "body": "{{form}}" },
60
+ "action": {
61
+ "path": "/app/api/actions/start/convergence-loop",
62
+ "body": "{{form}}"
63
+ },
51
64
  "fields": [
52
- { "key": "pr", "label": "owner/repo#123 or a GitHub PR URL", "type": "text" },
53
- { "key": "maxRounds", "label": "Max review rounds (blank = fleet default)", "type": "number" },
54
- { "key": "convergeOnly", "label": "Converge only stop at review consensus, do not merge", "type": "checkbox" }
65
+ {
66
+ "key": "pr",
67
+ "label": "owner/repo#123 or a GitHub PR URL",
68
+ "type": "text"
69
+ },
70
+ {
71
+ "key": "maxRounds",
72
+ "label": "Max review rounds (blank = fleet default)",
73
+ "type": "number"
74
+ },
75
+ {
76
+ "key": "convergeOnly",
77
+ "label": "Converge only \u2014 stop at review consensus, do not merge",
78
+ "type": "checkbox"
79
+ }
55
80
  ]
56
81
  }
57
82
  },
@@ -67,50 +92,140 @@
67
92
  "kind": "datasource",
68
93
  "source": "app",
69
94
  "table": "pull_requests",
70
- "orderBy": { "field": "updated_at", "dir": "desc" },
95
+ "orderBy": {
96
+ "field": "updated_at",
97
+ "dir": "desc"
98
+ },
71
99
  "filter": [
72
- { "field": "status", "in": ["converging", "waiting_review", "escalated", "waiting_deps", "waiting_merge", "queued", "merging"] }
100
+ {
101
+ "field": "status",
102
+ "in": [
103
+ "converging",
104
+ "waiting_review",
105
+ "escalated",
106
+ "waiting_deps",
107
+ "waiting_merge",
108
+ "queued",
109
+ "merging"
110
+ ]
111
+ }
73
112
  ]
74
113
  },
75
114
  "tabs": [
76
115
  {
77
116
  "label": "Active",
78
117
  "filter": [
79
- { "field": "status", "in": ["converging", "waiting_review", "escalated", "waiting_deps", "waiting_merge", "queued", "merging"] }
118
+ {
119
+ "field": "status",
120
+ "in": [
121
+ "converging",
122
+ "waiting_review",
123
+ "escalated",
124
+ "waiting_deps",
125
+ "waiting_merge",
126
+ "queued",
127
+ "merging"
128
+ ]
129
+ }
80
130
  ]
81
131
  },
82
132
  {
83
133
  "label": "History",
84
- "filter": [{ "field": "status", "in": ["converged", "merged", "abandoned"] }]
134
+ "filter": [
135
+ {
136
+ "field": "status",
137
+ "in": [
138
+ "converged",
139
+ "merged",
140
+ "abandoned"
141
+ ]
142
+ }
143
+ ]
85
144
  }
86
145
  ],
87
146
  "columns": [
88
- { "field": "pr_key", "header": "PR", "linkField": "url" },
89
- { "field": "status", "header": "Status", "link": { "kind": "processExplorer", "keyField": "process_key" } },
90
- { "field": "incident_message", "header": "Incident", "badge": { "tone": "danger", "label": "1" } },
91
- { "field": "current_round", "header": "Round" },
92
- { "field": "active_worker", "header": "Agent" },
93
- { "field": "updated_at", "header": "Updated" }
147
+ {
148
+ "field": "pr_key",
149
+ "header": "PR",
150
+ "linkField": "url"
151
+ },
152
+ {
153
+ "field": "status",
154
+ "header": "Status",
155
+ "link": {
156
+ "kind": "processExplorer",
157
+ "keyField": "process_key"
158
+ }
159
+ },
160
+ {
161
+ "field": "incident_message",
162
+ "header": "Incident",
163
+ "badge": {
164
+ "tone": "danger",
165
+ "label": "1"
166
+ }
167
+ },
168
+ {
169
+ "field": "current_round",
170
+ "header": "Round"
171
+ },
172
+ {
173
+ "field": "active_worker",
174
+ "header": "Agent"
175
+ },
176
+ {
177
+ "field": "updated_at",
178
+ "header": "Updated"
179
+ }
94
180
  ],
95
181
  "rowActions": [
96
182
  {
97
183
  "label": "Cancel",
98
184
  "confirm": "Cancel this PR's review run?",
99
185
  "showWhenField": "process_key",
100
- "action": { "path": "/app/actions/cancel", "body": { "processInstanceKey": "{{row.process_key}}" } }
186
+ "action": {
187
+ "path": "/app/actions/cancel",
188
+ "body": {
189
+ "processInstanceKey": "{{row.process_key}}"
190
+ }
191
+ }
101
192
  }
102
193
  ],
103
194
  "detail": {
104
195
  "linkField": "url",
105
196
  "fields": [
106
- { "field": "repo", "label": "Repository" },
107
- { "field": "number", "label": "PR number" },
108
- { "field": "active_worker", "label": "Agent (leasing worker)" },
109
- { "field": "lease_until", "label": "Activation lease until" },
110
- { "field": "incident_message", "label": "Incident" },
111
- { "field": "incident_key", "label": "Incident key" },
112
- { "field": "merged_at", "label": "Merged at" },
113
- { "field": "outcome", "label": "Outcome" }
197
+ {
198
+ "field": "repo",
199
+ "label": "Repository"
200
+ },
201
+ {
202
+ "field": "number",
203
+ "label": "PR number"
204
+ },
205
+ {
206
+ "field": "active_worker",
207
+ "label": "Agent (leasing worker)"
208
+ },
209
+ {
210
+ "field": "lease_until",
211
+ "label": "Activation lease until"
212
+ },
213
+ {
214
+ "field": "incident_message",
215
+ "label": "Incident"
216
+ },
217
+ {
218
+ "field": "incident_key",
219
+ "label": "Incident key"
220
+ },
221
+ {
222
+ "field": "merged_at",
223
+ "label": "Merged at"
224
+ },
225
+ {
226
+ "field": "outcome",
227
+ "label": "Outcome"
228
+ }
114
229
  ],
115
230
  "children": [
116
231
  {
@@ -119,14 +234,33 @@
119
234
  "table": "rounds",
120
235
  "parentField": "pr_key",
121
236
  "childField": "pr_key",
122
- "orderBy": { "field": "round_no", "dir": "asc" },
237
+ "orderBy": {
238
+ "field": "round_no",
239
+ "dir": "asc"
240
+ },
123
241
  "columns": [
124
- { "field": "round_no", "header": "#" },
125
- { "field": "status", "header": "Result" },
126
- { "field": "worker", "header": "Worker" },
127
- { "field": "summary", "header": "Summary" }
242
+ {
243
+ "field": "round_no",
244
+ "header": "#"
245
+ },
246
+ {
247
+ "field": "status",
248
+ "header": "Result"
249
+ },
250
+ {
251
+ "field": "worker",
252
+ "header": "Worker"
253
+ },
254
+ {
255
+ "field": "summary",
256
+ "header": "Summary"
257
+ }
128
258
  ],
129
- "lazyField": { "field": "transcript", "label": "Transcript", "lazy": true }
259
+ "lazyField": {
260
+ "field": "transcript",
261
+ "label": "Transcript",
262
+ "lazy": true
263
+ }
130
264
  },
131
265
  {
132
266
  "title": "Escalations",
@@ -134,16 +268,41 @@
134
268
  "table": "escalations",
135
269
  "parentField": "pr_key",
136
270
  "childField": "pr_key",
137
- "orderBy": { "field": "id", "dir": "asc" },
271
+ "orderBy": {
272
+ "field": "id",
273
+ "dir": "asc"
274
+ },
138
275
  "columns": [
139
- { "field": "round_no", "header": "#" },
140
- { "field": "kind", "header": "Kind" },
141
- { "field": "worker", "header": "Worker" },
142
- { "field": "question", "header": "Question" },
143
- { "field": "status", "header": "Status" },
144
- { "field": "answer", "header": "Answer" }
276
+ {
277
+ "field": "round_no",
278
+ "header": "#"
279
+ },
280
+ {
281
+ "field": "kind",
282
+ "header": "Kind"
283
+ },
284
+ {
285
+ "field": "worker",
286
+ "header": "Worker"
287
+ },
288
+ {
289
+ "field": "question",
290
+ "header": "Question"
291
+ },
292
+ {
293
+ "field": "status",
294
+ "header": "Status"
295
+ },
296
+ {
297
+ "field": "answer",
298
+ "header": "Answer"
299
+ }
145
300
  ],
146
- "lazyField": { "field": "transcript", "label": "Agent response", "lazy": true }
301
+ "lazyField": {
302
+ "field": "transcript",
303
+ "label": "Agent response",
304
+ "lazy": true
305
+ }
147
306
  },
148
307
  {
149
308
  "title": "Depends on",
@@ -151,10 +310,19 @@
151
310
  "table": "pr_dependencies",
152
311
  "parentField": "pr_key",
153
312
  "childField": "pr_key",
154
- "orderBy": { "field": "created_at", "dir": "asc" },
313
+ "orderBy": {
314
+ "field": "created_at",
315
+ "dir": "asc"
316
+ },
155
317
  "columns": [
156
- { "field": "depends_on_key", "header": "PR that must merge first" },
157
- { "field": "created_at", "header": "Declared" }
318
+ {
319
+ "field": "depends_on_key",
320
+ "header": "PR that must merge first"
321
+ },
322
+ {
323
+ "field": "created_at",
324
+ "header": "Declared"
325
+ }
158
326
  ]
159
327
  }
160
328
  ],
@@ -167,7 +335,11 @@
167
335
  "submitLabel": "Send answer",
168
336
  "action": {
169
337
  "path": "/app/api/actions/message",
170
- "body": { "name": "escalation-answered", "correlationKey": "{{row.pr_key}}", "variables": "{{form}}" }
338
+ "body": {
339
+ "name": "escalation-answered",
340
+ "correlationKey": "{{row.pr_key}}",
341
+ "variables": "{{form}}"
342
+ }
171
343
  }
172
344
  }
173
345
  }