@nanobpm/nano-workforce 0.164.0 → 0.166.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.
package/CHANGELOG.md CHANGED
@@ -1,3 +1,15 @@
1
+ ## [0.166.0](https://github.com/nanobpm/nano-workforce/compare/v0.165.0...v0.166.0) (2026-08-31)
2
+
3
+ ### Features
4
+
5
+ * **cells:** s4 composition — feature/plan-fanout waves as callActivity ([#632](https://github.com/nanobpm/nano-workforce/issues/632)) ([#634](https://github.com/nanobpm/nano-workforce/issues/634)) ([44065ff](https://github.com/nanobpm/nano-workforce/commit/44065ff55ba7637ecaec31a6ef911a8464d65c63)), closes [#631](https://github.com/nanobpm/nano-workforce/issues/631) [#631](https://github.com/nanobpm/nano-workforce/issues/631)
6
+
7
+ ## [0.165.0](https://github.com/nanobpm/nano-workforce/compare/v0.164.0...v0.165.0) (2026-08-31)
8
+
9
+ ### Features
10
+
11
+ * **overview:** add Dismiss row action to Active Features grid ([#644](https://github.com/nanobpm/nano-workforce/issues/644)) ([cda5962](https://github.com/nanobpm/nano-workforce/commit/cda59628d31a37faf26e3a749b6443b33f532d7d)), closes [#643](https://github.com/nanobpm/nano-workforce/issues/643)
12
+
1
13
  ## [0.164.0](https://github.com/nanobpm/nano-workforce/compare/v0.163.3...v0.164.0) (2026-08-31)
2
14
 
3
15
  ### Features
@@ -6,11 +6,13 @@
6
6
  // per cell instead of copy-pasting the inlined subProcess three ways (#464 "the duplication today").
7
7
  //
8
8
  // These are STRUCTURAL invariants (the cells exist, keep their engine-native task types, and wire
9
- // escalation through the shared `human-escalation` cell). The live converge seam on `feature.bpmn`
10
- // stays an INLINE `pr.converge-feature` serviceTask: the engine (and the urban-testkit WASM engine)
11
- // treats a callActivity as a pass-through that never runs the called process, so a callActivity
12
- // converge would never enroll the PR (see `e2e/feature-run.e2e.ts`). This guard pins the
13
- // decomposition so the shared cells can't silently drift back into per-caller copies.
9
+ // escalation through the shared `human-escalation` cell) plus the live composition seam:
10
+ // `feature.bpmn` composes its converge step via a `callActivity` to the `converge-cell` (with an
11
+ // explicit `zeebe:ioMapping` carrying `ConvergeFeatureIn`), so the inlined `pr.converge-feature`
12
+ // serviceTask no longer sits on the feature path. Native callActivity execution is provided by
13
+ // urban-testkit 1.0.0 (#631) the earlier "engine pass-through" was the testkit's callActivity
14
+ // rewrite, removed in 1.0.0. This guard pins the decomposition so the shared cells can't silently
15
+ // drift back into per-caller copies.
14
16
  import { test } from "node:test";
15
17
  import { assert } from "#test-assert";
16
18
  import { readFileSync } from "node:fs";
@@ -63,21 +65,37 @@ test("wait-gate is a readiness-probe cell; human-escalation parks on the shared
63
65
  assert(/<zeebe:formDefinition\b[^>]*\bformId="feature-escalation"/.test(he), "human-escalation renders the feature-escalation form");
64
66
  });
65
67
 
66
- test("feature.bpmn composes its converge step as an inline pr.converge-feature serviceTask", () => {
67
- // The live converge seam must stay INLINE, not a callActivity to converge-cell: the engine
68
- // (and the urban-testkit WASM engine the e2e boots) treats a BPMN callActivity as an immediate
69
- // pass-through it never instantiates the called process, so the `pr.converge-feature` worker
70
- // would never run and the feature run could never reach `converging` / enroll its PR into the
71
- // convergence loop (proven by `e2e/feature-run.e2e.ts` "raise + converge"). The `converge-cell`
72
- // process still exists as a standalone, composable cell for future composition seams, but
73
- // feature.bpmn hands off converge directly so the behaviour is real.
68
+ test("feature.bpmn composes its converge step via callActivity to converge-cell — no inlined converge serviceTask", () => {
69
+ // The live converge seam composes the shared `converge-cell` via a `callActivity` with an explicit
70
+ // `zeebe:ioMapping` (mapping `ConvergeFeatureIn`'s fields into the child's process scope), rather
71
+ // than an inlined `pr.converge-feature` serviceTask. Native callActivity execution is provided by
72
+ // urban-testkit 1.0.0 (#631): the child process really instantiates, the `pr.converge-feature`
73
+ // worker runs, and the feature run reaches `converging` / enrolls its PR (proven by
74
+ // `e2e/feature-run.e2e.ts` "raise + converge"). The earlier "engine pass-through" was the testkit's
75
+ // callActivity rewrite, removed in 1.0.0 not an engine limitation.
74
76
  const xml = flat("feature");
75
77
  assert(
76
- /<bpmn:serviceTask\b[^>]*\bid="converge"[\s\S]*?<zeebe:taskDefinition\b[^>]*\btype="pr.converge-feature"/.test(xml),
77
- "feature.bpmn must compose converge as an inline pr.converge-feature serviceTask",
78
+ /<bpmn:callActivity\b[^>]*\bid="converge"[\s\S]*?<zeebe:calledElement\b[^>]*\bprocessId="converge-cell"/.test(xml),
79
+ "feature.bpmn must compose converge as a callActivity to converge-cell",
78
80
  );
79
81
  assert(
80
- !/<bpmn:callActivity\b[^>]*\bid="converge"/.test(xml),
81
- "feature.bpmn must not route its live converge step through a callActivity (a testkit/engine pass-through)",
82
+ !/<bpmn:serviceTask\b[^>]*\bid="converge"/.test(xml),
83
+ "feature.bpmn must not keep an inlined converge serviceTask once the cell is composed",
82
84
  );
85
+ // Pin the explicit `zeebe:ioMapping` itself: without it (or any of its inputs) the child cell
86
+ // receives no mapped scope and the engine-wasm `propagateAll*` incompatibility this seam avoids
87
+ // would silently return. Assert against the converge callActivity block alone so an ioMapping on
88
+ // any other element can't satisfy the guard.
89
+ const convergeBlock =
90
+ xml.match(/<bpmn:callActivity\b[^>]*\bid="converge"[\s\S]*?<\/bpmn:callActivity>/)?.[0] ?? "";
91
+ assert(
92
+ /<zeebe:ioMapping>[\s\S]*?<\/zeebe:ioMapping>/.test(convergeBlock),
93
+ "the converge callActivity must carry an explicit zeebe:ioMapping",
94
+ );
95
+ for (const field of ["featureKey", "prKey", "autoMerge"]) {
96
+ assert(
97
+ new RegExp(`<zeebe:input\\b[^>]*\\btarget="${field}"`).test(convergeBlock),
98
+ `the converge callActivity ioMapping must map ConvergeFeatureIn.${field} into the child scope`,
99
+ );
100
+ }
83
101
  });
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@nanobpm/nano-workforce",
3
- "version": "0.164.0",
3
+ "version": "0.166.0",
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",
@@ -187,6 +187,17 @@
187
187
  { "field": "delivery_label", "header": "Delivery" },
188
188
  { "field": "updated_at", "header": "Updated", "width": "9rem", "format": "datetime" }
189
189
  ],
190
+ "rowActions": [
191
+ {
192
+ "label": "Dismiss",
193
+ "confirm": "Tick off this finished run? It acknowledges the run as done and files it under History.",
194
+ "showWhenField": "stage_state",
195
+ "action": {
196
+ "path": "/app/api/actions/acknowledge-done",
197
+ "body": { "feature_key": "{{row.feature_key}}" }
198
+ }
199
+ }
200
+ ],
190
201
  "detail": {
191
202
  "fields": [
192
203
  { "field": "outcome", "label": "Outcome" }
@@ -264,16 +264,18 @@
264
264
  <bpmn:outgoing>f_converge</bpmn:outgoing>
265
265
  <bpmn:outgoing>f_noConverge</bpmn:outgoing>
266
266
  </bpmn:exclusiveGateway>
267
- <bpmn:serviceTask id="converge" name="Hand off to convergence loop">
267
+ <bpmn:callActivity id="converge" name="Converge cell">
268
268
  <bpmn:extensionElements>
269
- <zeebe:taskDefinition type="pr.converge-feature" />
270
- <zeebe:properties>
271
- <zeebe:property name="io.nanobpm.dataEnvelope.in" value="ConvergeFeatureIn" />
272
- </zeebe:properties>
269
+ <zeebe:calledElement processId="converge-cell" />
270
+ <zeebe:ioMapping>
271
+ <zeebe:input source="=featureKey" target="featureKey" />
272
+ <zeebe:input source="=prKey" target="prKey" />
273
+ <zeebe:input source="=autoMerge" target="autoMerge" />
274
+ </zeebe:ioMapping>
273
275
  </bpmn:extensionElements>
274
276
  <bpmn:incoming>f_converge</bpmn:incoming>
275
277
  <bpmn:outgoing>f_toEndConverged</bpmn:outgoing>
276
- </bpmn:serviceTask>
278
+ </bpmn:callActivity>
277
279
  <bpmn:endEvent id="End" name="Done">
278
280
  <bpmn:incoming>f_noConverge</bpmn:incoming>
279
281
  <bpmn:incoming>f_toEndConverged</bpmn:incoming>