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.
Files changed (135) hide show
  1. package/README.md +35 -2
  2. package/dist/src/alpha6/adoption.js +13 -3
  3. package/dist/src/alpha6/adoption.js.map +1 -1
  4. package/dist/src/alpha6/handoff.d.ts +23 -0
  5. package/dist/src/alpha6/handoff.js +221 -28
  6. package/dist/src/alpha6/handoff.js.map +1 -1
  7. package/dist/src/alpha6/milestone.d.ts +2 -0
  8. package/dist/src/alpha6/milestone.js +15 -0
  9. package/dist/src/alpha6/milestone.js.map +1 -1
  10. package/dist/src/alpha6/plan-risk.d.ts +1 -0
  11. package/dist/src/alpha6/plan-risk.js +15 -7
  12. package/dist/src/alpha6/plan-risk.js.map +1 -1
  13. package/dist/src/alpha6/review.d.ts +1 -0
  14. package/dist/src/alpha6/review.js +9 -0
  15. package/dist/src/alpha6/review.js.map +1 -1
  16. package/dist/src/cli.js +253 -67
  17. package/dist/src/cli.js.map +1 -1
  18. package/dist/src/contracts.d.ts +111 -5
  19. package/dist/src/contracts.js +1 -1
  20. package/dist/src/credential-output.d.ts +10 -0
  21. package/dist/src/credential-output.js +73 -0
  22. package/dist/src/credential-output.js.map +1 -0
  23. package/dist/src/errors.d.ts +1 -1
  24. package/dist/src/errors.js.map +1 -1
  25. package/dist/src/index.d.ts +1 -1
  26. package/dist/src/index.js +1 -1
  27. package/dist/src/index.js.map +1 -1
  28. package/dist/src/lifecycle/canonical-hash.d.ts +6 -0
  29. package/dist/src/lifecycle/canonical-hash.js +24 -0
  30. package/dist/src/lifecycle/canonical-hash.js.map +1 -0
  31. package/dist/src/lifecycle/catalog.d.ts +26 -0
  32. package/dist/src/lifecycle/catalog.js +208 -0
  33. package/dist/src/lifecycle/catalog.js.map +1 -0
  34. package/dist/src/lifecycle/compiler-inspection.d.ts +48 -0
  35. package/dist/src/lifecycle/compiler-inspection.js +29 -0
  36. package/dist/src/lifecycle/compiler-inspection.js.map +1 -0
  37. package/dist/src/lifecycle/core-static-readiness.d.ts +6 -0
  38. package/dist/src/lifecycle/core-static-readiness.js +130 -0
  39. package/dist/src/lifecycle/core-static-readiness.js.map +1 -0
  40. package/dist/src/lifecycle/corrective-replan-authority.d.ts +53 -0
  41. package/dist/src/lifecycle/corrective-replan-authority.js +139 -0
  42. package/dist/src/lifecycle/corrective-replan-authority.js.map +1 -0
  43. package/dist/src/lifecycle/corrective-replan-binding-manifest.d.ts +21 -0
  44. package/dist/src/lifecycle/corrective-replan-binding-manifest.js +35 -0
  45. package/dist/src/lifecycle/corrective-replan-binding-manifest.js.map +1 -0
  46. package/dist/src/lifecycle/corrective-replan-credential-core.d.ts +86 -0
  47. package/dist/src/lifecycle/corrective-replan-credential-core.js +563 -0
  48. package/dist/src/lifecycle/corrective-replan-credential-core.js.map +1 -0
  49. package/dist/src/lifecycle/corrective-replan-credential-schema.d.ts +17 -0
  50. package/dist/src/lifecycle/corrective-replan-credential-schema.js +44 -0
  51. package/dist/src/lifecycle/corrective-replan-credential-schema.js.map +1 -0
  52. package/dist/src/lifecycle/corrective-replan-credentials.d.ts +47 -0
  53. package/dist/src/lifecycle/corrective-replan-credentials.js +103 -0
  54. package/dist/src/lifecycle/corrective-replan-credentials.js.map +1 -0
  55. package/dist/src/lifecycle/corrective-replan.d.ts +64 -0
  56. package/dist/src/lifecycle/corrective-replan.js +548 -0
  57. package/dist/src/lifecycle/corrective-replan.js.map +1 -0
  58. package/dist/src/lifecycle/evaluator.d.ts +2 -0
  59. package/dist/src/lifecycle/evaluator.js +35 -0
  60. package/dist/src/lifecycle/evaluator.js.map +1 -0
  61. package/dist/src/lifecycle/fingerprint.d.ts +31 -0
  62. package/dist/src/lifecycle/fingerprint.js +388 -0
  63. package/dist/src/lifecycle/fingerprint.js.map +1 -0
  64. package/dist/src/lifecycle/immutable.d.ts +1 -0
  65. package/dist/src/lifecycle/immutable.js +10 -0
  66. package/dist/src/lifecycle/immutable.js.map +1 -0
  67. package/dist/src/lifecycle/implementation-table.d.ts +29 -0
  68. package/dist/src/lifecycle/implementation-table.js +87 -0
  69. package/dist/src/lifecycle/implementation-table.js.map +1 -0
  70. package/dist/src/lifecycle/index.d.ts +4 -0
  71. package/dist/src/lifecycle/index.js +5 -0
  72. package/dist/src/lifecycle/index.js.map +1 -0
  73. package/dist/src/lifecycle/schema-artifact.d.ts +12 -0
  74. package/dist/src/lifecycle/schema-artifact.js +214 -0
  75. package/dist/src/lifecycle/schema-artifact.js.map +1 -0
  76. package/dist/src/lifecycle/semantic-registry.d.ts +6 -0
  77. package/dist/src/lifecycle/semantic-registry.js +489 -0
  78. package/dist/src/lifecycle/semantic-registry.js.map +1 -0
  79. package/dist/src/lifecycle/types.d.ts +718 -0
  80. package/dist/src/lifecycle/types.js +4 -0
  81. package/dist/src/lifecycle/types.js.map +1 -0
  82. package/dist/src/observation.d.ts +20 -0
  83. package/dist/src/observation.js +171 -0
  84. package/dist/src/observation.js.map +1 -0
  85. package/dist/src/reviewer.d.ts +39 -1
  86. package/dist/src/reviewer.js +179 -43
  87. package/dist/src/reviewer.js.map +1 -1
  88. package/dist/src/state/corrective-replan-executor.d.ts +64 -0
  89. package/dist/src/state/corrective-replan-executor.js +608 -0
  90. package/dist/src/state/corrective-replan-executor.js.map +1 -0
  91. package/dist/src/state/corrective-replan-public-schema.d.ts +3 -0
  92. package/dist/src/state/corrective-replan-public-schema.js +43 -0
  93. package/dist/src/state/corrective-replan-public-schema.js.map +1 -0
  94. package/dist/src/state/corrective-replan-public.d.ts +95 -0
  95. package/dist/src/state/corrective-replan-public.js +665 -0
  96. package/dist/src/state/corrective-replan-public.js.map +1 -0
  97. package/dist/src/state/corrective-replan-transaction.d.ts +160 -0
  98. package/dist/src/state/corrective-replan-transaction.js +730 -0
  99. package/dist/src/state/corrective-replan-transaction.js.map +1 -0
  100. package/dist/src/state/corrective-yield-executor.d.ts +31 -0
  101. package/dist/src/state/corrective-yield-executor.js +236 -0
  102. package/dist/src/state/corrective-yield-executor.js.map +1 -0
  103. package/dist/src/state/corrective-yield-transaction.d.ts +97 -0
  104. package/dist/src/state/corrective-yield-transaction.js +591 -0
  105. package/dist/src/state/corrective-yield-transaction.js.map +1 -0
  106. package/dist/src/state/lock.d.ts +76 -3
  107. package/dist/src/state/lock.js +611 -30
  108. package/dist/src/state/lock.js.map +1 -1
  109. package/dist/src/state/store.d.ts +3 -0
  110. package/dist/src/state/store.js +65 -12
  111. package/dist/src/state/store.js.map +1 -1
  112. package/dist/src/transition-core.d.ts +67 -0
  113. package/dist/src/transition-core.js +318 -0
  114. package/dist/src/transition-core.js.map +1 -0
  115. package/dist/src/version.d.ts +1 -1
  116. package/dist/src/version.js +1 -1
  117. package/dist/src/workflow.d.ts +62 -25
  118. package/dist/src/workflow.js +892 -183
  119. package/dist/src/workflow.js.map +1 -1
  120. package/docs/lifecycle/state-machine-stabilization.md +641 -0
  121. package/docs/release.md +6 -2
  122. package/docs/updating-existing-project.md +9 -0
  123. package/package.json +4 -1
  124. package/plugins/codex-workflow-gateway/skills/codex-workflow-gateway/SKILL.md +36 -0
  125. package/schemas/adoption-posture-event.schema.json +1 -1
  126. package/schemas/context-envelope.schema.json +1 -1
  127. package/schemas/corrective-replan-credentials.private.schema.json +98 -0
  128. package/schemas/corrective-replan-execution-event.private.schema.json +53 -0
  129. package/schemas/corrective-replan-public.schema.json +142 -0
  130. package/schemas/corrective-replan-task-transaction.private.schema.json +151 -0
  131. package/schemas/corrective-yield-task-transaction.private.schema.json +98 -0
  132. package/schemas/remediation-event.schema.json +11 -1
  133. package/schemas/task-handoff-event.schema.json +1 -1
  134. package/schemas/transition-definition.schema.json +2609 -0
  135. package/schemas/transition-payloads.schema.json +140 -0
