@nanobpm/nano-workforce 0.57.0 → 0.58.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.
Files changed (82) hide show
  1. package/.github/workflows/ci.yml +7 -0
  2. package/AGENTS.md +83 -1
  3. package/CHANGELOG.md +7 -0
  4. package/README.md +1 -1
  5. package/SPEC.md +21 -22
  6. package/app/agentCompletion.test.ts +337 -0
  7. package/app/agentCompletion.ts +219 -0
  8. package/app/answer-escalation.test.ts +106 -0
  9. package/app/answerEscalation.test.ts +67 -0
  10. package/app/baseGuard.test.ts +9 -1
  11. package/app/baseGuard.ts +11 -0
  12. package/app/escalationSla.test.ts +39 -0
  13. package/app/escalationSla.ts +28 -0
  14. package/app/escalationTaxonomy.test.ts +115 -0
  15. package/app/escalationTaxonomy.ts +115 -0
  16. package/app/feature.test.ts +161 -0
  17. package/app/feature.ts +173 -0
  18. package/app/mergeProtocol.test.ts +15 -0
  19. package/app/mergeProtocol.ts +10 -0
  20. package/app/persist-escalation.test.ts +34 -36
  21. package/app/plan.test.ts +0 -294
  22. package/app/plan.ts +26 -216
  23. package/app/reviewWait.ts +12 -4
  24. package/app/roundResultDefault.test.ts +111 -2
  25. package/app/roundResultDefault.ts +35 -0
  26. package/app/service.test.ts +6 -7
  27. package/app/service.ts +52 -35
  28. package/db/migrations/026_agent_completion.sql +36 -0
  29. package/db/migrations/027_retire_escalation_subsystem.sql +43 -0
  30. package/db/migrations/028_feature_runs.sql +28 -0
  31. package/e2e/agent-answerable.e2e.ts +185 -0
  32. package/e2e/convergence-escalation.e2e.ts +180 -0
  33. package/e2e/convergence-loop.e2e.ts +1 -1
  34. package/e2e/feature-run.e2e.ts +231 -0
  35. package/e2e/plan-fanout-sla.e2e.ts +238 -0
  36. package/e2e/plan-fanout.e2e.ts +303 -0
  37. package/e2e/retire-escalation-subsystem.e2e.ts +223 -0
  38. package/e2e/support/github-admit.ts +99 -0
  39. package/e2e/user-task-spine.e2e.ts +155 -0
  40. package/nano.app.json +37 -11
  41. package/openapi.yaml +181 -73
  42. package/operations/agentCompleteEscalation.ts +53 -0
  43. package/operations/listActivePrs.test.ts +39 -6
  44. package/operations/postMessage.ts +10 -41
  45. package/operations/revertEscalationCompletion.ts +44 -0
  46. package/operations/startAndMessage.test.ts +0 -58
  47. package/operations/startFeature.ts +127 -0
  48. package/package.json +4 -1
  49. package/pages/cockpit.page.json +1 -0
  50. package/pages/epic-detail.page.json +11 -37
  51. package/pages/epic.page.json +1 -1
  52. package/pages/feature.page.json +82 -0
  53. package/pages/home.page.json +6 -18
  54. package/resources/agent-guide.md +52 -24
  55. package/resources/forms/feature-escalation.form +27 -0
  56. package/resources/forms/plan-review-decision.form +27 -0
  57. package/resources/forms/pr-escalation.form +23 -0
  58. package/resources/forms/spine-demo.form +15 -0
  59. package/resources/forms/trial-merge-decision.form +25 -0
  60. package/resources/processes/convergence-loop.bpmn +127 -75
  61. package/resources/processes/feature.bpmn +240 -0
  62. package/resources/processes/plan-fanout.bpmn +304 -223
  63. package/resources/processes/spine-demo.bpmn +72 -0
  64. package/scripts/check-migrations.ts +68 -0
  65. package/workers/answer-escalation/worker.ts +78 -0
  66. package/workers/converge-feature/worker.ts +51 -0
  67. package/workers/finalize/worker.ts +0 -2
  68. package/workers/mark-merged/worker.ts +0 -2
  69. package/workers/merge/worker.ts +6 -5
  70. package/workers/persist-escalation/worker.ts +28 -32
  71. package/workers/record-feature/worker.ts +61 -0
  72. package/workers/record-plan-review/worker.test.ts +9 -10
  73. package/workers/record-plan-review/worker.ts +15 -5
  74. package/workers/resolve-trial-attention/worker.test.ts +77 -0
  75. package/workers/resolve-trial-attention/worker.ts +43 -0
  76. package/operations/answerFeatureEscalation.test.ts +0 -112
  77. package/operations/answerFeatureEscalation.ts +0 -58
  78. package/operations/answerPlanEscalation.test.ts +0 -115
  79. package/operations/answerPlanEscalation.ts +0 -41
  80. package/workers/persist-plan-escalation/worker.test.ts +0 -80
  81. package/workers/persist-plan-escalation/worker.ts +0 -73
  82. package/workers/persist-task-escalation/worker.ts +0 -120
