codex-workflow-v2 2.0.0-beta.2 → 2.0.0-beta.5
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 +35 -2
- package/dist/src/alpha6/adoption.js +13 -3
- package/dist/src/alpha6/adoption.js.map +1 -1
- package/dist/src/alpha6/handoff.d.ts +23 -0
- package/dist/src/alpha6/handoff.js +221 -28
- package/dist/src/alpha6/handoff.js.map +1 -1
- package/dist/src/alpha6/milestone.d.ts +2 -0
- package/dist/src/alpha6/milestone.js +15 -0
- package/dist/src/alpha6/milestone.js.map +1 -1
- package/dist/src/alpha6/plan-risk.d.ts +1 -0
- package/dist/src/alpha6/plan-risk.js +15 -7
- package/dist/src/alpha6/plan-risk.js.map +1 -1
- package/dist/src/alpha6/review.d.ts +1 -0
- package/dist/src/alpha6/review.js +9 -0
- package/dist/src/alpha6/review.js.map +1 -1
- package/dist/src/cli.js +253 -67
- package/dist/src/cli.js.map +1 -1
- package/dist/src/contracts.d.ts +111 -5
- package/dist/src/contracts.js +1 -1
- package/dist/src/credential-output.d.ts +10 -0
- package/dist/src/credential-output.js +73 -0
- package/dist/src/credential-output.js.map +1 -0
- package/dist/src/errors.d.ts +1 -1
- package/dist/src/errors.js.map +1 -1
- package/dist/src/index.d.ts +1 -1
- package/dist/src/index.js +1 -1
- package/dist/src/index.js.map +1 -1
- package/dist/src/lifecycle/canonical-hash.d.ts +6 -0
- package/dist/src/lifecycle/canonical-hash.js +24 -0
- package/dist/src/lifecycle/canonical-hash.js.map +1 -0
- package/dist/src/lifecycle/catalog.d.ts +26 -0
- package/dist/src/lifecycle/catalog.js +208 -0
- package/dist/src/lifecycle/catalog.js.map +1 -0
- package/dist/src/lifecycle/compiler-inspection.d.ts +48 -0
- package/dist/src/lifecycle/compiler-inspection.js +29 -0
- package/dist/src/lifecycle/compiler-inspection.js.map +1 -0
- package/dist/src/lifecycle/core-static-readiness.d.ts +6 -0
- package/dist/src/lifecycle/core-static-readiness.js +130 -0
- package/dist/src/lifecycle/core-static-readiness.js.map +1 -0
- package/dist/src/lifecycle/corrective-replan-authority.d.ts +53 -0
- package/dist/src/lifecycle/corrective-replan-authority.js +139 -0
- package/dist/src/lifecycle/corrective-replan-authority.js.map +1 -0
- package/dist/src/lifecycle/corrective-replan-binding-manifest.d.ts +21 -0
- package/dist/src/lifecycle/corrective-replan-binding-manifest.js +35 -0
- package/dist/src/lifecycle/corrective-replan-binding-manifest.js.map +1 -0
- package/dist/src/lifecycle/corrective-replan-credential-core.d.ts +86 -0
- package/dist/src/lifecycle/corrective-replan-credential-core.js +563 -0
- package/dist/src/lifecycle/corrective-replan-credential-core.js.map +1 -0
- package/dist/src/lifecycle/corrective-replan-credential-schema.d.ts +17 -0
- package/dist/src/lifecycle/corrective-replan-credential-schema.js +44 -0
- package/dist/src/lifecycle/corrective-replan-credential-schema.js.map +1 -0
- package/dist/src/lifecycle/corrective-replan-credentials.d.ts +47 -0
- package/dist/src/lifecycle/corrective-replan-credentials.js +103 -0
- package/dist/src/lifecycle/corrective-replan-credentials.js.map +1 -0
- package/dist/src/lifecycle/corrective-replan.d.ts +64 -0
- package/dist/src/lifecycle/corrective-replan.js +548 -0
- package/dist/src/lifecycle/corrective-replan.js.map +1 -0
- package/dist/src/lifecycle/evaluator.d.ts +2 -0
- package/dist/src/lifecycle/evaluator.js +35 -0
- package/dist/src/lifecycle/evaluator.js.map +1 -0
- package/dist/src/lifecycle/fingerprint.d.ts +31 -0
- package/dist/src/lifecycle/fingerprint.js +388 -0
- package/dist/src/lifecycle/fingerprint.js.map +1 -0
- package/dist/src/lifecycle/immutable.d.ts +1 -0
- package/dist/src/lifecycle/immutable.js +10 -0
- package/dist/src/lifecycle/immutable.js.map +1 -0
- package/dist/src/lifecycle/implementation-table.d.ts +29 -0
- package/dist/src/lifecycle/implementation-table.js +87 -0
- package/dist/src/lifecycle/implementation-table.js.map +1 -0
- package/dist/src/lifecycle/index.d.ts +4 -0
- package/dist/src/lifecycle/index.js +5 -0
- package/dist/src/lifecycle/index.js.map +1 -0
- package/dist/src/lifecycle/schema-artifact.d.ts +12 -0
- package/dist/src/lifecycle/schema-artifact.js +214 -0
- package/dist/src/lifecycle/schema-artifact.js.map +1 -0
- package/dist/src/lifecycle/semantic-registry.d.ts +6 -0
- package/dist/src/lifecycle/semantic-registry.js +489 -0
- package/dist/src/lifecycle/semantic-registry.js.map +1 -0
- package/dist/src/lifecycle/types.d.ts +718 -0
- package/dist/src/lifecycle/types.js +4 -0
- package/dist/src/lifecycle/types.js.map +1 -0
- package/dist/src/observation.d.ts +20 -0
- package/dist/src/observation.js +171 -0
- package/dist/src/observation.js.map +1 -0
- package/dist/src/reviewer.d.ts +39 -1
- package/dist/src/reviewer.js +179 -43
- package/dist/src/reviewer.js.map +1 -1
- package/dist/src/state/corrective-replan-executor.d.ts +64 -0
- package/dist/src/state/corrective-replan-executor.js +608 -0
- package/dist/src/state/corrective-replan-executor.js.map +1 -0
- package/dist/src/state/corrective-replan-public-schema.d.ts +3 -0
- package/dist/src/state/corrective-replan-public-schema.js +43 -0
- package/dist/src/state/corrective-replan-public-schema.js.map +1 -0
- package/dist/src/state/corrective-replan-public.d.ts +95 -0
- package/dist/src/state/corrective-replan-public.js +665 -0
- package/dist/src/state/corrective-replan-public.js.map +1 -0
- package/dist/src/state/corrective-replan-transaction.d.ts +160 -0
- package/dist/src/state/corrective-replan-transaction.js +730 -0
- package/dist/src/state/corrective-replan-transaction.js.map +1 -0
- package/dist/src/state/corrective-yield-executor.d.ts +31 -0
- package/dist/src/state/corrective-yield-executor.js +236 -0
- package/dist/src/state/corrective-yield-executor.js.map +1 -0
- package/dist/src/state/corrective-yield-transaction.d.ts +97 -0
- package/dist/src/state/corrective-yield-transaction.js +591 -0
- package/dist/src/state/corrective-yield-transaction.js.map +1 -0
- package/dist/src/state/lock.d.ts +76 -3
- package/dist/src/state/lock.js +611 -30
- package/dist/src/state/lock.js.map +1 -1
- package/dist/src/state/store.d.ts +3 -0
- package/dist/src/state/store.js +65 -12
- package/dist/src/state/store.js.map +1 -1
- package/dist/src/transition-core.d.ts +67 -0
- package/dist/src/transition-core.js +318 -0
- package/dist/src/transition-core.js.map +1 -0
- package/dist/src/version.d.ts +1 -1
- package/dist/src/version.js +1 -1
- package/dist/src/workflow.d.ts +62 -25
- package/dist/src/workflow.js +892 -183
- package/dist/src/workflow.js.map +1 -1
- package/docs/lifecycle/state-machine-stabilization.md +641 -0
- package/docs/release.md +6 -2
- package/docs/updating-existing-project.md +9 -0
- package/package.json +4 -1
- package/plugins/codex-workflow-gateway/skills/codex-workflow-gateway/SKILL.md +36 -0
- package/schemas/adoption-posture-event.schema.json +1 -1
- package/schemas/context-envelope.schema.json +1 -1
- package/schemas/corrective-replan-credentials.private.schema.json +98 -0
- package/schemas/corrective-replan-execution-event.private.schema.json +53 -0
- package/schemas/corrective-replan-public.schema.json +142 -0
- package/schemas/corrective-replan-task-transaction.private.schema.json +151 -0
- package/schemas/corrective-yield-task-transaction.private.schema.json +98 -0
- package/schemas/remediation-event.schema.json +11 -1
- package/schemas/task-handoff-event.schema.json +1 -1
- package/schemas/transition-definition.schema.json +2609 -0
- package/schemas/transition-payloads.schema.json +140 -0
package/dist/src/cli.js
CHANGED
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
import { createHash } from 'node:crypto';
|
|
3
2
|
import { readFileSync } from 'node:fs';
|
|
4
3
|
import path from 'node:path';
|
|
5
4
|
import process from 'node:process';
|
|
6
5
|
import { defaultTaskWorkerActor } from './alpha6/handoff.js';
|
|
6
|
+
import { assertCliSuccessCredentialSafety, projectCliErrorMessage, projectCliErrorValue, UnsafeCredentialOutputError, } from './credential-output.js';
|
|
7
7
|
import { integrationDiagnostics } from './diagnostics.js';
|
|
8
8
|
import { WorkflowError } from './errors.js';
|
|
9
9
|
import { prepareGraphView } from './graph.js';
|
|
10
10
|
import { migrateState } from './migration.js';
|
|
11
|
-
import { changedFiles, currentBranch, isClean } from './repository.js';
|
|
11
|
+
import { changedFiles, currentBranch, isClean, resolveRepositoryIdentity } from './repository.js';
|
|
12
12
|
import { launchStrictReviewer } from './reviewer.js';
|
|
13
13
|
import { WorkflowService } from './workflow.js';
|
|
14
14
|
import { PACKAGE_NAME, PACKAGE_VERSION } from './version.js';
|
|
@@ -35,14 +35,26 @@ const CLI_ACTIONS = {
|
|
|
35
35
|
'submit',
|
|
36
36
|
'review-record',
|
|
37
37
|
'review-launch',
|
|
38
|
+
'review-packet',
|
|
39
|
+
'review-sealed-record',
|
|
38
40
|
'step-review',
|
|
41
|
+
'step-review-packet',
|
|
42
|
+
'step-review-record',
|
|
39
43
|
'corrective-decision-recover',
|
|
40
44
|
'remediation-mode-recover',
|
|
41
45
|
'corrective-decision',
|
|
46
|
+
'corrective-yield',
|
|
47
|
+
'corrective-yield-recover',
|
|
48
|
+
'corrective-replan-prepare',
|
|
49
|
+
'corrective-replan-confirm',
|
|
50
|
+
'corrective-replan-execute',
|
|
51
|
+
'corrective-replan-recover',
|
|
42
52
|
'handoff',
|
|
43
53
|
'handoff-prepare',
|
|
54
|
+
'handoff-replace',
|
|
44
55
|
'handoff-show',
|
|
45
56
|
'claim',
|
|
57
|
+
'writer-credential-replace',
|
|
46
58
|
'handback',
|
|
47
59
|
'handback-create',
|
|
48
60
|
'result-set',
|
|
@@ -84,6 +96,38 @@ const CLI_HELP_SPECS = {
|
|
|
84
96
|
requiredOptions: ['--id', '--expected-revision', '--file', '--risk-audit-file'],
|
|
85
97
|
optionalOptions: ['--corrective-audit-file', '--repo', '--json'],
|
|
86
98
|
},
|
|
99
|
+
'task handoff-replace': {
|
|
100
|
+
requiredOptions: ['--id', '--expected-revision', '--actor', '--target-actor', '--reason'],
|
|
101
|
+
optionalOptions: ['--delegation-grant', '--expires-at', '--repo', '--json'],
|
|
102
|
+
},
|
|
103
|
+
'task writer-credential-replace': {
|
|
104
|
+
requiredOptions: ['--id', '--expected-revision', '--actor'],
|
|
105
|
+
optionalOptions: ['--repo', '--json'],
|
|
106
|
+
},
|
|
107
|
+
'task corrective-yield': {
|
|
108
|
+
requiredOptions: ['--id', '--expected-revision', '--actor', '--writer-token', '--reason'],
|
|
109
|
+
optionalOptions: ['--repo', '--json'],
|
|
110
|
+
},
|
|
111
|
+
'task corrective-yield-recover': {
|
|
112
|
+
requiredOptions: ['--id', '--transaction-id'],
|
|
113
|
+
optionalOptions: ['--repo', '--json'],
|
|
114
|
+
},
|
|
115
|
+
'task corrective-replan-prepare': {
|
|
116
|
+
requiredOptions: ['--id', '--file'],
|
|
117
|
+
optionalOptions: ['--repo', '--json'],
|
|
118
|
+
},
|
|
119
|
+
'task corrective-replan-confirm': {
|
|
120
|
+
requiredOptions: ['--id', '--file', '--gate-file', '--confirmation-code'],
|
|
121
|
+
optionalOptions: ['--repo', '--json'],
|
|
122
|
+
},
|
|
123
|
+
'task corrective-replan-execute': {
|
|
124
|
+
requiredOptions: ['--id', '--file', '--credential-file'],
|
|
125
|
+
optionalOptions: ['--repo', '--json'],
|
|
126
|
+
},
|
|
127
|
+
'task corrective-replan-recover': {
|
|
128
|
+
requiredOptions: ['--id', '--transaction-id'],
|
|
129
|
+
optionalOptions: ['--repo', '--json'],
|
|
130
|
+
},
|
|
87
131
|
'task authorize': {
|
|
88
132
|
requiredOptions: ['--id', '--expected-revision'],
|
|
89
133
|
optionalOptions: ['--actor', '--reason', '--delegation-grant', '--repo', '--json'],
|
|
@@ -108,6 +152,22 @@ const CLI_HELP_SPECS = {
|
|
|
108
152
|
requiredOptions: ['--id', '--expected-revision'],
|
|
109
153
|
optionalOptions: ['--actor', '--writer-token', '--repo', '--json'],
|
|
110
154
|
},
|
|
155
|
+
'task review-packet': {
|
|
156
|
+
requiredOptions: ['--id', '--expected-revision'],
|
|
157
|
+
optionalOptions: ['--repo', '--json'],
|
|
158
|
+
},
|
|
159
|
+
'task review-sealed-record': {
|
|
160
|
+
requiredOptions: ['--id', '--expected-revision', '--actor', '--file'],
|
|
161
|
+
optionalOptions: ['--writer-token', '--repo', '--json'],
|
|
162
|
+
},
|
|
163
|
+
'task step-review-packet': {
|
|
164
|
+
requiredOptions: ['--id', '--step', '--expected-revision'],
|
|
165
|
+
optionalOptions: ['--repo', '--json'],
|
|
166
|
+
},
|
|
167
|
+
'task step-review-record': {
|
|
168
|
+
requiredOptions: ['--id', '--step', '--expected-revision', '--actor', '--file'],
|
|
169
|
+
optionalOptions: ['--writer-token', '--repo', '--json'],
|
|
170
|
+
},
|
|
111
171
|
'task result-set': {
|
|
112
172
|
requiredOptions: ['--id', '--expected-revision', '--summary'],
|
|
113
173
|
optionalOptions: ['--limitation', '--repo', '--json'],
|
|
@@ -163,14 +223,17 @@ function cliHelp(args) {
|
|
|
163
223
|
}
|
|
164
224
|
if (!action) {
|
|
165
225
|
if (['doctor', 'status', 'next'].includes(noun)) {
|
|
226
|
+
const taskSelector = noun === 'next' ? ['--task'] : [];
|
|
166
227
|
return {
|
|
167
228
|
kind: 'cli-help',
|
|
168
229
|
readOnly: true,
|
|
169
230
|
scope: 'command',
|
|
170
231
|
command: noun,
|
|
171
|
-
usage:
|
|
232
|
+
usage: noun === 'next'
|
|
233
|
+
? 'codex-workflow next [--task <task-id>] [--repo <path>] [--json]'
|
|
234
|
+
: `codex-workflow ${noun} [--repo <path>] [--json]`,
|
|
172
235
|
requiredOptions: [],
|
|
173
|
-
optionalOptions: ['--repo', '--json'],
|
|
236
|
+
optionalOptions: [...taskSelector, '--repo', '--json'],
|
|
174
237
|
exactOptionContractAvailable: true,
|
|
175
238
|
};
|
|
176
239
|
}
|
|
@@ -308,6 +371,10 @@ function workflowCapabilities() {
|
|
|
308
371
|
'plan-proof-obligations-v1',
|
|
309
372
|
'terminal-task-replacement-transaction-v1',
|
|
310
373
|
'project-composite-transaction-journal-v1',
|
|
374
|
+
'corrective-yield-journal-v1',
|
|
375
|
+
'corrective-replan-journal-v1',
|
|
376
|
+
'corrective-replan-human-gate-v1',
|
|
377
|
+
'corrective-replan-protocol-v2',
|
|
311
378
|
];
|
|
312
379
|
}
|
|
313
380
|
async function dispatch(args) {
|
|
@@ -326,19 +393,19 @@ async function dispatch(args) {
|
|
|
326
393
|
}
|
|
327
394
|
const workflow = new WorkflowService();
|
|
328
395
|
if (noun === 'doctor') {
|
|
329
|
-
const
|
|
330
|
-
const integration = integrationDiagnostics(
|
|
396
|
+
const identity = resolveRepositoryIdentity(repo);
|
|
397
|
+
const integration = integrationDiagnostics(identity.repositoryRoot);
|
|
331
398
|
const nodeSupported = Number(process.versions.node.split('.')[0]) >= 22;
|
|
332
399
|
return {
|
|
333
400
|
ok: nodeSupported && integration.localDependency.current,
|
|
334
401
|
node: process.versions.node,
|
|
335
402
|
requiredNode: '>=22',
|
|
336
|
-
repositoryRoot:
|
|
337
|
-
projectId:
|
|
338
|
-
stateRoot:
|
|
339
|
-
branch: currentBranch(
|
|
340
|
-
clean: isClean(
|
|
341
|
-
changedFiles: changedFiles(
|
|
403
|
+
repositoryRoot: identity.repositoryRoot,
|
|
404
|
+
projectId: identity.projectId,
|
|
405
|
+
stateRoot: workflow.store.root,
|
|
406
|
+
branch: currentBranch(identity.repositoryRoot),
|
|
407
|
+
clean: isClean(identity.repositoryRoot),
|
|
408
|
+
changedFiles: changedFiles(identity.repositoryRoot),
|
|
342
409
|
integration,
|
|
343
410
|
limitations: [
|
|
344
411
|
'CLI diagnostics cannot prove that Codex enforced a role, model, sandbox, or read-only reviewer.',
|
|
@@ -349,7 +416,7 @@ async function dispatch(args) {
|
|
|
349
416
|
if (noun === 'status')
|
|
350
417
|
return workflow.status(repo);
|
|
351
418
|
if (noun === 'next')
|
|
352
|
-
return workflow.next(repo);
|
|
419
|
+
return workflow.next(repo, option(args, 'task') ?? null);
|
|
353
420
|
if (noun === 'update' && action === 'preflight')
|
|
354
421
|
return workflow.updatePreflight(repo);
|
|
355
422
|
if (noun === 'update' && action === 'rescue-preflight') {
|
|
@@ -362,12 +429,12 @@ async function dispatch(args) {
|
|
|
362
429
|
return workflow.grantDelegation(repo, jsonFile(args), required(args, 'confirmation-code'));
|
|
363
430
|
}
|
|
364
431
|
if (noun === 'delegation' && action === 'list') {
|
|
365
|
-
const
|
|
366
|
-
return
|
|
432
|
+
const identity = resolveRepositoryIdentity(repo);
|
|
433
|
+
return workflow.store.listDelegations(identity.projectId);
|
|
367
434
|
}
|
|
368
435
|
if (noun === 'delegation' && action === 'show') {
|
|
369
|
-
const
|
|
370
|
-
return
|
|
436
|
+
const identity = resolveRepositoryIdentity(repo);
|
|
437
|
+
return workflow.store.readDelegation(identity.projectId, required(args, 'id'));
|
|
371
438
|
}
|
|
372
439
|
if (noun === 'delegation' && action === 'revoke') {
|
|
373
440
|
return workflow.revokeDelegation(repo, required(args, 'id'), revision(args), required(args, 'actor'), required(args, 'reason'));
|
|
@@ -470,8 +537,8 @@ async function dispatch(args) {
|
|
|
470
537
|
return workflow.updateDiscovery(repo, required(args, 'id'), revision(args), patch);
|
|
471
538
|
}
|
|
472
539
|
if (noun === 'discovery' && action === 'show') {
|
|
473
|
-
const
|
|
474
|
-
return
|
|
540
|
+
const identity = resolveRepositoryIdentity(repo);
|
|
541
|
+
return workflow.store.readDiscovery(identity.projectId, required(args, 'id'));
|
|
475
542
|
}
|
|
476
543
|
if (noun === 'discovery' && action === 'materialize') {
|
|
477
544
|
const kind = option(args, 'kind') ?? 'task';
|
|
@@ -484,8 +551,8 @@ async function dispatch(args) {
|
|
|
484
551
|
throw new WorkflowError('INVALID_ARGUMENT', '--kind must be task or milestone.');
|
|
485
552
|
}
|
|
486
553
|
if (noun === 'task' && action === 'show') {
|
|
487
|
-
const
|
|
488
|
-
return
|
|
554
|
+
const identity = resolveRepositoryIdentity(repo);
|
|
555
|
+
return workflow.store.readTask(identity.projectId, required(args, 'id'));
|
|
489
556
|
}
|
|
490
557
|
if (noun === 'task' && action === 'replacement-materialize') {
|
|
491
558
|
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');
|
|
@@ -516,21 +583,29 @@ async function dispatch(args) {
|
|
|
516
583
|
}
|
|
517
584
|
if (noun === 'task' && action === 'run') {
|
|
518
585
|
const outcome = workflow.runStep(repo, required(args, 'id'), required(args, 'step'), revision(args), option(args, 'owner') ?? 'worker', option(args, 'writer-token') ?? null);
|
|
519
|
-
const {
|
|
520
|
-
|
|
586
|
+
const { writerToken, ...envelope } = outcome.envelope;
|
|
587
|
+
if (outcome.writerCredential.disposition === 'issued' && !writerToken) {
|
|
588
|
+
throw new WorkflowError('STATE_CORRUPT', 'Fresh task run credential issuance did not return its protocol-v1 writer token.');
|
|
589
|
+
}
|
|
590
|
+
if (outcome.writerCredential.disposition === 'renewed' && writerToken !== null) {
|
|
591
|
+
throw new WorkflowError('STATE_CORRUPT', 'Renewed task run credential unexpectedly returned a writer token.');
|
|
592
|
+
}
|
|
521
593
|
return {
|
|
522
|
-
|
|
523
|
-
|
|
524
|
-
|
|
525
|
-
|
|
526
|
-
|
|
527
|
-
|
|
528
|
-
|
|
529
|
-
|
|
530
|
-
|
|
531
|
-
|
|
594
|
+
writerCredential: { disposition: outcome.writerCredential.disposition },
|
|
595
|
+
...(writerToken ? {
|
|
596
|
+
writerLeaseReceipt: {
|
|
597
|
+
token: writerToken,
|
|
598
|
+
kind: 'writer-lease',
|
|
599
|
+
owner: outcome.lease.owner,
|
|
600
|
+
action: 'task step-complete',
|
|
601
|
+
option: '--writer-token',
|
|
602
|
+
source: 'task run',
|
|
603
|
+
sensitive: true,
|
|
604
|
+
oneTime: false,
|
|
605
|
+
},
|
|
606
|
+
} : {}),
|
|
532
607
|
task: outcome.task,
|
|
533
|
-
lease,
|
|
608
|
+
lease: outcome.lease,
|
|
534
609
|
envelope,
|
|
535
610
|
};
|
|
536
611
|
}
|
|
@@ -545,10 +620,10 @@ async function dispatch(args) {
|
|
|
545
620
|
return workflow.recordReview(repo, required(args, 'id'), revision(args), review, option(args, 'actor'), option(args, 'writer-token') ?? null);
|
|
546
621
|
}
|
|
547
622
|
if (noun === 'task' && action === 'review-launch') {
|
|
548
|
-
const
|
|
623
|
+
const identity = resolveRepositoryIdentity(repo);
|
|
549
624
|
const id = required(args, 'id');
|
|
550
625
|
const expectedRevision = revision(args);
|
|
551
|
-
const task =
|
|
626
|
+
const task = workflow.store.readTask(identity.projectId, id);
|
|
552
627
|
if (task.revision !== expectedRevision) {
|
|
553
628
|
throw new WorkflowError('STATE_CONFLICT', `State revision conflict for ${id}`, {
|
|
554
629
|
expectedRevision,
|
|
@@ -556,17 +631,29 @@ async function dispatch(args) {
|
|
|
556
631
|
});
|
|
557
632
|
}
|
|
558
633
|
const envelope = workflow.taskContext(repo, id, 'independent-reviewer');
|
|
559
|
-
const launch = launchStrictReviewer(
|
|
634
|
+
const launch = launchStrictReviewer(identity.repositoryRoot, task, workflow.store.taskRoot(task.projectId, task.id), envelope);
|
|
560
635
|
// The independent reviewer identity belongs to the strict reviewer payload. CLI --actor
|
|
561
636
|
// remains the lifecycle mutation actor, such as the current C1 claimant.
|
|
562
637
|
const saved = workflow.recordReview(repo, id, expectedRevision, launch.review, option(args, 'actor'), option(args, 'writer-token') ?? null);
|
|
563
638
|
return { launch, task: saved };
|
|
564
639
|
}
|
|
640
|
+
if (noun === 'task' && action === 'review-packet') {
|
|
641
|
+
return workflow.prepareExternalTaskReview(repo, required(args, 'id'), revision(args));
|
|
642
|
+
}
|
|
643
|
+
if (noun === 'task' && action === 'review-sealed-record') {
|
|
644
|
+
return workflow.recordExternalTaskReview(repo, required(args, 'id'), revision(args), jsonFile(args), required(args, 'actor'), option(args, 'writer-token') ?? null);
|
|
645
|
+
}
|
|
565
646
|
if (noun === 'task' && action === 'step-review') {
|
|
566
647
|
// Strict Step Review launches and records the isolated reviewer inside Core. CLI --actor
|
|
567
648
|
// remains the lifecycle actor from next, typically the active C1 claimant.
|
|
568
649
|
return workflow.reviewStep(repo, required(args, 'id'), required(args, 'step'), revision(args), undefined, option(args, 'actor'), option(args, 'writer-token') ?? null);
|
|
569
650
|
}
|
|
651
|
+
if (noun === 'task' && action === 'step-review-packet') {
|
|
652
|
+
return workflow.prepareExternalStepReview(repo, required(args, 'id'), required(args, 'step'), revision(args));
|
|
653
|
+
}
|
|
654
|
+
if (noun === 'task' && action === 'step-review-record') {
|
|
655
|
+
return workflow.recordExternalStepReview(repo, required(args, 'id'), required(args, 'step'), revision(args), jsonFile(args), required(args, 'actor'), option(args, 'writer-token') ?? null);
|
|
656
|
+
}
|
|
570
657
|
if (noun === 'task' && action === 'corrective-decision-recover') {
|
|
571
658
|
return workflow.recoverStepCorrectiveDecision(repo, required(args, 'id'), required(args, 'step'), revision(args), required(args, 'actor'), option(args, 'writer-token') ?? null);
|
|
572
659
|
}
|
|
@@ -576,8 +663,29 @@ async function dispatch(args) {
|
|
|
576
663
|
if (noun === 'task' && action === 'corrective-decision') {
|
|
577
664
|
return workflow.recordStepCorrectiveDecision(repo, required(args, 'id'), required(args, 'step'), revision(args), jsonFile(args), option(args, 'actor'), option(args, 'writer-token') ?? null);
|
|
578
665
|
}
|
|
579
|
-
if (noun === 'task' &&
|
|
580
|
-
|
|
666
|
+
if (noun === 'task' && action === 'corrective-yield') {
|
|
667
|
+
return workflow.executeCorrectiveYield(repo, required(args, 'id'), revision(args), required(args, 'actor'), required(args, 'writer-token'), required(args, 'reason'));
|
|
668
|
+
}
|
|
669
|
+
if (noun === 'task' && action === 'corrective-yield-recover') {
|
|
670
|
+
return workflow.recoverCorrectiveYield(repo, required(args, 'id'), required(args, 'transaction-id'));
|
|
671
|
+
}
|
|
672
|
+
if (noun === 'task' && action === 'corrective-replan-prepare') {
|
|
673
|
+
return workflow.prepareCorrectiveReplan(repo, required(args, 'id'), jsonFile(args));
|
|
674
|
+
}
|
|
675
|
+
if (noun === 'task' && action === 'corrective-replan-confirm') {
|
|
676
|
+
return workflow.confirmCorrectiveReplan(repo, required(args, 'id'), jsonFile(args), jsonFile(args, 'gate-file'), required(args, 'confirmation-code'));
|
|
677
|
+
}
|
|
678
|
+
if (noun === 'task' && action === 'corrective-replan-execute') {
|
|
679
|
+
return workflow.executeCorrectiveReplan(repo, required(args, 'id'), jsonFile(args), jsonFile(args, 'credential-file'));
|
|
680
|
+
}
|
|
681
|
+
if (noun === 'task' && action === 'corrective-replan-recover') {
|
|
682
|
+
return workflow.recoverCorrectiveReplan(repo, required(args, 'id'), required(args, 'transaction-id'));
|
|
683
|
+
}
|
|
684
|
+
if (noun === 'task' && (action === 'handoff' || action === 'handoff-prepare' || action === 'handoff-replace')) {
|
|
685
|
+
const replacePending = action === 'handoff-replace';
|
|
686
|
+
const outcome = workflow.handoffTask(repo, required(args, 'id'), revision(args), required(args, 'actor'), replacePending
|
|
687
|
+
? required(args, 'target-actor')
|
|
688
|
+
: 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, replacePending);
|
|
581
689
|
const { claimToken, ...bundle } = outcome.bundle;
|
|
582
690
|
return {
|
|
583
691
|
credentialHandoff: {
|
|
@@ -586,7 +694,7 @@ async function dispatch(args) {
|
|
|
586
694
|
targetActor: outcome.bundle.delegate,
|
|
587
695
|
action: 'task claim',
|
|
588
696
|
option: '--claim-token',
|
|
589
|
-
source: 'task handoff-prepare',
|
|
697
|
+
source: replacePending ? 'task handoff-replace' : 'task handoff-prepare',
|
|
590
698
|
sensitive: true,
|
|
591
699
|
oneTime: true,
|
|
592
700
|
},
|
|
@@ -600,21 +708,38 @@ async function dispatch(args) {
|
|
|
600
708
|
}
|
|
601
709
|
if (noun === 'task' && action === 'claim') {
|
|
602
710
|
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
711
|
return {
|
|
712
|
+
writerCredential: { disposition: outcome.writerCredential.disposition },
|
|
713
|
+
...(outcome.writerCredential.disposition === 'issued' ? {
|
|
714
|
+
writerLeaseReceipt: {
|
|
715
|
+
token: outcome.writerCredential.token,
|
|
716
|
+
kind: 'writer-lease',
|
|
717
|
+
owner: outcome.lease.owner,
|
|
718
|
+
action: 'task run',
|
|
719
|
+
option: '--writer-token',
|
|
720
|
+
source: 'task claim',
|
|
721
|
+
sensitive: true,
|
|
722
|
+
oneTime: false,
|
|
723
|
+
},
|
|
724
|
+
} : {}),
|
|
725
|
+
task: outcome.task,
|
|
726
|
+
event: outcome.event,
|
|
727
|
+
lease: outcome.lease,
|
|
728
|
+
};
|
|
729
|
+
}
|
|
730
|
+
if (noun === 'task' && action === 'writer-credential-replace') {
|
|
731
|
+
const outcome = workflow.replaceClaimedWriterCredential(repo, required(args, 'id'), revision(args), required(args, 'actor'));
|
|
732
|
+
return {
|
|
733
|
+
writerCredential: { disposition: outcome.writerCredential.disposition },
|
|
605
734
|
writerLeaseReceipt: {
|
|
606
|
-
token,
|
|
735
|
+
token: outcome.writerCredential.token,
|
|
607
736
|
kind: 'writer-lease',
|
|
608
|
-
|
|
609
|
-
action: 'task run',
|
|
610
|
-
option: '--writer-token',
|
|
611
|
-
source: 'task claim',
|
|
737
|
+
source: 'task writer-credential-replace',
|
|
612
738
|
sensitive: true,
|
|
613
739
|
oneTime: false,
|
|
614
740
|
},
|
|
615
741
|
task: outcome.task,
|
|
616
|
-
|
|
617
|
-
lease,
|
|
742
|
+
lease: outcome.lease,
|
|
618
743
|
};
|
|
619
744
|
}
|
|
620
745
|
if (noun === 'task' && (action === 'handback' || action === 'handback-create')) {
|
|
@@ -638,8 +763,8 @@ async function dispatch(args) {
|
|
|
638
763
|
return workflow.confirmExternalMerge(repo, required(args, 'id'), revision(args), required(args, 'writer-token'), option(args, 'actor'));
|
|
639
764
|
}
|
|
640
765
|
if (noun === 'milestone' && action === 'show') {
|
|
641
|
-
const
|
|
642
|
-
return
|
|
766
|
+
const identity = resolveRepositoryIdentity(repo);
|
|
767
|
+
return workflow.store.readMilestone(identity.projectId, required(args, 'id'));
|
|
643
768
|
}
|
|
644
769
|
if (noun === 'milestone' && action === 'plan-set') {
|
|
645
770
|
return workflow.setMilestonePlan(repo, required(args, 'id'), revision(args), jsonFile(args));
|
|
@@ -672,39 +797,100 @@ async function dispatch(args) {
|
|
|
672
797
|
return workflow.cancelMilestone(repo, required(args, 'id'), revision(args), required(args, 'reason'));
|
|
673
798
|
}
|
|
674
799
|
if (noun === 'locks' && (action === 'inspect' || action === 'repair')) {
|
|
675
|
-
const context = workflow.context(repo);
|
|
676
800
|
const id = required(args, 'id');
|
|
677
|
-
|
|
678
|
-
|
|
679
|
-
|
|
680
|
-
|
|
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;
|
|
801
|
+
if (action === 'repair')
|
|
802
|
+
return workflow.repairStaleWriterLease(repo, id);
|
|
803
|
+
const inspection = workflow.inspectWriterLease(repo, id);
|
|
804
|
+
return inspection ? { ...inspection, repaired: false } : null;
|
|
690
805
|
}
|
|
691
806
|
throw new WorkflowError('INVALID_ARGUMENT', 'Unknown command.', {
|
|
692
807
|
command: args.positionals.join(' '),
|
|
693
808
|
hint: 'Use doctor, status, next, update preflight, state <action>, delegation <action>, project-memory <action>, discovery <action>, task <action>, milestone <action>, or locks <action>.',
|
|
694
809
|
});
|
|
695
810
|
}
|
|
811
|
+
function credentialAllowancesForResult(args, value) {
|
|
812
|
+
const [noun, action] = args.positionals;
|
|
813
|
+
if (!isRecord(value))
|
|
814
|
+
return [];
|
|
815
|
+
if (noun === 'task' && (action === 'run' || action === 'claim' || action === 'writer-credential-replace')) {
|
|
816
|
+
const disposition = isRecord(value.writerCredential) ? value.writerCredential.disposition : null;
|
|
817
|
+
const receipt = isRecord(value.writerLeaseReceipt) ? value.writerLeaseReceipt : null;
|
|
818
|
+
if (disposition === 'issued'
|
|
819
|
+
&& receipt?.kind === 'writer-lease'
|
|
820
|
+
&& receipt.source === `task ${action}`
|
|
821
|
+
&& receipt.sensitive === true) {
|
|
822
|
+
return [{ path: '$.writerLeaseReceipt.token' }];
|
|
823
|
+
}
|
|
824
|
+
return [];
|
|
825
|
+
}
|
|
826
|
+
if (noun === 'task' && (action === 'handoff' || action === 'handoff-prepare' || action === 'handoff-replace')) {
|
|
827
|
+
const receipt = isRecord(value.credentialHandoff) ? value.credentialHandoff : null;
|
|
828
|
+
if (receipt?.kind === 'claim-token'
|
|
829
|
+
&& receipt.source === (action === 'handoff-replace' ? 'task handoff-replace' : 'task handoff-prepare')
|
|
830
|
+
&& receipt.sensitive === true
|
|
831
|
+
&& receipt.oneTime === true) {
|
|
832
|
+
return [{ path: '$.credentialHandoff.token' }];
|
|
833
|
+
}
|
|
834
|
+
}
|
|
835
|
+
return [];
|
|
836
|
+
}
|
|
837
|
+
function rawCredentialInputs(argv) {
|
|
838
|
+
const values = [];
|
|
839
|
+
for (let index = 0; index < argv.length; index += 1) {
|
|
840
|
+
const argument = argv[index];
|
|
841
|
+
for (const optionName of ['--writer-token', '--claim-token', '--confirmation-code']) {
|
|
842
|
+
if (argument === optionName && argv[index + 1])
|
|
843
|
+
values.push(argv[index + 1]);
|
|
844
|
+
if (argument.startsWith(`${optionName}=`))
|
|
845
|
+
values.push(argument.slice(optionName.length + 1));
|
|
846
|
+
}
|
|
847
|
+
}
|
|
848
|
+
return [...new Set(values.filter(Boolean))];
|
|
849
|
+
}
|
|
850
|
+
function isRecord(value) {
|
|
851
|
+
return typeof value === 'object' && value !== null;
|
|
852
|
+
}
|
|
696
853
|
async function main() {
|
|
854
|
+
const argv = process.argv.slice(2);
|
|
855
|
+
const sensitiveInputs = rawCredentialInputs(argv);
|
|
697
856
|
try {
|
|
698
|
-
const
|
|
857
|
+
const args = parseArguments(argv);
|
|
858
|
+
const value = await dispatch(args);
|
|
859
|
+
assertCliSuccessCredentialSafety(value, credentialAllowancesForResult(args, value), sensitiveInputs);
|
|
699
860
|
process.stdout.write(`${JSON.stringify({ ok: true, value }, null, 2)}\n`);
|
|
700
861
|
}
|
|
701
862
|
catch (error) {
|
|
863
|
+
if (error instanceof UnsafeCredentialOutputError) {
|
|
864
|
+
process.stderr.write(`${JSON.stringify({
|
|
865
|
+
ok: false,
|
|
866
|
+
error: {
|
|
867
|
+
code: 'STATE_CORRUPT',
|
|
868
|
+
message: error.message,
|
|
869
|
+
details: { credentialPaths: error.paths },
|
|
870
|
+
},
|
|
871
|
+
}, null, 2)}\n`);
|
|
872
|
+
process.exitCode = 2;
|
|
873
|
+
return;
|
|
874
|
+
}
|
|
702
875
|
if (error instanceof WorkflowError) {
|
|
703
|
-
process.stderr.write(`${JSON.stringify({
|
|
876
|
+
process.stderr.write(`${JSON.stringify({
|
|
877
|
+
ok: false,
|
|
878
|
+
error: {
|
|
879
|
+
code: error.code,
|
|
880
|
+
message: projectCliErrorMessage(error.message, sensitiveInputs),
|
|
881
|
+
details: projectCliErrorValue(error.details, sensitiveInputs),
|
|
882
|
+
},
|
|
883
|
+
}, null, 2)}\n`);
|
|
704
884
|
process.exitCode = 2;
|
|
705
885
|
return;
|
|
706
886
|
}
|
|
707
|
-
process.stderr.write(`${JSON.stringify({
|
|
887
|
+
process.stderr.write(`${JSON.stringify({
|
|
888
|
+
ok: false,
|
|
889
|
+
error: {
|
|
890
|
+
code: 'UNEXPECTED',
|
|
891
|
+
message: projectCliErrorMessage(error instanceof Error ? error.message : String(error), sensitiveInputs),
|
|
892
|
+
},
|
|
893
|
+
}, null, 2)}\n`);
|
|
708
894
|
process.exitCode = 1;
|
|
709
895
|
}
|
|
710
896
|
}
|