@tomflow/proflow-task-orchestration 0.1.9 → 0.1.11
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/dist/deployment/adapter.d.ts +3 -3
- package/dist/deployment/descriptor.d.ts +1 -1
- package/dist/deployment/descriptor.js +1 -1
- package/dist/src/contracts.js +2 -2
- package/dist/src/model.d.ts +2 -0
- package/dist/src/model.js +5 -0
- package/dist/src/services.d.ts +1 -0
- package/dist/src/services.js +32 -5
- package/dist/src/transitions.js +1 -1
- package/package.json +4 -4
- package/proflow.module.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,17 @@
|
|
|
1
1
|
# @tomflow/proflow-task-orchestration
|
|
2
2
|
|
|
3
|
+
## 0.1.11
|
|
4
|
+
|
|
5
|
+
### Patch Changes
|
|
6
|
+
|
|
7
|
+
- Release the verified Real-3 B1 task recovery, exact execution identity, durable observer resume, bounded gateway error, and matching Agent Action contract fixes.
|
|
8
|
+
|
|
9
|
+
## 0.1.10
|
|
10
|
+
|
|
11
|
+
### Patch Changes
|
|
12
|
+
|
|
13
|
+
- Close the Real-3 source candidate and real-workspace loop: fail-closed Browser submit verification, worker-bound Task mutation and WAKE confirmation, detached platform start ownership with shell return, discoverable docs, and targeted single-package Workspace update.
|
|
14
|
+
|
|
3
15
|
## 0.1.9
|
|
4
16
|
|
|
5
17
|
### Patch Changes
|
|
@@ -4,7 +4,7 @@ declare const success: () => {
|
|
|
4
4
|
readonly ok: true;
|
|
5
5
|
readonly status: "SUCCEEDED";
|
|
6
6
|
readonly moduleRef: "task-orchestration";
|
|
7
|
-
readonly moduleVersion: "0.1.
|
|
7
|
+
readonly moduleVersion: "0.1.11";
|
|
8
8
|
};
|
|
9
9
|
observedEffects: string[];
|
|
10
10
|
};
|
|
@@ -17,7 +17,7 @@ export declare const behaviorAdapter: {
|
|
|
17
17
|
ok: true;
|
|
18
18
|
status: "SUCCEEDED";
|
|
19
19
|
moduleRef: "task-orchestration";
|
|
20
|
-
moduleVersion: "0.1.
|
|
20
|
+
moduleVersion: "0.1.11";
|
|
21
21
|
data: {
|
|
22
22
|
setupStatus: "READY";
|
|
23
23
|
runtimeStatus: "NOT_APPLICABLE";
|
|
@@ -32,7 +32,7 @@ export declare const behaviorAdapter: {
|
|
|
32
32
|
ok: true;
|
|
33
33
|
status: "SUCCEEDED";
|
|
34
34
|
moduleRef: "task-orchestration";
|
|
35
|
-
moduleVersion: "0.1.
|
|
35
|
+
moduleVersion: "0.1.11";
|
|
36
36
|
data: {
|
|
37
37
|
docs: string;
|
|
38
38
|
};
|
|
@@ -3,7 +3,7 @@ export declare const descriptor: {
|
|
|
3
3
|
readonly contractVersion: "1.0.0";
|
|
4
4
|
readonly moduleRef: "task-orchestration";
|
|
5
5
|
readonly packageName: "@tomflow/proflow-task-orchestration";
|
|
6
|
-
readonly moduleVersion: "0.1.
|
|
6
|
+
readonly moduleVersion: "0.1.11";
|
|
7
7
|
readonly kind: "library";
|
|
8
8
|
readonly templateVersion: "1.0.0";
|
|
9
9
|
readonly platformCompatibility: ">=1.0.0 <2.0.0";
|
|
@@ -3,7 +3,7 @@ export const descriptor = {
|
|
|
3
3
|
contractVersion: "1.0.0",
|
|
4
4
|
moduleRef: "task-orchestration",
|
|
5
5
|
packageName: "@tomflow/proflow-task-orchestration",
|
|
6
|
-
moduleVersion: "0.1.
|
|
6
|
+
moduleVersion: "0.1.11",
|
|
7
7
|
kind: "library",
|
|
8
8
|
templateVersion: "1.0.0",
|
|
9
9
|
platformCompatibility: ">=1.0.0 <2.0.0",
|
package/dist/src/contracts.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { z } from "zod";
|
|
2
|
-
import { requiredTaskAgentPackageRefs } from "./model.js";
|
|
2
|
+
import { requiredTaskAgentPackageRefs, taskWaitTypes } from "./model.js";
|
|
3
3
|
export const publicOperationNames = [
|
|
4
4
|
"createTaskGroup",
|
|
5
5
|
"getTaskGroup",
|
|
@@ -136,7 +136,7 @@ const schemas = {
|
|
|
136
136
|
waitNode: z
|
|
137
137
|
.object({
|
|
138
138
|
...nodeVersion,
|
|
139
|
-
waitType:
|
|
139
|
+
waitType: z.enum(taskWaitTypes),
|
|
140
140
|
reasonCode: id,
|
|
141
141
|
message: id,
|
|
142
142
|
relatedRef: id.optional(),
|
package/dist/src/model.d.ts
CHANGED
|
@@ -1,4 +1,6 @@
|
|
|
1
1
|
export declare const requiredTaskAgentPackageRefs: readonly ["@tomflow/proflow-agent-product", "@tomflow/proflow-agent-controller-dev", "@tomflow/proflow-agent-test-ops"];
|
|
2
|
+
export declare const taskWaitTypes: readonly ["BUSINESS_CONFIRMATION", "REQUIREMENT_BLOCKED", "EXTERNAL_BUSINESS_DEPENDENCY"];
|
|
3
|
+
export type TaskWaitType = (typeof taskWaitTypes)[number];
|
|
2
4
|
export type TaskGroupStatus = "READY" | "ACTIVE" | "SUCCEEDED";
|
|
3
5
|
export type TaskStatus = "PENDING" | "READY" | "ACTIVE" | "WAITING" | "FAILED" | "PAUSED" | "SUCCEEDED" | "TERMINATED";
|
|
4
6
|
export type NodeStatus = "PENDING" | "READY" | "IN_PROGRESS" | "WAITING" | "FAILED" | "SUCCEEDED" | "TERMINATED";
|
package/dist/src/model.js
CHANGED
package/dist/src/services.d.ts
CHANGED
|
@@ -144,6 +144,7 @@ export declare function createTaskServices(options: {
|
|
|
144
144
|
} | null;
|
|
145
145
|
canDrive: boolean;
|
|
146
146
|
blockedReason: string | null;
|
|
147
|
+
resumeSignalRef: string | null;
|
|
147
148
|
}>;
|
|
148
149
|
getNodeContext: (raw: unknown) => TaskResult<{
|
|
149
150
|
task: Pick<Task, "taskId" | "title" | "objective" | "status" | "version">;
|
package/dist/src/services.js
CHANGED
|
@@ -726,15 +726,24 @@ export function createTaskServices(options) {
|
|
|
726
726
|
const current = task.currentNodeId
|
|
727
727
|
? tx.nodes.get(task.currentNodeId)
|
|
728
728
|
: undefined;
|
|
729
|
+
if (task.status === "WAITING" && current?.status !== "WAITING")
|
|
730
|
+
throw new DomainError("TASK_INVALID_STATE", "A WAITING Task must have a current WAITING Node.");
|
|
729
731
|
if (current?.status === "FAILED")
|
|
730
732
|
throw new DomainError("TASK_INVALID_STATE", "A failed Node must be explicitly reopened before resume.");
|
|
731
|
-
if (current?.status === "WAITING")
|
|
733
|
+
if (current?.status === "WAITING") {
|
|
734
|
+
const unresolved = tx.messages
|
|
735
|
+
.listPending()
|
|
736
|
+
.some((message) => message.taskId === task.taskId &&
|
|
737
|
+
message.nodeId === current.nodeId);
|
|
738
|
+
if (unresolved)
|
|
739
|
+
throw new DomainError("TASK_BLOCKER_UNRESOLVED", "The current Node still has an unresolved business blocker.");
|
|
732
740
|
tx.nodes.update({
|
|
733
741
|
...current,
|
|
734
742
|
status: "IN_PROGRESS",
|
|
735
743
|
version: current.version + 1,
|
|
736
744
|
updatedAt: timestamp,
|
|
737
745
|
});
|
|
746
|
+
}
|
|
738
747
|
const updated = {
|
|
739
748
|
...task,
|
|
740
749
|
status: "ACTIVE",
|
|
@@ -782,6 +791,8 @@ export function createTaskServices(options) {
|
|
|
782
791
|
const binding = tx.roleBindings.get(task.taskId, node.requiredAgentPackageRef);
|
|
783
792
|
if (!binding?.workerRef || !binding.conversationLocator)
|
|
784
793
|
throw new DomainError("TASK_ROLE_BINDING_REQUIRED", "Node role is not bound.");
|
|
794
|
+
if (!matchesWorker(input.actorRef, binding.workerRef))
|
|
795
|
+
throw new DomainError("WORKER_MISMATCH", "Only the Task-bound Worker may start the Node.");
|
|
785
796
|
const updatedNode = {
|
|
786
797
|
...node,
|
|
787
798
|
status: "IN_PROGRESS",
|
|
@@ -908,6 +919,8 @@ export function createTaskServices(options) {
|
|
|
908
919
|
checkVersion(node.version, input.expectedNodeVersion, "NODE_VERSION_CONFLICT");
|
|
909
920
|
if (task.status !== "ACTIVE")
|
|
910
921
|
throw new DomainError("TASK_INVALID_STATE", "Task must be ACTIVE before a Node can wait.");
|
|
922
|
+
if (task.currentNodeId !== node.nodeId)
|
|
923
|
+
throw new DomainError("NODE_NOT_CURRENT", "Only the current Node can enter WAITING.");
|
|
911
924
|
if (node.status !== "IN_PROGRESS" ||
|
|
912
925
|
!matchesWorker(input.actorRef, node.workerRef))
|
|
913
926
|
throw new DomainError(!matchesWorker(input.actorRef, node.workerRef)
|
|
@@ -948,10 +961,14 @@ export function createTaskServices(options) {
|
|
|
948
961
|
const node = requireNode(tx, input.taskId, input.nodeId);
|
|
949
962
|
checkVersion(task.version, input.expectedTaskVersion, "TASK_VERSION_CONFLICT");
|
|
950
963
|
checkVersion(node.version, input.expectedNodeVersion, "NODE_VERSION_CONFLICT");
|
|
951
|
-
if (
|
|
952
|
-
throw new DomainError("TASK_INVALID_STATE", "Task
|
|
953
|
-
if (
|
|
954
|
-
throw new DomainError("
|
|
964
|
+
if (task.status !== "ACTIVE")
|
|
965
|
+
throw new DomainError("TASK_INVALID_STATE", "Task must be ACTIVE before the current run can fail.");
|
|
966
|
+
if (task.currentNodeId !== node.nodeId)
|
|
967
|
+
throw new DomainError("NODE_NOT_CURRENT", "Only the current Node can record a run failure.");
|
|
968
|
+
if (!matchesWorker(input.actorRef, node.workerRef))
|
|
969
|
+
throw new DomainError("WORKER_MISMATCH", "Only the bound running Worker may fail the current Node.");
|
|
970
|
+
if (node.status !== "IN_PROGRESS")
|
|
971
|
+
throw new DomainError("NODE_INVALID_STATE", "Only the current IN_PROGRESS run can fail.");
|
|
955
972
|
const failedNode = {
|
|
956
973
|
...node,
|
|
957
974
|
status: "FAILED",
|
|
@@ -1114,6 +1131,13 @@ export function createTaskServices(options) {
|
|
|
1114
1131
|
else if (!terminal && !roleBinding?.workerRef)
|
|
1115
1132
|
blockedReason = "TASK_ROLE_BINDING_REQUIRED";
|
|
1116
1133
|
const canDrive = !terminal && blockedReason === null;
|
|
1134
|
+
let durableResumeEventId;
|
|
1135
|
+
if (task.status === "ACTIVE" && currentNode?.status === "IN_PROGRESS")
|
|
1136
|
+
for (const taskEvent of tx.events.listByTask(task.taskId))
|
|
1137
|
+
if (taskEvent.eventType === "TASK_RESUMED" &&
|
|
1138
|
+
taskEvent.taskVersion === task.version &&
|
|
1139
|
+
taskEvent.eventId !== undefined)
|
|
1140
|
+
durableResumeEventId = taskEvent.eventId;
|
|
1117
1141
|
return {
|
|
1118
1142
|
taskId: task.taskId,
|
|
1119
1143
|
taskStatus: task.status,
|
|
@@ -1138,6 +1162,9 @@ export function createTaskServices(options) {
|
|
|
1138
1162
|
: null,
|
|
1139
1163
|
canDrive,
|
|
1140
1164
|
blockedReason,
|
|
1165
|
+
resumeSignalRef: durableResumeEventId === undefined
|
|
1166
|
+
? null
|
|
1167
|
+
: `task-event:${durableResumeEventId}`,
|
|
1141
1168
|
};
|
|
1142
1169
|
}),
|
|
1143
1170
|
getNodeContext: (raw) => queryWithDocumentRecovery("getNodeContext", raw, (tx, input) => {
|
package/dist/src/transitions.js
CHANGED
|
@@ -7,7 +7,7 @@ const taskTransitions = {
|
|
|
7
7
|
READY: ["ACTIVE", "TERMINATED"],
|
|
8
8
|
ACTIVE: ["WAITING", "PAUSED", "FAILED", "SUCCEEDED", "TERMINATED"],
|
|
9
9
|
WAITING: ["ACTIVE", "PAUSED", "TERMINATED"],
|
|
10
|
-
FAILED: ["
|
|
10
|
+
FAILED: ["TERMINATED"],
|
|
11
11
|
PAUSED: ["ACTIVE", "TERMINATED"],
|
|
12
12
|
SUCCEEDED: [],
|
|
13
13
|
TERMINATED: [],
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@tomflow/proflow-task-orchestration",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.11",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"publishConfig": {
|
|
6
6
|
"access": "public"
|
|
@@ -23,9 +23,9 @@
|
|
|
23
23
|
"@tomflow/proflow-module-contract": "^0.1.13"
|
|
24
24
|
},
|
|
25
25
|
"devDependencies": {
|
|
26
|
-
"@tomflow/proflow-task-
|
|
27
|
-
"@tomflow/proflow-deployment-conformance": "^0.1.
|
|
28
|
-
"@tomflow/proflow-task-
|
|
26
|
+
"@tomflow/proflow-task-migration-runner": "^0.1.11",
|
|
27
|
+
"@tomflow/proflow-deployment-conformance": "^0.1.13",
|
|
28
|
+
"@tomflow/proflow-task-store-sqlite": "^0.1.11"
|
|
29
29
|
},
|
|
30
30
|
"description": "Owns the Task & Orchestration public contract, domain rules and application services.",
|
|
31
31
|
"keywords": [
|
package/proflow.module.json
CHANGED
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
"contractVersion": "1.0.0",
|
|
4
4
|
"moduleRef": "task-orchestration",
|
|
5
5
|
"packageName": "@tomflow/proflow-task-orchestration",
|
|
6
|
-
"moduleVersion": "0.1.
|
|
6
|
+
"moduleVersion": "0.1.11",
|
|
7
7
|
"kind": "library",
|
|
8
8
|
"templateVersion": "1.0.0",
|
|
9
9
|
"platformCompatibility": ">=1.0.0 <2.0.0",
|