@@ -0,0 +1,240 @@
1
+ <?xml version="1.0" encoding="UTF-8"?>
2
+ <bpmn:definitions xmlns:bpmn="http://www.omg.org/spec/BPMN/20100524/MODEL" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:bpmndi="http://www.omg.org/spec/BPMN/20100524/DI" xmlns:dc="http://www.omg.org/spec/DD/20100524/DC" xmlns:di="http://www.omg.org/spec/DD/20100524/DI" xmlns:zeebe="http://camunda.org/schema/zeebe/1.0" id="Definitions_nano_workforce_feature" targetNamespace="http://nanobpm.io/nano-workforce">
3
+ <bpmn:process id="feature" name="Single-issue feature run" isExecutable="true">
4
+ <bpmn:startEvent id="Start" name="Issue submitted">
5
+ <bpmn:outgoing>f_toEnsureBase</bpmn:outgoing>
6
+ </bpmn:startEvent>
7
+ <bpmn:serviceTask id="ensure-base-branch" name="Ensure base branch">
8
+ <bpmn:extensionElements>
9
+ <zeebe:taskDefinition type="pr.ensure-base-branch" />
10
+ <zeebe:ioMapping>
11
+ <zeebe:input source="=repo" target="repo" />
12
+ <zeebe:input source="=baseBranch" target="baseBranch" />
13
+ </zeebe:ioMapping>
14
+ </bpmn:extensionElements>
15
+ <bpmn:incoming>f_toEnsureBase</bpmn:incoming>
16
+ <bpmn:outgoing>f_toImplement</bpmn:outgoing>
17
+ </bpmn:serviceTask>
18
+ <bpmn:serviceTask id="implement-task" name="Implement (agent)">
19
+ <bpmn:extensionElements>
20
+ <zeebe:taskDefinition type="senior:feature" />
21
+ <zeebe:taskHeaders>
22
+ <zeebe:header key="io.nanobpm.agentTask.task.prompt" value="{{feature}}" />
23
+ </zeebe:taskHeaders>
24
+ <zeebe:ioMapping>
25
+ <zeebe:input source="=&#34;&#10;&#10;---&#10;&#10;&#34; + task.prompt + (if (baseBranchBrief = null) then &#34;&#34; else baseBranchBrief)" target="appendPrompt" />
26
+ <zeebe:output source="=status" target="status" />
27
+ <zeebe:output source="=question" target="question" />
28
+ </zeebe:ioMapping>
29
+ </bpmn:extensionElements>
30
+ <bpmn:incoming>f_toImplement</bpmn:incoming>
31
+ <bpmn:incoming>w_answerLoop</bpmn:incoming>
32
+ <bpmn:outgoing>w_toGw</bpmn:outgoing>
33
+ </bpmn:serviceTask>
34
+ <bpmn:exclusiveGateway id="w_gw" name="escalated?" default="w_done">
35
+ <bpmn:incoming>w_toGw</bpmn:incoming>
36
+ <bpmn:outgoing>w_escalate</bpmn:outgoing>
37
+ <bpmn:outgoing>w_done</bpmn:outgoing>
38
+ </bpmn:exclusiveGateway>
39
+ <bpmn:userTask id="feature-escalation" name="Task escalation (human)">
40
+ <bpmn:extensionElements>
41
+ <zeebe:formDefinition formId="feature-escalation" />
42
+ <zeebe:userTask />
43
+ <zeebe:assignmentDefinition candidateGroups="operators" assignee="=escalationAssignee" />
44
+ </bpmn:extensionElements>
45
+ <bpmn:incoming>w_escalate</bpmn:incoming>
46
+ <bpmn:outgoing>w_toAnswerGw</bpmn:outgoing>
47
+ </bpmn:userTask>
48
+ <bpmn:boundaryEvent id="be_feature_sla" name="SLA elapsed" attachedToRef="feature-escalation">
49
+ <bpmn:outgoing>w_sla</bpmn:outgoing>
50
+ <bpmn:timerEventDefinition id="ted_feature_sla">
51
+ <bpmn:timeDuration xsi:type="bpmn:tFormalExpression">=escalationSlaTimeout</bpmn:timeDuration>
52
+ </bpmn:timerEventDefinition>
53
+ </bpmn:boundaryEvent>
54
+ <bpmn:exclusiveGateway id="w_gw_answer" name="answer?" default="w_abandon">
55
+ <bpmn:incoming>w_toAnswerGw</bpmn:incoming>
56
+ <bpmn:outgoing>w_answerLoop</bpmn:outgoing>
57
+ <bpmn:outgoing>w_abandon</bpmn:outgoing>
58
+ </bpmn:exclusiveGateway>
59
+ <bpmn:serviceTask id="record-feature" name="Record result">
60
+ <bpmn:extensionElements>
61
+ <zeebe:taskDefinition type="pr.record-feature" />
62
+ </bpmn:extensionElements>
63
+ <bpmn:incoming>w_done</bpmn:incoming>
64
+ <bpmn:incoming>w_abandon</bpmn:incoming>
65
+ <bpmn:incoming>w_sla</bpmn:incoming>
66
+ <bpmn:outgoing>f_toConvergeGw</bpmn:outgoing>
67
+ </bpmn:serviceTask>
68
+ <bpmn:exclusiveGateway id="gw-converge" name="converge?" default="f_noConverge">
69
+ <bpmn:incoming>f_toConvergeGw</bpmn:incoming>
70
+ <bpmn:outgoing>f_converge</bpmn:outgoing>
71
+ <bpmn:outgoing>f_noConverge</bpmn:outgoing>
72
+ </bpmn:exclusiveGateway>
73
+ <bpmn:serviceTask id="converge" name="Hand off to convergence loop">
74
+ <bpmn:extensionElements>
75
+ <zeebe:taskDefinition type="pr.converge-feature" />
76
+ </bpmn:extensionElements>
77
+ <bpmn:incoming>f_converge</bpmn:incoming>
78
+ <bpmn:outgoing>f_toEndConverged</bpmn:outgoing>
79
+ </bpmn:serviceTask>
80
+ <bpmn:endEvent id="End" name="Done">
81
+ <bpmn:incoming>f_noConverge</bpmn:incoming>
82
+ <bpmn:incoming>f_toEndConverged</bpmn:incoming>
83
+ </bpmn:endEvent>
84
+ <bpmn:sequenceFlow id="f_toEnsureBase" sourceRef="Start" targetRef="ensure-base-branch" />
85
+ <bpmn:sequenceFlow id="f_toImplement" sourceRef="ensure-base-branch" targetRef="implement-task" />
86
+ <bpmn:sequenceFlow id="w_toGw" sourceRef="implement-task" targetRef="w_gw" />
87
+ <bpmn:sequenceFlow id="w_escalate" name="escalated" sourceRef="w_gw" targetRef="feature-escalation">
88
+ <bpmn:conditionExpression xsi:type="bpmn:tFormalExpression">=status = "escalated" and question != null and trim(question) != ""</bpmn:conditionExpression>
89
+ </bpmn:sequenceFlow>
90
+ <bpmn:sequenceFlow id="w_done" name="done" sourceRef="w_gw" targetRef="record-feature" />
91
+ <bpmn:sequenceFlow id="w_toAnswerGw" sourceRef="feature-escalation" targetRef="w_gw_answer" />
92
+ <bpmn:sequenceFlow id="w_answerLoop" name="answer" sourceRef="w_gw_answer" targetRef="implement-task">
93
+ <bpmn:conditionExpression xsi:type="bpmn:tFormalExpression">=resolution = "answer"</bpmn:conditionExpression>
94
+ </bpmn:sequenceFlow>
95
+ <bpmn:sequenceFlow id="w_abandon" name="abandon" sourceRef="w_gw_answer" targetRef="record-feature" />
96
+ <bpmn:sequenceFlow id="w_sla" name="SLA auto-abandon" sourceRef="be_feature_sla" targetRef="record-feature" />
97
+ <bpmn:sequenceFlow id="f_toConvergeGw" sourceRef="record-feature" targetRef="gw-converge" />
98
+ <bpmn:sequenceFlow id="f_converge" name="converge" sourceRef="gw-converge" targetRef="converge">
99
+ <bpmn:conditionExpression xsi:type="bpmn:tFormalExpression">=converge = true and featureStatus = "opened" and prKey != null</bpmn:conditionExpression>
100
+ </bpmn:sequenceFlow>
101
+ <bpmn:sequenceFlow id="f_noConverge" name="raise only" sourceRef="gw-converge" targetRef="End" />
102
+ <bpmn:sequenceFlow id="f_toEndConverged" sourceRef="converge" targetRef="End" />
103
+ </bpmn:process>
104
+ <bpmndi:BPMNDiagram id="BPMNDiagram_feature">
105
+ <bpmndi:BPMNPlane id="BPMNPlane_feature" bpmnElement="feature">
106
+ <bpmndi:BPMNShape id="BPMNShape_Start" bpmnElement="Start">
107
+ <dc:Bounds x="80" y="102" width="36" height="36" />
108
+ <bpmndi:BPMNLabel>
109
+ <dc:Bounds x="63" y="143" width="70" height="28" />
110
+ </bpmndi:BPMNLabel>
111
+ </bpmndi:BPMNShape>
112
+ <bpmndi:BPMNShape id="BPMNShape_ensure-base-branch" bpmnElement="ensure-base-branch">
113
+ <dc:Bounds x="216" y="80" width="100" height="80" />
114
+ </bpmndi:BPMNShape>
115
+ <bpmndi:BPMNShape id="BPMNShape_implement-task" bpmnElement="implement-task">
116
+ <dc:Bounds x="416" y="80" width="100" height="80" />
117
+ </bpmndi:BPMNShape>
118
+ <bpmndi:BPMNShape id="BPMNShape_w_gw" bpmnElement="w_gw" isMarkerVisible="true">
119
+ <dc:Bounds x="616" y="95" width="50" height="50" />
120
+ <bpmndi:BPMNLabel>
121
+ <dc:Bounds x="604" y="76" width="74" height="14" />
122
+ </bpmndi:BPMNLabel>
123
+ </bpmndi:BPMNShape>
124
+ <bpmndi:BPMNShape id="BPMNShape_feature-escalation" bpmnElement="feature-escalation">
125
+ <dc:Bounds x="766" y="240" width="100" height="80" />
126
+ </bpmndi:BPMNShape>
127
+ <bpmndi:BPMNShape id="BPMNShape_w_gw_answer" bpmnElement="w_gw_answer" isMarkerVisible="true">
128
+ <dc:Bounds x="966" y="255" width="50" height="50" />
129
+ <bpmndi:BPMNLabel>
130
+ <dc:Bounds x="963" y="236" width="56" height="14" />
131
+ </bpmndi:BPMNLabel>
132
+ </bpmndi:BPMNShape>
133
+ <bpmndi:BPMNShape id="BPMNShape_record-feature" bpmnElement="record-feature">
134
+ <dc:Bounds x="1116" y="80" width="100" height="80" />
135
+ </bpmndi:BPMNShape>
136
+ <bpmndi:BPMNShape id="BPMNShape_gw-converge" bpmnElement="gw-converge" isMarkerVisible="true">
137
+ <dc:Bounds x="1316" y="95" width="50" height="50" />
138
+ <bpmndi:BPMNLabel>
139
+ <dc:Bounds x="1308" y="76" width="67" height="14" />
140
+ </bpmndi:BPMNLabel>
141
+ </bpmndi:BPMNShape>
142
+ <bpmndi:BPMNShape id="BPMNShape_converge" bpmnElement="converge">
143
+ <dc:Bounds x="1466" y="240" width="100" height="80" />
144
+ </bpmndi:BPMNShape>
145
+ <bpmndi:BPMNShape id="BPMNShape_End" bpmnElement="End">
146
+ <dc:Bounds x="1666" y="102" width="36" height="36" />
147
+ <bpmndi:BPMNLabel>
148
+ <dc:Bounds x="1667" y="83" width="34" height="14" />
149
+ </bpmndi:BPMNLabel>
150
+ </bpmndi:BPMNShape>
151
+ <bpmndi:BPMNShape id="BPMNShape_be_feature_sla" bpmnElement="be_feature_sla">
152
+ <dc:Bounds x="798" y="302" width="36" height="36" />
153
+ <bpmndi:BPMNLabel>
154
+ <dc:Bounds x="774" y="383" width="84" height="14" />
155
+ </bpmndi:BPMNLabel>
156
+ </bpmndi:BPMNShape>
157
+ <bpmndi:BPMNEdge id="BPMNEdge_f_toEnsureBase" bpmnElement="f_toEnsureBase">
158
+ <di:waypoint x="116" y="120" />
159
+ <di:waypoint x="216" y="120" />
160
+ </bpmndi:BPMNEdge>
161
+ <bpmndi:BPMNEdge id="BPMNEdge_f_toImplement" bpmnElement="f_toImplement">
162
+ <di:waypoint x="316" y="120" />
163
+ <di:waypoint x="416" y="120" />
164
+ </bpmndi:BPMNEdge>
165
+ <bpmndi:BPMNEdge id="BPMNEdge_w_toGw" bpmnElement="w_toGw">
166
+ <di:waypoint x="516" y="120" />
167
+ <di:waypoint x="616" y="120" />
168
+ </bpmndi:BPMNEdge>
169
+ <bpmndi:BPMNEdge id="BPMNEdge_w_done" bpmnElement="w_done">
170
+ <di:waypoint x="666" y="120" />
171
+ <di:waypoint x="1116" y="120" />
172
+ <bpmndi:BPMNLabel>
173
+ <dc:Bounds x="875" y="98" width="32" height="14" />
174
+ </bpmndi:BPMNLabel>
175
+ </bpmndi:BPMNEdge>
176
+ <bpmndi:BPMNEdge id="BPMNEdge_f_toConvergeGw" bpmnElement="f_toConvergeGw">
177
+ <di:waypoint x="1216" y="120" />
178
+ <di:waypoint x="1316" y="120" />
179
+ </bpmndi:BPMNEdge>
180
+ <bpmndi:BPMNEdge id="BPMNEdge_f_noConverge" bpmnElement="f_noConverge">
181
+ <di:waypoint x="1366" y="120" />
182
+ <di:waypoint x="1666" y="120" />
183
+ <bpmndi:BPMNLabel>
184
+ <dc:Bounds x="1481" y="98" width="71" height="14" />
185
+ </bpmndi:BPMNLabel>
186
+ </bpmndi:BPMNEdge>
187
+ <bpmndi:BPMNEdge id="BPMNEdge_w_abandon" bpmnElement="w_abandon">
188
+ <di:waypoint x="1016" y="280" />
189
+ <di:waypoint x="1166" y="280" />
190
+ <di:waypoint x="1166" y="160" />
191
+ <bpmndi:BPMNLabel>
192
+ <dc:Bounds x="1065" y="258" width="53" height="14" />
193
+ </bpmndi:BPMNLabel>
194
+ </bpmndi:BPMNEdge>
195
+ <bpmndi:BPMNEdge id="BPMNEdge_w_escalate" bpmnElement="w_escalate">
196
+ <di:waypoint x="641" y="145" />
197
+ <di:waypoint x="641" y="280" />
198
+ <di:waypoint x="766" y="280" />
199
+ <bpmndi:BPMNLabel>
200
+ <dc:Bounds x="646" y="206" width="67" height="14" />
201
+ </bpmndi:BPMNLabel>
202
+ </bpmndi:BPMNEdge>
203
+ <bpmndi:BPMNEdge id="BPMNEdge_f_converge" bpmnElement="f_converge">
204
+ <di:waypoint x="1341" y="145" />
205
+ <di:waypoint x="1341" y="280" />
206
+ <di:waypoint x="1466" y="280" />
207
+ <bpmndi:BPMNLabel>
208
+ <dc:Bounds x="1346" y="206" width="60" height="14" />
209
+ </bpmndi:BPMNLabel>
210
+ </bpmndi:BPMNEdge>
211
+ <bpmndi:BPMNEdge id="BPMNEdge_w_toAnswerGw" bpmnElement="w_toAnswerGw">
212
+ <di:waypoint x="866" y="280" />
213
+ <di:waypoint x="966" y="280" />
214
+ </bpmndi:BPMNEdge>
215
+ <bpmndi:BPMNEdge id="BPMNEdge_f_toEndConverged" bpmnElement="f_toEndConverged">
216
+ <di:waypoint x="1566" y="280" />
217
+ <di:waypoint x="1684" y="280" />
218
+ <di:waypoint x="1684" y="138" />
219
+ </bpmndi:BPMNEdge>
220
+ <bpmndi:BPMNEdge id="BPMNEdge_w_sla" bpmnElement="w_sla">
221
+ <di:waypoint x="816" y="338" />
222
+ <di:waypoint x="816" y="358" />
223
+ <di:waypoint x="1166" y="358" />
224
+ <di:waypoint x="1166" y="160" />
225
+ <bpmndi:BPMNLabel>
226
+ <dc:Bounds x="1007" y="325" width="88" height="28" />
227
+ </bpmndi:BPMNLabel>
228
+ </bpmndi:BPMNEdge>
229
+ <bpmndi:BPMNEdge id="BPMNEdge_w_answerLoop" bpmnElement="w_answerLoop">
230
+ <di:waypoint x="991" y="305" />
231
+ <di:waypoint x="991" y="360" />
232
+ <di:waypoint x="466" y="360" />
233
+ <di:waypoint x="466" y="160" />
234
+ <bpmndi:BPMNLabel>
235
+ <dc:Bounds x="704" y="338" width="49" height="14" />
236
+ </bpmndi:BPMNLabel>
237
+ </bpmndi:BPMNEdge>
238
+ </bpmndi:BPMNPlane>
239
+ </bpmndi:BPMNDiagram>
240
+ </bpmn:definitions>