@nanobpm/nano-workforce 0.26.0 → 0.28.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 +14 -0
- package/README.md +1 -1
- package/app/blackboard.test.ts +4 -0
- package/app/blackboard.ts +21 -5
- package/deno.json +1 -1
- package/deno.lock +13 -12
- package/package.json +2 -2
package/CHANGELOG.md
CHANGED
|
@@ -1,3 +1,17 @@
|
|
|
1
|
+
# [0.28.0](https://github.com/nanobpm/nano-workforce/compare/v0.27.0...v0.28.0) (2026-08-08)
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
### Features
|
|
5
|
+
|
|
6
|
+
* **blackboard:** first-class 'learning' kind for shared gotchas ([#82](https://github.com/nanobpm/nano-workforce/issues/82)) ([35ff09d](https://github.com/nanobpm/nano-workforce/commit/35ff09dce4a46dab03811fa5657828ca1f027c7c))
|
|
7
|
+
|
|
8
|
+
# [0.27.0](https://github.com/nanobpm/nano-workforce/compare/v0.26.0...v0.27.0) (2026-08-08)
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
### Features
|
|
12
|
+
|
|
13
|
+
* adopt @nanobpm/urban 0.27.0 for the themed console embed ([#81](https://github.com/nanobpm/nano-workforce/issues/81)) ([11ffecb](https://github.com/nanobpm/nano-workforce/commit/11ffecb3897a1ba5d57a9cda49f6859648c66f85)), closes [122/#123](https://github.com/nanobpm/nano-workforce/issues/123)
|
|
14
|
+
|
|
1
15
|
# [0.26.0](https://github.com/jwulf/urban-pr-review/compare/v0.25.0...v0.26.0) (2026-08-08)
|
|
2
16
|
|
|
3
17
|
|
package/README.md
CHANGED
|
@@ -7,7 +7,7 @@ every resulting pull request to **review convergence** against an automated
|
|
|
7
7
|
reviewer, and **merges** it — escalating to a human only when an agent is stuck or
|
|
8
8
|
a round cap is hit.
|
|
9
9
|
|
|
10
|
-
It is a [Nano](https://
|
|
10
|
+
It is a [Nano](https://nanobpm.io) **Urban app**: a set of durable
|
|
11
11
|
BPMN processes (`resources/processes/*.bpmn`) executed by the Nano engine, with the
|
|
12
12
|
orchestration graph — planning, implementation, review, and merge — modelled
|
|
13
13
|
explicitly so the whole lifecycle survives restarts, latency, and failure.
|
package/app/blackboard.test.ts
CHANGED
|
@@ -86,6 +86,7 @@ Deno.test("blackboardUrl: capability token rides the query string", () => {
|
|
|
86
86
|
Deno.test("normalizeKind: valid passes through, anything else becomes note", () => {
|
|
87
87
|
assertEquals(normalizeKind("file-claim"), "file-claim");
|
|
88
88
|
assertEquals(normalizeKind("constraint-change"), "constraint-change");
|
|
89
|
+
assertEquals(normalizeKind("learning"), "learning");
|
|
89
90
|
assertEquals(normalizeKind("bogus"), "note");
|
|
90
91
|
assertEquals(normalizeKind(undefined), "note");
|
|
91
92
|
});
|
|
@@ -105,6 +106,9 @@ Deno.test("renderCoordinationBrief: leads with a separator and teaches the proto
|
|
|
105
106
|
assertStringIncludes(brief, "cursor");
|
|
106
107
|
assertStringIncludes(brief, "&since=");
|
|
107
108
|
assertStringIncludes(brief, "conflicts");
|
|
109
|
+
// Learnings: teaches reading prior gotchas and posting a reusable `learning`.
|
|
110
|
+
assertStringIncludes(brief, "learning");
|
|
111
|
+
assertStringIncludes(brief, "Share what you learn");
|
|
108
112
|
});
|
|
109
113
|
|
|
110
114
|
Deno.test("planKeyForToken: resolves a token to its plan, undefined otherwise", async () => {
|
package/app/blackboard.ts
CHANGED
|
@@ -21,7 +21,7 @@ import type { DataLayer } from "@nanobpm/urban";
|
|
|
21
21
|
|
|
22
22
|
const now = () => new Date().toISOString();
|
|
23
23
|
|
|
24
|
-
export const BLACKBOARD_KINDS = ["file-claim", "constraint-change", "scope-change", "note"] as const;
|
|
24
|
+
export const BLACKBOARD_KINDS = ["file-claim", "constraint-change", "scope-change", "learning", "note"] as const;
|
|
25
25
|
export type BlackboardKind = (typeof BLACKBOARD_KINDS)[number];
|
|
26
26
|
|
|
27
27
|
/** The stored row shape (files is a JSON-encoded string of paths, or NULL). */
|
|
@@ -109,13 +109,16 @@ Your blackboard endpoint (already scoped to this epic — no auth header needed)
|
|
|
109
109
|
|
|
110
110
|
${url}
|
|
111
111
|
|
|
112
|
-
**On start — READ it** to see what siblings have claimed or
|
|
112
|
+
**On start — READ it** to see what siblings have claimed, changed, or **learned**:
|
|
113
113
|
|
|
114
114
|
curl -s "${url}"
|
|
115
115
|
|
|
116
116
|
Returns \`{ "planKey": "...", "cursor": <head-entry-id>, "entries": [ { "id", "author_task", "kind", "files", "body", "wave", "created_at" }, ... ] }\` (\`cursor\` is the head entry id, or \`0\` for an empty plan).
|
|
117
117
|
If an entry overlaps your slice (same file, a changed contract/constraint), adapt: coordinate,
|
|
118
118
|
rebase your plan, or if it genuinely blocks you, escalate with a \`question\` per your normal contract.
|
|
119
|
+
**Apply prior \`learning\` entries before you start** — a gotcha a sibling already hit (e.g. "run
|
|
120
|
+
\`make generate\` before \`cargo build\` or the build fails on a stale generated surface") saves you
|
|
121
|
+
from re-discovering it the hard way.
|
|
119
122
|
|
|
120
123
|
**When your work affects others — POST an entry** (do this as soon as it's true, not only at the end):
|
|
121
124
|
|
|
@@ -124,9 +127,22 @@ rebase your plan, or if it genuinely blocks you, escalate with a \`question\` pe
|
|
|
124
127
|
|
|
125
128
|
\`kind\` is one of: \`file-claim\` (you now edit a file outside your original slice),
|
|
126
129
|
\`constraint-change\` (you discovered a constraint that changes another task's direction),
|
|
127
|
-
\`scope-change\` (your contract/scope shifted), or \`note\`. Set
|
|
128
|
-
If a retry might make you re-POST the same fact, include a stable
|
|
129
|
-
one entry.
|
|
130
|
+
\`scope-change\` (your contract/scope shifted), \`learning\` (see below), or \`note\`. Set
|
|
131
|
+
\`author_task\` to your task id. If a retry might make you re-POST the same fact, include a stable
|
|
132
|
+
\`"dedupe_key"\` so it collapses to one entry.
|
|
133
|
+
|
|
134
|
+
**Share what you learn — POST a \`learning\`.** Whenever you hit a **reusable, non-obvious gotcha**
|
|
135
|
+
that a sibling working this repo would also hit — a required build/codegen step, a test or lint
|
|
136
|
+
incantation, an environment/toolchain footgun, a workaround for a sharp edge — post it immediately
|
|
137
|
+
so nobody re-learns it independently, and so we can later lift the recurring ones into a script, CI,
|
|
138
|
+
or \`AGENTS.md\`. Keep the \`body\` concrete and actionable (the exact command / the exact cause), and
|
|
139
|
+
give it a stable \`"dedupe_key"\` (e.g. a short slug of the gotcha) so the same learning collapses to
|
|
140
|
+
one entry across retries and siblings:
|
|
141
|
+
|
|
142
|
+
curl -s -X POST "${url}" -H 'content-type: application/json' \\
|
|
143
|
+
-d '{"author_task":"<your-task-id>","kind":"learning","dedupe_key":"regen-before-build","body":"Run \`make generate\` before \`cargo build --features console\` — a stale generated surface fails the build with a confusing error."}'
|
|
144
|
+
|
|
145
|
+
A \`learning\` is advisory and never blocks anyone; it is knowledge for the fleet, not a claim on a file.
|
|
130
146
|
|
|
131
147
|
**Stay in sync while you work (this matters most while siblings run in parallel).** The GET
|
|
132
148
|
response includes a \`"cursor"\`. Re-read incrementally — before you start each new file, and at
|
package/deno.json
CHANGED
package/deno.lock
CHANGED
|
@@ -3,6 +3,7 @@
|
|
|
3
3
|
"specifiers": {
|
|
4
4
|
"jsr:@std/assert@1": "1.0.19",
|
|
5
5
|
"jsr:@std/internal@^1.0.12": "1.0.14",
|
|
6
|
+
"npm:@nanobpm/urban@0.27": "0.27.0",
|
|
6
7
|
"npm:@semantic-release/changelog@^6.0.3": "6.0.3_semantic-release@24.2.9__typescript@5.9.3_typescript@5.9.3",
|
|
7
8
|
"npm:@semantic-release/git@^10.0.1": "10.0.1_semantic-release@24.2.9__typescript@5.9.3_typescript@5.9.3",
|
|
8
9
|
"npm:@semantic-release/npm@^13.1.5": "13.1.5_semantic-release@24.2.9__typescript@5.9.3",
|
|
@@ -66,8 +67,8 @@
|
|
|
66
67
|
"@colors/colors@1.5.0": {
|
|
67
68
|
"integrity": "sha512-ooWCrlZP11i8GImSjTHYHLkvFDP48nS4+204nGb1RiX/WXYHmJA2III9/e2DWVabCESdW7hBAEzHRqUn9OUVvQ=="
|
|
68
69
|
},
|
|
69
|
-
"@nanobpm/nano-app-schema@0.
|
|
70
|
-
"integrity": "sha512-
|
|
70
|
+
"@nanobpm/nano-app-schema@0.3.0": {
|
|
71
|
+
"integrity": "sha512-bz7wqYsfetcSMYIMW2e1rmbE2k844TCtXWwBd+uVV/s3iRsi09Ff0WMaBEZWuvBPopwHhD2JATCNCXdEBULjfA==",
|
|
71
72
|
"dependencies": [
|
|
72
73
|
"bpmn-moddle@9.0.4",
|
|
73
74
|
"dmn-moddle",
|
|
@@ -81,8 +82,8 @@
|
|
|
81
82
|
"ws"
|
|
82
83
|
]
|
|
83
84
|
},
|
|
84
|
-
"@nanobpm/urban@0.
|
|
85
|
-
"integrity": "sha512-
|
|
85
|
+
"@nanobpm/urban@0.27.0": {
|
|
86
|
+
"integrity": "sha512-FjGv0ttj2TqRTvYUjHDKwBWmZImn17VWjbYVmy6cMAjhtGa5cFsuJOWHwV1WTdkJhcvC3WcsjB6gaAxYQNzglg==",
|
|
86
87
|
"dependencies": [
|
|
87
88
|
"@nanobpm/nano-app-schema",
|
|
88
89
|
"@nanobpm/nano-sdk",
|
|
@@ -92,8 +93,8 @@
|
|
|
92
93
|
],
|
|
93
94
|
"bin": true
|
|
94
95
|
},
|
|
95
|
-
"@nanobpm/workflow@0.8.
|
|
96
|
-
"integrity": "sha512-
|
|
96
|
+
"@nanobpm/workflow@0.8.1_bpmn-auto-layout@2.0.0-alpha.2": {
|
|
97
|
+
"integrity": "sha512-Ql6sMGc6uKKRHWR4KBtAz4xmVbMmKpgTYmLQfWbTDCKqyUk0s4DS+xocdto6tymSY4PJeIAOyOLvKaFfW5WHrA==",
|
|
97
98
|
"dependencies": [
|
|
98
99
|
"@nanobpm/nano-sdk",
|
|
99
100
|
"bpmn-auto-layout"
|
|
@@ -571,8 +572,8 @@
|
|
|
571
572
|
"typescript"
|
|
572
573
|
]
|
|
573
574
|
},
|
|
574
|
-
"create-urban-app@0.
|
|
575
|
-
"integrity": "sha512-
|
|
575
|
+
"create-urban-app@0.7.0": {
|
|
576
|
+
"integrity": "sha512-N8VxbuFIrnycSYiFBIxKGpRKGuUa3U+rgRWCsqULPnJprbb9cqv7EYLL6R+4cziZ0S2a+HLyy0K0NOk0Cvyhew==",
|
|
576
577
|
"bin": true
|
|
577
578
|
},
|
|
578
579
|
"cross-spawn@7.0.6": {
|
|
@@ -1705,8 +1706,8 @@
|
|
|
1705
1706
|
"strip-ansi"
|
|
1706
1707
|
]
|
|
1707
1708
|
},
|
|
1708
|
-
"ws@8.21.
|
|
1709
|
-
"integrity": "sha512-
|
|
1709
|
+
"ws@8.21.3": {
|
|
1710
|
+
"integrity": "sha512-201TZ/kPWxoPr/OKWjquZR1SWKXcvxdH+e1xrx89b3YbmzLMFCLfnaG1HFIgWzJOEWZ7MvpK++odZufgYR50Rw=="
|
|
1710
1711
|
},
|
|
1711
1712
|
"xtend@4.0.2": {
|
|
1712
1713
|
"integrity": "sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ=="
|
|
@@ -1756,11 +1757,11 @@
|
|
|
1756
1757
|
},
|
|
1757
1758
|
"workspace": {
|
|
1758
1759
|
"dependencies": [
|
|
1759
|
-
"npm:@nanobpm/urban@0.
|
|
1760
|
+
"npm:@nanobpm/urban@0.27"
|
|
1760
1761
|
],
|
|
1761
1762
|
"packageJson": {
|
|
1762
1763
|
"dependencies": [
|
|
1763
|
-
"npm:@nanobpm/urban@0.
|
|
1764
|
+
"npm:@nanobpm/urban@0.27",
|
|
1764
1765
|
"npm:@semantic-release/changelog@^6.0.3",
|
|
1765
1766
|
"npm:@semantic-release/git@^10.0.1",
|
|
1766
1767
|
"npm:@semantic-release/npm@^13.1.5",
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@nanobpm/nano-workforce",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.28.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",
|
|
@@ -40,7 +40,7 @@
|
|
|
40
40
|
"test": "deno test -A"
|
|
41
41
|
},
|
|
42
42
|
"dependencies": {
|
|
43
|
-
"@nanobpm/urban": "^0.
|
|
43
|
+
"@nanobpm/urban": "^0.27.0"
|
|
44
44
|
},
|
|
45
45
|
"devDependencies": {
|
|
46
46
|
"@semantic-release/changelog": "^6.0.3",
|