@nanobpm/nano-workforce 0.138.1 → 0.138.2

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/AGENTS.md CHANGED
@@ -211,6 +211,42 @@ Two different `nano:dataEnvelope` uses have different rules — don't conflate t
211
211
  deriving a worker's array inputs from the model this way over a hand-typed
212
212
  `interface In`; don't "fix" a modelled `list="true"` array back to a joined
213
213
  scalar.
214
+ - **A service-task/worker `dataEnvelope.in` field is read from PROCESS scope, not
215
+ task-local `ioMapping`.** (This applies to service-task/worker job envelopes; a
216
+ `dataEnvelope.in` on a **message subscription** — e.g. `CapsResolved` at
217
+ `plan-fanout.bpmn:12` — is instead populated from the correlated **message
218
+ payload**, so this gotcha does not apply there.) At runtime the engine populates
219
+ each declared `.in` field *by name* from the process variables in scope — a
220
+ `<zeebe:ioMapping>` input that synthesises a **new** name with no backing process
221
+ variable is silently ignored, so the field arrives **blank**. The engine itself
222
+ raises no incident for that *omitted* field (an `.in` name with no backing
223
+ variable resolves to null and blanks) — but this is distinct from a FEEL
224
+ `ioMapping` that **errors**: on the pinned engine (`@nanobpm/engine-wasm` 0.8.1's
225
+ `IO_MAPPING_ERROR` fix — before it, a failed mapping silently blanked, e.g. a
226
+ blocked converge-gate's escalation *question*; see the `e2e/*escalation*.e2e.ts`
227
+ comments) a failed FEEL mapping now raises an **incident** rather than blanking
228
+ through. A consumer that fails fast on the blank value will also incident (e.g.
229
+ `pr.readiness-probe` once read an empty `gateKey`;
230
+ `readGateVars` in `workers/readiness-probe/worker.ts` now *throws* on a blank
231
+ `gateKey`, creating an incident). Tasks like `ensure-base-branch` work only because
232
+ `repo`/`baseBranch` already exist as process variables. Seed any field a task must
233
+ read — **that is not already created in the task's visible process scope** — as a
234
+ real process variable at plan start (e.g. in `startPlan`); don't rely on
235
+ `ioMapping` to synthesise it. (A field already materialised in scope by the
236
+ process — e.g. `ReadinessProbeIn.probe`, seeded per multi-instance child via
237
+ `inputElement="probe"` in `resources/processes/feature.bpmn` — needs no such
238
+ seeding.) A **constant/literal** ioMapping source is different again: a
239
+ `<zeebe:input source="=true" target="lastAttempt"/>` (the readiness-gate
240
+ boundary's last-attempt marker — `readiness-gate.bpmn:125`, `feature.bpmn:105`,
241
+ `plan-fanout.bpmn:198`, and the generated `deliveryGraphCompiler.ts:1011`) is
242
+ *evaluated* and materialised into the job's scope, so it needs **no** backing
243
+ process variable — its value is the literal, not a reference to an (absent)
244
+ variable. The "arrives blank" failure above is specific to a field whose value
245
+ must be *derived from a process variable that isn't in scope* (the `gateKey`
246
+ case). Do **not** "fix" a working literal marker like `lastAttempt` by seeding
247
+ it as a process variable: besides being unnecessary, seeding a var an
248
+ in-subprocess gateway reads re-introduces the multi-instance `=null`-shadow
249
+ gotcha above.
214
250
 
215
251
  ## Urban page runtime: rendering primitives are not JS-truthy
216
252
 
@@ -235,6 +271,21 @@ silently — cheap to avoid, annoying to debug after the fact.
235
271
  `showWhenField` is hidden for `0`/`null`/`""` alike — so a `0`-or-`NULL` flag
236
272
  correctly hides it either way. (This is why the same flag can need `NULL` for a
237
273
  badge yet work as `0` for a `showWhenField` button.)
