@nanobpm/nano-workforce 0.178.1 → 0.178.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.
@@ -7,6 +7,16 @@ on:
7
7
  workflow_run:
8
8
  workflows: ["CI", "Whole-repo invariants (merge-skew guard)"]
9
9
  types: [completed]
10
+ # Manual escape hatch. The automatic path above depends on the post-merge
11
+ # `push:main` event that normally follows a merge-queue landing. That event can
12
+ # go MISSING when an out-of-band bypass push to `main` (a `chore(release)
13
+ # [skip ci]` commit from the release App) races the queue's merge — the merged
14
+ # commit then lands with only its `merge_group` run and no `push` run, so the
15
+ # `workflow_run` trigger never sees `event == 'push'` and the release wedges
16
+ # with no way to retrigger. Dispatching runs the SAME green-gate against
17
+ # `main`'s HEAD (the merge_group checks are attached to that commit), so a
18
+ # manual recovery still never ships from a red `main`.
19
+ workflow_dispatch:
10
20
 
11
21
  # Prevent overlapping releases from racing on the same branch.
12
22
  concurrency:
@@ -26,9 +36,10 @@ jobs:
26
36
  name: release gate
27
37
  runs-on: ubuntu-latest
28
38
  if: >-
29
- github.event.workflow_run.event == 'push' &&
30
- github.event.workflow_run.head_branch == 'main' &&
31
- github.event.workflow_run.conclusion == 'success'
39
+ github.event_name == 'workflow_dispatch' ||
40
+ (github.event.workflow_run.event == 'push' &&
41
+ github.event.workflow_run.head_branch == 'main' &&
42
+ github.event.workflow_run.conclusion == 'success')
32
43
  permissions:
33
44
  checks: read
34
45
  contents: read
@@ -39,7 +50,7 @@ jobs:
39
50
  id: gate
40
51
  env:
41
52
  GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
42
- SHA: ${{ github.event.workflow_run.head_sha }}
53
+ SHA: ${{ github.event.workflow_run.head_sha || github.sha }}
43
54
  REPO: ${{ github.repository }}
44
55
  run: |
45
56
  set -euo pipefail
@@ -78,7 +89,7 @@ jobs:
78
89
  # done with the release App token below — it is the ruleset bypass actor. The
79
90
  # job's own GITHUB_TOKEN only needs OIDC for npm Trusted Publishing.
80
91
  contents: read
81
- id-token: write # OIDC token for npm Trusted Publishing (no NPM_TOKEN)
92
+ id-token: write # OIDC for npm Trusted Publishing + provenance (the only auth path)
82
93
  steps:
83
94
  # Mint a short-lived token for the dedicated release GitHub App. This App is
84
95
  # the ruleset's bypass actor, so @semantic-release/git can push the version
@@ -96,7 +107,7 @@ jobs:
96
107
  - name: Checkout
97
108
  uses: actions/checkout@v4
98
109
  with:
99
- ref: ${{ github.event.workflow_run.head_sha }} # release the exact gated commit
110
+ ref: ${{ github.event.workflow_run.head_sha || github.sha }} # release the exact gated commit
100
111
  fetch-depth: 0 # semantic-release needs full history + tags
101
112
  persist-credentials: true # let @semantic-release/git push the release commit
102
113
  token: ${{ steps.app-token.outputs.token }} # push as the bypass-actor App
@@ -129,8 +140,63 @@ jobs:
129
140
  run: npm ci
130
141
 
131
142
  - name: Release
143
+ id: release
144
+ # OIDC Trusted Publishing is the ONLY automated auth path: npm has retired
145
+ # automation tokens that bypass 2FA, so there is no CI token fallback — it is
146
+ # OIDC or a human `npm publish` locally. OIDC is intermittently flaky, though:
147
+ # npm has returned `401 … Failed to generate Web Auth URLs … token is invalid`
148
+ # mid-publish. @semantic-release/git pushes the tag + release commit in the
149
+ # `prepare` step BEFORE @semantic-release/npm `publish`, so an OIDC publish
150
+ # failure orphans a git tag with no npm package (the v0.178.3 phantom).
151
+ # Don't fail the job here — let the OIDC publish-retry step below recover it.
152
+ continue-on-error: true
132
153
  env:
133
154
  GITHUB_TOKEN: ${{ steps.app-token.outputs.token }} # bypass-actor App token
134
- # No NPM_TOKEN / NODE_AUTH_TOKEN: publishing uses OIDC Trusted Publishing.
155
+ # No NPM_TOKEN / NODE_AUTH_TOKEN: publishing is OIDC Trusted Publishing only.
135
156
  NPM_CONFIG_PROVENANCE: "true"
136
157
  run: npx semantic-release
