@nanobpm/nano-workforce 0.171.2 → 0.171.3
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/CHANGELOG.md +6 -0
- package/app/deliveryDispatch.test.ts +6 -2
- package/app/escalationTaxonomy.ts +5 -4
- package/app/fineGrainedCells.test.ts +93 -0
- package/app/planFanoutCleanTerminal.test.ts +29 -26
- package/app/planFanoutPreflight.test.ts +11 -4
- package/app/service.ts +44 -25
- package/e2e/agent-answerable.e2e.ts +15 -12
- package/e2e/feature-preflight.e2e.ts +6 -4
- package/e2e/feature-run.e2e.ts +38 -26
- package/e2e/plan-fanout-sla.e2e.ts +14 -10
- package/e2e/plan-fanout.e2e.ts +26 -21
- package/nano.app.json +0 -4
- package/package.json +3 -3
- package/resources/processes/feature.bpmn +55 -175
- package/resources/processes/implement-cell.bpmn +78 -22
- package/resources/processes/plan-fanout.bpmn +245 -296
- package/workers/record-feature-escalation/worker.test.ts +74 -25
- package/workers/record-feature-escalation/worker.ts +79 -32
- package/workers/record-feature-implementing/worker.test.ts +31 -1
- package/workers/record-feature-implementing/worker.ts +36 -12
- package/workers/record-wave-escalation/worker.test.ts +0 -95
- package/workers/record-wave-escalation/worker.ts +0 -69
|
@@ -108,7 +108,10 @@ describe("plan-fanout escalation SLA + assignment (U5)", () => {
|
|
|
108
108
|
}
|
|
109
109
|
|
|
110
110
|
async function openTask(app: TestApp, processKey: string, elementId: string): Promise<InboxTask> {
|
|
111
|
-
|
|
111
|
+
// Root-scoped: the implement-stage escalation now parks on a `human-escalation` grandchild the
|
|
112
|
+
// shared `implement-cell` spawns (ADR 0006 S4); plan-level tasks (plan-review, trial-merge) still
|
|
113
|
+
// park on the root instance and remain discoverable under a root-scoped search (superset).
|
|
114
|
+
const tasks = await app.engine.searchUserTasks({ rootProcessInstanceKey: processKey });
|
|
112
115
|
const match = tasks.find((t) => t.elementId === elementId);
|
|
113
116
|
assert.ok(match, `expected an open ${elementId} user task (open: ${tasks.map((t) => t.elementId).join(", ")})`);
|
|
114
117
|
return match!;
|
|
@@ -118,7 +121,7 @@ describe("plan-fanout escalation SLA + assignment (U5)", () => {
|
|
|
118
121
|
* filter) and NOT by a bogus group — proving `zeebe:assignmentDefinition candidateGroups` took. */
|
|
119
122
|
async function assertAssignmentFilterable(app: TestApp, processKey: string, elementId: string) {
|
|
120
123
|
const byOperators = await app.engine.searchUserTasks({
|
|
121
|
-
|
|
124
|
+
rootProcessInstanceKey: processKey,
|
|
122
125
|
candidateGroup: "operators",
|
|
123
126
|
});
|
|
124
127
|
assert.ok(
|
|
@@ -126,7 +129,7 @@ describe("plan-fanout escalation SLA + assignment (U5)", () => {
|
|
|
126
129
|
`${elementId} is filterable by the operators candidate group`,
|
|
127
130
|
);
|
|
128
131
|
const byBogus = await app.engine.searchUserTasks({
|
|
129
|
-
|
|
132
|
+
rootProcessInstanceKey: processKey,
|
|
130
133
|
candidateGroup: "nobody-here",
|
|
131
134
|
});
|
|
132
135
|
assert.ok(
|
|
@@ -150,20 +153,21 @@ describe("plan-fanout escalation SLA + assignment (U5)", () => {
|
|
|
150
153
|
}),
|
|
151
154
|
},
|
|
152
155
|
async ({ app, processKey }) => {
|
|
153
|
-
await openTask(app, processKey, "
|
|
154
|
-
await assertAssignmentFilterable(app, processKey, "
|
|
156
|
+
await openTask(app, processKey, "escalation");
|
|
157
|
+
await assertAssignmentFilterable(app, processKey, "escalation");
|
|
155
158
|
|
|
156
|
-
// Never answer — let the SLA elapse. The interrupting boundary
|
|
157
|
-
//
|
|
159
|
+
// Never answer — let the SLA elapse. The interrupting boundary (on the human-escalation cell's
|
|
160
|
+
// `escalation` task) cancels the parked task and routes to its SLA auto-abandon end; the cell
|
|
161
|
+
// then takes its abandon default (the safe auto-abandon of the slice).
|
|
158
162
|
await advancePastTimer(app, PAST_SLA_MS);
|
|
159
163
|
|
|
160
164
|
const flows = takenFlows(app);
|
|
161
165
|
assert.ok(
|
|
162
|
-
flows.includes("
|
|
163
|
-
`the SLA boundary auto-abandoned to the
|
|
166
|
+
flows.includes("be_he_sla->he_end_sla"),
|
|
167
|
+
`the SLA boundary auto-abandoned to the human-escalation cell's SLA end (flows: ${flows.join(", ")})`,
|
|
164
168
|
);
|
|
165
169
|
assert.ok(
|
|
166
|
-
!flows.includes("
|
|
170
|
+
!flows.includes("ic_gw_answer->record-implementing"),
|
|
167
171
|
"the human answer loop was NOT taken",
|
|
168
172
|
);
|
|
169
173
|
},
|
package/e2e/plan-fanout.e2e.ts
CHANGED
|
@@ -106,7 +106,11 @@ describe("plan-fanout escalations (U2 — task + plan-review + trial-merge → u
|
|
|
106
106
|
}
|
|
107
107
|
|
|
108
108
|
async function openTask(app: TestApp, processKey: string, elementId: string): Promise<InboxTask> {
|
|
109
|
-
|
|
109
|
+
// Root-scoped: the implement-stage escalation now parks on a `human-escalation` grandchild the
|
|
110
|
+
// shared `implement-cell` spawns (ADR 0006 S4); plan-level tasks (plan-review, empty-plan,
|
|
111
|
+
// trial-merge, the caps-timeout `feature-escalation`) still park on the root and remain
|
|
112
|
+
// discoverable under a root-scoped search (a superset of the parent's own tasks).
|
|
113
|
+
const tasks = await app.engine.searchUserTasks({ rootProcessInstanceKey: processKey });
|
|
110
114
|
const match = tasks.find((t) => t.elementId === elementId);
|
|
111
115
|
assert.ok(match, `expected an open ${elementId} user task (open: ${tasks.map((t) => t.elementId).join(", ")})`);
|
|
112
116
|
return match!;
|
|
@@ -131,20 +135,20 @@ describe("plan-fanout escalations (U2 — task + plan-review + trial-merge → u
|
|
|
131
135
|
},
|
|
132
136
|
},
|
|
133
137
|
async ({ app, processKey }) => {
|
|
134
|
-
const task = await openTask(app, processKey, "
|
|
135
|
-
assert.ok(task.userTaskKey, "the
|
|
138
|
+
const task = await openTask(app, processKey, "escalation");
|
|
139
|
+
assert.ok(task.userTaskKey, "the human-escalation cell task carries a completable userTaskKey");
|
|
136
140
|
|
|
137
|
-
// Answer it: the typed resolution loops the
|
|
141
|
+
// Answer it: the typed resolution loops the cell back to re-dispatch the SAME task.
|
|
138
142
|
await app.engine.completeUserTask(task.userTaskKey, { resolution: "answer", answer: "use v2" });
|
|
139
143
|
await app.settle();
|
|
140
144
|
|
|
141
145
|
const flows = takenFlows(app);
|
|
142
146
|
assert.ok(
|
|
143
|
-
flows.includes("
|
|
144
|
-
`answer routed back to implement-task (flows: ${flows.join(", ")})`,
|
|
147
|
+
flows.includes("ic_gw_answer->record-implementing") && flows.includes("record-implementing->implement-task"),
|
|
148
|
+
`answer routed back to implement-task through the cell reset (flows: ${flows.join(", ")})`,
|
|
145
149
|
);
|
|
146
150
|
assert.ok(
|
|
147
|
-
!flows.includes("
|
|
151
|
+
!flows.includes("ic_gw_answer->ic_end"),
|
|
148
152
|
"the abandon (default) flow was NOT taken",
|
|
149
153
|
);
|
|
150
154
|
},
|
|
@@ -163,17 +167,17 @@ describe("plan-fanout escalations (U2 — task + plan-review + trial-merge → u
|
|
|
163
167
|
}),
|
|
164
168
|
},
|
|
165
169
|
async ({ app, processKey }) => {
|
|
166
|
-
const task = await openTask(app, processKey, "
|
|
170
|
+
const task = await openTask(app, processKey, "escalation");
|
|
167
171
|
await app.engine.completeUserTask(task.userTaskKey, { resolution: "abandon" });
|
|
168
172
|
await app.settle();
|
|
169
173
|
|
|
170
174
|
const flows = takenFlows(app);
|
|
171
175
|
assert.ok(
|
|
172
|
-
flows.includes("
|
|
173
|
-
`abandon routed to the task-done end (flows: ${flows.join(", ")})`,
|
|
176
|
+
flows.includes("ic_gw_answer->ic_end"),
|
|
177
|
+
`abandon routed to the cell's task-done end (flows: ${flows.join(", ")})`,
|
|
174
178
|
);
|
|
175
179
|
assert.ok(
|
|
176
|
-
!flows.includes("
|
|
180
|
+
!flows.includes("ic_gw_answer->record-implementing"),
|
|
177
181
|
"the answer loop was NOT taken",
|
|
178
182
|
);
|
|
179
183
|
},
|
|
@@ -454,7 +458,7 @@ describe("plan-fanout escalations (U2 — task + plan-review + trial-merge → u
|
|
|
454
458
|
`task with needs routed through the barrier gateway to wait-caps-resolved (flows: ${parked.join(", ")})`,
|
|
455
459
|
);
|
|
456
460
|
assert.ok(
|
|
457
|
-
!parked.includes("w_gw_needs->implement-
|
|
461
|
+
!parked.includes("w_gw_needs->implement-cell-call"),
|
|
458
462
|
"the no-needs shortcut was NOT taken for a task that declares needs",
|
|
459
463
|
);
|
|
460
464
|
assert.equal(featureBrief, undefined, "the agent has not been dispatched while parked at the barrier");
|
|
@@ -471,8 +475,8 @@ describe("plan-fanout escalations (U2 — task + plan-review + trial-merge → u
|
|
|
471
475
|
|
|
472
476
|
const flows = takenFlows(app);
|
|
473
477
|
assert.ok(
|
|
474
|
-
flows.includes("wait-caps-resolved->implement-task"),
|
|
475
|
-
`caps-resolved released the barrier into implement
|
|
478
|
+
flows.includes("wait-caps-resolved->implement-cell-call") && flows.includes("Start->implement-task"),
|
|
479
|
+
`caps-resolved released the barrier into the implement cell (flows: ${flows.join(", ")})`,
|
|
476
480
|
);
|
|
477
481
|
assert.equal(
|
|
478
482
|
featureBrief,
|
|
@@ -534,15 +538,16 @@ describe("plan-fanout escalations (U2 — task + plan-review + trial-merge → u
|
|
|
534
538
|
`the caps bound escalated the parked task to the operator (flows: ${flows.join(", ")})`,
|
|
535
539
|
);
|
|
536
540
|
assert.ok(
|
|
537
|
-
!flows.includes("wait-caps-resolved->implement-
|
|
541
|
+
!flows.includes("wait-caps-resolved->implement-cell-call"),
|
|
538
542
|
"the resolve arm was withdrawn — the token did not also proceed as if resolved",
|
|
539
543
|
);
|
|
540
544
|
assert.equal(featureRan, false, "the agent was NOT dispatched — the unresolved task escalated instead");
|
|
541
545
|
|
|
542
|
-
// The escalation is a genuine, operable operator decision point: answering it
|
|
543
|
-
//
|
|
544
|
-
//
|
|
545
|
-
//
|
|
546
|
+
// The escalation is a genuine, operable operator decision point: answering it releases the
|
|
547
|
+
// caps barrier into the implement cell (the operator having unblocked/decided), proving this is
|
|
548
|
+
// a real bounded wait + operator escalation, not a dead end. This is the plan-fanout's OWN
|
|
549
|
+
// caps-timeout `feature-escalation` task (the fan-out-specific barrier is surrounding
|
|
550
|
+
// orchestration, retained per ADR 0006 S4), distinct from the implement cell's `escalation`.
|
|
546
551
|
const task = await openTask(app, processKey, "feature-escalation");
|
|
547
552
|
assert.ok(task.userTaskKey, "the caps-timeout escalation carries a completable userTaskKey");
|
|
548
553
|
await app.engine.completeUserTask(task.userTaskKey, { resolution: "answer", answer: "shipped it manually" });
|
|
@@ -550,8 +555,8 @@ describe("plan-fanout escalations (U2 — task + plan-review + trial-merge → u
|
|
|
550
555
|
|
|
551
556
|
const answered = takenFlows(app);
|
|
552
557
|
assert.ok(
|
|
553
|
-
answered.includes("w_gw_answer->implement-task"),
|
|
554
|
-
`answering the caps escalation
|
|
558
|
+
answered.includes("w_gw_answer->implement-cell-call") && answered.includes("Start->implement-task"),
|
|
559
|
+
`answering the caps escalation released the barrier into the implement cell (flows: ${answered.join(", ")})`,
|
|
555
560
|
);
|
|
556
561
|
assert.equal(featureRan, true, "the agent was dispatched once the operator answered the caps escalation");
|
|
557
562
|
},
|
package/nano.app.json
CHANGED
|
@@ -172,10 +172,6 @@
|
|
|
172
172
|
"taskType": "pr.record-wave",
|
|
173
173
|
"handler": "workers/record-wave/worker.ts"
|
|
174
174
|
},
|
|
175
|
-
{
|
|
176
|
-
"taskType": "pr.record-wave-escalation",
|
|
177
|
-
"handler": "workers/record-wave-escalation/worker.ts"
|
|
178
|
-
},
|
|
179
175
|
{
|
|
180
176
|
"taskType": "pr.record-feature",
|
|
181
177
|
"handler": "workers/record-feature/worker.ts"
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@nanobpm/nano-workforce",
|
|
3
|
-
"version": "0.171.
|
|
3
|
+
"version": "0.171.3",
|
|
4
4
|
"description": "Nano Workforce — an Agent Graph Orchestration application for Agentic SDLC: durable BPMN processes that coordinate a graph of AI agents across the software delivery lifecycle.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "main.ts",
|
|
@@ -63,12 +63,12 @@
|
|
|
63
63
|
},
|
|
64
64
|
"dependencies": {
|
|
65
65
|
"@nanobpm/agentic": "^0.10.0",
|
|
66
|
-
"@nanobpm/urban": "^0.
|
|
66
|
+
"@nanobpm/urban": "^0.90.0",
|
|
67
67
|
"bpmn-auto-layout": "^2.0.0-alpha.2"
|
|
68
68
|
},
|
|
69
69
|
"devDependencies": {
|
|
70
70
|
"@biomejs/biome": "^2.4.11",
|
|
71
|
-
"@nanobpm/urban-testkit": "^1.0
|
|
71
|
+
"@nanobpm/urban-testkit": "^1.2.0",
|
|
72
72
|
"@nanobpm/workflow": "^0.14.0",
|
|
73
73
|
"@semantic-release/changelog": "^7.0.0",
|
|
74
74
|
"@semantic-release/git": "^11.0.0",
|
|
@@ -9,12 +9,9 @@
|
|
|
9
9
|
<nano:extend name="pr" type="string" optional="true" />
|
|
10
10
|
<nano:extend name="summary" type="string" optional="true" />
|
|
11
11
|
</nano:shape>
|
|
12
|
-
<nano:shape id="RecordFeatureEscalationIn" name="Record feature escalation — input">
|
|
13
|
-
<nano:extend name="featureKey" type="string" />
|
|
14
|
-
<nano:extend name="question" type="string" optional="true" />
|
|
15
|
-
</nano:shape>
|
|
16
12
|
<nano:shape id="RecordFeatureImplementingIn" name="Record feature implementing — input">
|
|
17
|
-
<nano:extend name="featureKey" type="string" />
|
|
13
|
+
<nano:extend name="featureKey" type="string" optional="true" />
|
|
14
|
+
<nano:extend name="subjectKey" type="string" optional="true" />
|
|
18
15
|
</nano:shape>
|
|
19
16
|
<nano:shape id="ConvergeFeatureIn" name="Converge feature PR — input">
|
|
20
17
|
<nano:extend name="featureKey" type="string" />
|
|
@@ -172,23 +169,28 @@
|
|
|
172
169
|
<bpmn:incoming>f_readiness_done</bpmn:incoming>
|
|
173
170
|
<bpmn:outgoing>f_toImplement</bpmn:outgoing>
|
|
174
171
|
</bpmn:serviceTask>
|
|
175
|
-
<bpmn:
|
|
172
|
+
<bpmn:callActivity id="implement" name="Implement cell">
|
|
176
173
|
<bpmn:extensionElements>
|
|
177
|
-
<zeebe:
|
|
178
|
-
<zeebe:linkedResources>
|
|
179
|
-
<zeebe:linkedResource resourceId="prompts/feature.md" bindingType="latest" resourceType="GenericScript" linkName="prompt" />
|
|
180
|
-
</zeebe:linkedResources>
|
|
174
|
+
<zeebe:calledElement processId="implement-cell" />
|
|
181
175
|
<zeebe:ioMapping>
|
|
182
|
-
<zeebe:input source="
|
|
176
|
+
<zeebe:input source="=task" target="task" />
|
|
177
|
+
<zeebe:input source="=if (is defined(baseBranchBrief)) then baseBranchBrief else null" target="baseBranchBrief" />
|
|
178
|
+
<zeebe:input source="=if (is defined(resolvedArtifacts)) then resolvedArtifacts else null" target="resolvedArtifacts" />
|
|
179
|
+
<zeebe:input source="=if (is defined(customInstructions)) then customInstructions else null" target="customInstructions" />
|
|
183
180
|
<zeebe:input source="=if (is defined(transcriptUrlBase)) then transcriptUrlBase else null" target="transcriptUrlBase" />
|
|
181
|
+
<zeebe:input source="=if (is defined(escalationAssignee)) then escalationAssignee else null" target="escalationAssignee" />
|
|
182
|
+
<zeebe:input source="=escalationSlaTimeout" target="escalationSlaTimeout" />
|
|
183
|
+
<zeebe:input source="=featureKey" target="subjectKey" />
|
|
184
184
|
<zeebe:output source="=status" target="status" />
|
|
185
|
-
<zeebe:output source="=
|
|
185
|
+
<zeebe:output source="=if (is defined(summary)) then summary else null" target="summary" />
|
|
186
|
+
<zeebe:output source="=if (is defined(pr)) then pr else null" target="pr" />
|
|
187
|
+
<zeebe:output source="=if (is defined(question)) then question else null" target="question" />
|
|
186
188
|
<zeebe:output source="=if (is defined(transcriptUrl)) then transcriptUrl else null" target="transcriptUrl" />
|
|
187
189
|
</zeebe:ioMapping>
|
|
188
190
|
</bpmn:extensionElements>
|
|
189
191
|
<bpmn:incoming>f_implementing</bpmn:incoming>
|
|
190
|
-
<bpmn:outgoing>
|
|
191
|
-
</bpmn:
|
|
192
|
+
<bpmn:outgoing>w_toRecord</bpmn:outgoing>
|
|
193
|
+
</bpmn:callActivity>
|
|
192
194
|
<bpmn:serviceTask id="record-feature-implementing" name="Record implementing">
|
|
193
195
|
<bpmn:extensionElements>
|
|
194
196
|
<zeebe:taskDefinition type="pr.record-feature-implementing" />
|
|
@@ -197,44 +199,8 @@
|
|
|
197
199
|
</zeebe:properties>
|
|
198
200
|
</bpmn:extensionElements>
|
|
199
201
|
<bpmn:incoming>f_toImplement</bpmn:incoming>
|
|
200
|
-
<bpmn:incoming>w_answerLoop</bpmn:incoming>
|
|
201
202
|
<bpmn:outgoing>f_implementing</bpmn:outgoing>
|
|
202
203
|
</bpmn:serviceTask>
|
|
203
|
-
<bpmn:exclusiveGateway id="w_gw" name="escalated?" default="w_done">
|
|
204
|
-
<bpmn:incoming>w_toGw</bpmn:incoming>
|
|
205
|
-
<bpmn:outgoing>w_escalate</bpmn:outgoing>
|
|
206
|
-
<bpmn:outgoing>w_done</bpmn:outgoing>
|
|
207
|
-
</bpmn:exclusiveGateway>
|
|
208
|
-
<bpmn:serviceTask id="record-feature-escalation" name="Record escalation">
|
|
209
|
-
<bpmn:extensionElements>
|
|
210
|
-
<zeebe:taskDefinition type="pr.record-feature-escalation" />
|
|
211
|
-
<zeebe:properties>
|
|
212
|
-
<zeebe:property name="io.nanobpm.dataEnvelope.in" value="RecordFeatureEscalationIn" />
|
|
213
|
-
</zeebe:properties>
|
|
214
|
-
</bpmn:extensionElements>
|
|
215
|
-
<bpmn:incoming>w_escalate</bpmn:incoming>
|
|
216
|
-
<bpmn:outgoing>w_toEscalationTask</bpmn:outgoing>
|
|
217
|
-
</bpmn:serviceTask>
|
|
218
|
-
<bpmn:userTask id="feature-escalation" name="Task escalation (human)">
|
|
219
|
-
<bpmn:extensionElements>
|
|
220
|
-
<zeebe:formDefinition formId="feature-escalation" />
|
|
221
|
-
<zeebe:userTask />
|
|
222
|
-
<zeebe:assignmentDefinition candidateGroups="operators" assignee="=if (is defined(escalationAssignee) and escalationAssignee != null and trim(string(escalationAssignee)) != "") then escalationAssignee else null" />
|
|
223
|
-
</bpmn:extensionElements>
|
|
224
|
-
<bpmn:incoming>w_toEscalationTask</bpmn:incoming>
|
|
225
|
-
<bpmn:outgoing>w_toAnswerGw</bpmn:outgoing>
|
|
226
|
-
</bpmn:userTask>
|
|
227
|
-
<bpmn:boundaryEvent id="be_feature_sla" name="SLA elapsed" attachedToRef="feature-escalation">
|
|
228
|
-
<bpmn:outgoing>w_sla</bpmn:outgoing>
|
|
229
|
-
<bpmn:timerEventDefinition id="ted_feature_sla">
|
|
230
|
-
<bpmn:timeDuration xsi:type="bpmn:tFormalExpression">=escalationSlaTimeout</bpmn:timeDuration>
|
|
231
|
-
</bpmn:timerEventDefinition>
|
|
232
|
-
</bpmn:boundaryEvent>
|
|
233
|
-
<bpmn:exclusiveGateway id="w_gw_answer" name="answer?" default="w_abandon">
|
|
234
|
-
<bpmn:incoming>w_toAnswerGw</bpmn:incoming>
|
|
235
|
-
<bpmn:outgoing>w_answerLoop</bpmn:outgoing>
|
|
236
|
-
<bpmn:outgoing>w_abandon</bpmn:outgoing>
|
|
237
|
-
</bpmn:exclusiveGateway>
|
|
238
204
|
<bpmn:serviceTask id="record-feature" name="Record result">
|
|
239
205
|
<bpmn:extensionElements>
|
|
240
206
|
<zeebe:taskDefinition type="pr.record-feature" />
|
|
@@ -242,9 +208,7 @@
|
|
|
242
208
|
<zeebe:property name="io.nanobpm.dataEnvelope.in" value="RecordFeatureIn" />
|
|
243
209
|
</zeebe:properties>
|
|
244
210
|
</bpmn:extensionElements>
|
|
245
|
-
<bpmn:incoming>
|
|
246
|
-
<bpmn:incoming>w_abandon</bpmn:incoming>
|
|
247
|
-
<bpmn:incoming>w_sla</bpmn:incoming>
|
|
211
|
+
<bpmn:incoming>w_toRecord</bpmn:incoming>
|
|
248
212
|
<bpmn:outgoing>f_toBlockedGw</bpmn:outgoing>
|
|
249
213
|
</bpmn:serviceTask>
|
|
250
214
|
<bpmn:exclusiveGateway id="gw-blocked" name="blocked?" default="f_notBlocked">
|
|
@@ -301,19 +265,8 @@
|
|
|
301
265
|
<bpmn:sequenceFlow id="f_readiness_skip" name="no gate" sourceRef="gw-readiness" targetRef="ensure-base-branch" />
|
|
302
266
|
<bpmn:sequenceFlow id="f_readiness_done" sourceRef="readiness-preflight" targetRef="ensure-base-branch" />
|
|
303
267
|
<bpmn:sequenceFlow id="f_toImplement" sourceRef="ensure-base-branch" targetRef="record-feature-implementing" />
|
|
304
|
-
<bpmn:sequenceFlow id="f_implementing" sourceRef="record-feature-implementing" targetRef="implement
|
|
305
|
-
<bpmn:sequenceFlow id="
|
|
306
|
-
<bpmn:sequenceFlow id="w_escalate" name="escalated" sourceRef="w_gw" targetRef="record-feature-escalation">
|
|
307
|
-
<bpmn:conditionExpression xsi:type="bpmn:tFormalExpression">=status = "escalated" and question != null and trim(question) != ""</bpmn:conditionExpression>
|
|
308
|
-
</bpmn:sequenceFlow>
|
|
309
|
-
<bpmn:sequenceFlow id="w_toEscalationTask" sourceRef="record-feature-escalation" targetRef="feature-escalation" />
|
|
310
|
-
<bpmn:sequenceFlow id="w_done" name="done" sourceRef="w_gw" targetRef="record-feature" />
|
|
311
|
-
<bpmn:sequenceFlow id="w_toAnswerGw" sourceRef="feature-escalation" targetRef="w_gw_answer" />
|
|
312
|
-
<bpmn:sequenceFlow id="w_answerLoop" name="answer" sourceRef="w_gw_answer" targetRef="record-feature-implementing">
|
|
313
|
-
<bpmn:conditionExpression xsi:type="bpmn:tFormalExpression">=resolution = "answer"</bpmn:conditionExpression>
|
|
314
|
-
</bpmn:sequenceFlow>
|
|
315
|
-
<bpmn:sequenceFlow id="w_abandon" name="abandon" sourceRef="w_gw_answer" targetRef="record-feature" />
|
|
316
|
-
<bpmn:sequenceFlow id="w_sla" name="SLA auto-abandon" sourceRef="be_feature_sla" targetRef="record-feature" />
|
|
268
|
+
<bpmn:sequenceFlow id="f_implementing" sourceRef="record-feature-implementing" targetRef="implement" />
|
|
269
|
+
<bpmn:sequenceFlow id="w_toRecord" sourceRef="implement" targetRef="record-feature" />
|
|
317
270
|
<bpmn:sequenceFlow id="f_toBlockedGw" sourceRef="record-feature" targetRef="gw-blocked" />
|
|
318
271
|
<bpmn:sequenceFlow id="f_blocked" name="blocked" sourceRef="gw-blocked" targetRef="feature-blocked">
|
|
319
272
|
<bpmn:conditionExpression xsi:type="bpmn:tFormalExpression">=featureStatus = "blocked"</bpmn:conditionExpression>
|
|
@@ -347,64 +300,40 @@
|
|
|
347
300
|
<bpmndi:BPMNShape id="BPMNShape_ensure-base-branch" bpmnElement="ensure-base-branch">
|
|
348
301
|
<dc:Bounds x="566" y="80" width="100" height="80" />
|
|
349
302
|
</bpmndi:BPMNShape>
|
|
350
|
-
<bpmndi:BPMNShape id="BPMNShape_implement
|
|
303
|
+
<bpmndi:BPMNShape id="BPMNShape_implement" bpmnElement="implement">
|
|
351
304
|
<dc:Bounds x="966" y="80" width="100" height="80" />
|
|
352
305
|
</bpmndi:BPMNShape>
|
|
353
306
|
<bpmndi:BPMNShape id="BPMNShape_record-feature-implementing" bpmnElement="record-feature-implementing">
|
|
354
307
|
<dc:Bounds x="766" y="80" width="100" height="80" />
|
|
355
308
|
</bpmndi:BPMNShape>
|
|
356
|
-
<bpmndi:BPMNShape id="BPMNShape_w_gw" bpmnElement="w_gw" isMarkerVisible="true">
|
|
357
|
-
<dc:Bounds x="1166" y="95" width="50" height="50" />
|
|
358
|
-
<bpmndi:BPMNLabel>
|
|
359
|
-
<dc:Bounds x="1154" y="76" width="74" height="14" />
|
|
360
|
-
</bpmndi:BPMNLabel>
|
|
361
|
-
</bpmndi:BPMNShape>
|
|
362
|
-
<bpmndi:BPMNShape id="BPMNShape_record-feature-escalation" bpmnElement="record-feature-escalation">
|
|
363
|
-
<dc:Bounds x="1316" y="240" width="100" height="80" />
|
|
364
|
-
</bpmndi:BPMNShape>
|
|
365
|
-
<bpmndi:BPMNShape id="BPMNShape_feature-escalation" bpmnElement="feature-escalation">
|
|
366
|
-
<dc:Bounds x="1516" y="240" width="100" height="80" />
|
|
367
|
-
</bpmndi:BPMNShape>
|
|
368
|
-
<bpmndi:BPMNShape id="BPMNShape_w_gw_answer" bpmnElement="w_gw_answer" isMarkerVisible="true">
|
|
369
|
-
<dc:Bounds x="1716" y="255" width="50" height="50" />
|
|
370
|
-
<bpmndi:BPMNLabel>
|
|
371
|
-
<dc:Bounds x="1713" y="236" width="56" height="14" />
|
|
372
|
-
</bpmndi:BPMNLabel>
|
|
373
|
-
</bpmndi:BPMNShape>
|
|
374
309
|
<bpmndi:BPMNShape id="BPMNShape_record-feature" bpmnElement="record-feature">
|
|
375
|
-
<dc:Bounds x="
|
|
310
|
+
<dc:Bounds x="1166" y="80" width="100" height="80" />
|
|
376
311
|
</bpmndi:BPMNShape>
|
|
377
312
|
<bpmndi:BPMNShape id="BPMNShape_gw-blocked" bpmnElement="gw-blocked" isMarkerVisible="true">
|
|
378
|
-
<dc:Bounds x="
|
|
313
|
+
<dc:Bounds x="1366" y="95" width="50" height="50" />
|
|
379
314
|
<bpmndi:BPMNLabel>
|
|
380
|
-
<dc:Bounds x="
|
|
315
|
+
<dc:Bounds x="1361" y="76" width="60" height="14" />
|
|
381
316
|
</bpmndi:BPMNLabel>
|
|
382
317
|
</bpmndi:BPMNShape>
|
|
383
318
|
<bpmndi:BPMNShape id="BPMNShape_feature-blocked" bpmnElement="feature-blocked">
|
|
384
|
-
<dc:Bounds x="
|
|
319
|
+
<dc:Bounds x="1516" y="400" width="100" height="80" />
|
|
385
320
|
</bpmndi:BPMNShape>
|
|
386
321
|
<bpmndi:BPMNShape id="BPMNShape_record-blocked-ack" bpmnElement="record-blocked-ack">
|
|
387
|
-
<dc:Bounds x="
|
|
322
|
+
<dc:Bounds x="1716" y="400" width="100" height="80" />
|
|
388
323
|
</bpmndi:BPMNShape>
|
|
389
324
|
<bpmndi:BPMNShape id="BPMNShape_gw-converge" bpmnElement="gw-converge" isMarkerVisible="true">
|
|
390
|
-
<dc:Bounds x="
|
|
325
|
+
<dc:Bounds x="1541" y="95" width="50" height="50" />
|
|
391
326
|
<bpmndi:BPMNLabel>
|
|
392
|
-
<dc:Bounds x="
|
|
327
|
+
<dc:Bounds x="1533" y="76" width="67" height="14" />
|
|
393
328
|
</bpmndi:BPMNLabel>
|
|
394
329
|
</bpmndi:BPMNShape>
|
|
395
330
|
<bpmndi:BPMNShape id="BPMNShape_converge" bpmnElement="converge">
|
|
396
|
-
<dc:Bounds x="
|
|
331
|
+
<dc:Bounds x="1716" y="240" width="100" height="80" />
|
|
397
332
|
</bpmndi:BPMNShape>
|
|
398
333
|
<bpmndi:BPMNShape id="BPMNShape_End" bpmnElement="End">
|
|
399
|
-
<dc:Bounds x="
|
|
400
|
-
<bpmndi:BPMNLabel>
|
|
401
|
-
<dc:Bounds x="2617" y="83" width="34" height="14" />
|
|
402
|
-
</bpmndi:BPMNLabel>
|
|
403
|
-
</bpmndi:BPMNShape>
|
|
404
|
-
<bpmndi:BPMNShape id="BPMNShape_be_feature_sla" bpmnElement="be_feature_sla">
|
|
405
|
-
<dc:Bounds x="1548" y="302" width="36" height="36" />
|
|
334
|
+
<dc:Bounds x="1916" y="102" width="36" height="36" />
|
|
406
335
|
<bpmndi:BPMNLabel>
|
|
407
|
-
<dc:Bounds x="
|
|
336
|
+
<dc:Bounds x="1917" y="83" width="34" height="14" />
|
|
408
337
|
</bpmndi:BPMNLabel>
|
|
409
338
|
</bpmndi:BPMNShape>
|
|
410
339
|
<bpmndi:BPMNEdge id="BPMNEdge_f_toReadinessGw" bpmnElement="f_toReadinessGw">
|
|
@@ -426,41 +355,26 @@
|
|
|
426
355
|
<di:waypoint x="866" y="120" />
|
|
427
356
|
<di:waypoint x="966" y="120" />
|
|
428
357
|
</bpmndi:BPMNEdge>
|
|
429
|
-
<bpmndi:BPMNEdge id="
|
|
358
|
+
<bpmndi:BPMNEdge id="BPMNEdge_w_toRecord" bpmnElement="w_toRecord">
|
|
430
359
|
<di:waypoint x="1066" y="120" />
|
|
431
360
|
<di:waypoint x="1166" y="120" />
|
|
432
361
|
</bpmndi:BPMNEdge>
|
|
433
|
-
<bpmndi:BPMNEdge id="BPMNEdge_w_done" bpmnElement="w_done">
|
|
434
|
-
<di:waypoint x="1216" y="120" />
|
|
435
|
-
<di:waypoint x="1866" y="120" />
|
|
436
|
-
<bpmndi:BPMNLabel>
|
|
437
|
-
<dc:Bounds x="1525" y="98" width="32" height="14" />
|
|
438
|
-
</bpmndi:BPMNLabel>
|
|
439
|
-
</bpmndi:BPMNEdge>
|
|
440
362
|
<bpmndi:BPMNEdge id="BPMNEdge_f_toBlockedGw" bpmnElement="f_toBlockedGw">
|
|
441
|
-
<di:waypoint x="
|
|
442
|
-
<di:waypoint x="
|
|
363
|
+
<di:waypoint x="1266" y="120" />
|
|
364
|
+
<di:waypoint x="1366" y="120" />
|
|
443
365
|
</bpmndi:BPMNEdge>
|
|
444
366
|
<bpmndi:BPMNEdge id="BPMNEdge_f_notBlocked" bpmnElement="f_notBlocked">
|
|
445
|
-
<di:waypoint x="
|
|
446
|
-
<di:waypoint x="
|
|
367
|
+
<di:waypoint x="1416" y="120" />
|
|
368
|
+
<di:waypoint x="1541" y="120" />
|
|
447
369
|
<bpmndi:BPMNLabel>
|
|
448
|
-
<dc:Bounds x="
|
|
370
|
+
<dc:Bounds x="1440" y="98" width="78" height="14" />
|
|
449
371
|
</bpmndi:BPMNLabel>
|
|
450
372
|
</bpmndi:BPMNEdge>
|
|
451
373
|
<bpmndi:BPMNEdge id="BPMNEdge_f_noConverge" bpmnElement="f_noConverge">
|
|
452
|
-
<di:waypoint x="
|
|
453
|
-
<di:waypoint x="
|
|
454
|
-
<bpmndi:BPMNLabel>
|
|
455
|
-
<dc:Bounds x="2418" y="98" width="71" height="14" />
|
|
456
|
-
</bpmndi:BPMNLabel>
|
|
457
|
-
</bpmndi:BPMNEdge>
|
|
458
|
-
<bpmndi:BPMNEdge id="BPMNEdge_w_abandon" bpmnElement="w_abandon">
|
|
459
|
-
<di:waypoint x="1766" y="280" />
|
|
460
|
-
<di:waypoint x="1916" y="280" />
|
|
461
|
-
<di:waypoint x="1916" y="160" />
|
|
374
|
+
<di:waypoint x="1591" y="120" />
|
|
375
|
+
<di:waypoint x="1916" y="120" />
|
|
462
376
|
<bpmndi:BPMNLabel>
|
|
463
|
-
<dc:Bounds x="
|
|
377
|
+
<dc:Bounds x="1718" y="98" width="71" height="14" />
|
|
464
378
|
</bpmndi:BPMNLabel>
|
|
465
379
|
</bpmndi:BPMNEdge>
|
|
466
380
|
<bpmndi:BPMNEdge id="BPMNEdge_f_readiness_gate" bpmnElement="f_readiness_gate">
|
|
@@ -471,28 +385,20 @@
|
|
|
471
385
|
<dc:Bounds x="246" y="206" width="39" height="14" />
|
|
472
386
|
</bpmndi:BPMNLabel>
|
|
473
387
|
</bpmndi:BPMNEdge>
|
|
474
|
-
<bpmndi:BPMNEdge id="BPMNEdge_w_escalate" bpmnElement="w_escalate">
|
|
475
|
-
<di:waypoint x="1191" y="145" />
|
|
476
|
-
<di:waypoint x="1191" y="280" />
|
|
477
|
-
<di:waypoint x="1316" y="280" />
|
|
478
|
-
<bpmndi:BPMNLabel>
|
|
479
|
-
<dc:Bounds x="1196" y="206" width="67" height="14" />
|
|
480
|
-
</bpmndi:BPMNLabel>
|
|
481
|
-
</bpmndi:BPMNEdge>
|
|
482
388
|
<bpmndi:BPMNEdge id="BPMNEdge_f_blocked" bpmnElement="f_blocked">
|
|
483
|
-
<di:waypoint x="
|
|
484
|
-
<di:waypoint x="
|
|
485
|
-
<di:waypoint x="
|
|
389
|
+
<di:waypoint x="1391" y="145" />
|
|
390
|
+
<di:waypoint x="1391" y="440" />
|
|
391
|
+
<di:waypoint x="1516" y="440" />
|
|
486
392
|
<bpmndi:BPMNLabel>
|
|
487
|
-
<dc:Bounds x="
|
|
393
|
+
<dc:Bounds x="1396" y="286" width="53" height="14" />
|
|
488
394
|
</bpmndi:BPMNLabel>
|
|
489
395
|
</bpmndi:BPMNEdge>
|
|
490
396
|
<bpmndi:BPMNEdge id="BPMNEdge_f_converge" bpmnElement="f_converge">
|
|
491
|
-
<di:waypoint x="
|
|
492
|
-
<di:waypoint x="
|
|
493
|
-
<di:waypoint x="
|
|
397
|
+
<di:waypoint x="1566" y="145" />
|
|
398
|
+
<di:waypoint x="1566" y="280" />
|
|
399
|
+
<di:waypoint x="1716" y="280" />
|
|
494
400
|
<bpmndi:BPMNLabel>
|
|
495
|
-
<dc:Bounds x="
|
|
401
|
+
<dc:Bounds x="1571" y="206" width="60" height="14" />
|
|
496
402
|
</bpmndi:BPMNLabel>
|
|
497
403
|
</bpmndi:BPMNEdge>
|
|
498
404
|
<bpmndi:BPMNEdge id="BPMNEdge_f_readiness_done" bpmnElement="f_readiness_done">
|
|
@@ -500,45 +406,19 @@
|
|
|
500
406
|
<di:waypoint x="616" y="280" />
|
|
501
407
|
<di:waypoint x="616" y="160" />
|
|
502
408
|
</bpmndi:BPMNEdge>
|
|
503
|
-
<bpmndi:BPMNEdge id="BPMNEdge_w_toEscalationTask" bpmnElement="w_toEscalationTask">
|
|
504
|
-
<di:waypoint x="1416" y="280" />
|
|
505
|
-
<di:waypoint x="1516" y="280" />
|
|
506
|
-
</bpmndi:BPMNEdge>
|
|
507
|
-
<bpmndi:BPMNEdge id="BPMNEdge_w_toAnswerGw" bpmnElement="w_toAnswerGw">
|
|
508
|
-
<di:waypoint x="1616" y="280" />
|
|
509
|
-
<di:waypoint x="1716" y="280" />
|
|
510
|
-
</bpmndi:BPMNEdge>
|
|
511
409
|
<bpmndi:BPMNEdge id="BPMNEdge_f_toBlockedAck" bpmnElement="f_toBlockedAck">
|
|
512
|
-
<di:waypoint x="
|
|
513
|
-
<di:waypoint x="
|
|
410
|
+
<di:waypoint x="1616" y="440" />
|
|
411
|
+
<di:waypoint x="1716" y="440" />
|
|
514
412
|
</bpmndi:BPMNEdge>
|
|
515
413
|
<bpmndi:BPMNEdge id="BPMNEdge_f_blockedEnd" bpmnElement="f_blockedEnd">
|
|
516
|
-
<di:waypoint x="
|
|
517
|
-
<di:waypoint x="
|
|
518
|
-
<di:waypoint x="
|
|
414
|
+
<di:waypoint x="1816" y="440" />
|
|
415
|
+
<di:waypoint x="1934" y="440" />
|
|
416
|
+
<di:waypoint x="1934" y="138" />
|
|
519
417
|
</bpmndi:BPMNEdge>
|
|
520
418
|
<bpmndi:BPMNEdge id="BPMNEdge_f_toEndConverged" bpmnElement="f_toEndConverged">
|
|
521
|
-
<di:waypoint x="
|
|
522
|
-
<di:waypoint x="
|
|
523
|
-
<di:waypoint x="
|
|
524
|
-
</bpmndi:BPMNEdge>
|
|
525
|
-
<bpmndi:BPMNEdge id="BPMNEdge_w_sla" bpmnElement="w_sla">
|
|
526
|
-
<di:waypoint x="1566" y="338" />
|
|
527
|
-
<di:waypoint x="1566" y="358" />
|
|
528
|
-
<di:waypoint x="1916" y="358" />
|
|
529
|
-
<di:waypoint x="1916" y="160" />
|
|
530
|
-
<bpmndi:BPMNLabel>
|
|
531
|
-
<dc:Bounds x="1757" y="325" width="88" height="28" />
|
|
532
|
-
</bpmndi:BPMNLabel>
|
|
533
|
-
</bpmndi:BPMNEdge>
|
|
534
|
-
<bpmndi:BPMNEdge id="BPMNEdge_w_answerLoop" bpmnElement="w_answerLoop">
|
|
535
|
-
<di:waypoint x="1741" y="305" />
|
|
536
|
-
<di:waypoint x="1741" y="360" />
|
|
537
|
-
<di:waypoint x="816" y="360" />
|
|
538
|
-
<di:waypoint x="816" y="160" />
|
|
539
|
-
<bpmndi:BPMNLabel>
|
|
540
|
-
<dc:Bounds x="1254" y="338" width="49" height="14" />
|
|
541
|
-
</bpmndi:BPMNLabel>
|
|
419
|
+
<di:waypoint x="1816" y="280" />
|
|
420
|
+
<di:waypoint x="1934" y="280" />
|
|
421
|
+
<di:waypoint x="1934" y="138" />
|
|
542
422
|
</bpmndi:BPMNEdge>
|
|
543
423
|
</bpmndi:BPMNPlane>
|
|
544
424
|
</bpmndi:BPMNDiagram>
|