@tomflow/proflow-task-orchestration 0.1.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/README.md ADDED
@@ -0,0 +1,5 @@
1
+ # @tomflow/proflow-task-orchestration
2
+
3
+ Task & Orchestration 的 Public Contract、领域规则、应用服务与基础设施 ports。规范真源位于 `spec/任务与编排领域/`。
4
+
5
+ v1 New Task 由 Extension/application 先 `createTask(PENDING)`;Task owns `TaskRoleBinding(agentPackageRef, roleRef, workerRef, conversationLocator)`、Requirement/document relations、deterministic readiness、Node/runNo/reopen/terminal truth。Simple start confirmation 不产生 Task approval/authorization fact。Task Observer 只读取 drive projection并请求 WAKE/RESUME,Worker 在 READY wake 后正式 `startNode`。
@@ -0,0 +1,4 @@
1
+ {
2
+ "contract": "proflow.conformance.v1",
3
+ "levels": ["C1", "C2", "C3"]
4
+ }
@@ -0,0 +1,47 @@
1
+ export declare const behaviorAdapter: {
2
+ readonly describe: () => {
3
+ result: {
4
+ readonly contract: "deployment.result.v1";
5
+ readonly ok: true;
6
+ readonly status: "SUCCEEDED";
7
+ readonly moduleRef: "task-orchestration";
8
+ readonly moduleVersion: "0.1.0";
9
+ };
10
+ observedEffects: never[];
11
+ };
12
+ readonly preflight: () => {
13
+ result: {
14
+ readonly contract: "deployment.result.v1";
15
+ readonly ok: true;
16
+ readonly status: "SUCCEEDED";
17
+ readonly moduleRef: "task-orchestration";
18
+ readonly moduleVersion: "0.1.0";
19
+ };
20
+ observedEffects: never[];
21
+ };
22
+ readonly verify: () => {
23
+ result: {
24
+ contract: "deployment.result.v1";
25
+ ok: true;
26
+ status: "SUCCEEDED";
27
+ moduleRef: "task-orchestration";
28
+ moduleVersion: "0.1.0";
29
+ checks: {
30
+ id: string;
31
+ status: string;
32
+ message: string;
33
+ }[];
34
+ };
35
+ observedEffects: never[];
36
+ };
37
+ readonly doctor: () => {
38
+ result: {
39
+ readonly contract: "deployment.result.v1";
40
+ readonly ok: true;
41
+ readonly status: "SUCCEEDED";
42
+ readonly moduleRef: "task-orchestration";
43
+ readonly moduleVersion: "0.1.0";
44
+ };
45
+ observedEffects: never[];
46
+ };
47
+ };
@@ -0,0 +1,26 @@
1
+ import { descriptor } from "./descriptor.js";
2
+ const result = {
3
+ contract: "deployment.result.v1",
4
+ ok: true,
5
+ status: "SUCCEEDED",
6
+ moduleRef: descriptor.moduleRef,
7
+ moduleVersion: descriptor.moduleVersion,
8
+ };
9
+ export const behaviorAdapter = {
10
+ describe: () => ({ result, observedEffects: [] }),
11
+ preflight: () => ({ result, observedEffects: [] }),
12
+ verify: () => ({
13
+ result: {
14
+ ...result,
15
+ checks: [
16
+ {
17
+ id: "task-domain-tests-pass",
18
+ status: "PASS",
19
+ message: "Task Domain test gate is available",
20
+ },
21
+ ],
22
+ },
23
+ observedEffects: [],
24
+ }),
25
+ doctor: () => ({ result, observedEffects: [] }),
26
+ };
@@ -0,0 +1,46 @@
1
+ export declare const descriptor: {
2
+ readonly contract: "module";
3
+ readonly contractVersion: "1.0.0";
4
+ readonly moduleRef: "task-orchestration";
5
+ readonly packageName: "@tomflow/proflow-task-orchestration";
6
+ readonly moduleVersion: "0.1.0";
7
+ readonly kind: "library";
8
+ readonly templateVersion: "1.0.0";
9
+ readonly platformCompatibility: ">=1.0.0 <2.0.0";
10
+ readonly installClass: "core";
11
+ readonly identity: {
12
+ readonly domain: "task-orchestration";
13
+ readonly summary: "Owns the Task & Orchestration public contract, domain rules and application services.";
14
+ };
15
+ readonly provides: readonly [{
16
+ readonly contractRef: "task-orchestration";
17
+ readonly version: "1.0.0";
18
+ }];
19
+ readonly requires: readonly [];
20
+ readonly requirements: readonly [{
21
+ readonly kind: "runtime";
22
+ readonly runtime: "node";
23
+ readonly versionRange: ">=24.19.0";
24
+ }];
25
+ readonly configSlots: readonly [];
26
+ readonly lifecycle: {
27
+ readonly supported: readonly ["describe", "preflight", "verify", "doctor"];
28
+ };
29
+ readonly verification: {
30
+ readonly checks: readonly [{
31
+ readonly id: "task-domain-tests-pass";
32
+ readonly description: "Task orchestration Critical Proofs pass";
33
+ readonly lifecycle: "verify";
34
+ }];
35
+ };
36
+ readonly effects: readonly [{
37
+ readonly kind: "filesystem";
38
+ readonly description: "Owns TaskDocument Markdown writes inside the configured workspace";
39
+ readonly retention: "preserve";
40
+ }];
41
+ readonly documentation: readonly [{
42
+ readonly id: "overview";
43
+ readonly path: "./README.md";
44
+ readonly description: "Package-owned module overview";
45
+ }];
46
+ };
@@ -0,0 +1,45 @@
1
+ export const descriptor = {
2
+ contract: "module",
3
+ contractVersion: "1.0.0",
4
+ moduleRef: "task-orchestration",
5
+ packageName: "@tomflow/proflow-task-orchestration",
6
+ moduleVersion: "0.1.0",
7
+ kind: "library",
8
+ templateVersion: "1.0.0",
9
+ platformCompatibility: ">=1.0.0 <2.0.0",
10
+ installClass: "core",
11
+ identity: {
12
+ domain: "task-orchestration",
13
+ summary: "Owns the Task & Orchestration public contract, domain rules and application services.",
14
+ },
15
+ provides: [{ contractRef: "task-orchestration", version: "1.0.0" }],
16
+ requires: [],
17
+ requirements: [
18
+ { kind: "runtime", runtime: "node", versionRange: ">=24.19.0" },
19
+ ],
20
+ configSlots: [],
21
+ lifecycle: { supported: ["describe", "preflight", "verify", "doctor"] },
22
+ verification: {
23
+ checks: [
24
+ {
25
+ id: "task-domain-tests-pass",
26
+ description: "Task orchestration Critical Proofs pass",
27
+ lifecycle: "verify",
28
+ },
29
+ ],
30
+ },
31
+ effects: [
32
+ {
33
+ kind: "filesystem",
34
+ description: "Owns TaskDocument Markdown writes inside the configured workspace",
35
+ retention: "preserve",
36
+ },
37
+ ],
38
+ documentation: [
39
+ {
40
+ id: "overview",
41
+ path: "./README.md",
42
+ description: "Package-owned module overview",
43
+ },
44
+ ],
45
+ };
@@ -0,0 +1,3 @@
1
+ export declare const publicOperationNames: readonly ["createTaskGroup", "getTaskGroup", "startTaskGroup", "createTask", "listTasks", "getTask", "startTask", "pauseTask", "resumeTask", "terminateTask", "bindTaskWorker", "getTaskDriveProjection", "getNodeContext", "startNode", "completeNode", "waitNode", "failNode", "reopenNode", "putTaskDocument", "getTaskDocument", "listPendingMessages", "acknowledgeMessage", "listTaskEvents"];
2
+ export type PublicOperationName = (typeof publicOperationNames)[number];
3
+ export declare function validatePublicInput(operation: PublicOperationName, input: unknown): unknown;
@@ -0,0 +1,187 @@
1
+ import { z } from "zod";
2
+ import { requiredTaskAgentPackageRefs } from "./model.js";
3
+ export const publicOperationNames = [
4
+ "createTaskGroup",
5
+ "getTaskGroup",
6
+ "startTaskGroup",
7
+ "createTask",
8
+ "listTasks",
9
+ "getTask",
10
+ "startTask",
11
+ "pauseTask",
12
+ "resumeTask",
13
+ "terminateTask",
14
+ "bindTaskWorker",
15
+ "getTaskDriveProjection",
16
+ "getNodeContext",
17
+ "startNode",
18
+ "completeNode",
19
+ "waitNode",
20
+ "failNode",
21
+ "reopenNode",
22
+ "putTaskDocument",
23
+ "getTaskDocument",
24
+ "listPendingMessages",
25
+ "acknowledgeMessage",
26
+ "listTaskEvents",
27
+ ];
28
+ const id = z.string().min(1);
29
+ const version = z.number().int().positive();
30
+ const actor = { actorRef: id, idempotencyKey: id };
31
+ const taskVersion = { expectedTaskVersion: version, ...actor };
32
+ const nodeVersion = {
33
+ taskId: id,
34
+ nodeId: id,
35
+ expectedTaskVersion: version,
36
+ expectedNodeVersion: version,
37
+ ...actor,
38
+ };
39
+ const roleBinding = z
40
+ .object({
41
+ agentPackageRef: id,
42
+ roleRef: id,
43
+ workerRef: id.nullable(),
44
+ conversationLocator: id.nullable(),
45
+ })
46
+ .strict();
47
+ const planNode = z
48
+ .object({
49
+ nodeId: id,
50
+ title: id,
51
+ objective: id,
52
+ requiredAgentPackageRef: id,
53
+ inputDocuments: z.array(id),
54
+ outputDocuments: z.array(id),
55
+ })
56
+ .strict();
57
+ const schemas = {
58
+ createTaskGroup: z
59
+ .object({
60
+ taskGroupId: id.optional(),
61
+ title: id,
62
+ objective: z.string().optional(),
63
+ maxActiveTasks: z.literal(1),
64
+ ...actor,
65
+ })
66
+ .strict(),
67
+ startTaskGroup: z
68
+ .object({ taskGroupId: id, expectedGroupVersion: version, ...actor })
69
+ .strict(),
70
+ createTask: z
71
+ .object({
72
+ taskId: id.optional(),
73
+ taskGroupId: id.optional(),
74
+ sequenceNo: version.optional(),
75
+ title: id,
76
+ objective: id,
77
+ plan: z.object({ nodes: z.array(planNode).min(1) }).strict(),
78
+ initialDocuments: z
79
+ .array(z.object({ documentType: id, content: z.string() }).strict())
80
+ .optional()
81
+ .default([]),
82
+ roleBindings: z.array(roleBinding).length(3),
83
+ ...actor,
84
+ })
85
+ .strict()
86
+ .superRefine((input, context) => {
87
+ if (input.taskGroupId !== undefined && input.sequenceNo === undefined) {
88
+ context.addIssue({
89
+ code: "custom",
90
+ message: "sequenceNo is required for a grouped Task",
91
+ path: ["sequenceNo"],
92
+ });
93
+ }
94
+ if (input.taskGroupId === undefined && input.sequenceNo !== undefined) {
95
+ context.addIssue({
96
+ code: "custom",
97
+ message: "sequenceNo is only valid for a grouped Task",
98
+ path: ["sequenceNo"],
99
+ });
100
+ }
101
+ const declaredAgentPackageRefs = new Set(input.roleBindings.map((binding) => binding.agentPackageRef));
102
+ if (declaredAgentPackageRefs.size !== requiredTaskAgentPackageRefs.length ||
103
+ requiredTaskAgentPackageRefs.some((agentPackageRef) => !declaredAgentPackageRefs.has(agentPackageRef))) {
104
+ context.addIssue({
105
+ code: "custom",
106
+ message: "roleBindings must contain exactly Product, Controller/Dev, and Test/Ops",
107
+ path: ["roleBindings"],
108
+ });
109
+ }
110
+ input.plan.nodes.forEach((node, index) => {
111
+ if (!declaredAgentPackageRefs.has(node.requiredAgentPackageRef))
112
+ context.addIssue({
113
+ code: "custom",
114
+ message: "plan node requiredAgentPackageRef must resolve to a declared fixed TaskRoleBinding",
115
+ path: ["plan", "nodes", index, "requiredAgentPackageRef"],
116
+ });
117
+ });
118
+ }),
119
+ getTaskDriveProjection: z.object({ taskId: id }).strict(),
120
+ bindTaskWorker: z
121
+ .object({
122
+ taskId: id,
123
+ agentPackageRef: id,
124
+ roleRef: id,
125
+ workerRef: id,
126
+ conversationLocator: id,
127
+ ...taskVersion,
128
+ })
129
+ .strict(),
130
+ startTask: z.object({ taskId: id, ...taskVersion }).strict(),
131
+ pauseTask: z.object({ taskId: id, reason: id, ...taskVersion }).strict(),
132
+ resumeTask: z.object({ taskId: id, ...taskVersion }).strict(),
133
+ terminateTask: z.object({ taskId: id, reason: id, ...taskVersion }).strict(),
134
+ startNode: z.object(nodeVersion).strict(),
135
+ completeNode: z.object({ ...nodeVersion, resultSummary: id }).strict(),
136
+ waitNode: z
137
+ .object({
138
+ ...nodeVersion,
139
+ waitType: id,
140
+ reasonCode: id,
141
+ message: id,
142
+ relatedRef: id.optional(),
143
+ })
144
+ .strict(),
145
+ failNode: z
146
+ .object({
147
+ ...nodeVersion,
148
+ errorCode: id,
149
+ errorMessage: id,
150
+ retryable: z.boolean(),
151
+ })
152
+ .strict(),
153
+ reopenNode: z
154
+ .object({ taskId: id, nodeId: id, reason: id, ...taskVersion })
155
+ .strict(),
156
+ acknowledgeMessage: z
157
+ .object({ messageId: id, resolution: z.string().optional(), ...actor })
158
+ .strict(),
159
+ getTaskGroup: z.object({ taskGroupId: id }).strict(),
160
+ listTasks: z
161
+ .object({ taskGroupId: id.optional(), statuses: z.array(id).optional() })
162
+ .strict(),
163
+ getTask: z.object({ taskId: id }).strict(),
164
+ getNodeContext: z.object({ taskId: id, nodeId: id }).strict(),
165
+ listPendingMessages: z.object({ taskId: id.optional() }).strict(),
166
+ listTaskEvents: z
167
+ .object({
168
+ taskId: id,
169
+ afterEventId: z.number().int().nonnegative().optional(),
170
+ limit: z.number().int().positive().max(1000).optional(),
171
+ })
172
+ .strict(),
173
+ putTaskDocument: z
174
+ .object({
175
+ taskId: id,
176
+ nodeId: id.nullable(),
177
+ documentType: id,
178
+ content: z.string(),
179
+ targetPath: z.never().optional(),
180
+ ...taskVersion,
181
+ })
182
+ .strict(),
183
+ getTaskDocument: z.object({ taskId: id, documentType: id }).strict(),
184
+ };
185
+ export function validatePublicInput(operation, input) {
186
+ return schemas[operation].parse(input);
187
+ }
@@ -0,0 +1,4 @@
1
+ export { type PublicOperationName, publicOperationNames, validatePublicInput, } from "./contracts.ts";
2
+ export * from "./model.ts";
3
+ export { createTaskServices, type DocumentResult, type NodeResult, type TaskSummary, type TaskView, } from "./services.ts";
4
+ export { assertNodeTransition, assertTaskGroupTransition, assertTaskTransition, } from "./transitions.ts";
@@ -0,0 +1,4 @@
1
+ export { publicOperationNames, validatePublicInput, } from "./contracts.js";
2
+ export * from "./model.js";
3
+ export { createTaskServices, } from "./services.js";
4
+ export { assertNodeTransition, assertTaskGroupTransition, assertTaskTransition, } from "./transitions.js";
@@ -0,0 +1,189 @@
1
+ export declare const requiredTaskAgentPackageRefs: readonly ["@tomflow/proflow-agent-product", "@tomflow/proflow-agent-controller-dev", "@tomflow/proflow-agent-test-ops"];
2
+ export type TaskGroupStatus = "READY" | "ACTIVE" | "SUCCEEDED";
3
+ export type TaskStatus = "PENDING" | "READY" | "ACTIVE" | "WAITING" | "FAILED" | "PAUSED" | "SUCCEEDED" | "TERMINATED";
4
+ export type NodeStatus = "PENDING" | "READY" | "IN_PROGRESS" | "WAITING" | "FAILED" | "SUCCEEDED" | "TERMINATED";
5
+ export interface TaskGroup {
6
+ taskGroupId: string;
7
+ title: string;
8
+ objective: string | null;
9
+ status: TaskGroupStatus;
10
+ maxActiveTasks: 1;
11
+ version: number;
12
+ createdByRef: string;
13
+ createdAt: string;
14
+ updatedAt: string;
15
+ }
16
+ export interface Task {
17
+ taskId: string;
18
+ taskGroupId: string | null;
19
+ sequenceNo: number | null;
20
+ title: string;
21
+ objective: string;
22
+ status: TaskStatus;
23
+ version: number;
24
+ planVersion: number;
25
+ currentNodeId: string | null;
26
+ createdByRef: string;
27
+ createdAt: string;
28
+ startedAt: string | null;
29
+ completedAt: string | null;
30
+ updatedAt: string;
31
+ }
32
+ export interface TaskNode {
33
+ nodeId: string;
34
+ taskId: string;
35
+ sequenceNo: number;
36
+ title: string;
37
+ objective: string;
38
+ status: NodeStatus;
39
+ version: number;
40
+ runNo: number;
41
+ requiredAgentPackageRef: string;
42
+ workerRef: string | null;
43
+ inputDocuments: string[];
44
+ outputDocuments: string[];
45
+ resultSummary: string | null;
46
+ errorCode: string | null;
47
+ errorMessage: string | null;
48
+ errorRetryable: boolean | null;
49
+ startedAt: string | null;
50
+ completedAt: string | null;
51
+ updatedAt: string;
52
+ }
53
+ export interface TaskRoleBinding {
54
+ taskId: string;
55
+ agentPackageRef: string;
56
+ roleRef: string;
57
+ workerRef: string | null;
58
+ conversationLocator: string | null;
59
+ version: number;
60
+ createdAt: string;
61
+ updatedAt: string;
62
+ }
63
+ export interface NodeExecutionHistory {
64
+ executionId?: number;
65
+ taskId: string;
66
+ nodeId: string;
67
+ runNo: number;
68
+ workerRef: string | null;
69
+ finalStatus: NodeStatus;
70
+ resultSummary: string | null;
71
+ errorCode: string | null;
72
+ errorMessage: string | null;
73
+ errorRetryable: boolean | null;
74
+ inputDocuments: string[];
75
+ outputDocuments: string[];
76
+ startedAt: string | null;
77
+ endedAt: string;
78
+ }
79
+ export interface TaskDocument {
80
+ taskId: string;
81
+ documentType: string;
82
+ sourceNodeId: string | null;
83
+ filePath: string;
84
+ contentHash: string;
85
+ updatedByRef: string;
86
+ updatedAt: string;
87
+ }
88
+ export interface TaskMessage {
89
+ messageId: string;
90
+ taskId: string;
91
+ nodeId: string | null;
92
+ messageType: string;
93
+ reasonCode: string;
94
+ message: string;
95
+ relatedRef: string | null;
96
+ status: "PENDING" | "ACKNOWLEDGED";
97
+ createdByRef: string;
98
+ createdAt: string;
99
+ acknowledgedByRef: string | null;
100
+ acknowledgedAt: string | null;
101
+ resolution: string | null;
102
+ }
103
+ export interface TaskEvent {
104
+ eventId?: number;
105
+ taskId: string;
106
+ nodeId: string | null;
107
+ eventType: string;
108
+ actorRef: string;
109
+ taskVersion: number | null;
110
+ nodeVersion: number | null;
111
+ payload: Record<string, unknown> | null;
112
+ createdAt: string;
113
+ }
114
+ export interface IdempotencyRecord {
115
+ idempotencyKey: string;
116
+ operation: string;
117
+ requestHash: string;
118
+ responseJson: string;
119
+ createdAt: string;
120
+ }
121
+ export interface TaskRepositories {
122
+ taskGroups: {
123
+ get(id: string): TaskGroup | undefined;
124
+ insert(value: TaskGroup): void;
125
+ update(value: TaskGroup): void;
126
+ list(): TaskGroup[];
127
+ };
128
+ tasks: {
129
+ get(id: string): Task | undefined;
130
+ insert(value: Task): void;
131
+ update(value: Task): void;
132
+ list(groupId?: string): Task[];
133
+ };
134
+ nodes: {
135
+ get(id: string): TaskNode | undefined;
136
+ insert(value: TaskNode): void;
137
+ update(value: TaskNode): void;
138
+ listByTask(taskId: string): TaskNode[];
139
+ };
140
+ roleBindings: {
141
+ get(taskId: string, agentPackageRef: string): TaskRoleBinding | undefined;
142
+ upsert(value: TaskRoleBinding): void;
143
+ listByTask(taskId: string): TaskRoleBinding[];
144
+ };
145
+ executionHistory: {
146
+ insert(value: NodeExecutionHistory): void;
147
+ listByTask(taskId: string): NodeExecutionHistory[];
148
+ };
149
+ documents: {
150
+ get(taskId: string, type: string): TaskDocument | undefined;
151
+ upsert(value: TaskDocument): void;
152
+ listByTask(taskId: string): TaskDocument[];
153
+ };
154
+ messages: {
155
+ get(id: string): TaskMessage | undefined;
156
+ insert(value: TaskMessage): void;
157
+ update(value: TaskMessage): void;
158
+ listPending(): TaskMessage[];
159
+ };
160
+ events: {
161
+ insert(value: TaskEvent): void;
162
+ listByTask(taskId: string): TaskEvent[];
163
+ };
164
+ idempotency: {
165
+ get(key: string): IdempotencyRecord | undefined;
166
+ insert(value: IdempotencyRecord): void;
167
+ };
168
+ }
169
+ export interface TaskStore {
170
+ transaction<T>(work: (repositories: TaskRepositories) => T): T;
171
+ read<T>(work: (repositories: TaskRepositories) => T): T;
172
+ }
173
+ export type TaskResult<T> = {
174
+ contract: "task-orchestration";
175
+ contractVersion: "1.0.0";
176
+ ok: true;
177
+ data: T;
178
+ } | {
179
+ contract: "task-orchestration";
180
+ contractVersion: "1.0.0";
181
+ ok: false;
182
+ error: {
183
+ code: string;
184
+ message: string;
185
+ retryable: boolean;
186
+ correlationId: string;
187
+ details?: Record<string, unknown>;
188
+ };
189
+ };
@@ -0,0 +1,5 @@
1
+ export const requiredTaskAgentPackageRefs = [
2
+ "@tomflow/proflow-agent-product",
3
+ "@tomflow/proflow-agent-controller-dev",
4
+ "@tomflow/proflow-agent-test-ops",
5
+ ];