@abelxiaoxing/cadence 1.0.0 → 1.0.2

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.
@@ -63,6 +63,7 @@ export interface SubmitClassification {
63
63
 
64
64
  export function createSubmitTool(input: {
65
65
  requestId: string;
66
+ taskId?: string;
66
67
  role: string;
67
68
  phase: string;
68
69
  output: "evidence" | "diff";
@@ -98,7 +99,8 @@ export function createSubmitTool(input: {
98
99
  if (value.id !== input.requestId) identity.request = false;
99
100
  if (value.role !== input.role) identity.role = false;
100
101
  if (input.output === "diff") {
101
- if (value.taskId !== input.requestId) identity.task = false;
102
+ if (value.taskId !== (input.taskId ?? input.requestId))
103
+ identity.task = false;
102
104
  if (value.phase !== input.phase) identity.phase = false;
103
105
  }
104
106
  const validation =
package/src/worker.ts CHANGED
@@ -1,77 +1,149 @@
1
1
  // Process-local logical Worker registry for private orchestration. A Worker
2
- // is pinned by the first accepted phase: logical ID, stage, role, the
3
- // provider/model/API/thinking identity, and the approved non-snapshot
4
- // contract. Later accepted Red/Green/optional Refactor phases receive fresh
5
- // snapshots and fresh phase-local auth for the SAME pinned identity. A failed
6
- // phase may be mechanically redispatched exactly once when its canonical
7
- // request is identical apart from refreshed snapshot hashes; a second failure
8
- // blocks that branch. No credential, transcript, or retry ledger is retained.
2
+ // is keyed by stable task identity. Its immutable task contract is separate
3
+ // from the current phase request, snapshot, verification, and launch budget.
4
+ // No credential, transcript, provider diagnostic, or unbounded retry ledger
5
+ // is retained.
9
6
 
10
- import type { RequestEnvelope } from "./contracts.ts";
7
+ import type { RequestEnvelope, VerificationContract } from "./contracts.ts";
11
8
 
12
9
  export interface WorkerContract {
13
10
  stage: string;
14
11
  role: string;
15
- id: string;
12
+ taskId: string;
16
13
  objective: string;
17
14
  roots: string[];
18
15
  agents: string;
19
16
  contractText: string;
20
17
  read: string[];
21
- write: string[];
22
18
  conflicts: string[];
23
19
  resources: string[];
24
- verificationLock?: string;
25
20
  output: string;
21
+ currentPhase: WorkerPhaseContract;
22
+ }
23
+
24
+ export interface WorkerTaskContract {
25
+ stage: string;
26
+ role: string;
27
+ taskId: string;
28
+ objective: string;
29
+ roots: string[];
30
+ agents: string;
31
+ contractText: string;
32
+ read: string[];
33
+ conflicts: string[];
34
+ resources: string[];
35
+ output: string;
36
+ }
37
+
38
+ export interface WorkerPhaseContract {
39
+ requestId: string;
40
+ phase: string;
41
+ readSet: string[];
42
+ writeSet: string[];
43
+ conflicts: string[];
44
+ resources: string[];
45
+ verificationLock?: string;
46
+ snapshot?: unknown;
47
+ verification?: VerificationContract;
48
+ correctionIndex: 0 | 1;
26
49
  }
27
50
 
28
51
  export interface LogicalWorker {
29
52
  identity: string;
30
- contract: WorkerContract;
31
- redispatchUsed: boolean;
53
+ taskContract: WorkerTaskContract;
54
+ currentPhase: WorkerPhaseContract;
55
+ state: WorkerState;
32
56
  }
33
57
 
34
- // Pins the semantic scope of a logical Worker, excluding the phase label so a
35
- // later Red/Green/Refactor phase is recognized as the same Worker.
58
+ export type WorkerState =
59
+ | { kind: "ready" }
60
+ | { kind: "candidate-pending" }
61
+ | { kind: "phase-applied" }
62
+ | { kind: "artifact-correction-pending"; rejection: string }
63
+ | { kind: "stale-redispatch-pending" }
64
+ | { kind: "blocked"; reason: "artifact" | "mechanical" };
65
+
36
66
  export function contractOf(envelope: RequestEnvelope): WorkerContract {
37
67
  return {
38
68
  stage: envelope.stage,
39
69
  role: envelope.role,
40
- id: envelope.id,
70
+ taskId: envelope.taskId ?? envelope.id,
41
71
  objective: envelope.objective,
42
72
  roots: [...envelope.roots],
43
73
  agents: envelope.context.agents,
44
74
  contractText: envelope.context.contract,
45
75
  read: [...envelope.declared.read],
46
- write: [...envelope.declared.write],
47
76
  conflicts: [...envelope.declared.conflicts],
48
77
  resources: [...envelope.declared.resources],
49
- verificationLock: envelope.declared.verificationLock,
50
78
  output: envelope.output,
79
+ currentPhase: phaseOf(envelope, 0),
51
80
  };
52
81
  }
53
82
 
54
- export function sameContract(a: WorkerContract, b: WorkerContract): boolean {
83
+ export function sameContract(
84
+ a: WorkerTaskContract,
85
+ b: WorkerTaskContract,
86
+ ): boolean {
55
87
  if (
56
88
  a.stage !== b.stage ||
57
89
  a.role !== b.role ||
58
- a.id !== b.id ||
90
+ a.taskId !== b.taskId ||
59
91
  a.objective !== b.objective ||
60
92
  a.agents !== b.agents ||
61
93
  a.contractText !== b.contractText ||
62
- a.output !== b.output ||
63
- a.verificationLock !== b.verificationLock
94
+ a.output !== b.output
64
95
  )
65
96
  return false;
66
97
  return (
67
98
  arrayEqual(a.roots, b.roots) &&
68
99
  arrayEqual(a.read, b.read) &&
69
- arrayEqual(a.write, b.write) &&
70
100
  arrayEqual(a.conflicts, b.conflicts) &&
71
101
  arrayEqual(a.resources, b.resources)
72
102
  );
73
103
  }
74
104
 
105
+ export function samePhaseContract(
106
+ a: WorkerPhaseContract,
107
+ b: WorkerPhaseContract,
108
+ ): boolean {
109
+ return (
110
+ a.phase === b.phase &&
111
+ arrayEqual(a.readSet, b.readSet) &&
112
+ arrayEqual(a.writeSet, b.writeSet) &&
113
+ arrayEqual(a.conflicts, b.conflicts) &&
114
+ arrayEqual(a.resources, b.resources) &&
115
+ a.verificationLock === b.verificationLock &&
116
+ JSON.stringify(a.verification) === JSON.stringify(b.verification)
117
+ );
118
+ }
119
+
120
+ function phaseOf(
121
+ envelope: RequestEnvelope,
122
+ correctionIndex: 0 | 1,
123
+ ): WorkerPhaseContract {
124
+ return {
125
+ requestId: envelope.id,
126
+ phase: envelope.phase,
127
+ readSet: [...envelope.declared.read],
128
+ writeSet: [...envelope.declared.write],
129
+ conflicts: [...envelope.declared.conflicts],
130
+ resources: [...envelope.declared.resources],
131
+ verificationLock: envelope.declared.verificationLock,
132
+ snapshot:
133
+ envelope.snapshot === undefined
134
+ ? undefined
135
+ : structuredClone(envelope.snapshot),
136
+ verification:
137
+ envelope.verification === undefined
138
+ ? undefined
139
+ : {
140
+ ...envelope.verification,
141
+ argv: [...envelope.verification.argv],
142
+ },
143
+ correctionIndex,
144
+ };
145
+ }
146
+
75
147
  function arrayEqual(a: string[], b: string[]): boolean {
76
148
  return a.length === b.length && a.every((value, index) => value === b[index]);
77
149
  }
@@ -104,12 +176,30 @@ export class WorkerRegistry {
104
176
  }
105
177
 
106
178
  pin(contract: WorkerContract, identity: string): LogicalWorker {
179
+ const currentPhase = clonePhase(contract.currentPhase);
107
180
  const worker: LogicalWorker = {
108
181
  identity,
109
- contract,
110
- redispatchUsed: false,
182
+ taskContract: cloneTask(contract),
183
+ currentPhase,
184
+ state: { kind: "ready" },
111
185
  };
112
- this.workers.set(contract.id, worker);
186
+ this.workers.set(contract.taskId, worker);
187
+ return worker;
188
+ }
189
+
190
+ setCurrentPhase(
191
+ taskId: string,
192
+ contract: WorkerContract,
193
+ correctionIndex: 0 | 1,
194
+ ): LogicalWorker | undefined {
195
+ const worker = this.workers.get(taskId);
196
+ if (!worker) return undefined;
197
+ const currentPhase = {
198
+ ...clonePhase(contract.currentPhase),
199
+ correctionIndex,
200
+ };
201
+ worker.currentPhase = currentPhase;
202
+ worker.state = { kind: "ready" };
113
203
  return worker;
114
204
  }
115
205
 
@@ -117,3 +207,23 @@ export class WorkerRegistry {
117
207
  this.workers.clear();
118
208
  }
119
209
  }
210
+
211
+ function cloneTask(contract: WorkerContract): WorkerTaskContract {
212
+ return {
213
+ stage: contract.stage,
214
+ role: contract.role,
215
+ taskId: contract.taskId,
216
+ objective: contract.objective,
217
+ roots: [...contract.roots],
218
+ agents: contract.agents,
219
+ contractText: contract.contractText,
220
+ read: [...contract.read],
221
+ conflicts: [...contract.conflicts],
222
+ resources: [...contract.resources],
223
+ output: contract.output,
224
+ };
225
+ }
226
+
227
+ function clonePhase(phase: WorkerPhaseContract): WorkerPhaseContract {
228
+ return structuredClone(phase);
229
+ }