@@ -0,0 +1,64 @@
1
+ import type { PlanRiskAuditDecision, PlanRiskAuditStepClassification, TaskPlanInput, TaskState } from '../contracts.js';
2
+ import type { CorrectiveReplanCredentialKernel, ReceiptHandle, StoredPlanValidationEventHandle } from '../lifecycle/corrective-replan-credential-core.js';
3
+ import { type CoreTaskOperationHandle } from './lock.js';
4
+ import { CorrectiveReplanTaskTransactionStore, type CorrectiveReplanTaskTransactionJournal } from './corrective-replan-transaction.js';
5
+ type JsonRecord = Record<string, unknown>;
6
+ export interface CorrectiveReplanRiskAuditInput {
7
+ readonly summary: string;
8
+ readonly decision: PlanRiskAuditDecision;
9
+ readonly splitRationale: string | null;
10
+ readonly stepClassifications: readonly PlanRiskAuditStepClassification[];
11
+ }
12
+ export type CorrectiveReplanCrashBoundary = 'after-intent' | 'after-applying-phase' | `after-target-${0 | 1 | 2 | 3 | 4}` | `after-target-phase-${0 | 1 | 2 | 3 | 4}` | 'after-published-phase' | 'after-domain-readback' | 'after-completed-phase' | 'after-terminal-readback';
13
+ export interface ExecuteCorrectiveReplanInput {
14
+ readonly projectId: string;
15
+ readonly taskId: string;
16
+ readonly receipt: ReceiptHandle;
17
+ readonly candidateReceipt: unknown;
18
+ readonly planValidationEvent: StoredPlanValidationEventHandle;
19
+ readonly candidatePlanValidationEvent: unknown;
20
+ readonly plan: TaskPlanInput;
21
+ readonly riskAudit: CorrectiveReplanRiskAuditInput;
22
+ }
23
+ export interface CorrectiveReplanExecutionResult {
24
+ readonly kind: 'corrective-replan-execution-result';
25
+ readonly disposition: 'executed' | 'recovered' | 'replayed';
26
+ readonly taskId: string;
27
+ readonly transactionId: string;
28
+ readonly resultSha256: string;
29
+ }
30
+ export interface CorrectiveReplanExecutor {
31
+ execute(input: ExecuteCorrectiveReplanInput): CorrectiveReplanExecutionResult;
32
+ recover(input: {
33
+ taskId: string;
34
+ transactionId: string;
35
+ }): CorrectiveReplanExecutionResult;
36
+ replay(input: {
37
+ taskId: string;
38
+ transactionId: string;
39
+ receiptHash: string;
40
+ }): CorrectiveReplanExecutionResult;
41
+ }
42
+ interface ExecutorOptions {
43
+ readonly taskRoot: string;
44
+ readonly locksRoot: string;
45
+ readonly trustedRoot: string;
46
+ readonly credentialKernel: CorrectiveReplanCredentialKernel;
47
+ readonly admissionCheck?: (input: Readonly<{
48
+ task: TaskState;
49
+ plan: TaskPlanInput;
50
+ riskAudit: CorrectiveReplanRiskAuditInput;
51
+ receiptVerified: true;
52
+ validationEventVerified: true;
53
+ taskOperationLockHeld: true;
54
+ }>) => void;
55
+ readonly now?: () => Date;
56
+ readonly faultInjector?: (boundary: CorrectiveReplanCrashBoundary) => void;
57
+ }
58
+ export declare function createCorrectiveReplanExecutor(options: ExecutorOptions): CorrectiveReplanExecutor;
59
+ export declare function correctiveReplanStepSetHash(stepIds: readonly string[]): string;
60
+ export declare function correctiveReplanRiskAuditHash(bindingValues: unknown, input: CorrectiveReplanRiskAuditInput): string;
61
+ export declare function driveCorrectiveReplanTransaction(transactions: CorrectiveReplanTaskTransactionStore, handle: CoreTaskOperationHandle, transactionId: string, disposition: CorrectiveReplanExecutionResult['disposition'], fault: (boundary: CorrectiveReplanCrashBoundary) => void): CorrectiveReplanExecutionResult;
62
+ export declare function correctiveReplanTerminalReadback(transactions: CorrectiveReplanTaskTransactionStore, handle: CoreTaskOperationHandle, journal: CorrectiveReplanTaskTransactionJournal): string;
63
+ export declare function correctiveReplanExecutionKeyHash(binding: JsonRecord): string;
64
+ export {};
@@ -0,0 +1,608 @@
1
+ import { createHash } from 'node:crypto';
2
+ import { existsSync, readFileSync } from 'node:fs';
3
+ import { types as utilTypes } from 'node:util';
4
+ import { Ajv2020 } from 'ajv/dist/2020.js';
5
+ import { validatePlan } from '../domain/validation.js';
6
+ import { WorkflowError } from '../errors.js';
7
+ import { computeSidecarEventHash, prepareSidecarAppend, } from '../alpha6/store-sidecars.js';
8
+ import { validateCorrectiveReplanRiskAuditPayload } from '../alpha6/plan-risk.js';
9
+ import { correctiveReplanBindingManifest } from '../lifecycle/corrective-replan-binding-manifest.js';
10
+ import { correctiveReplanCredentialSchemaValidators } from '../lifecycle/corrective-replan-credential-schema.js';
11
+ import { hashCorrectivePlanBytes, prepareCorrectiveReplanCandidate, } from '../lifecycle/corrective-replan.js';
12
+ import { hashCanonical } from '../lifecycle/fingerprint.js';
13
+ import { deepFreeze } from '../lifecycle/immutable.js';
14
+ import { CoreTaskOperationLockManager, } from './lock.js';
15
+ import { CORRECTIVE_REPLAN_TARGETS, CorrectiveReplanTaskTransactionStore, } from './corrective-replan-transaction.js';
16
+ const HASH = /^[a-f0-9]{64}$/;
17
+ const executionSchema = JSON.parse(readFileSync(new URL('../../../schemas/corrective-replan-execution-event.private.schema.json', import.meta.url), 'utf8'));
18
+ const riskSchema = JSON.parse(readFileSync(new URL('../../../schemas/plan-risk-audit-event.schema.json', import.meta.url), 'utf8'));
19
+ const taskSchema = JSON.parse(readFileSync(new URL('../../../schemas/task.schema.json', import.meta.url), 'utf8'));
20
+ const canonicalDateTimeFormat = {
21
+ type: 'string',
22
+ validate(value) {
23
+ const parsed = Date.parse(value);
24
+ return Number.isFinite(parsed) && new Date(parsed).toISOString() === value;
25
+ },
26
+ };
27
+ const exactAjv = new Ajv2020({ allErrors: true, strict: true, formats: { 'date-time': canonicalDateTimeFormat } });
28
+ const legacyAjv = new Ajv2020({
29
+ allErrors: true,
30
+ strict: false,
31
+ formats: { 'date-time': canonicalDateTimeFormat },
32
+ });
33
+ if (!exactAjv.validateSchema(executionSchema))
34
+ throw new TypeError(`Invalid CD-3 schema: ${exactAjv.errorsText(exactAjv.errors)}`);
35
+ for (const candidate of [riskSchema, taskSchema]) {
36
+ if (!legacyAjv.validateSchema(candidate))
37
+ throw new TypeError(`Invalid legacy CD-3 input schema: ${legacyAjv.errorsText(legacyAjv.errors)}`);
38
+ }
39
+ const validateExecutionEvent = exactAjv.compile(executionSchema);
40
+ const validateRiskEvent = legacyAjv.compile(riskSchema);
41
+ const validateTask = legacyAjv.compile(taskSchema);
42
+ const planValidationValidator = correctiveReplanCredentialSchemaValidators
43
+ .find((entry) => entry.id === 'schema.corrective-replan-stored-plan-validation-event');
44
+ if (!planValidationValidator)
45
+ throw new TypeError('Installed Plan Validation event validator is missing.');
46
+ const validatePlanValidationEvent = planValidationValidator.callable;
47
+ export function createCorrectiveReplanExecutor(options) {
48
+ const now = options.now ?? (() => new Date());
49
+ const locks = new CoreTaskOperationLockManager(options.locksRoot, now, options.trustedRoot);
50
+ const transactions = new CorrectiveReplanTaskTransactionStore({
51
+ taskRoot: options.taskRoot,
52
+ locksRoot: options.locksRoot,
53
+ trustedRoot: options.trustedRoot,
54
+ now,
55
+ });
56
+ const fault = (boundary) => options.faultInjector?.(boundary);
57
+ const recover = (input) => {
58
+ assertExactRecord(input, ['taskId', 'transactionId'], 'Recovery input');
59
+ assertHash(input.transactionId, 'Recovery transaction id');
60
+ const journal = transactions.read(input.transactionId);
61
+ if (journal.taskId !== input.taskId)
62
+ throw new WorkflowError('STATE_CONFLICT', 'Recovery Task identity mismatch.');
63
+ const handle = locks.acquireForRecovery({
64
+ entityId: journal.taskId,
65
+ operationId: journal.executionKeyHash,
66
+ transitionId: journal.transitionId,
67
+ });
68
+ let succeeded = false;
69
+ try {
70
+ const result = driveCorrectiveReplanTransaction(transactions, handle, journal.transactionId, 'recovered', fault);
71
+ succeeded = true;
72
+ return result;
73
+ }
74
+ finally {
75
+ if (succeeded)
76
+ locks.release(handle);
77
+ }
78
+ };
79
+ const replay = (input) => {
80
+ assertExactRecord(input, ['receiptHash', 'taskId', 'transactionId'], 'Replay input');
81
+ assertHash(input.receiptHash, 'Replay receipt hash');
82
+ const journal = transactions.read(input.transactionId);
83
+ if (journal.taskId !== input.taskId || journal.receiptHash !== input.receiptHash) {
84
+ throw new WorkflowError('STATE_CONFLICT', 'Corrective-replan replay binding mismatch.');
85
+ }
86
+ const recovered = recover({ taskId: input.taskId, transactionId: input.transactionId });
87
+ return deepFreeze({ ...recovered, disposition: journal.phase === 'completed' ? 'replayed' : 'recovered' });
88
+ };
89
+ const execute = (input) => {
90
+ assertExactRecord(input, [
91
+ 'candidatePlanValidationEvent', 'candidateReceipt', 'plan', 'planValidationEvent', 'projectId',
92
+ 'receipt', 'riskAudit', 'taskId',
93
+ ], 'Execution input');
94
+ const plan = copyJsonInput(input.plan, 'Plan');
95
+ const riskAudit = copyJsonInput(input.riskAudit, 'Risk Audit');
96
+ validatePlan(plan);
97
+ const receiptVerification = options.credentialKernel.verifyReceipt({
98
+ receipt: input.receipt,
99
+ candidate: input.candidateReceipt,
100
+ });
101
+ if (!receiptVerification.valid)
102
+ throw credentialFailure('Receipt verification failed.', receiptVerification.issues);
103
+ const receipt = receiptVerification.projection;
104
+ const validationVerification = options.credentialKernel.verifyStoredEvent({
105
+ event: input.planValidationEvent,
106
+ candidate: input.candidatePlanValidationEvent,
107
+ });
108
+ if (!validationVerification.valid)
109
+ throw credentialFailure('Plan Validation event verification failed.', validationVerification.issues);
110
+ const validationEvent = validationVerification.projection;
111
+ const binding = record(receipt.binding);
112
+ const values = record(binding.values);
113
+ const transactionId = correctiveReplanExecutionKeyHash(binding);
114
+ assertReceiptExecutionIdentity(receipt, values, input, validationEvent, transactionId);
115
+ if (existsSync(transactions.journalPath(transactionId))) {
116
+ return replay({ taskId: input.taskId, transactionId, receiptHash: string(receipt.receiptHash) });
117
+ }
118
+ const handle = locks.acquire({
119
+ entityId: input.taskId,
120
+ operationId: transactionId,
121
+ transitionId: 'task.plan.corrective-replan',
122
+ });
123
+ let intentCreated = false;
124
+ let succeeded = false;
125
+ try {
126
+ const underLock = options.credentialKernel.verifyReceipt({ receipt: input.receipt, candidate: input.candidateReceipt });
127
+ if (!underLock.valid)
128
+ throw credentialFailure('Receipt revalidation failed under the Task lock.', underLock.issues);
129
+ const underLockValidation = options.credentialKernel.verifyStoredEvent({
130
+ event: input.planValidationEvent, candidate: input.candidatePlanValidationEvent,
131
+ });
132
+ if (!underLockValidation.valid)
133
+ throw credentialFailure('Plan Validation revalidation failed under the Task lock.', underLockValidation.issues);
134
+ const currentStateBytes = requiredCurrentTarget(transactions, handle, input.taskId, transactionId, 'task-state');
135
+ const currentTask = parseTask(currentStateBytes);
136
+ assertCurrentTaskBinding(currentTask, input.projectId, values);
137
+ const prepared = prepareCorrectiveReplanCandidate(currentTask, plan);
138
+ if (prepared.planHash !== values.candidatePlanHash
139
+ || correctiveReplanStepSetHash(prepared.stepIds) !== values.candidateStepSetHash) {
140
+ throw new WorkflowError('TRANSITION_BLOCKED', 'Replacement Plan does not match the admitted receipt candidate.');
141
+ }
142
+ options.admissionCheck?.({
143
+ task: currentTask, plan, riskAudit,
144
+ receiptVerified: true, validationEventVerified: true, taskOperationLockHeld: true,
145
+ });
146
+ const recordedAt = now().toISOString();
147
+ const resultTask = materializeResultTask(currentTask, plan, prepared.planHash, recordedAt);
148
+ const taskState = jsonBytes(resultTask);
149
+ const validationBytes = appendEventBytes(transactions.captureCurrentTarget(handle, { taskId: input.taskId, operationId: transactionId, targetId: 'plan-validation' }), validationEvent);
150
+ const risk = materializeRiskAuditEvent(transactions.captureCurrentTarget(handle, { taskId: input.taskId, operationId: transactionId, targetId: 'plan-risk-audit' }), resultTask, values, riskAudit, transactionId, recordedAt);
151
+ const execution = materializeExecutionEvent(transactions.captureCurrentTarget(handle, { taskId: input.taskId, operationId: transactionId, targetId: 'execution-evidence' }), receipt, values, validationEvent, risk.event, transactionId, resultTask.revision, sha256(taskState), hashCorrectivePlanBytes(prepared.planBytes), recordedAt);
152
+ transactions.createIntent(handle, {
153
+ projectId: input.projectId,
154
+ taskId: input.taskId,
155
+ transitionId: 'task.plan.corrective-replan',
156
+ executionKeyHash: transactionId,
157
+ runtimeFingerprint: string(values.runtimeFingerprint),
158
+ catalogHash: string(values.catalogHash),
159
+ lifecycleEpoch: number(values.lifecycleEpoch),
160
+ bindingManifest: {
161
+ id: correctiveReplanBindingManifest.id,
162
+ version: correctiveReplanBindingManifest.version,
163
+ manifestSha256: correctiveReplanBindingManifest.manifestSha256,
164
+ },
165
+ bindingSha256: string(binding.bindingSha256),
166
+ receiptHash: string(receipt.receiptHash),
167
+ actorIdentityHash: string(values.actorIdentityHash),
168
+ humanPrincipalIdentityHash: string(values.humanPrincipalIdentityHash),
169
+ expectedTaskRevision: currentTask.revision,
170
+ resultTaskRevision: resultTask.revision,
171
+ postimages: {
172
+ taskState,
173
+ plan: Buffer.from(prepared.planBytes, 'utf8'),
174
+ planValidation: validationBytes,
175
+ planRiskAudit: risk.bytes,
176
+ executionEvidence: execution.bytes,
177
+ },
178
+ });
179
+ intentCreated = true;
180
+ fault('after-intent');
181
+ const result = driveCorrectiveReplanTransaction(transactions, handle, transactionId, 'executed', fault);
182
+ succeeded = true;
183
+ return result;
184
+ }
185
+ finally {
186
+ if (succeeded || !intentCreated)
187
+ locks.release(handle);
188
+ }
189
+ };
190
+ return deepFreeze({ execute, recover, replay });
191
+ }
192
+ export function correctiveReplanStepSetHash(stepIds) {
193
+ return hashCanonical({
194
+ domain: 'codex-workflow/corrective-replan-step-set/v1',
195
+ stepIds: [...stepIds].sort(),
196
+ });
197
+ }
198
+ export function correctiveReplanRiskAuditHash(bindingValues, input) {
199
+ const values = record(bindingValues);
200
+ return hashCanonical({
201
+ domain: 'codex-workflow/corrective-replan-risk-audit/v1',
202
+ taskId: values.taskId,
203
+ taskRevision: number(values.revision) + 1,
204
+ briefHash: values.briefHash,
205
+ planHash: values.candidatePlanHash,
206
+ knowledgeMapRevision: values.knowledgeRevision,
207
+ knowledgeMapHash: values.knowledgeHash,
208
+ planner: values.planAuthorIdentityHash,
209
+ auditor: values.riskAuditorIdentityHash,
210
+ summary: input.summary,
211
+ decision: input.decision,
212
+ splitRationale: input.splitRationale,
213
+ stepClassifications: input.stepClassifications,
214
+ });
215
+ }
216
+ export function driveCorrectiveReplanTransaction(transactions, handle, transactionId, disposition, fault) {
217
+ let journal = transactions.read(transactionId);
218
+ if (journal.phase === 'intent') {
219
+ journal = transactions.compareAndSetPhase(handle, transactionId, {
220
+ expectedPhase: 'intent', expectedRevision: journal.phaseRevision,
221
+ nextPhase: 'applying', nextTargetOrdinal: 0,
222
+ });
223
+ fault('after-applying-phase');
224
+ }
225
+ while (journal.phase === 'applying' && journal.nextTargetOrdinal < CORRECTIVE_REPLAN_TARGETS.length) {
226
+ const ordinal = journal.nextTargetOrdinal;
227
+ transactions.applyTarget(handle, transactionId, CORRECTIVE_REPLAN_TARGETS[ordinal].targetId);
228
+ fault(`after-target-${ordinal}`);
229
+ journal = transactions.compareAndSetPhase(handle, transactionId, {
230
+ expectedPhase: 'applying', expectedRevision: journal.phaseRevision,
231
+ nextPhase: 'applying', nextTargetOrdinal: ordinal + 1,
232
+ });
233
+ fault(`after-target-phase-${ordinal}`);
234
+ }
235
+ if (journal.phase === 'applying') {
236
+ journal = transactions.compareAndSetPhase(handle, transactionId, {
237
+ expectedPhase: 'applying', expectedRevision: journal.phaseRevision,
238
+ nextPhase: 'published-pending-readback', nextTargetOrdinal: CORRECTIVE_REPLAN_TARGETS.length,
239
+ });
240
+ fault('after-published-phase');
241
+ }
242
+ if (journal.phase === 'published-pending-readback') {
243
+ const resultSha256 = domainReadback(transactions, handle, journal);
244
+ fault('after-domain-readback');
245
+ journal = transactions.compareAndSetPhase(handle, transactionId, {
246
+ expectedPhase: 'published-pending-readback', expectedRevision: journal.phaseRevision,
247
+ nextPhase: 'completed', nextTargetOrdinal: CORRECTIVE_REPLAN_TARGETS.length,
248
+ completedResultSha256: resultSha256,
249
+ });
250
+ fault('after-completed-phase');
251
+ }
252
+ const resultSha256 = correctiveReplanTerminalReadback(transactions, handle, journal);
253
+ fault('after-terminal-readback');
254
+ return deepFreeze({
255
+ kind: 'corrective-replan-execution-result',
256
+ disposition,
257
+ taskId: journal.taskId,
258
+ transactionId: journal.transactionId,
259
+ resultSha256,
260
+ });
261
+ }
262
+ function domainReadback(transactions, handle, journal) {
263
+ return validateReadback(journal, Object.fromEntries(CORRECTIVE_REPLAN_TARGETS.map((target) => [
264
+ target.targetId,
265
+ transactions.readCanonicalTarget(handle, journal.transactionId, target.targetId),
266
+ ])));
267
+ }
268
+ export function correctiveReplanTerminalReadback(transactions, handle, journal) {
269
+ const completed = transactions.read(journal.transactionId);
270
+ if (completed.phase !== 'completed' || !completed.completedResult) {
271
+ throw new WorkflowError('TASK_RECOVERY_REQUIRED', 'Corrective-replan transaction is not terminal.');
272
+ }
273
+ const result = domainReadback(transactions, handle, completed);
274
+ if (result !== completed.completedResult.resultSha256) {
275
+ throw new WorkflowError('STATE_CORRUPT', 'Completed corrective-replan result digest mismatch.');
276
+ }
277
+ return result;
278
+ }
279
+ function validateReadback(journal, targets) {
280
+ const task = parseTask(targets['task-state']);
281
+ const plan = targets.plan;
282
+ const validationEvents = parseSidecarBytes(targets['plan-validation']);
283
+ const riskEvents = parseSidecarBytes(targets['plan-risk-audit']);
284
+ const executionEvents = parseSidecarBytes(targets['execution-evidence']);
285
+ const validation = record(validationEvents.at(-1));
286
+ const risk = record(riskEvents.at(-1));
287
+ const execution = record(executionEvents.at(-1));
288
+ if (task.id !== journal.taskId || task.projectId !== journal.projectId
289
+ || task.revision !== journal.targets[0].taskCas.resultRevision
290
+ || task.status !== 'awaiting_execution_authorization'
291
+ || task.planHash !== sha256(plan)
292
+ || task.authorizations.some((authorization) => authorization.kind === 'execution' && authorization.decision === 'approved')) {
293
+ throw new WorkflowError('STATE_CORRUPT', 'Corrective-replan Task/Plan readback mismatch.');
294
+ }
295
+ if (validatePlanValidationEvent(validation) !== true || validation.receiptHash !== journal.receiptHash
296
+ || validation.taskId !== journal.taskId || validation.candidatePlanHash !== task.planHash) {
297
+ throw new WorkflowError('STATE_CORRUPT', 'Plan Validation readback mismatch.');
298
+ }
299
+ if (validateRiskEvent(risk) !== true)
300
+ throw new WorkflowError('STATE_CORRUPT', 'Plan Risk Audit readback schema mismatch.');
301
+ validateCorrectiveReplanRiskAuditPayload(task, risk, task.steps.map((step) => step.id));
302
+ if (risk.planHash !== task.planHash || risk.taskRevision !== task.revision) {
303
+ throw new WorkflowError('STATE_CORRUPT', 'Plan Risk Audit readback binding mismatch.');
304
+ }
305
+ if (validateExecutionEvent(execution) !== true
306
+ || execution.executionKeyHash !== journal.executionKeyHash
307
+ || execution.bindingSha256 !== journal.bindingSha256
308
+ || execution.receiptHash !== journal.receiptHash
309
+ || execution.taskId !== journal.taskId
310
+ || execution.taskRevision !== task.revision
311
+ || execution.candidatePlanHash !== task.planHash
312
+ || execution.planValidationEventHash !== validation.eventHash
313
+ || execution.planRiskAuditEventHash !== risk.eventHash
314
+ || execution.taskStateSha256 !== sha256(targets['task-state'])
315
+ || execution.planBytesSha256 !== sha256(plan)) {
316
+ throw new WorkflowError('STATE_CORRUPT', 'Execution evidence readback mismatch.');
317
+ }
318
+ return hashCanonical({
319
+ domain: 'codex-workflow/corrective-replan-execution-result/v1',
320
+ transactionId: journal.transactionId,
321
+ intentSha256: journal.intentSha256,
322
+ receiptHash: journal.receiptHash,
323
+ targets: journal.targets.map((target) => ({ targetId: target.targetId, contentSha256: target.postimage.contentSha256 })),
324
+ executionEventHash: execution.eventHash,
325
+ });
326
+ }
327
+ function materializeResultTask(task, plan, planHash, recordedAt) {
328
+ const completedIds = task.steps.filter((candidate) => candidate.status === 'completed').map((candidate) => candidate.id);
329
+ const plannedSteps = plan.steps.map((step) => {
330
+ const completed = preserveCompletedStep(task, step);
331
+ if (completed)
332
+ return completed;
333
+ const previous = task.steps.find((candidate) => candidate.id === step.id);
334
+ return {
335
+ ...step,
336
+ status: previous?.status === 'failed'
337
+ ? 'failed'
338
+ : step.dependencies.every((dependency) => completedIds.includes(dependency))
339
+ ? 'planned'
340
+ : 'blocked',
341
+ evidence: null,
342
+ };
343
+ });
344
+ const result = {
345
+ ...task,
346
+ revision: task.revision + 1,
347
+ updatedAt: recordedAt,
348
+ status: 'awaiting_execution_authorization',
349
+ planHash,
350
+ planObjective: plan.objective,
351
+ requirements: [...plan.requirements],
352
+ acceptance: [...plan.acceptance],
353
+ risks: [...plan.risks],
354
+ knowledgeImpact: plan.knowledgeImpact,
355
+ knowledgeImpactReason: plan.knowledgeImpactReason,
356
+ knowledgeTargets: structuredClone(plan.knowledgeTargets),
357
+ knowledgeMapRevision: plan.knowledgeMapRevision,
358
+ knowledgeMapHash: plan.knowledgeMapHash,
359
+ graphUse: plan.graphUse,
360
+ steps: plannedSteps,
361
+ authorizations: task.authorizations.map((authorization) => authorization.kind === 'execution' && authorization.decision === 'approved'
362
+ ? { ...authorization, decision: 'superseded' }
363
+ : authorization),
364
+ review: emptyReview(),
365
+ resultHash: null,
366
+ evidenceHash: null,
367
+ blockReason: null,
368
+ };
369
+ if (validateTask(result) !== true)
370
+ throw new WorkflowError('STATE_CORRUPT', 'Materialized corrective-replan Task is invalid.');
371
+ return result;
372
+ }
373
+ function materializeRiskAuditEvent(current, task, values, input, executionKeyHashValue, recordedAt) {
374
+ if (correctiveReplanRiskAuditHash(values, input) !== values.riskAuditHash) {
375
+ throw new WorkflowError('TRANSITION_BLOCKED', 'Plan Risk Audit does not match the admitted receipt.');
376
+ }
377
+ const event = {
378
+ eventId: `PRA-${executionKeyHashValue}`,
379
+ recordedAt,
380
+ taskId: task.id,
381
+ taskRevision: task.revision,
382
+ briefHash: values.briefHash,
383
+ planHash: values.candidatePlanHash,
384
+ knowledgeMapRevision: values.knowledgeRevision,
385
+ knowledgeMapHash: values.knowledgeHash,
386
+ planner: values.planAuthorIdentityHash,
387
+ auditor: values.riskAuditorIdentityHash,
388
+ summary: input.summary,
389
+ decision: input.decision,
390
+ splitRationale: input.splitRationale,
391
+ stepClassifications: input.stepClassifications,
392
+ };
393
+ validateCorrectiveReplanRiskAuditPayload(task, event, task.steps.map((step) => step.id));
394
+ const prepared = appendEvent(current, event);
395
+ if (validateRiskEvent(prepared.event) !== true)
396
+ throw new WorkflowError('INVALID_ARGUMENT', 'Plan Risk Audit event schema is invalid.');
397
+ return prepared;
398
+ }
399
+ function materializeExecutionEvent(current, receipt, values, validationEvent, riskEvent, executionKeyHashValue, taskRevision, taskStateSha256, planBytesSha256, recordedAt) {
400
+ const binding = record(receipt.binding);
401
+ const event = {
402
+ schemaVersion: 1,
403
+ kind: 'corrective-replan-execution-recorded',
404
+ eventId: `CRE-${executionKeyHashValue}`,
405
+ recordedAt,
406
+ taskId: values.taskId,
407
+ taskRevision,
408
+ taskStatus: 'awaiting_execution_authorization',
409
+ transitionId: values.transitionId,
410
+ executionKeyHash: executionKeyHashValue,
411
+ runtimeFingerprint: values.runtimeFingerprint,
412
+ catalogHash: values.catalogHash,
413
+ lifecycleEpoch: values.lifecycleEpoch,
414
+ bindingManifest: {
415
+ id: correctiveReplanBindingManifest.id,
416
+ version: correctiveReplanBindingManifest.version,
417
+ manifestSha256: correctiveReplanBindingManifest.manifestSha256,
418
+ },
419
+ bindingSha256: binding.bindingSha256,
420
+ receiptId: receipt.receiptId,
421
+ receiptHash: receipt.receiptHash,
422
+ receiptDomainHash: receipt.domainHash,
423
+ candidatePlanHash: values.candidatePlanHash,
424
+ planValidationEventHash: validationEvent.eventHash,
425
+ planRiskAuditEventHash: riskEvent.eventHash,
426
+ actorIdentityHash: values.actorIdentityHash,
427
+ humanPrincipalIdentityHash: values.humanPrincipalIdentityHash,
428
+ priorGrantHash: get(receipt, '/supersession/priorGrantHash'),
429
+ taskStateSha256,
430
+ planBytesSha256,
431
+ };
432
+ const prepared = appendEvent(current, event);
433
+ if (validateExecutionEvent(prepared.event) !== true) {
434
+ throw new WorkflowError('STATE_CORRUPT', 'Execution evidence materialization failed schema validation.');
435
+ }
436
+ return prepared;
437
+ }
438
+ function appendEvent(current, event) {
439
+ const prepared = prepareSidecarAppend(parseSidecarBytes(current), event);
440
+ return { bytes: Buffer.from(prepared.content, 'utf8'), event: prepared.event };
441
+ }
442
+ function appendEventBytes(current, event) {
443
+ return appendEvent(current, event).bytes;
444
+ }
445
+ function parseSidecarBytes(content) {
446
+ if (content === null || content.byteLength === 0)
447
+ return [];
448
+ const text = content.toString('utf8');
449
+ if (!text.endsWith('\n'))
450
+ throw new WorkflowError('STATE_CORRUPT', 'Corrective-replan sidecar is not newline terminated.');
451
+ const events = [];
452
+ let previous = null;
453
+ for (const line of text.slice(0, -1).split('\n')) {
454
+ let parsed;
455
+ try {
456
+ parsed = JSON.parse(line);
457
+ }
458
+ catch {
459
+ throw new WorkflowError('STATE_CORRUPT', 'Corrective-replan sidecar contains invalid JSON.');
460
+ }
461
+ const event = record(parsed);
462
+ if (typeof event.eventId !== 'string' || typeof event.recordedAt !== 'string' || event.previousEventHash !== previous
463
+ || !HASH.test(event.eventHash) || computeSidecarEventHash(event) !== event.eventHash) {
464
+ throw new WorkflowError('STATE_CORRUPT', 'Corrective-replan sidecar chain is invalid.');
465
+ }
466
+ previous = event.eventHash;
467
+ events.push(event);
468
+ }
469
+ return events;
470
+ }
471
+ function assertReceiptExecutionIdentity(receipt, values, input, validationEvent, transactionId) {
472
+ const binding = record(receipt.binding);
473
+ if (values.transitionId !== 'task.plan.corrective-replan' || values.taskId !== input.taskId
474
+ || binding.manifestSha256 !== correctiveReplanBindingManifest.manifestSha256
475
+ || get(binding, '/manifestRef/id') !== correctiveReplanBindingManifest.id
476
+ || get(binding, '/manifestRef/version') !== correctiveReplanBindingManifest.version
477
+ || validationEvent.receiptHash !== receipt.receiptHash
478
+ || validationEvent.taskId !== values.taskId
479
+ || validationEvent.candidatePlanHash !== values.candidatePlanHash
480
+ || !HASH.test(transactionId)) {
481
+ throw new WorkflowError('TRANSITION_BLOCKED', 'Credential does not bind the exact corrective-replan execution.');
482
+ }
483
+ }
484
+ function assertCurrentTaskBinding(task, projectId, values) {
485
+ if (task.projectId !== projectId || task.id !== values.taskId || task.revision !== values.revision
486
+ || task.planHash !== values.currentPlanHash || task.briefHash !== values.briefHash
487
+ || task.knowledgeMapRevision !== values.knowledgeRevision || task.knowledgeMapHash !== values.knowledgeHash) {
488
+ throw new WorkflowError('STATE_CONFLICT', 'Current Task no longer matches the admitted corrective-replan binding.');
489
+ }
490
+ }
491
+ export function correctiveReplanExecutionKeyHash(binding) {
492
+ return hashCanonical({
493
+ domain: 'codex-workflow/corrective-replan-execution-key/v1',
494
+ manifestRef: binding.manifestRef,
495
+ manifestSha256: binding.manifestSha256,
496
+ values: binding.values,
497
+ });
498
+ }
499
+ function requiredCurrentTarget(transactions, handle, taskId, operationId, targetId) {
500
+ const value = transactions.captureCurrentTarget(handle, { taskId, operationId, targetId });
501
+ if (value === null)
502
+ throw new WorkflowError('STATE_CONFLICT', 'Corrective-replan Task state is missing.');
503
+ return value;
504
+ }
505
+ function parseTask(content) {
506
+ let value;
507
+ try {
508
+ value = JSON.parse(content.toString('utf8'));
509
+ }
510
+ catch {
511
+ throw new WorkflowError('STATE_CORRUPT', 'Task state is invalid JSON.');
512
+ }
513
+ if (validateTask(value) !== true)
514
+ throw new WorkflowError('STATE_CORRUPT', 'Task state schema is invalid.');
515
+ return value;
516
+ }
517
+ function preserveCompletedStep(task, next) {
518
+ const previous = task.steps.find((candidate) => candidate.id === next.id && candidate.status === 'completed');
519
+ if (!previous)
520
+ return null;
521
+ const { status: _status, evidence: _evidence, ...definition } = previous;
522
+ return JSON.stringify(definition) === JSON.stringify(next) ? previous : null;
523
+ }
524
+ function emptyReview() {
525
+ return { status: 'pending', reviewer: '', recordedAt: null, headCommit: null, briefHash: null,
526
+ planHash: null, evidenceHash: null, summary: '', findings: [] };
527
+ }
528
+ function credentialFailure(message, issues) {
529
+ return new WorkflowError('TRANSITION_BLOCKED', message, { credentialIssueIds: issues.map((candidate) => record(candidate).issueId) });
530
+ }
531
+ function copyJsonInput(value, label) {
532
+ const copied = copyJson(value, new Set(), 0, { nodes: 0, bytes: 0 });
533
+ if (copied === undefined)
534
+ throw new WorkflowError('INVALID_ARGUMENT', `${label} must be bounded plain JSON data.`);
535
+ return copied;
536
+ }
537
+ function copyJson(value, active, depth, budget) {
538
+ if (++budget.nodes > 4096 || (budget.bytes += 8) > 262_144 || depth > 32)
539
+ return undefined;
540
+ if (typeof value === 'string') {
541
+ budget.bytes += Buffer.byteLength(value, 'utf8');
542
+ return budget.bytes > 262_144 ? undefined : value;
543
+ }
544
+ if (value === null || typeof value === 'boolean')
545
+ return value;
546
+ if (typeof value === 'number')
547
+ return Number.isFinite(value) && Number.isSafeInteger(value) ? value : undefined;
548
+ if (typeof value !== 'object' || utilTypes.isProxy(value) || active.has(value))
549
+ return undefined;
550
+ const arrayValue = Array.isArray(value);
551
+ if (arrayValue && value.length > 4096)
552
+ return undefined;
553
+ const prototype = Object.getPrototypeOf(value);
554
+ if (prototype !== (arrayValue ? Array.prototype : Object.prototype) && prototype !== null)
555
+ return undefined;
556
+ const keys = Reflect.ownKeys(value);
557
+ if (keys.some((key) => typeof key !== 'string'))
558
+ return undefined;
559
+ const names = keys.filter((key) => !arrayValue || key !== 'length');
560
+ if (arrayValue && (names.length !== value.length || names.some((key, index) => key !== String(index))))
561
+ return undefined;
562
+ const descriptors = Object.getOwnPropertyDescriptors(value);
563
+ const result = arrayValue ? [] : Object.create(null);
564
+ active.add(value);
565
+ for (const key of names) {
566
+ const descriptor = descriptors[key];
567
+ budget.bytes += Buffer.byteLength(key, 'utf8');
568
+ if (budget.bytes > 262_144)
569
+ return undefined;
570
+ if (!descriptor?.enumerable || !('value' in descriptor))
571
+ return undefined;
572
+ const child = copyJson(descriptor.value, active, depth + 1, budget);
573
+ if (child === undefined)
574
+ return undefined;
575
+ result[key] = child;
576
+ }
577
+ active.delete(value);
578
+ return result;
579
+ }
580
+ function assertExactRecord(value, keys, label) {
581
+ if (!value || typeof value !== 'object' || Array.isArray(value) || utilTypes.isProxy(value)
582
+ || Object.getPrototypeOf(value) !== Object.prototype) {
583
+ throw new WorkflowError('INVALID_ARGUMENT', `${label} has unknown or missing fields.`);
584
+ }
585
+ const ownKeys = Reflect.ownKeys(value);
586
+ const descriptors = Object.getOwnPropertyDescriptors(value);
587
+ if (ownKeys.some((key) => typeof key !== 'string')
588
+ || ownKeys.map(String).sort().join('\0') !== [...keys].sort().join('\0')
589
+ || ownKeys.some((key) => {
590
+ const descriptor = descriptors[String(key)];
591
+ return !descriptor?.enumerable || !('value' in descriptor);
592
+ })) {
593
+ throw new WorkflowError('INVALID_ARGUMENT', `${label} has unknown or missing fields.`);
594
+ }
595
+ }
596
+ function jsonBytes(value) { return Buffer.from(`${JSON.stringify(value, null, 2)}\n`, 'utf8'); }
597
+ function sha256(value) { return createHash('sha256').update(value).digest('hex'); }
598
+ function assertHash(value, label) {
599
+ if (typeof value !== 'string' || !HASH.test(value))
600
+ throw new WorkflowError('INVALID_ARGUMENT', `${label} must be lowercase SHA-256.`);
601
+ }
602
+ function record(value) { return value !== null && typeof value === 'object' && !Array.isArray(value) ? value : {}; }
603
+ function string(value) { return typeof value === 'string' ? value : ''; }
604
+ function number(value) { return typeof value === 'number' && Number.isSafeInteger(value) ? value : Number.NaN; }
605
+ function get(value, pointer) {
606
+ return pointer.split('/').filter(Boolean).reduce((current, key) => record(current)[key], value);
607
+ }
608
+ //# sourceMappingURL=corrective-replan-executor.js.map