@nanobpm/nano-workforce 0.176.0 → 0.177.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 +12 -0
- package/app/agentic/claim-registry.test.ts +155 -0
- package/app/agentic/claim-registry.ts +194 -0
- package/app/agentic/families/claim.family.test.ts +196 -0
- package/app/agentic/families/claim.family.ts +148 -0
- package/app/instanceTracking.ts +43 -0
- package/openapi.yaml +11 -5
- package/operations/cancelInstance.test.ts +157 -0
- package/operations/cancelInstance.ts +99 -13
- package/operations/getAgenticSupply.test.ts +32 -3
- package/operations/getAgenticSupply.ts +24 -15
- package/package.json +2 -2
- package/test/agentic-e2e.test.ts +11 -3
|
@@ -3,11 +3,14 @@
|
|
|
3
3
|
// worker list — family, host, current jobs, liveness — grouped by leaf token, sourced from the H1
|
|
4
4
|
// presence registry (#144). Read-only projection; it NEVER gates control flow (advisory-only, ADR 0056).
|
|
5
5
|
//
|
|
6
|
-
// H6
|
|
7
|
-
//
|
|
8
|
-
//
|
|
9
|
-
//
|
|
10
|
-
//
|
|
6
|
+
// H6/#713 closes the loop with an EXPLICIT claim registry (`app/agentic/claim-registry.ts`): it is the
|
|
7
|
+
// AUTHORITATIVE source the presence snapshot's `jobKeysFor` seam resolves against, so each worker's
|
|
8
|
+
// current jobKeys light up from `claim` frames — not inferred from the relay terminal — and appear even
|
|
9
|
+
// with ZERO transcript. Each worker's drill `stream` is repointed at its claimed jobKey-scoped relay
|
|
10
|
+
// stream (`job:<jobKey>`), keyed by the CLAIM (explicit instance+jobKey), not by a connection. The
|
|
11
|
+
// relay correlation registry is DEMOTED to drill-in context only: it still supplies the `correlations`
|
|
12
|
+
// — the process-instance / plan context for a job's terminal — so the cockpit lines a worker's terminal
|
|
13
|
+
// up with "that process instance / this plan", but it is no longer the visibility source.
|
|
11
14
|
//
|
|
12
15
|
// This is the supply half of the visibility plane only. The demand×supply matrix, missing-agent-type
|
|
13
16
|
// reds, and diversity-SLO lights are DE-SCOPED to the enrolment epic #152 — this report carries no
|
|
@@ -16,7 +19,8 @@
|
|
|
16
19
|
// The optional shared-secret guard stays HERE (the runtime does not enforce OpenAPI `security`): when
|
|
17
20
|
// NANO_PR_WEBHOOK_SECRET is set, callers must present it via the x-hook-secret header. Unset → open.
|
|
18
21
|
|
|
19
|
-
import { type
|
|
22
|
+
import { type ClaimRegistry, currentClaimRegistry } from "../app/agentic/claim-registry.ts";
|
|
23
|
+
import { currentCorrelation, type JobCorrelation } from "../app/agentic/correlation.ts";
|
|
20
24
|
import { currentPresenceRegistry, type SupplyWorker } from "../app/agentic/families/presence.family.ts";
|
|
21
25
|
import { envVar } from "../app/version.ts";
|
|
22
26
|
import type { AgenticJobCorrelation, AgenticSupplyReport, AgenticSupplyWorker } from "../nano-generated/api-io.d.ts";
|
|
@@ -27,13 +31,14 @@ import { defineOperation } from "../nano-generated/operations.ts";
|
|
|
27
31
|
const SECRET = envVar("NANO_PR_WEBHOOK_SECRET") ?? "";
|
|
28
32
|
|
|
29
33
|
// Project a presence-registry row to the wire worker. The drill `stream` defaults to the worker
|
|
30
|
-
// instance (H5) but is repointed at the worker's jobKey-scoped relay stream (`job:<jobKey>`)
|
|
31
|
-
//
|
|
32
|
-
|
|
34
|
+
// instance (H5) but is repointed at the worker's claimed jobKey-scoped relay stream (`job:<jobKey>`)
|
|
35
|
+
// when the claim registry knows a current claim for it (#713) — keyed by the CLAIM, not by the
|
|
36
|
+
// connection — so drilling in opens the LIVE job's terminal even before any transcript lands.
|
|
37
|
+
function toWorker(w: SupplyWorker, claims: ClaimRegistry | undefined): AgenticSupplyWorker {
|
|
33
38
|
const out: AgenticSupplyWorker = {
|
|
34
39
|
instance: w.instance,
|
|
35
40
|
identity: w.identity,
|
|
36
|
-
stream:
|
|
41
|
+
stream: claims?.primaryStreamFor(w.instance) ?? w.instance,
|
|
37
42
|
jobKeys: [...w.jobKeys],
|
|
38
43
|
live: w.live,
|
|
39
44
|
staleMs: w.staleMs,
|
|
@@ -67,15 +72,19 @@ export default defineOperation("getAgenticSupply", async ({ req }, app) => {
|
|
|
67
72
|
return { status: 200, body: empty };
|
|
68
73
|
}
|
|
69
74
|
|
|
70
|
-
//
|
|
71
|
-
// worker's current jobKeys
|
|
75
|
+
// #713: the CLAIM registry (if mounted) is the authoritative `jobKeysFor` source the presence
|
|
76
|
+
// snapshot resolves against — a worker's current jobKeys come from explicit `claim` frames, not the
|
|
77
|
+
// relay terminal, so they populate with zero transcript. Absent → jobKeys stay empty (advisory).
|
|
78
|
+
const claims = currentClaimRegistry();
|
|
79
|
+
// The correlation registry is demoted to drill-in context only: it still carries the per-job
|
|
80
|
+
// process-instance / plan context surfaced in `correlations`, but no longer feeds visibility.
|
|
72
81
|
const correlation = currentCorrelation();
|
|
73
|
-
const snapshot = registry.snapshot(
|
|
82
|
+
const snapshot = registry.snapshot(claims ? { jobKeysFor: (instance) => claims.jobKeysFor(instance) } : {});
|
|
74
83
|
const report: AgenticSupplyReport = {
|
|
75
84
|
count: snapshot.count,
|
|
76
85
|
generatedAt: new Date().toISOString(),
|
|
77
|
-
workers: snapshot.workers.map((w) => toWorker(w,
|
|
78
|
-
leaves: snapshot.leaves.map((leaf) => ({ token: leaf.token, workers: leaf.workers.map((w) => toWorker(w,
|
|
86
|
+
workers: snapshot.workers.map((w) => toWorker(w, claims)),
|
|
87
|
+
leaves: snapshot.leaves.map((leaf) => ({ token: leaf.token, workers: leaf.workers.map((w) => toWorker(w, claims)) })),
|
|
79
88
|
correlations: correlation ? correlation.snapshot().correlations.map(toCorrelation) : [],
|
|
80
89
|
};
|
|
81
90
|
return { status: 200, body: report };
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@nanobpm/nano-workforce",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.177.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",
|
|
@@ -62,7 +62,7 @@
|
|
|
62
62
|
"lint:fix": "biome check --write app operations workers pages components scripts e2e main.ts"
|
|
63
63
|
},
|
|
64
64
|
"dependencies": {
|
|
65
|
-
"@nanobpm/agentic": "^0.
|
|
65
|
+
"@nanobpm/agentic": "^0.11.0",
|
|
66
66
|
"@nanobpm/urban": "^0.90.0",
|
|
67
67
|
"bpmn-auto-layout": "^2.0.0-alpha.2"
|
|
68
68
|
},
|
package/test/agentic-e2e.test.ts
CHANGED
|
@@ -154,6 +154,7 @@ test("E2E: the whole visibility plane wires up — presence, correlation, supply
|
|
|
154
154
|
assert(names.includes("presence"), "H1 presence family is discovered by the H0 seam");
|
|
155
155
|
assert(names.includes("relay"), "H3 relay family is discovered by the H0 seam");
|
|
156
156
|
assert(names.includes("correlation"), "H6 correlation family is discovered by the H0 seam");
|
|
157
|
+
assert(names.includes("claim"), "#713 claim family is discovered by the H0 seam");
|
|
157
158
|
|
|
158
159
|
// ── H1: a worker connects and REGISTERs; a live presence row appears with its family/host. ──
|
|
159
160
|
const worker = conn("wk-conn-1", "leafA");
|
|
@@ -162,7 +163,14 @@ test("E2E: the whole visibility plane wires up — presence, correlation, supply
|
|
|
162
163
|
worker.feed({ lane: "control", family: "register", seq: 1, payload: { instance: "wk-a", capability: { family: "opus", host: "boxA" } } });
|
|
163
164
|
await flush();
|
|
164
165
|
|
|
165
|
-
// ──
|
|
166
|
+
// ── #713: the worker CLAIMs its active jobKey — the authoritative visibility source (explicit
|
|
167
|
+
// instance, no relay/connection inference). This is what lights up jobKeys, even before any
|
|
168
|
+
// transcript lands. ──
|
|
169
|
+
worker.feed({ lane: "control", family: "claim", seq: 2, payload: { instance: "wk-a", jobKey: JOB } });
|
|
170
|
+
await flush();
|
|
171
|
+
|
|
172
|
+
// ── H6: the orchestrator links the worker's active jobKey to its process instance / plan (drill-in
|
|
173
|
+
// context only, since #713 — no longer the visibility source). ──
|
|
166
174
|
const correlation = currentCorrelation();
|
|
167
175
|
assert(correlation !== undefined, "the correlation family installed the singleton");
|
|
168
176
|
correlation.link("wk-a", JOB, { processInstanceKey: "4612", bpmnProcessId: "plan-fanout", elementId: "implement-task", planKey: "nanobpm/nano-workforce#142" });
|
|
@@ -179,8 +187,8 @@ test("E2E: the whole visibility plane wires up — presence, correlation, supply
|
|
|
179
187
|
assertEquals(w.instance, "wk-a");
|
|
180
188
|
assertEquals(w.family, "opus");
|
|
181
189
|
assertEquals(w.host, "boxA");
|
|
182
|
-
assertEquals(w.jobKeys, [JOB], "
|
|
183
|
-
assertEquals(w.stream, STREAM, "
|
|
190
|
+
assertEquals(w.jobKeys, [JOB], "#713: the claim registry feeds the presence jobKeys seam");
|
|
191
|
+
assertEquals(w.stream, STREAM, "#713: the drill stream repoints at the claimed job's stream");
|
|
184
192
|
assertEquals(res.body.correlations.length, 1);
|
|
185
193
|
const c = res.body.correlations[0];
|
|
186
194
|
assertEquals(c.jobKey, JOB);
|