158
+
159
+ # Recovery: if the OIDC publish 401s, semantic-release has already bumped
160
+ # package.json + pushed the tag/release commit, but npm never got the tarball.
161
+ # The failure is INTERMITTENT (a prior version published fine), so retry the
162
+ # OIDC publish of the just-prepared version a few times with backoff — still no
163
+ # token, still OIDC + provenance via the job's id-token. This step is a NO-OP
164
+ # when the release step succeeded or when the version is already on npm, so it
165
+ # can never double-publish. If OIDC stays down through every retry, fail loudly:
166
+ # a human must `npm publish` the pushed tag locally (npm login with 2FA, then
167
+ # `git checkout vX.Y.Z && npm ci && npm publish --provenance --access public`).
168
+ - name: Retry OIDC publish if the release publish failed
169
+ if: steps.release.outcome == 'failure'
170
+ env:
171
+ NPM_CONFIG_PROVENANCE: "true"
172
+ GH_TOKEN: ${{ steps.app-token.outputs.token }} # to create the skipped GitHub Release
173
+ run: |
174
+ set -uo pipefail
175
+ PKG="$(node -p "require('./package.json').name")"
176
+ VERSION="$(node -p "require('./package.json').version")"
177
+ if npm view "${PKG}@${VERSION}" version >/dev/null 2>&1; then
178
+ echo "${PKG}@${VERSION} is already on npm — nothing to recover."
179
+ exit 0
180
+ fi
181
+ echo "semantic-release prepared + tagged ${PKG}@${VERSION} but the OIDC publish failed; retrying."
182
+ published=false
183
+ for attempt in 1 2 3; do
184
+ echo "OIDC publish attempt ${attempt}/3 for ${PKG}@${VERSION}"
185
+ if npm publish --provenance --access public; then
186
+ echo "Published ${PKG}@${VERSION} on retry ${attempt}."
187
+ published=true
188
+ break
189
+ fi
190
+ sleep $((attempt * 30))
191
+ done
192
+ if [ "$published" != true ]; then
193
+ echo "::error::OIDC publish of ${PKG}@${VERSION} still failing after retries. The git tag v${VERSION} is pushed but npm has no tarball. Publish it locally: 'git fetch --tags && git checkout v${VERSION} && npm ci && npm publish --provenance --access public' (npm login with 2FA first)."
194
+ exit 1
195
+ fi
196
+ # semantic-release aborts before @semantic-release/github when the npm
197
+ # publish throws, so the GitHub Release was never created — create it now.
198
+ if ! gh release view "v${VERSION}" >/dev/null 2>&1; then
199
+ echo "Creating the GitHub Release skipped by the aborted semantic-release run."
200
+ gh release create "v${VERSION}" --verify-tag --generate-notes --title "v${VERSION}" || \
201
+ echo "::warning::Published to npm but failed to create GitHub Release v${VERSION}; create it manually."
202
+ fi
@@ -3,17 +3,18 @@ name: Renovate
3
3
  # Self-hosted Renovate (issue #406). renovate.json declares the policy — auto-merge
4
4
  # non-major @nanobpm/* updates once CI is green, majors need a human — but nothing was
5
5
  # ever running it, so the config sat dormant and nwf stayed pinned to old @nanobpm/urban.
6
- # This workflow IS the runner: on a schedule (and on demand) it opens update PRs and, on a
7
- # later pass once the PR's CI is green, merges the automerge ones itself. We self-host via
8
- # GitHub Actions rather than the Mend hosted app so the whole capability is in-repo and
9
- # reproducible, with no external app-install state to drift.
6
+ # This workflow IS the runner: on a schedule (and on demand) it opens update PRs and enables
7
+ # GitHub-native auto-merge on the automerge ones, which ENQUEUES them into main's merge queue so
8
+ # they land when the queue's speculative checks pass. We self-host via GitHub Actions rather than
9
+ # the Mend hosted app so the whole capability is in-repo and reproducible, with no external
10
+ # app-install state to drift.
10
11
  on:
11
12
  schedule:
12
- # Every 3 hours. Renovate needs to run periodically not just to DISCOVER new versions,
13
- # but to COME BACK and merge automerge PRs: renovate.json sets platformAutomerge:false
14
- # (main is unprotected, so GitHub-native auto-merge is unavailable), which means Renovate
15
- # performs the merge itself on a subsequent run once the PR's branch status is green.
16
- # A few-hourly cadence keeps that merge latency low without burning Actions minutes.
13
+ # Every 3 hours. Renovate needs to run periodically to DISCOVER new versions and open/refresh
14
+ # update PRs. Once main went behind a merge queue, Renovate no longer self-merges; it enables
15
+ # GitHub-native auto-merge (platformAutomerge:true) which enqueues the PR, and the queue lands it
16
+ # when its checks pass. A few-hourly cadence keeps discovery latency low without burning Actions
17
+ # minutes.
17
18
  - cron: "0 */3 * * *"
18
19
  # On-demand runs for immediate pickup (e.g. right after a new urban publishes) and for
19
20
  # debugging with a raised log level.
