@nanobpm/nano-workforce 0.27.0 → 0.29.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,17 @@
1
+ # [0.29.0](https://github.com/nanobpm/nano-workforce/compare/v0.28.0...v0.29.0) (2026-08-08)
2
+
3
+
4
+ ### Features
5
+
6
+ * **app:** page nav bar + urban 0.28.0 multi-page navigation ([#83](https://github.com/nanobpm/nano-workforce/issues/83)) ([4011598](https://github.com/nanobpm/nano-workforce/commit/40115981211d4f50d6243ddf990c668e1a75c60c))
7
+
8
+ # [0.28.0](https://github.com/nanobpm/nano-workforce/compare/v0.27.0...v0.28.0) (2026-08-08)
9
+
10
+
11
+ ### Features
12
+
13
+ * **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))
14
+
1
15
  # [0.27.0](https://github.com/nanobpm/nano-workforce/compare/v0.26.0...v0.27.0) (2026-08-08)
2
16
 
3
17
 
@@ -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 changed:
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 \`author_task\` to your task id.
128
- If a retry might make you re-POST the same fact, include a stable \`"dedupe_key"\` so it collapses to
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
@@ -6,7 +6,7 @@
6
6
  ]
7
7
  },
8
8
  "imports": {
9
- "@nanobpm/urban": "npm:@nanobpm/urban@^0.27.0"
9
+ "@nanobpm/urban": "npm:@nanobpm/urban@^0.28.0"
10
10
  },
11
11
  "tasks": {
12
12
  "start": "deno run --allow-net --allow-read --allow-write --allow-run=gh --allow-env main.ts",
package/deno.lock CHANGED
@@ -3,7 +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
+ "npm:@nanobpm/urban@0.28": "0.28.0",
7
7
  "npm:@semantic-release/changelog@^6.0.3": "6.0.3_semantic-release@24.2.9__typescript@5.9.3_typescript@5.9.3",
8
8
  "npm:@semantic-release/git@^10.0.1": "10.0.1_semantic-release@24.2.9__typescript@5.9.3_typescript@5.9.3",
9
9
  "npm:@semantic-release/npm@^13.1.5": "13.1.5_semantic-release@24.2.9__typescript@5.9.3",
@@ -82,8 +82,8 @@
82
82
  "ws"
83
83
  ]
84
84
  },
85
- "@nanobpm/urban@0.27.0": {
86
- "integrity": "sha512-FjGv0ttj2TqRTvYUjHDKwBWmZImn17VWjbYVmy6cMAjhtGa5cFsuJOWHwV1WTdkJhcvC3WcsjB6gaAxYQNzglg==",
85
+ "@nanobpm/urban@0.28.0": {
86
+ "integrity": "sha512-rhzgOV+Vb1CPuNoVHVX3OtxjHqzSp2gJIV2pi3EBi245ZjDRN0gSoPGd/MEnJdufxgWwDKuvhyljRDHE8T957w==",
87
87
  "dependencies": [
88
88
  "@nanobpm/nano-app-schema",
89
89
  "@nanobpm/nano-sdk",
@@ -1757,11 +1757,11 @@
1757
1757
  },
1758
1758
  "workspace": {
1759
1759
  "dependencies": [
1760
- "npm:@nanobpm/urban@0.27"
1760
+ "npm:@nanobpm/urban@0.28"
1761
1761
  ],
1762
1762
  "packageJson": {
1763
1763
  "dependencies": [
1764
- "npm:@nanobpm/urban@0.27",
1764
+ "npm:@nanobpm/urban@0.28",
1765
1765
  "npm:@semantic-release/changelog@^6.0.3",
1766
1766
  "npm:@semantic-release/git@^10.0.1",
1767
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.27.0",
3
+ "version": "0.29.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.27.0"
43
+ "@nanobpm/urban": "^0.28.0"
44
44
  },
45
45
  "devDependencies": {
46
46
  "@semantic-release/changelog": "^6.0.3",
@@ -2,6 +2,18 @@
2
2
  "schemaVersion": "1.0",
3
3
  "title": "Epic Coordination",
4
4
  "nodes": [
5
+ {
6
+ "type": "nav",
7
+ "id": "nav",
8
+ "props": {
9
+ "variant": "bar",
10
+ "title": "Nano Workforce",
11
+ "items": [
12
+ { "label": "Convergence", "page": "home" },
13
+ { "label": "Epic", "page": "epic" }
14
+ ]
15
+ }
16
+ },
5
17
  {
6
18
  "type": "text",
7
19
  "id": "title",
@@ -2,6 +2,18 @@
2
2
  "schemaVersion": "1.0",
3
3
  "title": "PR Review Convergence",
4
4
  "nodes": [
5
+ {
6
+ "type": "nav",
7
+ "id": "nav",
8
+ "props": {
9
+ "variant": "bar",
10
+ "title": "Nano Workforce",
11
+ "items": [
12
+ { "label": "Convergence", "page": "home" },
13
+ { "label": "Epic", "page": "epic" }
14
+ ]
15
+ }
16
+ },
5
17
  {
6
18
  "type": "text",
7
19
  "id": "title",