codex-workflow-v2 2.0.0-alpha.7.2.1 → 2.0.0-beta.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.
- package/README.md +24 -5
- package/dist/src/alpha6/milestone.d.ts +27 -0
- package/dist/src/alpha6/milestone.js +152 -1
- package/dist/src/alpha6/milestone.js.map +1 -1
- package/dist/src/beta1/project-transaction.d.ts +52 -0
- package/dist/src/beta1/project-transaction.js +297 -0
- package/dist/src/beta1/project-transaction.js.map +1 -0
- package/dist/src/cli.js +239 -4
- package/dist/src/cli.js.map +1 -1
- package/dist/src/contracts.d.ts +20 -0
- package/dist/src/diagnostics.d.ts +11 -0
- package/dist/src/diagnostics.js +54 -0
- package/dist/src/diagnostics.js.map +1 -1
- package/dist/src/git.js +2 -5
- package/dist/src/git.js.map +1 -1
- package/dist/src/reviewer.d.ts +4 -0
- package/dist/src/reviewer.js +24 -7
- package/dist/src/reviewer.js.map +1 -1
- package/dist/src/version.d.ts +1 -1
- package/dist/src/version.js +1 -1
- package/dist/src/version.js.map +1 -1
- package/dist/src/workflow.d.ts +28 -1
- package/dist/src/workflow.js +658 -54
- package/dist/src/workflow.js.map +1 -1
- package/docs/autonomy-guardrails.md +11 -3
- package/docs/beta1-stabilization-brief.md +165 -0
- package/docs/beta2-initial-assembly-navigation-brief.md +616 -0
- package/docs/delegated-approval.md +4 -3
- package/docs/development-flow.md +23 -6
- package/docs/project-memory.md +7 -5
- package/docs/release.md +16 -2
- package/docs/split-required-recovery.md +54 -0
- package/docs/stable-release-defect-register.md +597 -0
- package/docs/updating-existing-project.md +2 -0
- package/package.json +2 -2
- package/plugins/codex-workflow-gateway/references/protocol.md +62 -3
- package/plugins/codex-workflow-gateway/skills/codex-workflow-gateway/SKILL.md +53 -2
- package/references/state-machine.md +4 -1
- package/schemas/task.schema.json +3 -1
|
@@ -0,0 +1,297 @@
|
|
|
1
|
+
import { createHash } from 'node:crypto';
|
|
2
|
+
import { existsSync, lstatSync, readFileSync, readdirSync, rmSync } from 'node:fs';
|
|
3
|
+
import path from 'node:path';
|
|
4
|
+
import os from 'node:os';
|
|
5
|
+
import { WorkflowError } from '../errors.js';
|
|
6
|
+
import { ensureDirectory, writeJsonAtomic, writeTextAtomic } from '../fs-utils.js';
|
|
7
|
+
const TRANSACTION_ID = /^[a-z0-9][a-z0-9-]{7,127}$/;
|
|
8
|
+
const activeProjectRoots = new Set();
|
|
9
|
+
export function applyProjectTransaction(options) {
|
|
10
|
+
recoverProjectTransactions(options.projectRoot, options.projectId);
|
|
11
|
+
validateTransactionId(options.transactionId);
|
|
12
|
+
if (!options.kind.trim())
|
|
13
|
+
throw new WorkflowError('INVALID_ARGUMENT', 'Project transaction kind is required.');
|
|
14
|
+
if (options.targets.length === 0)
|
|
15
|
+
throw new WorkflowError('INVALID_ARGUMENT', 'Project transaction requires targets.');
|
|
16
|
+
const paths = options.targets.map((target) => normalizeTargetPath(target.path));
|
|
17
|
+
if (new Set(paths).size !== paths.length) {
|
|
18
|
+
throw new WorkflowError('INVALID_ARGUMENT', 'Project transaction target paths must be unique.');
|
|
19
|
+
}
|
|
20
|
+
const journal = {
|
|
21
|
+
schemaVersion: 1,
|
|
22
|
+
transactionId: options.transactionId,
|
|
23
|
+
kind: options.kind.trim(),
|
|
24
|
+
projectId: options.projectId,
|
|
25
|
+
phase: 'prepared',
|
|
26
|
+
recoveryMode: 'roll-forward',
|
|
27
|
+
ownerPid: process.pid,
|
|
28
|
+
ownerHostname: os.hostname(),
|
|
29
|
+
targets: options.targets.map((target, index) => ({
|
|
30
|
+
path: paths[index],
|
|
31
|
+
preimage: captureSnapshot(resolveTarget(options.projectRoot, paths[index])),
|
|
32
|
+
staged: snapshotFromContent(target.content),
|
|
33
|
+
})),
|
|
34
|
+
preparedAt: options.now.toISOString(),
|
|
35
|
+
updatedAt: options.now.toISOString(),
|
|
36
|
+
};
|
|
37
|
+
writeJournal(options.projectRoot, journal);
|
|
38
|
+
const activeKey = path.resolve(options.projectRoot);
|
|
39
|
+
activeProjectRoots.add(activeKey);
|
|
40
|
+
try {
|
|
41
|
+
writeJournal(options.projectRoot, { ...journal, phase: 'applying', updatedAt: options.now.toISOString() });
|
|
42
|
+
journal.targets.forEach((target, index) => {
|
|
43
|
+
restoreSnapshot(resolveTarget(options.projectRoot, target.path), target.staged);
|
|
44
|
+
options.afterTargetWrite?.(index, options.targets[index]);
|
|
45
|
+
});
|
|
46
|
+
options.validate?.();
|
|
47
|
+
writeJournal(options.projectRoot, { ...journal, phase: 'applied', updatedAt: options.now.toISOString() });
|
|
48
|
+
removeJournal(options.projectRoot, options.transactionId);
|
|
49
|
+
}
|
|
50
|
+
catch (error) {
|
|
51
|
+
rollback(options.projectRoot, journal);
|
|
52
|
+
throw error;
|
|
53
|
+
}
|
|
54
|
+
finally {
|
|
55
|
+
activeProjectRoots.delete(activeKey);
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
export function recoverProjectTransactions(projectRoot, projectId) {
|
|
59
|
+
if (activeProjectRoots.has(path.resolve(projectRoot)))
|
|
60
|
+
return [];
|
|
61
|
+
const directory = transactionDirectory(projectRoot);
|
|
62
|
+
if (!existsSync(directory))
|
|
63
|
+
return [];
|
|
64
|
+
const recovered = [];
|
|
65
|
+
for (const entry of readdirSync(directory, { withFileTypes: true }).filter((item) => item.isFile() && item.name.endsWith('.json'))) {
|
|
66
|
+
const file = path.join(directory, entry.name);
|
|
67
|
+
const journal = parseJournal(file, projectRoot, projectId);
|
|
68
|
+
if ((journal.phase === 'prepared' || journal.phase === 'applying') && journal.ownerHostname === os.hostname() && processIsAlive(journal.ownerPid)) {
|
|
69
|
+
throw new WorkflowError('TRANSITION_BLOCKED', 'A project transaction is still owned by a live process.', {
|
|
70
|
+
transactionId: journal.transactionId,
|
|
71
|
+
kind: journal.kind,
|
|
72
|
+
ownerPid: journal.ownerPid,
|
|
73
|
+
requiredAction: 'Wait for the active command to finish, or run doctor after the owner process exits.',
|
|
74
|
+
});
|
|
75
|
+
}
|
|
76
|
+
if (journal.phase === 'prepared' || journal.phase === 'rolled_back') {
|
|
77
|
+
rollback(projectRoot, journal);
|
|
78
|
+
recovered.push(journal.transactionId);
|
|
79
|
+
continue;
|
|
80
|
+
}
|
|
81
|
+
if (journal.phase === 'applied') {
|
|
82
|
+
if (journal.recoveryMode === 'roll-forward') {
|
|
83
|
+
for (const target of journal.targets)
|
|
84
|
+
restoreSnapshot(resolveTarget(projectRoot, target.path), target.staged);
|
|
85
|
+
}
|
|
86
|
+
removeJournal(projectRoot, journal.transactionId);
|
|
87
|
+
recovered.push(journal.transactionId);
|
|
88
|
+
continue;
|
|
89
|
+
}
|
|
90
|
+
if (journal.recoveryMode === 'roll-back') {
|
|
91
|
+
rollback(projectRoot, journal);
|
|
92
|
+
recovered.push(journal.transactionId);
|
|
93
|
+
continue;
|
|
94
|
+
}
|
|
95
|
+
for (const target of journal.targets) {
|
|
96
|
+
const current = captureSnapshot(resolveTarget(projectRoot, target.path));
|
|
97
|
+
if (!snapshotsEqual(current, target.preimage) && !snapshotsEqual(current, target.staged)) {
|
|
98
|
+
throw new WorkflowError('STATE_CORRUPT', 'Project transaction target diverged during recovery.', {
|
|
99
|
+
transactionId: journal.transactionId,
|
|
100
|
+
target: target.path,
|
|
101
|
+
});
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
for (const target of journal.targets)
|
|
105
|
+
restoreSnapshot(resolveTarget(projectRoot, target.path), target.staged);
|
|
106
|
+
removeJournal(projectRoot, journal.transactionId);
|
|
107
|
+
recovered.push(journal.transactionId);
|
|
108
|
+
}
|
|
109
|
+
return recovered;
|
|
110
|
+
}
|
|
111
|
+
export function runRollbackProjectTransaction(options) {
|
|
112
|
+
recoverProjectTransactions(options.projectRoot, options.projectId);
|
|
113
|
+
validateTransactionId(options.transactionId);
|
|
114
|
+
const paths = options.targetPaths.map(normalizeTargetPath);
|
|
115
|
+
if (paths.length === 0 || new Set(paths).size !== paths.length) {
|
|
116
|
+
throw new WorkflowError('INVALID_ARGUMENT', 'Rollback project transaction requires unique targets.');
|
|
117
|
+
}
|
|
118
|
+
const targets = paths.map((targetPath) => {
|
|
119
|
+
const preimage = captureSnapshot(resolveTarget(options.projectRoot, targetPath));
|
|
120
|
+
return { path: targetPath, preimage, staged: preimage };
|
|
121
|
+
});
|
|
122
|
+
const journal = {
|
|
123
|
+
schemaVersion: 1,
|
|
124
|
+
transactionId: options.transactionId,
|
|
125
|
+
kind: options.kind,
|
|
126
|
+
projectId: options.projectId,
|
|
127
|
+
phase: 'prepared',
|
|
128
|
+
recoveryMode: 'roll-back',
|
|
129
|
+
ownerPid: process.pid,
|
|
130
|
+
ownerHostname: os.hostname(),
|
|
131
|
+
targets,
|
|
132
|
+
preparedAt: options.now.toISOString(),
|
|
133
|
+
updatedAt: options.now.toISOString(),
|
|
134
|
+
};
|
|
135
|
+
const activeKey = path.resolve(options.projectRoot);
|
|
136
|
+
writeJournal(options.projectRoot, journal);
|
|
137
|
+
activeProjectRoots.add(activeKey);
|
|
138
|
+
try {
|
|
139
|
+
writeJournal(options.projectRoot, { ...journal, phase: 'applying', updatedAt: options.now.toISOString() });
|
|
140
|
+
const result = options.mutate();
|
|
141
|
+
options.validate?.(result);
|
|
142
|
+
writeJournal(options.projectRoot, { ...journal, phase: 'applied', updatedAt: options.now.toISOString() });
|
|
143
|
+
removeJournal(options.projectRoot, journal.transactionId);
|
|
144
|
+
return result;
|
|
145
|
+
}
|
|
146
|
+
catch (error) {
|
|
147
|
+
rollback(options.projectRoot, journal);
|
|
148
|
+
throw error;
|
|
149
|
+
}
|
|
150
|
+
finally {
|
|
151
|
+
activeProjectRoots.delete(activeKey);
|
|
152
|
+
}
|
|
153
|
+
}
|
|
154
|
+
export function listProjectTransactions(projectRoot, projectId) {
|
|
155
|
+
const directory = transactionDirectory(projectRoot);
|
|
156
|
+
if (!existsSync(directory))
|
|
157
|
+
return [];
|
|
158
|
+
return readdirSync(directory, { withFileTypes: true })
|
|
159
|
+
.filter((entry) => entry.isFile() && entry.name.endsWith('.json'))
|
|
160
|
+
.map((entry) => parseJournal(path.join(directory, entry.name), projectRoot, projectId))
|
|
161
|
+
.map(({ transactionId, kind, phase, preparedAt }) => ({ transactionId, kind, phase, preparedAt }));
|
|
162
|
+
}
|
|
163
|
+
function rollback(projectRoot, journal) {
|
|
164
|
+
for (const target of journal.targets)
|
|
165
|
+
restoreSnapshot(resolveTarget(projectRoot, target.path), target.preimage);
|
|
166
|
+
writeJournal(projectRoot, { ...journal, phase: 'rolled_back', updatedAt: new Date().toISOString() });
|
|
167
|
+
removeJournal(projectRoot, journal.transactionId);
|
|
168
|
+
}
|
|
169
|
+
function transactionDirectory(projectRoot) {
|
|
170
|
+
return path.join(projectRoot, '.transactions-beta1');
|
|
171
|
+
}
|
|
172
|
+
function journalPath(projectRoot, transactionId) {
|
|
173
|
+
validateTransactionId(transactionId);
|
|
174
|
+
return path.join(transactionDirectory(projectRoot), `${transactionId}.json`);
|
|
175
|
+
}
|
|
176
|
+
function writeJournal(projectRoot, journal) {
|
|
177
|
+
ensureDirectory(transactionDirectory(projectRoot));
|
|
178
|
+
writeJsonAtomic(journalPath(projectRoot, journal.transactionId), journal);
|
|
179
|
+
}
|
|
180
|
+
function removeJournal(projectRoot, transactionId) {
|
|
181
|
+
rmSync(journalPath(projectRoot, transactionId), { force: true });
|
|
182
|
+
}
|
|
183
|
+
function parseJournal(file, projectRoot, projectId) {
|
|
184
|
+
let value;
|
|
185
|
+
try {
|
|
186
|
+
value = JSON.parse(readFileSync(file, 'utf8'));
|
|
187
|
+
}
|
|
188
|
+
catch (error) {
|
|
189
|
+
throw new WorkflowError('STATE_CORRUPT', `Cannot read project transaction journal: ${file}`, {
|
|
190
|
+
cause: error instanceof Error ? error.message : String(error),
|
|
191
|
+
});
|
|
192
|
+
}
|
|
193
|
+
const journal = value;
|
|
194
|
+
if (journal.schemaVersion !== 1 || journal.projectId !== projectId || !journal.transactionId || !journal.kind
|
|
195
|
+
|| !['roll-forward', 'roll-back'].includes(journal.recoveryMode ?? '')
|
|
196
|
+
|| !Number.isInteger(journal.ownerPid) || (journal.ownerPid ?? 0) < 1 || !journal.ownerHostname
|
|
197
|
+
|| !['prepared', 'applying', 'applied', 'rolled_back'].includes(journal.phase ?? '') || !Array.isArray(journal.targets)) {
|
|
198
|
+
throw new WorkflowError('STATE_CORRUPT', `Invalid project transaction journal: ${file}`);
|
|
199
|
+
}
|
|
200
|
+
validateTransactionId(journal.transactionId);
|
|
201
|
+
const expectedFile = journalPath(projectRoot, journal.transactionId);
|
|
202
|
+
if (path.resolve(file) !== path.resolve(expectedFile)) {
|
|
203
|
+
throw new WorkflowError('STATE_CORRUPT', `Project transaction journal filename mismatch: ${file}`);
|
|
204
|
+
}
|
|
205
|
+
for (const target of journal.targets) {
|
|
206
|
+
normalizeTargetPath(target.path);
|
|
207
|
+
validateSnapshot(target.preimage);
|
|
208
|
+
validateSnapshot(target.staged);
|
|
209
|
+
}
|
|
210
|
+
return journal;
|
|
211
|
+
}
|
|
212
|
+
function normalizeTargetPath(value) {
|
|
213
|
+
const normalized = value.split(path.sep).join('/');
|
|
214
|
+
if (!normalized || path.isAbsolute(normalized) || normalized.split('/').some((part) => !part || part === '.' || part === '..')) {
|
|
215
|
+
throw new WorkflowError('INVALID_ARGUMENT', `Invalid project transaction target: ${value}`);
|
|
216
|
+
}
|
|
217
|
+
if (normalized === '.transactions-beta1' || normalized.startsWith('.transactions-beta1/')) {
|
|
218
|
+
throw new WorkflowError('INVALID_ARGUMENT', 'Project transaction cannot target its journal directory.');
|
|
219
|
+
}
|
|
220
|
+
return normalized;
|
|
221
|
+
}
|
|
222
|
+
function resolveTarget(projectRoot, relativePath) {
|
|
223
|
+
const root = path.resolve(projectRoot);
|
|
224
|
+
const target = path.resolve(root, normalizeTargetPath(relativePath));
|
|
225
|
+
if (!target.startsWith(`${root}${path.sep}`))
|
|
226
|
+
throw new WorkflowError('INVALID_ARGUMENT', 'Project transaction target escaped project root.');
|
|
227
|
+
let current = root;
|
|
228
|
+
for (const part of path.relative(root, path.dirname(target)).split(path.sep).filter(Boolean)) {
|
|
229
|
+
current = path.join(current, part);
|
|
230
|
+
if (existsSync(current) && lstatSync(current).isSymbolicLink()) {
|
|
231
|
+
throw new WorkflowError('STATE_CORRUPT', `Project transaction target traverses a symlink: ${relativePath}`);
|
|
232
|
+
}
|
|
233
|
+
}
|
|
234
|
+
if (existsSync(target) && lstatSync(target).isSymbolicLink()) {
|
|
235
|
+
throw new WorkflowError('STATE_CORRUPT', `Project transaction target is a symlink: ${relativePath}`);
|
|
236
|
+
}
|
|
237
|
+
return target;
|
|
238
|
+
}
|
|
239
|
+
function captureSnapshot(file) {
|
|
240
|
+
if (!existsSync(file))
|
|
241
|
+
return { exists: false, contentHash: null, contentBase64: null };
|
|
242
|
+
const content = readFileSync(file);
|
|
243
|
+
return { exists: true, contentHash: sha256(content), contentBase64: content.toString('base64') };
|
|
244
|
+
}
|
|
245
|
+
function snapshotFromContent(content) {
|
|
246
|
+
if (content === null)
|
|
247
|
+
return { exists: false, contentHash: null, contentBase64: null };
|
|
248
|
+
const normalized = Buffer.from(content.endsWith('\n') ? content : `${content}\n`);
|
|
249
|
+
return { exists: true, contentHash: sha256(normalized), contentBase64: normalized.toString('base64') };
|
|
250
|
+
}
|
|
251
|
+
function restoreSnapshot(file, snapshot) {
|
|
252
|
+
validateSnapshot(snapshot);
|
|
253
|
+
if (!snapshot.exists) {
|
|
254
|
+
rmSync(file, { force: true });
|
|
255
|
+
return;
|
|
256
|
+
}
|
|
257
|
+
writeTextAtomic(file, Buffer.from(snapshot.contentBase64, 'base64').toString('utf8'));
|
|
258
|
+
if (!snapshotsEqual(captureSnapshot(file), snapshot)) {
|
|
259
|
+
throw new WorkflowError('STATE_CORRUPT', `Project transaction snapshot restore failed: ${file}`);
|
|
260
|
+
}
|
|
261
|
+
}
|
|
262
|
+
function validateSnapshot(snapshot) {
|
|
263
|
+
if (!snapshot || typeof snapshot !== 'object' || typeof snapshot.exists !== 'boolean') {
|
|
264
|
+
throw new WorkflowError('STATE_CORRUPT', 'Invalid project transaction snapshot.');
|
|
265
|
+
}
|
|
266
|
+
if (!snapshot.exists) {
|
|
267
|
+
if (snapshot.contentHash !== null || snapshot.contentBase64 !== null)
|
|
268
|
+
throw new WorkflowError('STATE_CORRUPT', 'Absent snapshot contains data.');
|
|
269
|
+
return;
|
|
270
|
+
}
|
|
271
|
+
if (!snapshot.contentHash || !/^[a-f0-9]{64}$/.test(snapshot.contentHash) || snapshot.contentBase64 === null) {
|
|
272
|
+
throw new WorkflowError('STATE_CORRUPT', 'Existing project transaction snapshot is incomplete.');
|
|
273
|
+
}
|
|
274
|
+
if (sha256(Buffer.from(snapshot.contentBase64, 'base64')) !== snapshot.contentHash) {
|
|
275
|
+
throw new WorkflowError('STATE_CORRUPT', 'Project transaction snapshot hash mismatch.');
|
|
276
|
+
}
|
|
277
|
+
}
|
|
278
|
+
function snapshotsEqual(left, right) {
|
|
279
|
+
return left.exists === right.exists && left.contentHash === right.contentHash;
|
|
280
|
+
}
|
|
281
|
+
function sha256(content) {
|
|
282
|
+
return createHash('sha256').update(content).digest('hex');
|
|
283
|
+
}
|
|
284
|
+
function validateTransactionId(value) {
|
|
285
|
+
if (!TRANSACTION_ID.test(value))
|
|
286
|
+
throw new WorkflowError('INVALID_ARGUMENT', `Invalid project transaction id: ${value}`);
|
|
287
|
+
}
|
|
288
|
+
function processIsAlive(pid) {
|
|
289
|
+
try {
|
|
290
|
+
process.kill(pid, 0);
|
|
291
|
+
return true;
|
|
292
|
+
}
|
|
293
|
+
catch (error) {
|
|
294
|
+
return Boolean(error && typeof error === 'object' && 'code' in error && error.code === 'EPERM');
|
|
295
|
+
}
|
|
296
|
+
}
|
|
297
|
+
//# sourceMappingURL=project-transaction.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"project-transaction.js","sourceRoot":"","sources":["../../../src/beta1/project-transaction.ts"],"names":[],"mappings":"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"}
|
package/dist/src/cli.js
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
+
import { createHash } from 'node:crypto';
|
|
2
3
|
import { readFileSync } from 'node:fs';
|
|
3
4
|
import path from 'node:path';
|
|
4
5
|
import process from 'node:process';
|
|
@@ -12,6 +13,118 @@ import { launchStrictReviewer } from './reviewer.js';
|
|
|
12
13
|
import { WorkflowService } from './workflow.js';
|
|
13
14
|
import { PACKAGE_NAME, PACKAGE_VERSION } from './version.js';
|
|
14
15
|
import { PROTOCOL_VERSION, STATE_SCHEMA_VERSION } from './contracts.js';
|
|
16
|
+
const CLI_ACTIONS = {
|
|
17
|
+
gateway: ['handshake'],
|
|
18
|
+
update: ['preflight', 'rescue-preflight'],
|
|
19
|
+
delegation: ['prepare', 'grant', 'list', 'show', 'revoke'],
|
|
20
|
+
'project-memory': ['scan', 'show', 'status', 'approve', 'reconcile'],
|
|
21
|
+
state: ['migrate', 'adoption-prepare', 'adoption-apply'],
|
|
22
|
+
graph: ['prepare', 'status', 'refresh-request', 'bind', 'fallback'],
|
|
23
|
+
discovery: ['start', 'update', 'show', 'materialize'],
|
|
24
|
+
task: [
|
|
25
|
+
'show',
|
|
26
|
+
'replacement-materialize',
|
|
27
|
+
'plan-set',
|
|
28
|
+
'knowledge-rebind',
|
|
29
|
+
'context-refresh',
|
|
30
|
+
'authorize',
|
|
31
|
+
'plan-risk-audit',
|
|
32
|
+
'start',
|
|
33
|
+
'run',
|
|
34
|
+
'step-complete',
|
|
35
|
+
'submit',
|
|
36
|
+
'review-record',
|
|
37
|
+
'review-launch',
|
|
38
|
+
'step-review',
|
|
39
|
+
'corrective-decision-recover',
|
|
40
|
+
'remediation-mode-recover',
|
|
41
|
+
'corrective-decision',
|
|
42
|
+
'handoff',
|
|
43
|
+
'handoff-prepare',
|
|
44
|
+
'handoff-show',
|
|
45
|
+
'claim',
|
|
46
|
+
'handback',
|
|
47
|
+
'handback-create',
|
|
48
|
+
'result-set',
|
|
49
|
+
'accept',
|
|
50
|
+
'sync-base',
|
|
51
|
+
'merge',
|
|
52
|
+
'merge-confirm',
|
|
53
|
+
],
|
|
54
|
+
milestone: [
|
|
55
|
+
'recover',
|
|
56
|
+
'show',
|
|
57
|
+
'plan-set',
|
|
58
|
+
'scope-change-prepare',
|
|
59
|
+
'scope-change-apply',
|
|
60
|
+
'autonomy-prepare',
|
|
61
|
+
'autonomy-grant',
|
|
62
|
+
'autonomy-evolve',
|
|
63
|
+
'authorize',
|
|
64
|
+
'validate',
|
|
65
|
+
'accept',
|
|
66
|
+
'cancel',
|
|
67
|
+
],
|
|
68
|
+
locks: ['inspect', 'repair'],
|
|
69
|
+
};
|
|
70
|
+
const CLI_HELP_SPECS = {
|
|
71
|
+
'milestone authorize': {
|
|
72
|
+
requiredOptions: ['--id', '--expected-revision'],
|
|
73
|
+
optionalOptions: ['--actor', '--reason', '--delegation-grant', '--repo', '--json'],
|
|
74
|
+
},
|
|
75
|
+
'milestone validate': {
|
|
76
|
+
requiredOptions: ['--id', '--expected-revision'],
|
|
77
|
+
optionalOptions: ['--repo', '--json'],
|
|
78
|
+
},
|
|
79
|
+
'milestone accept': {
|
|
80
|
+
requiredOptions: ['--id', '--expected-revision', '--actor', '--confirmation-code'],
|
|
81
|
+
optionalOptions: ['--delegation-grant', '--repo', '--json'],
|
|
82
|
+
},
|
|
83
|
+
'task plan-set': {
|
|
84
|
+
requiredOptions: ['--id', '--expected-revision', '--file', '--risk-audit-file'],
|
|
85
|
+
optionalOptions: ['--corrective-audit-file', '--repo', '--json'],
|
|
86
|
+
},
|
|
87
|
+
'task authorize': {
|
|
88
|
+
requiredOptions: ['--id', '--expected-revision'],
|
|
89
|
+
optionalOptions: ['--actor', '--reason', '--delegation-grant', '--repo', '--json'],
|
|
90
|
+
},
|
|
91
|
+
'task start': {
|
|
92
|
+
requiredOptions: ['--id', '--expected-revision', '--workspace-owner'],
|
|
93
|
+
optionalOptions: ['--repo', '--json'],
|
|
94
|
+
},
|
|
95
|
+
'task run': {
|
|
96
|
+
requiredOptions: ['--id', '--step', '--expected-revision'],
|
|
97
|
+
optionalOptions: ['--owner', '--writer-token', '--repo', '--json'],
|
|
98
|
+
},
|
|
99
|
+
'task step-complete': {
|
|
100
|
+
requiredOptions: ['--id', '--step', '--expected-revision', '--writer-token'],
|
|
101
|
+
optionalOptions: ['--note', '--actor', '--repo', '--json'],
|
|
102
|
+
},
|
|
103
|
+
'task submit': {
|
|
104
|
+
requiredOptions: ['--id', '--expected-revision', '--writer-token'],
|
|
105
|
+
optionalOptions: ['--actor', '--repo', '--json'],
|
|
106
|
+
},
|
|
107
|
+
'task review-launch': {
|
|
108
|
+
requiredOptions: ['--id', '--expected-revision'],
|
|
109
|
+
optionalOptions: ['--actor', '--writer-token', '--repo', '--json'],
|
|
110
|
+
},
|
|
111
|
+
'task result-set': {
|
|
112
|
+
requiredOptions: ['--id', '--expected-revision', '--summary'],
|
|
113
|
+
optionalOptions: ['--limitation', '--repo', '--json'],
|
|
114
|
+
},
|
|
115
|
+
'task accept': {
|
|
116
|
+
requiredOptions: ['--id', '--expected-revision'],
|
|
117
|
+
optionalOptions: ['--actor', '--delegation-grant', '--repo', '--json'],
|
|
118
|
+
},
|
|
119
|
+
'task merge': {
|
|
120
|
+
requiredOptions: ['--id', '--expected-revision', '--writer-token'],
|
|
121
|
+
optionalOptions: ['--actor', '--repo', '--json'],
|
|
122
|
+
},
|
|
123
|
+
'task merge-confirm': {
|
|
124
|
+
requiredOptions: ['--id', '--expected-revision', '--writer-token'],
|
|
125
|
+
optionalOptions: ['--actor', '--repo', '--json'],
|
|
126
|
+
},
|
|
127
|
+
};
|
|
15
128
|
function parseArguments(argv) {
|
|
16
129
|
const positionals = [];
|
|
17
130
|
const options = new Map();
|
|
@@ -37,6 +150,55 @@ function parseArguments(argv) {
|
|
|
37
150
|
function option(args, name) {
|
|
38
151
|
return args.options.get(name)?.at(-1);
|
|
39
152
|
}
|
|
153
|
+
function cliHelp(args) {
|
|
154
|
+
const [noun, action] = args.positionals;
|
|
155
|
+
if (!noun) {
|
|
156
|
+
return {
|
|
157
|
+
kind: 'cli-help',
|
|
158
|
+
readOnly: true,
|
|
159
|
+
scope: 'top-level',
|
|
160
|
+
usage: 'codex-workflow <command> [action] [options]',
|
|
161
|
+
commands: ['doctor', 'status', 'next', ...Object.keys(CLI_ACTIONS)],
|
|
162
|
+
};
|
|
163
|
+
}
|
|
164
|
+
if (!action) {
|
|
165
|
+
if (['doctor', 'status', 'next'].includes(noun)) {
|
|
166
|
+
return {
|
|
167
|
+
kind: 'cli-help',
|
|
168
|
+
readOnly: true,
|
|
169
|
+
scope: 'command',
|
|
170
|
+
command: noun,
|
|
171
|
+
usage: `codex-workflow ${noun} [--repo <path>] [--json]`,
|
|
172
|
+
requiredOptions: [],
|
|
173
|
+
optionalOptions: ['--repo', '--json'],
|
|
174
|
+
exactOptionContractAvailable: true,
|
|
175
|
+
};
|
|
176
|
+
}
|
|
177
|
+
return {
|
|
178
|
+
kind: 'cli-help',
|
|
179
|
+
readOnly: true,
|
|
180
|
+
scope: 'command',
|
|
181
|
+
command: noun,
|
|
182
|
+
usage: `codex-workflow ${noun} <action> [options]`,
|
|
183
|
+
actions: CLI_ACTIONS[noun] ?? [],
|
|
184
|
+
};
|
|
185
|
+
}
|
|
186
|
+
const command = `${noun} ${action}`;
|
|
187
|
+
const spec = CLI_HELP_SPECS[command];
|
|
188
|
+
return {
|
|
189
|
+
kind: 'cli-help',
|
|
190
|
+
readOnly: true,
|
|
191
|
+
scope: 'action',
|
|
192
|
+
command,
|
|
193
|
+
usage: spec
|
|
194
|
+
? ['codex-workflow', noun, action, ...spec.requiredOptions.map((name) => `${name} <value>`), '[options]'].join(' ')
|
|
195
|
+
: `codex-workflow ${noun} ${action} [options]`,
|
|
196
|
+
requiredOptions: spec?.requiredOptions ?? null,
|
|
197
|
+
optionalOptions: spec?.optionalOptions ?? null,
|
|
198
|
+
exactOptionContractAvailable: Boolean(spec),
|
|
199
|
+
...(spec ? {} : { note: 'Consult the packaged protocol for this action option contract.' }),
|
|
200
|
+
};
|
|
201
|
+
}
|
|
40
202
|
function required(args, name) {
|
|
41
203
|
const value = option(args, name)?.trim();
|
|
42
204
|
if (!value)
|
|
@@ -135,6 +297,7 @@ function workflowCapabilities() {
|
|
|
135
297
|
'alpha6-adoption-posture-v1',
|
|
136
298
|
'alpha6-strict-review-rescue-v1',
|
|
137
299
|
'milestone-initial-assembly-v1',
|
|
300
|
+
'milestone-initial-assembly-navigation-v2',
|
|
138
301
|
'milestone-autonomy-contract-v1',
|
|
139
302
|
'milestone-autonomy-content-refresh-v1',
|
|
140
303
|
'milestone-autonomous-membership-evolution-v1',
|
|
@@ -143,10 +306,14 @@ function workflowCapabilities() {
|
|
|
143
306
|
'corrective-decision-context-recovery-v1',
|
|
144
307
|
'remediation-mode-recovery-v1',
|
|
145
308
|
'plan-proof-obligations-v1',
|
|
309
|
+
'terminal-task-replacement-transaction-v1',
|
|
310
|
+
'project-composite-transaction-journal-v1',
|
|
146
311
|
];
|
|
147
312
|
}
|
|
148
313
|
async function dispatch(args) {
|
|
149
314
|
const [noun, action] = args.positionals;
|
|
315
|
+
if (args.options.has('help'))
|
|
316
|
+
return cliHelp(args);
|
|
150
317
|
const repo = repository(args);
|
|
151
318
|
if (noun === 'gateway' && action === 'handshake') {
|
|
152
319
|
return {
|
|
@@ -320,6 +487,9 @@ async function dispatch(args) {
|
|
|
320
487
|
const context = workflow.context(repo);
|
|
321
488
|
return context.store.readTask(context.identity.projectId, required(args, 'id'));
|
|
322
489
|
}
|
|
490
|
+
if (noun === 'task' && action === 'replacement-materialize') {
|
|
491
|
+
return workflow.replaceSplitRequiredTask(repo, required(args, 'id'), revision(args), required(args, 'discovery'), positiveIntegerOption(args, 'expected-discovery-revision'), positiveIntegerOption(args, 'expected-milestone-revision'), required(args, 'title'), option(args, 'actor') ?? 'user');
|
|
492
|
+
}
|
|
323
493
|
if (noun === 'task' && action === 'plan-set') {
|
|
324
494
|
return workflow.setTaskPlan(repo, required(args, 'id'), revision(args), jsonFile(args), option(args, 'corrective-audit-file')
|
|
325
495
|
? jsonFile(args, 'corrective-audit-file')
|
|
@@ -345,7 +515,24 @@ async function dispatch(args) {
|
|
|
345
515
|
return workflow.startTask(repo, required(args, 'id'), revision(args), owner);
|
|
346
516
|
}
|
|
347
517
|
if (noun === 'task' && action === 'run') {
|
|
348
|
-
|
|
518
|
+
const outcome = workflow.runStep(repo, required(args, 'id'), required(args, 'step'), revision(args), option(args, 'owner') ?? 'worker', option(args, 'writer-token') ?? null);
|
|
519
|
+
const { token, ...lease } = outcome.lease;
|
|
520
|
+
const { writerToken: _writerToken, ...envelope } = outcome.envelope;
|
|
521
|
+
return {
|
|
522
|
+
writerLeaseReceipt: {
|
|
523
|
+
token,
|
|
524
|
+
kind: 'writer-lease',
|
|
525
|
+
owner: outcome.lease.owner,
|
|
526
|
+
action: 'task step-complete',
|
|
527
|
+
option: '--writer-token',
|
|
528
|
+
source: 'task run',
|
|
529
|
+
sensitive: true,
|
|
530
|
+
oneTime: false,
|
|
531
|
+
},
|
|
532
|
+
task: outcome.task,
|
|
533
|
+
lease,
|
|
534
|
+
envelope,
|
|
535
|
+
};
|
|
349
536
|
}
|
|
350
537
|
if (noun === 'task' && action === 'step-complete') {
|
|
351
538
|
return workflow.completeStep(repo, required(args, 'id'), required(args, 'step'), revision(args), required(args, 'writer-token'), repeated(args, 'note'), option(args, 'actor'));
|
|
@@ -370,10 +557,14 @@ async function dispatch(args) {
|
|
|
370
557
|
}
|
|
371
558
|
const envelope = workflow.taskContext(repo, id, 'independent-reviewer');
|
|
372
559
|
const launch = launchStrictReviewer(context.identity.repositoryRoot, task, context.store.taskRoot(task.projectId, task.id), envelope);
|
|
560
|
+
// The independent reviewer identity belongs to the strict reviewer payload. CLI --actor
|
|
561
|
+
// remains the lifecycle mutation actor, such as the current C1 claimant.
|
|
373
562
|
const saved = workflow.recordReview(repo, id, expectedRevision, launch.review, option(args, 'actor'), option(args, 'writer-token') ?? null);
|
|
374
563
|
return { launch, task: saved };
|
|
375
564
|
}
|
|
376
565
|
if (noun === 'task' && action === 'step-review') {
|
|
566
|
+
// Strict Step Review launches and records the isolated reviewer inside Core. CLI --actor
|
|
567
|
+
// remains the lifecycle actor from next, typically the active C1 claimant.
|
|
377
568
|
return workflow.reviewStep(repo, required(args, 'id'), required(args, 'step'), revision(args), undefined, option(args, 'actor'), option(args, 'writer-token') ?? null);
|
|
378
569
|
}
|
|
379
570
|
if (noun === 'task' && action === 'corrective-decision-recover') {
|
|
@@ -386,13 +577,45 @@ async function dispatch(args) {
|
|
|
386
577
|
return workflow.recordStepCorrectiveDecision(repo, required(args, 'id'), required(args, 'step'), revision(args), jsonFile(args), option(args, 'actor'), option(args, 'writer-token') ?? null);
|
|
387
578
|
}
|
|
388
579
|
if (noun === 'task' && (action === 'handoff' || action === 'handoff-prepare')) {
|
|
389
|
-
|
|
580
|
+
const outcome = workflow.handoffTask(repo, required(args, 'id'), revision(args), required(args, 'actor'), option(args, 'target-actor') ?? defaultTaskWorkerActor(required(args, 'id')), required(args, 'reason'), option(args, 'writer-token') ?? null, option(args, 'delegation-grant') ?? null, option(args, 'expires-at') ?? null);
|
|
581
|
+
const { claimToken, ...bundle } = outcome.bundle;
|
|
582
|
+
return {
|
|
583
|
+
credentialHandoff: {
|
|
584
|
+
token: claimToken,
|
|
585
|
+
kind: 'claim-token',
|
|
586
|
+
targetActor: outcome.bundle.delegate,
|
|
587
|
+
action: 'task claim',
|
|
588
|
+
option: '--claim-token',
|
|
589
|
+
source: 'task handoff-prepare',
|
|
590
|
+
sensitive: true,
|
|
591
|
+
oneTime: true,
|
|
592
|
+
},
|
|
593
|
+
task: outcome.task,
|
|
594
|
+
event: outcome.event,
|
|
595
|
+
bundle,
|
|
596
|
+
};
|
|
390
597
|
}
|
|
391
598
|
if (noun === 'task' && action === 'handoff-show') {
|
|
392
599
|
return workflow.showTaskHandoff(repo, required(args, 'id'));
|
|
393
600
|
}
|
|
394
601
|
if (noun === 'task' && action === 'claim') {
|
|
395
|
-
|
|
602
|
+
const outcome = workflow.claimTask(repo, required(args, 'id'), revision(args), required(args, 'actor'), required(args, 'claim-token'), option(args, 'writer-token') ?? null);
|
|
603
|
+
const { token, ...lease } = outcome.lease;
|
|
604
|
+
return {
|
|
605
|
+
writerLeaseReceipt: {
|
|
606
|
+
token,
|
|
607
|
+
kind: 'writer-lease',
|
|
608
|
+
owner: outcome.lease.owner,
|
|
609
|
+
action: 'task run',
|
|
610
|
+
option: '--writer-token',
|
|
611
|
+
source: 'task claim',
|
|
612
|
+
sensitive: true,
|
|
613
|
+
oneTime: false,
|
|
614
|
+
},
|
|
615
|
+
task: outcome.task,
|
|
616
|
+
event: outcome.event,
|
|
617
|
+
lease,
|
|
618
|
+
};
|
|
396
619
|
}
|
|
397
620
|
if (noun === 'task' && (action === 'handback' || action === 'handback-create')) {
|
|
398
621
|
return workflow.handbackTask(repo, required(args, 'id'), revision(args), required(args, 'actor'), required(args, 'reason'), option(args, 'writer-token') ?? null, repeated(args, 'limitation'), action === 'handback-create'
|
|
@@ -451,7 +674,19 @@ async function dispatch(args) {
|
|
|
451
674
|
if (noun === 'locks' && (action === 'inspect' || action === 'repair')) {
|
|
452
675
|
const context = workflow.context(repo);
|
|
453
676
|
const id = required(args, 'id');
|
|
454
|
-
|
|
677
|
+
const lease = action === 'inspect' ? context.locks.inspect(id) : context.locks.repairStale(id);
|
|
678
|
+
return lease ? {
|
|
679
|
+
schemaVersion: lease.schemaVersion,
|
|
680
|
+
entityId: lease.entityId,
|
|
681
|
+
tokenFingerprint: createHash('sha256').update(lease.token).digest('hex').slice(0, 16),
|
|
682
|
+
owner: lease.owner,
|
|
683
|
+
pid: lease.pid,
|
|
684
|
+
hostname: lease.hostname,
|
|
685
|
+
acquiredAt: lease.acquiredAt,
|
|
686
|
+
heartbeatAt: lease.heartbeatAt,
|
|
687
|
+
expiresAt: lease.expiresAt,
|
|
688
|
+
repaired: action === 'repair',
|
|
689
|
+
} : null;
|
|
455
690
|
}
|
|
456
691
|
throw new WorkflowError('INVALID_ARGUMENT', 'Unknown command.', {
|
|
457
692
|
command: args.positionals.join(' '),
|