274
+ - **Renderer kinds are a version-pinned set — verify against the installed
275
+ package, not an issue reference.** The page renderers are a finite set fixed by
276
+ the pinned `@nanobpm/urban`; a version *range* only guarantees *some* matching
277
+ build is installed. Do **not** assume a primitive exists because an issue,
278
+ changelog, or *Links* section mentions it — `urban check` (a CI gate) rejects
279
+ unknown renderer kinds only *after* you've authored a page around a phantom one
280
+ (epic #254 bounced three review rounds asserting a page-level "stepper" that
281
+ never shipped). Confirm the kind against the installed `RENDERERS` map
282
+ (`node_modules/@nanobpm/urban/dist/runtime/core/modules/pages.js`) and the kinds
283
+ already used across `pages/*.page.json`. Note a **nano-ide issue can ship a data
284
+ read-model, not a page renderer** (nano-ide#254 shipped the lineage projection, a data
285
+ primitive) — read *what kind* of primitive it delivers. Build composite visuals
286
+ as a `dataGrid` column renderer over stored columns (e.g. the `"kind":
287
+ "pipeline"` column in `pages/feature.page.json`), not a page-level primitive,
288
+ unless you've verified that primitive exists in the installed build.
238
289
 
239
290
  ### The top nav has a single source of truth — edit `pages/_nav.json`
240
291
 
@@ -271,10 +322,24 @@ Migrations live in `db/migrations/*.sql` and are **auto-applied on boot** from
271
322
  - Number a new migration after the current highest prefix (they apply in order).
272
323
  Check `origin/main`, not your branch point — a fan-out epic branch forks at one
273
324
  prefix while `main` keeps advancing, so the branch-local "next" number collides
274
- on merge. Two files must never share a prefix; `npm run check:migrations`
325
+ on merge. **In a *simultaneous* fan-out wave, checking `origin/main` isn't
326
+ enough**: every sibling forks at the same commit, sees the same highest prefix,
327
+ and independently takes the same next number (main hasn't advanced yet), so the
328
+ planner must **pre-assign each slice a disjoint prefix block at decomposition
329
+ time** (e.g. give slice A `NNN`–`NNN+1`, slice B `NNN+2`–`NNN+3`, plus a separate
330
+ cleanup block — start the whole allocation *after* the current highest committed
331
+ prefix, never at fixed literals like `060`, which are long occupied) rather than
332
+ have each
333
+ agent compute "the next free" prefix. (This is the same "coarsen parallel work on
334
+ a shared surface" principle as the one-task-owns-each-`.bpmn` rule above — a
335
+ migration-prefix block is a shared numbering surface just like a `.bpmn`
336
+ diagram.) Two files must never share a prefix; `npm run check:migrations`
275
337
  (a CI gate) enforces this and fails the build on any new duplicate. Because a
276
- prefix collision only exists in the *union* of two branches, this gate — like
277
- `layout:check` and the generated-artifact `--check`s is also re-run on the
338
+ **merge-skew** prefix collision only exists in the *union* of two branches (a
339
+ single branch that adds two same-prefix files is a self-collision
340
+ `check:migrations` already catches on the PR itself), this gate — like
341
+ `layout:check`, the navigation-index check (`sync:nav:check`), and a catch-all
342
+ committed-artifact backstop (`git diff --exit-code`) — is also re-run on the
278
343
  merge queue's **prospective merged commit** and on **push to `main`** by
279
344
  `.github/workflows/invariants.yml` (issue #366), so a merge-skew collision is
280
345
  blocked at merge time or fails a `main`-scoped build within minutes rather than
package/CHANGELOG.md CHANGED
@@ -1,3 +1,9 @@
1
+ ## [0.138.2](https://github.com/nanobpm/nano-workforce/compare/v0.138.1...v0.138.2) (2026-08-24)
2
+
3
+ ### Documentation
4
+
5
+ * **agents:** consolidate retro feedback ([#268](https://github.com/nanobpm/nano-workforce/issues/268), [#322](https://github.com/nanobpm/nano-workforce/issues/322), [#449](https://github.com/nanobpm/nano-workforce/issues/449)); drop stale [#415](https://github.com/nanobpm/nano-workforce/issues/415) ([#518](https://github.com/nanobpm/nano-workforce/issues/518)) ([3c47cb2](https://github.com/nanobpm/nano-workforce/commit/3c47cb21d079b6b9f5470abacb0190373208d0ca)), closes [#416](https://github.com/nanobpm/nano-workforce/issues/416) [#887](https://github.com/nanobpm/nano-workforce/issues/887) [#254](https://github.com/nanobpm/nano-workforce/issues/254) [#254](https://github.com/nanobpm/nano-workforce/issues/254) [nano-ide#254](https://github.com/nanobpm/nano-ide/issues/254)
6
+
1
7
  ## [0.138.1](https://github.com/nanobpm/nano-workforce/compare/v0.138.0...v0.138.1) (2026-08-24)
2
8
 
3
9
  ### Bug Fixes
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@nanobpm/nano-workforce",
3
- "version": "0.138.1",
3
+ "version": "0.138.2",
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",