package/CHANGELOG.md CHANGED
@@ -1,3 +1,20 @@
1
+ ## [0.178.3](https://github.com/nanobpm/nano-workforce/compare/v0.178.2...v0.178.3) (2026-09-03)
2
+
3
+ ### Bug Fixes
4
+
5
+ * **ci:** add manual workflow_dispatch escape hatch to the release pipeline ([#723](https://github.com/nanobpm/nano-workforce/issues/723)) ([4d06f25](https://github.com/nanobpm/nano-workforce/commit/4d06f259aee7a5689844ddd0dfe3f68253c9fc37))
6
+ * **ci:** retry OIDC publish when the release publish 401s; reclaim v0.178.3 ([#722](https://github.com/nanobpm/nano-workforce/issues/722)) ([208c02d](https://github.com/nanobpm/nano-workforce/commit/208c02dd1936c70635a5108887f452143a8dbc26))
7
+
8
+ ### Documentation
9
+
10
+ * refresh stale --version pin example in the upgrade guide ([#721](https://github.com/nanobpm/nano-workforce/issues/721)) ([75dbcec](https://github.com/nanobpm/nano-workforce/commit/75dbcecc93b4adef3bb4d6a05f6010ed44ea74dd))
11
+
12
+ ## [0.178.2](https://github.com/nanobpm/nano-workforce/compare/v0.178.1...v0.178.2) (2026-09-03)
13
+
14
+ ### Bug Fixes
15
+
16
+ * **ci:** enqueue Renovate @nanobpm/* automerge via the merge queue ([#720](https://github.com/nanobpm/nano-workforce/issues/720)) ([a788c3c](https://github.com/nanobpm/nano-workforce/commit/a788c3cc664ee7324c0706bf5182d180b8a17c0e)), closes [#421](https://github.com/nanobpm/nano-workforce/issues/421)
17
+
1
18
  ## [0.178.1](https://github.com/nanobpm/nano-workforce/compare/v0.178.0...v0.178.1) (2026-09-03)
2
19
 
3
20
  ### Bug Fixes
package/README.md CHANGED
@@ -185,7 +185,7 @@ and runs the review-ready poller.
185
185
  ```sh
186
186
  npm run upgrade # dry-run against @latest
187
187
  npm run upgrade -- --apply # apply the overlay, preserving app.db
188
- npm run upgrade -- --version 0.26.0 --apply # pin a specific version
188
+ npm run upgrade -- --version 0.178.2 --apply # pin a specific version
189
189
  npm run upgrade -- --from ./pkg.tgz --apply # from a local tarball (offline)
190
190
  ```
191
191
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@nanobpm/nano-workforce",
3
- "version": "0.178.1",
3
+ "version": "0.178.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",
@@ -64,7 +64,7 @@
64
64
  "lint:fix": "biome check --write app operations workers pages components scripts e2e main.ts"
65
65
  },
66
66
  "dependencies": {
67
- "@nanobpm/agentic": "^0.11.0",
67
+ "@nanobpm/agentic": "^0.12.0",
68
68
  "@nanobpm/urban": "^0.90.0",
69
69
  "bpmn-auto-layout": "^2.0.0-alpha.2"
70
70
  },
package/renovate.json CHANGED
@@ -3,11 +3,11 @@
3
3
  "extends": ["config:recommended"],
4
4
  "packageRules": [
5
5
  {
6
- "description": "Auto-merge non-major @nanobpm/* updates once CI is green. These are first-party packages we publish from nano-ide; CI (typecheck + test) is the gate. For 0.x pins a caret range locks the minor, so Renovate's range bump is what actually pulls a new minor through; automerging it keeps nwf on the latest urban without manual PRs. platformAutomerge is off because main is unprotected, so Renovate waits for its own green branch status before merging.",
6
+ "description": "Auto-merge non-major @nanobpm/* updates once CI is green. These are first-party packages we publish from nano-ide; CI (typecheck + test) is the gate. For 0.x pins a caret range locks the minor, so Renovate's range bump is what actually pulls a new minor through; automerging it keeps nwf on the latest agentic/urban without manual PRs. platformAutomerge is ON because main is now protected by an active ruleset with a GitHub merge queue (merge_queue rule): a direct self-merge is rejected by the queue, so Renovate must enable GitHub-native auto-merge, which ENQUEUES the PR and lets it land when the queue's speculative checks pass. (Historically this was false when main was unprotected; leaving it false silently wedged green update PRs open — e.g. the agentic 0.11->0.12 bump sat unmerged for weeks.)",
7
7
  "matchPackageNames": ["/^@nanobpm//"],
8
8
  "matchUpdateTypes": ["minor", "patch"],
9
9
  "automerge": true,
10
- "platformAutomerge": false
10
+ "platformAutomerge": true
11
11
  },
12
12
  {
13
13
  "description": "Major @nanobpm/* updates may be breaking - require a human to review and merge.",