@nanobpm/nano-workforce 0.208.5 → 0.209.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,9 @@
1
+ ## [0.209.0](https://github.com/nanobpm/nano-workforce/compare/v0.208.5...v0.209.0) (2026-11-12)
2
+
3
+ ### Features
4
+
5
+ * **nav:** green Delivery Graphs badge counting staged proposals awaiting approval ([#954](https://github.com/nanobpm/nano-workforce/issues/954)) ([21622b4](https://github.com/nanobpm/nano-workforce/commit/21622b4529383c575de7ffcf77548a704353c4d4))
6
+
1
7
  ## [0.208.5](https://github.com/nanobpm/nano-workforce/compare/v0.208.4...v0.208.5) (2026-11-11)
2
8
 
3
9
  ### Bug Fixes
package/build-info.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
- "version": "0.208.5",
3
- "gitSha": "c3f19d50ef6cf4f731f50ab778b5cd7ebdb3454e",
4
- "gitTag": "v0.208.5",
5
- "builtAt": "2026-11-11T09:26:21.393Z"
2
+ "version": "0.209.0",
3
+ "gitSha": "21622b4529383c575de7ffcf77548a704353c4d4",
4
+ "gitTag": "v0.209.0",
5
+ "builtAt": "2026-11-12T05:08:52.210Z"
6
6
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@nanobpm/nano-workforce",
3
- "version": "0.208.5",
3
+ "version": "0.209.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",
package/pages/_nav.json CHANGED
@@ -11,7 +11,18 @@
11
11
  { "label": "Convergence", "page": "home" },
12
12
  { "label": "Epics", "page": "epic" },
13
13
  { "label": "Feature", "page": "feature" },
14
- { "label": "Delivery Graphs", "page": "delivery-graphs" },
14
+ {
15
+ "label": "Delivery Graphs",
16
+ "page": "delivery-graphs",
17
+ "badge": {
18
+ "source": "app",
19
+ "table": "delivery_graph_proposals",
20
+ "filter": [{ "field": "status", "eq": "staged" }],
21
+ "tone": "ok",
22
+ "refreshMs": 5000,
23
+ "hideWhenZero": true
24
+ }
25
+ },
15
26
  {
16
27
  "label": "Tasks",
17
28
  "page": "tasks",
@@ -35,7 +35,20 @@
35
35
  },
36
36
  {
37
37
  "label": "Delivery Graphs",
38
- "page": "delivery-graphs"
38
+ "page": "delivery-graphs",
39
+ "badge": {
40
+ "source": "app",
41
+ "table": "delivery_graph_proposals",
42
+ "filter": [
43
+ {
44
+ "field": "status",
45
+ "eq": "staged"
46
+ }
47
+ ],
48
+ "tone": "ok",
49
+ "refreshMs": 5000,
50
+ "hideWhenZero": true
51
+ }
39
52
  },
40
53
  {
41
54
  "label": "Tasks",
@@ -35,7 +35,20 @@
35
35
  },
36
36
  {
37
37
  "label": "Delivery Graphs",
38
- "page": "delivery-graphs"
38
+ "page": "delivery-graphs",
39
+ "badge": {
40
+ "source": "app",
41
+ "table": "delivery_graph_proposals",
42
+ "filter": [
43
+ {
44
+ "field": "status",
45
+ "eq": "staged"
46
+ }
47
+ ],
48
+ "tone": "ok",
49
+ "refreshMs": 5000,
50
+ "hideWhenZero": true
51
+ }
39
52
  },
40
53
  {
41
54
  "label": "Tasks",
@@ -35,7 +35,20 @@
35
35
  },
36
36
  {
37
37
  "label": "Delivery Graphs",
38
- "page": "delivery-graphs"
38
+ "page": "delivery-graphs",
39
+ "badge": {
40
+ "source": "app",
41
+ "table": "delivery_graph_proposals",
42
+ "filter": [
43
+ {
44
+ "field": "status",
45
+ "eq": "staged"
46
+ }
47
+ ],
48
+ "tone": "ok",
49
+ "refreshMs": 5000,
50
+ "hideWhenZero": true
51
+ }
39
52
  },
40
53
  {
41
54
  "label": "Tasks",
@@ -35,7 +35,20 @@
35
35
  },
36
36
  {
37
37
  "label": "Delivery Graphs",
38
- "page": "delivery-graphs"
38
+ "page": "delivery-graphs",
39
+ "badge": {
40
+ "source": "app",
41
+ "table": "delivery_graph_proposals",
42
+ "filter": [
43
+ {
44
+ "field": "status",
45
+ "eq": "staged"
46
+ }
47
+ ],
48
+ "tone": "ok",
49
+ "refreshMs": 5000,
50
+ "hideWhenZero": true
51
+ }
39
52
  },
40
53
  {
41
54
  "label": "Tasks",
@@ -35,7 +35,20 @@
35
35
  },
36
36
  {
37
37
  "label": "Delivery Graphs",
38
- "page": "delivery-graphs"
38
+ "page": "delivery-graphs",
39
+ "badge": {
40
+ "source": "app",
41
+ "table": "delivery_graph_proposals",
42
+ "filter": [
43
+ {
44
+ "field": "status",
45
+ "eq": "staged"
46
+ }
47
+ ],
48
+ "tone": "ok",
49
+ "refreshMs": 5000,
50
+ "hideWhenZero": true
51
+ }
39
52
  },
40
53
  {
41
54
  "label": "Tasks",
@@ -35,7 +35,20 @@
35
35
  },
36
36
  {
37
37
  "label": "Delivery Graphs",
38
- "page": "delivery-graphs"
38
+ "page": "delivery-graphs",
39
+ "badge": {
40
+ "source": "app",
41
+ "table": "delivery_graph_proposals",
42
+ "filter": [
43
+ {
44
+ "field": "status",
45
+ "eq": "staged"
46
+ }
47
+ ],
48
+ "tone": "ok",
49
+ "refreshMs": 5000,
50
+ "hideWhenZero": true
51
+ }
39
52
  },
40
53
  {
41
54
  "label": "Tasks",
@@ -35,7 +35,20 @@
35
35
  },
36
36
  {
37
37
  "label": "Delivery Graphs",
38
- "page": "delivery-graphs"
38
+ "page": "delivery-graphs",
39
+ "badge": {
40
+ "source": "app",
41
+ "table": "delivery_graph_proposals",
42
+ "filter": [
43
+ {
44
+ "field": "status",
45
+ "eq": "staged"
46
+ }
47
+ ],
48
+ "tone": "ok",
49
+ "refreshMs": 5000,
50
+ "hideWhenZero": true
51
+ }
39
52
  },
40
53
  {
41
54
  "label": "Tasks",
@@ -35,7 +35,20 @@
35
35
  },
36
36
  {
37
37
  "label": "Delivery Graphs",
38
- "page": "delivery-graphs"
38
+ "page": "delivery-graphs",
39
+ "badge": {
40
+ "source": "app",
41
+ "table": "delivery_graph_proposals",
42
+ "filter": [
43
+ {
44
+ "field": "status",
45
+ "eq": "staged"
46
+ }
47
+ ],
48
+ "tone": "ok",
49
+ "refreshMs": 5000,
50
+ "hideWhenZero": true
51
+ }
39
52
  },
40
53
  {
41
54
  "label": "Tasks",
@@ -35,7 +35,20 @@
35
35
  },
36
36
  {
37
37
  "label": "Delivery Graphs",
38
- "page": "delivery-graphs"
38
+ "page": "delivery-graphs",
39
+ "badge": {
40
+ "source": "app",
41
+ "table": "delivery_graph_proposals",
42
+ "filter": [
43
+ {
44
+ "field": "status",
45
+ "eq": "staged"
46
+ }
47
+ ],
48
+ "tone": "ok",
49
+ "refreshMs": 5000,
50
+ "hideWhenZero": true
51
+ }
39
52
  },
40
53
  {
41
54
  "label": "Tasks",
@@ -35,7 +35,20 @@
35
35
  },
36
36
  {
37
37
  "label": "Delivery Graphs",
38
- "page": "delivery-graphs"
38
+ "page": "delivery-graphs",
39
+ "badge": {
40
+ "source": "app",
41
+ "table": "delivery_graph_proposals",
42
+ "filter": [
43
+ {
44
+ "field": "status",
45
+ "eq": "staged"
46
+ }
47
+ ],
48
+ "tone": "ok",
49
+ "refreshMs": 5000,
50
+ "hideWhenZero": true
51
+ }
39
52
  },
40
53
  {
41
54
  "label": "Tasks",
@@ -35,7 +35,20 @@
35
35
  },
36
36
  {
37
37
  "label": "Delivery Graphs",
38
- "page": "delivery-graphs"
38
+ "page": "delivery-graphs",
39
+ "badge": {
40
+ "source": "app",
41
+ "table": "delivery_graph_proposals",
42
+ "filter": [
43
+ {
44
+ "field": "status",
45
+ "eq": "staged"
46
+ }
47
+ ],
48
+ "tone": "ok",
49
+ "refreshMs": 5000,
50
+ "hideWhenZero": true
51
+ }
39
52
  },
40
53
  {
41
54
  "label": "Tasks",
@@ -35,7 +35,20 @@
35
35
  },
36
36
  {
37
37
  "label": "Delivery Graphs",
38
- "page": "delivery-graphs"
38
+ "page": "delivery-graphs",
39
+ "badge": {
40
+ "source": "app",
41
+ "table": "delivery_graph_proposals",
42
+ "filter": [
43
+ {
44
+ "field": "status",
45
+ "eq": "staged"
46
+ }
47
+ ],
48
+ "tone": "ok",
49
+ "refreshMs": 5000,
50
+ "hideWhenZero": true
51
+ }
39
52
  },
40
53
  {
41
54
  "label": "Tasks",
@@ -35,7 +35,20 @@
35
35
  },
36
36
  {
37
37
  "label": "Delivery Graphs",
38
- "page": "delivery-graphs"
38
+ "page": "delivery-graphs",
39
+ "badge": {
40
+ "source": "app",
41
+ "table": "delivery_graph_proposals",
42
+ "filter": [
43
+ {
44
+ "field": "status",
45
+ "eq": "staged"
46
+ }
47
+ ],
48
+ "tone": "ok",
49
+ "refreshMs": 5000,
50
+ "hideWhenZero": true
51
+ }
39
52
  },
40
53
  {
41
54
  "label": "Tasks",
@@ -35,7 +35,20 @@
35
35
  },
36
36
  {
37
37
  "label": "Delivery Graphs",
38
- "page": "delivery-graphs"
38
+ "page": "delivery-graphs",
39
+ "badge": {
40
+ "source": "app",
41
+ "table": "delivery_graph_proposals",
42
+ "filter": [
43
+ {
44
+ "field": "status",
45
+ "eq": "staged"
46
+ }
47
+ ],
48
+ "tone": "ok",
49
+ "refreshMs": 5000,
50
+ "hideWhenZero": true
51
+ }
39
52
  },
40
53
  {
41
54
  "label": "Tasks",
@@ -85,3 +85,41 @@ test("issue #306: the badge's user_tasks table is defined by the migrations", ()
85
85
  "badge table \"user_tasks\" must be created (TABLE or VIEW) by db/migrations/*.sql",
86
86
  );
87
87
  });
88
+
89
+ test("the Delivery Graphs nav item carries the staged-proposals-awaiting-approval badge", () => {
90
+ const canon = JSON.parse(readFileSync(`${ROOT}pages/_nav.json`, "utf8"));
91
+ const items = canon?.props?.items ?? [];
92
+ const dg = items.find((i: Json) => i?.page === "delivery-graphs");
93
+ assert(dg, "canonical nav has no Delivery Graphs item");
94
+ const badge = dg.badge;
95
+ assert(badge, "Delivery Graphs nav item must declare a live count badge");
96
+ // Counts ONLY proposals awaiting approval (status = staged) — dropping the filter
97
+ // would count approved/rejected proposals too; the drift check alone can't catch that.
98
+ assert(badge.source === "app", "badge.source must be \"app\"");
99
+ assert(
100
+ badge.table === "delivery_graph_proposals",
101
+ "badge.table must be \"delivery_graph_proposals\"",
102
+ );
103
+ assert(
104
+ stable(badge.filter) === stable([{ field: "status", eq: "staged" }]),
105
+ "badge.filter must be exactly [{ field: \"status\", eq: \"staged\" }]",
106
+ );
107
+ assert(badge.tone === "ok", "badge.tone must be \"ok\" (green)");
108
+ assert(badge.refreshMs === 5000, "badge.refreshMs must be 5000");
109
+ assert(badge.hideWhenZero === true, "badge.hideWhenZero must be true");
110
+
111
+ let sql = "";
112
+ for (const e of readdirSync(`${ROOT}db/migrations`, { withFileTypes: true })) {
113
+ if (e.isFile() && e.name.endsWith(".sql")) {
114
+ sql += readFileSync(`${ROOT}db/migrations/${e.name}`, "utf8");
115
+ }
116
+ }
117
+ assert(
118
+ /CREATE\s+(?:TABLE|VIEW)\s+(?:IF\s+NOT\s+EXISTS\s+)?["`]?delivery_graph_proposals["`]?/i.test(sql),
119
+ "badge table \"delivery_graph_proposals\" must be created by db/migrations/*.sql",
120
+ );
121
+ assert(
122
+ /delivery_graph_proposals[\s\S]*?\bstatus\b/i.test(sql),
123
+ "delivery_graph_proposals must have a status column",
124
+ );
125
+ });