codex-workflow-v2 2.0.0-beta.1 → 2.0.0-beta.11

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 (187) hide show
  1. package/README.md +94 -12
  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 +26 -2
  5. package/dist/src/alpha6/handoff.js +277 -29
  6. package/dist/src/alpha6/handoff.js.map +1 -1
  7. package/dist/src/alpha6/mechanical-feasibility.d.ts +7 -0
  8. package/dist/src/alpha6/mechanical-feasibility.js +303 -0
  9. package/dist/src/alpha6/mechanical-feasibility.js.map +1 -0
  10. package/dist/src/alpha6/milestone.d.ts +37 -2
  11. package/dist/src/alpha6/milestone.js +472 -33
  12. package/dist/src/alpha6/milestone.js.map +1 -1
  13. package/dist/src/alpha6/plan-integrity.d.ts +14 -0
  14. package/dist/src/alpha6/plan-integrity.js +127 -0
  15. package/dist/src/alpha6/plan-integrity.js.map +1 -0
  16. package/dist/src/alpha6/plan-risk.d.ts +1 -0
  17. package/dist/src/alpha6/plan-risk.js +15 -7
  18. package/dist/src/alpha6/plan-risk.js.map +1 -1
  19. package/dist/src/alpha6/remediation.d.ts +2 -1
  20. package/dist/src/alpha6/remediation.js +186 -9
  21. package/dist/src/alpha6/remediation.js.map +1 -1
  22. package/dist/src/alpha6/review.d.ts +3 -0
  23. package/dist/src/alpha6/review.js +24 -0
  24. package/dist/src/alpha6/review.js.map +1 -1
  25. package/dist/src/cli.js +486 -46
  26. package/dist/src/cli.js.map +1 -1
  27. package/dist/src/contracts.d.ts +238 -6
  28. package/dist/src/contracts.js +1 -1
  29. package/dist/src/credential-output.d.ts +10 -0
  30. package/dist/src/credential-output.js +73 -0
  31. package/dist/src/credential-output.js.map +1 -0
  32. package/dist/src/dependency-provenance.d.ts +19 -0
  33. package/dist/src/dependency-provenance.js +185 -0
  34. package/dist/src/dependency-provenance.js.map +1 -0
  35. package/dist/src/errors.d.ts +1 -1
  36. package/dist/src/errors.js.map +1 -1
  37. package/dist/src/git.d.ts +1 -1
  38. package/dist/src/git.js +13 -5
  39. package/dist/src/git.js.map +1 -1
  40. package/dist/src/index.d.ts +2 -1
  41. package/dist/src/index.js +2 -1
  42. package/dist/src/index.js.map +1 -1
  43. package/dist/src/lifecycle/canonical-hash.d.ts +6 -0
  44. package/dist/src/lifecycle/canonical-hash.js +24 -0
  45. package/dist/src/lifecycle/canonical-hash.js.map +1 -0
  46. package/dist/src/lifecycle/catalog.d.ts +26 -0
  47. package/dist/src/lifecycle/catalog.js +208 -0
  48. package/dist/src/lifecycle/catalog.js.map +1 -0
  49. package/dist/src/lifecycle/compiler-inspection.d.ts +48 -0
  50. package/dist/src/lifecycle/compiler-inspection.js +29 -0
  51. package/dist/src/lifecycle/compiler-inspection.js.map +1 -0
  52. package/dist/src/lifecycle/core-static-readiness.d.ts +6 -0
  53. package/dist/src/lifecycle/core-static-readiness.js +130 -0
  54. package/dist/src/lifecycle/core-static-readiness.js.map +1 -0
  55. package/dist/src/lifecycle/corrective-replan-authority.d.ts +53 -0
  56. package/dist/src/lifecycle/corrective-replan-authority.js +139 -0
  57. package/dist/src/lifecycle/corrective-replan-authority.js.map +1 -0
  58. package/dist/src/lifecycle/corrective-replan-binding-manifest.d.ts +21 -0
  59. package/dist/src/lifecycle/corrective-replan-binding-manifest.js +35 -0
  60. package/dist/src/lifecycle/corrective-replan-binding-manifest.js.map +1 -0
  61. package/dist/src/lifecycle/corrective-replan-credential-core.d.ts +86 -0
  62. package/dist/src/lifecycle/corrective-replan-credential-core.js +563 -0
  63. package/dist/src/lifecycle/corrective-replan-credential-core.js.map +1 -0
  64. package/dist/src/lifecycle/corrective-replan-credential-schema.d.ts +17 -0
  65. package/dist/src/lifecycle/corrective-replan-credential-schema.js +44 -0
  66. package/dist/src/lifecycle/corrective-replan-credential-schema.js.map +1 -0
  67. package/dist/src/lifecycle/corrective-replan-credentials.d.ts +47 -0
  68. package/dist/src/lifecycle/corrective-replan-credentials.js +103 -0
  69. package/dist/src/lifecycle/corrective-replan-credentials.js.map +1 -0
  70. package/dist/src/lifecycle/corrective-replan.d.ts +64 -0
  71. package/dist/src/lifecycle/corrective-replan.js +553 -0
  72. package/dist/src/lifecycle/corrective-replan.js.map +1 -0
  73. package/dist/src/lifecycle/evaluator.d.ts +2 -0
  74. package/dist/src/lifecycle/evaluator.js +35 -0
  75. package/dist/src/lifecycle/evaluator.js.map +1 -0
  76. package/dist/src/lifecycle/fingerprint.d.ts +31 -0
  77. package/dist/src/lifecycle/fingerprint.js +388 -0
  78. package/dist/src/lifecycle/fingerprint.js.map +1 -0
  79. package/dist/src/lifecycle/immutable.d.ts +1 -0
  80. package/dist/src/lifecycle/immutable.js +10 -0
  81. package/dist/src/lifecycle/immutable.js.map +1 -0
  82. package/dist/src/lifecycle/implementation-table.d.ts +29 -0
  83. package/dist/src/lifecycle/implementation-table.js +87 -0
  84. package/dist/src/lifecycle/implementation-table.js.map +1 -0
  85. package/dist/src/lifecycle/index.d.ts +4 -0
  86. package/dist/src/lifecycle/index.js +5 -0
  87. package/dist/src/lifecycle/index.js.map +1 -0
  88. package/dist/src/lifecycle/schema-artifact.d.ts +12 -0
  89. package/dist/src/lifecycle/schema-artifact.js +214 -0
  90. package/dist/src/lifecycle/schema-artifact.js.map +1 -0
  91. package/dist/src/lifecycle/semantic-registry.d.ts +6 -0
  92. package/dist/src/lifecycle/semantic-registry.js +489 -0
  93. package/dist/src/lifecycle/semantic-registry.js.map +1 -0
  94. package/dist/src/lifecycle/types.d.ts +718 -0
  95. package/dist/src/lifecycle/types.js +4 -0
  96. package/dist/src/lifecycle/types.js.map +1 -0
  97. package/dist/src/observation.d.ts +20 -0
  98. package/dist/src/observation.js +171 -0
  99. package/dist/src/observation.js.map +1 -0
  100. package/dist/src/reviewer.d.ts +43 -1
  101. package/dist/src/reviewer.js +203 -50
  102. package/dist/src/reviewer.js.map +1 -1
  103. package/dist/src/state/corrective-replan-executor.d.ts +64 -0
  104. package/dist/src/state/corrective-replan-executor.js +608 -0
  105. package/dist/src/state/corrective-replan-executor.js.map +1 -0
  106. package/dist/src/state/corrective-replan-public-schema.d.ts +3 -0
  107. package/dist/src/state/corrective-replan-public-schema.js +43 -0
  108. package/dist/src/state/corrective-replan-public-schema.js.map +1 -0
  109. package/dist/src/state/corrective-replan-public.d.ts +95 -0
  110. package/dist/src/state/corrective-replan-public.js +665 -0
  111. package/dist/src/state/corrective-replan-public.js.map +1 -0
  112. package/dist/src/state/corrective-replan-transaction.d.ts +160 -0
  113. package/dist/src/state/corrective-replan-transaction.js +730 -0
  114. package/dist/src/state/corrective-replan-transaction.js.map +1 -0
  115. package/dist/src/state/corrective-yield-executor.d.ts +31 -0
  116. package/dist/src/state/corrective-yield-executor.js +236 -0
  117. package/dist/src/state/corrective-yield-executor.js.map +1 -0
  118. package/dist/src/state/corrective-yield-transaction.d.ts +97 -0
  119. package/dist/src/state/corrective-yield-transaction.js +591 -0
  120. package/dist/src/state/corrective-yield-transaction.js.map +1 -0
  121. package/dist/src/state/lock.d.ts +76 -3
  122. package/dist/src/state/lock.js +611 -30
  123. package/dist/src/state/lock.js.map +1 -1
  124. package/dist/src/state/store.d.ts +3 -0
  125. package/dist/src/state/store.js +65 -12
  126. package/dist/src/state/store.js.map +1 -1
  127. package/dist/src/transition-core.d.ts +67 -0
  128. package/dist/src/transition-core.js +318 -0
  129. package/dist/src/transition-core.js.map +1 -0
  130. package/dist/src/version.d.ts +1 -1
  131. package/dist/src/version.js +1 -1
  132. package/dist/src/version.js.map +1 -1
  133. package/dist/src/workflow.d.ts +88 -24
  134. package/dist/src/workflow.js +1647 -270
  135. package/dist/src/workflow.js.map +1 -1
  136. package/docs/autonomy-guardrails.md +61 -1
  137. package/docs/beta11-plan-integrity-recovery-brief.md +38 -0
  138. package/docs/beta2-initial-assembly-navigation-brief.md +616 -0
  139. package/docs/delegated-approval.md +26 -1
  140. package/docs/development-flow.md +63 -8
  141. package/docs/lifecycle/state-machine-stabilization.md +641 -0
  142. package/docs/pdf/README.md +24 -0
  143. package/docs/pdf/codex-workflow-v2-architecture-ru.pdf +0 -0
  144. package/docs/pdf/codex-workflow-v2-chat-only-guide-ru.pdf +0 -0
  145. package/docs/pdf/codex-workflow-v2-technical-reference-ru.pdf +0 -0
  146. package/docs/pdf/requirements.txt +1 -0
  147. package/docs/pdf/sources/codex-workflow-v2-architecture-ru.md +234 -0
  148. package/docs/pdf/sources/codex-workflow-v2-chat-only-guide-ru.md +334 -0
  149. package/docs/pdf/sources/codex-workflow-v2-technical-reference-ru.md +413 -0
  150. package/docs/problem-briefs/01-pre-implementation-integrity.md +478 -0
  151. package/docs/problem-briefs/02-minimal-step-integrity.md +411 -0
  152. package/docs/problem-briefs/03-minimal-agent-context-integrity.md +358 -0
  153. package/docs/problem-briefs/04-task-dependency-and-structural-replacement-integrity.md +566 -0
  154. package/docs/problem-briefs/BRIEF-TEMPLATE.md +56 -0
  155. package/docs/problem-briefs/README.md +120 -0
  156. package/docs/problem-briefs/evidence/p01-mechanical-feasibility-corpus.md +90 -0
  157. package/docs/problem-briefs/evidence/signal-v4-pre-m3-replay.md +246 -0
  158. package/docs/release.md +30 -6
  159. package/docs/split-required-recovery.md +19 -25
  160. package/docs/stable-release-defect-register.md +465 -3
  161. package/docs/updating-existing-project.md +59 -4
  162. package/docs/validation-report.md +124 -56
  163. package/package.json +9 -1
  164. package/plugins/codex-workflow-gateway/.codex-plugin/plugin.json +10 -3
  165. package/plugins/codex-workflow-gateway/references/protocol.md +92 -4
  166. package/plugins/codex-workflow-gateway/scripts/chat-registry.mjs +376 -0
  167. package/plugins/codex-workflow-gateway/skills/codex-workflow-gateway/SKILL.md +263 -4
  168. package/references/state-machine.md +13 -6
  169. package/roles/delivery-coordinator.md +39 -0
  170. package/schemas/adoption-posture-event.schema.json +1 -1
  171. package/schemas/authorization-event.schema.json +64 -1
  172. package/schemas/context-envelope.schema.json +1 -1
  173. package/schemas/corrective-decision-event.schema.json +48 -3
  174. package/schemas/corrective-replan-credentials.private.schema.json +98 -0
  175. package/schemas/corrective-replan-execution-event.private.schema.json +53 -0
  176. package/schemas/corrective-replan-public.schema.json +142 -0
  177. package/schemas/corrective-replan-task-transaction.private.schema.json +151 -0
  178. package/schemas/corrective-yield-task-transaction.private.schema.json +98 -0
  179. package/schemas/milestone-scope-change-event.schema.json +6 -1
  180. package/schemas/milestone.schema.json +6 -1
  181. package/schemas/remediation-event.schema.json +11 -1
  182. package/schemas/task-handoff-event.schema.json +19 -3
  183. package/schemas/task.schema.json +24 -1
  184. package/schemas/transition-definition.schema.json +2609 -0
  185. package/schemas/transition-payloads.schema.json +140 -0
  186. package/scripts/generate-pdf-docs.py +512 -0
  187. package/scripts/run-pdf-docs.mjs +62 -0
package/dist/src/cli.js CHANGED
@@ -1,18 +1,208 @@
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';
15
15
  import { PROTOCOL_VERSION, STATE_SCHEMA_VERSION } from './contracts.js';
16
+ const CLI_ACTIONS = {
17
+ gateway: ['handshake'],
18
+ update: ['preflight', 'rescue-preflight', 'dependency-provenance-preflight', 'dependency-provenance-recover'],
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
+ 'review-packet',
39
+ 'review-sealed-record',
40
+ 'step-review',
41
+ 'step-review-packet',
42
+ 'step-review-record',
43
+ 'corrective-decision-recover',
44
+ 'remediation-mode-recover',
45
+ 'plan-integrity-recover',
46
+ 'corrective-decision',
47
+ 'corrective-yield',
48
+ 'corrective-yield-recover',
49
+ 'corrective-replan-prepare',
50
+ 'corrective-replan-confirm',
51
+ 'corrective-replan-execute',
52
+ 'corrective-replan-recover',
53
+ 'handoff',
54
+ 'handoff-prepare',
55
+ 'handoff-replace',
56
+ 'handoff-show',
57
+ 'claim',
58
+ 'writer-credential-replace',
59
+ 'handback',
60
+ 'handback-create',
61
+ 'result-set',
62
+ 'accept',
63
+ 'sync-base',
64
+ 'merge',
65
+ 'merge-confirm',
66
+ ],
67
+ milestone: [
68
+ 'recover',
69
+ 'show',
70
+ 'progress',
71
+ 'plan-set',
72
+ 'scope-change-prepare',
73
+ 'scope-change-apply',
74
+ 'autonomy-prepare',
75
+ 'autonomy-grant',
76
+ 'autonomy-evolve',
77
+ 'authorize',
78
+ 'validate',
79
+ 'accept',
80
+ 'cancel',
81
+ ],
82
+ locks: ['inspect', 'repair'],
83
+ };
84
+ const CLI_HELP_SPECS = {
85
+ 'update dependency-provenance-preflight': {
86
+ requiredOptions: ['--id'],
87
+ optionalOptions: ['--repo', '--json'],
88
+ },
89
+ 'update dependency-provenance-recover': {
90
+ requiredOptions: ['--id', '--expected-revision', '--actor', '--reason'],
91
+ optionalOptions: ['--repo', '--json'],
92
+ },
93
+ 'milestone progress': {
94
+ requiredOptions: ['--id'],
95
+ optionalOptions: ['--repo', '--json'],
96
+ },
97
+ 'milestone authorize': {
98
+ requiredOptions: ['--id', '--expected-revision'],
99
+ optionalOptions: ['--actor', '--reason', '--delegation-grant', '--repo', '--json'],
100
+ },
101
+ 'milestone validate': {
102
+ requiredOptions: ['--id', '--expected-revision'],
103
+ optionalOptions: ['--repo', '--json'],
104
+ },
105
+ 'milestone accept': {
106
+ requiredOptions: ['--id', '--expected-revision', '--actor', '--confirmation-code'],
107
+ optionalOptions: ['--delegation-grant', '--repo', '--json'],
108
+ },
109
+ 'task plan-set': {
110
+ requiredOptions: ['--id', '--expected-revision', '--file', '--risk-audit-file'],
111
+ optionalOptions: ['--corrective-audit-file', '--repo', '--json'],
112
+ },
113
+ 'task handoff-replace': {
114
+ requiredOptions: ['--id', '--expected-revision', '--actor', '--target-actor', '--reason'],
115
+ optionalOptions: ['--delegation-grant', '--expires-at', '--repo', '--json'],
116
+ },
117
+ 'task writer-credential-replace': {
118
+ requiredOptions: ['--id', '--expected-revision', '--actor'],
119
+ optionalOptions: ['--repo', '--json'],
120
+ },
121
+ 'task corrective-yield': {
122
+ requiredOptions: ['--id', '--expected-revision', '--actor', '--writer-token', '--reason'],
123
+ optionalOptions: ['--repo', '--json'],
124
+ },
125
+ 'task plan-integrity-recover': {
126
+ requiredOptions: ['--id', '--step', '--expected-revision', '--actor'],
127
+ optionalOptions: ['--writer-token', '--repo', '--json'],
128
+ },
129
+ 'task corrective-yield-recover': {
130
+ requiredOptions: ['--id', '--transaction-id'],
131
+ optionalOptions: ['--repo', '--json'],
132
+ },
133
+ 'task corrective-replan-prepare': {
134
+ requiredOptions: ['--id', '--file'],
135
+ optionalOptions: ['--repo', '--json'],
136
+ },
137
+ 'task corrective-replan-confirm': {
138
+ requiredOptions: ['--id', '--file', '--gate-file', '--confirmation-code'],
139
+ optionalOptions: ['--repo', '--json'],
140
+ },
141
+ 'task corrective-replan-execute': {
142
+ requiredOptions: ['--id', '--file', '--credential-file'],
143
+ optionalOptions: ['--repo', '--json'],
144
+ },
145
+ 'task corrective-replan-recover': {
146
+ requiredOptions: ['--id', '--transaction-id'],
147
+ optionalOptions: ['--repo', '--json'],
148
+ },
149
+ 'task authorize': {
150
+ requiredOptions: ['--id', '--expected-revision'],
151
+ optionalOptions: ['--actor', '--reason', '--delegation-grant', '--repo', '--json'],
152
+ },
153
+ 'task start': {
154
+ requiredOptions: ['--id', '--expected-revision', '--workspace-owner'],
155
+ optionalOptions: ['--repo', '--json'],
156
+ },
157
+ 'task run': {
158
+ requiredOptions: ['--id', '--step', '--expected-revision'],
159
+ optionalOptions: ['--owner', '--writer-token', '--repo', '--json'],
160
+ },
161
+ 'task step-complete': {
162
+ requiredOptions: ['--id', '--step', '--expected-revision', '--writer-token'],
163
+ optionalOptions: ['--note', '--actor', '--repo', '--json'],
164
+ },
165
+ 'task submit': {
166
+ requiredOptions: ['--id', '--expected-revision', '--writer-token'],
167
+ optionalOptions: ['--actor', '--repo', '--json'],
168
+ },
169
+ 'task review-launch': {
170
+ requiredOptions: ['--id', '--expected-revision'],
171
+ optionalOptions: ['--actor', '--writer-token', '--repo', '--json'],
172
+ },
173
+ 'task review-packet': {
174
+ requiredOptions: ['--id', '--expected-revision'],
175
+ optionalOptions: ['--repo', '--json'],
176
+ },
177
+ 'task review-sealed-record': {
178
+ requiredOptions: ['--id', '--expected-revision', '--actor', '--file'],
179
+ optionalOptions: ['--writer-token', '--repo', '--json'],
180
+ },
181
+ 'task step-review-packet': {
182
+ requiredOptions: ['--id', '--step', '--expected-revision'],
183
+ optionalOptions: ['--repo', '--json'],
184
+ },
185
+ 'task step-review-record': {
186
+ requiredOptions: ['--id', '--step', '--expected-revision', '--actor', '--file'],
187
+ optionalOptions: ['--writer-token', '--repo', '--json'],
188
+ },
189
+ 'task result-set': {
190
+ requiredOptions: ['--id', '--expected-revision', '--summary'],
191
+ optionalOptions: ['--limitation', '--repo', '--json'],
192
+ },
193
+ 'task accept': {
194
+ requiredOptions: ['--id', '--expected-revision'],
195
+ optionalOptions: ['--actor', '--delegation-grant', '--repo', '--json'],
196
+ },
197
+ 'task merge': {
198
+ requiredOptions: ['--id', '--expected-revision', '--writer-token'],
199
+ optionalOptions: ['--actor', '--repo', '--json'],
200
+ },
201
+ 'task merge-confirm': {
202
+ requiredOptions: ['--id', '--expected-revision', '--writer-token'],
203
+ optionalOptions: ['--actor', '--repo', '--json'],
204
+ },
205
+ };
16
206
  function parseArguments(argv) {
17
207
  const positionals = [];
18
208
  const options = new Map();
@@ -38,6 +228,58 @@ function parseArguments(argv) {
38
228
  function option(args, name) {
39
229
  return args.options.get(name)?.at(-1);
40
230
  }
231
+ function cliHelp(args) {
232
+ const [noun, action] = args.positionals;
233
+ if (!noun) {
234
+ return {
235
+ kind: 'cli-help',
236
+ readOnly: true,
237
+ scope: 'top-level',
238
+ usage: 'codex-workflow <command> [action] [options]',
239
+ commands: ['doctor', 'status', 'next', ...Object.keys(CLI_ACTIONS)],
240
+ };
241
+ }
242
+ if (!action) {
243
+ if (['doctor', 'status', 'next'].includes(noun)) {
244
+ const taskSelector = noun === 'next' ? ['--task'] : [];
245
+ return {
246
+ kind: 'cli-help',
247
+ readOnly: true,
248
+ scope: 'command',
249
+ command: noun,
250
+ usage: noun === 'next'
251
+ ? 'codex-workflow next [--task <task-id>] [--repo <path>] [--json]'
252
+ : `codex-workflow ${noun} [--repo <path>] [--json]`,
253
+ requiredOptions: [],
254
+ optionalOptions: [...taskSelector, '--repo', '--json'],
255
+ exactOptionContractAvailable: true,
256
+ };
257
+ }
258
+ return {
259
+ kind: 'cli-help',
260
+ readOnly: true,
261
+ scope: 'command',
262
+ command: noun,
263
+ usage: `codex-workflow ${noun} <action> [options]`,
264
+ actions: CLI_ACTIONS[noun] ?? [],
265
+ };
266
+ }
267
+ const command = `${noun} ${action}`;
268
+ const spec = CLI_HELP_SPECS[command];
269
+ return {
270
+ kind: 'cli-help',
271
+ readOnly: true,
272
+ scope: 'action',
273
+ command,
274
+ usage: spec
275
+ ? ['codex-workflow', noun, action, ...spec.requiredOptions.map((name) => `${name} <value>`), '[options]'].join(' ')
276
+ : `codex-workflow ${noun} ${action} [options]`,
277
+ requiredOptions: spec?.requiredOptions ?? null,
278
+ optionalOptions: spec?.optionalOptions ?? null,
279
+ exactOptionContractAvailable: Boolean(spec),
280
+ ...(spec ? {} : { note: 'Consult the packaged protocol for this action option contract.' }),
281
+ };
282
+ }
41
283
  function required(args, name) {
42
284
  const value = option(args, name)?.trim();
43
285
  if (!value)
@@ -121,6 +363,11 @@ function workflowCapabilities() {
121
363
  'task-context-refresh-v1',
122
364
  'corrective-plan-audit-v1',
123
365
  'safe-update-preflight-v1',
366
+ 'bounded-dependency-provenance-recovery-v1',
367
+ 'retained-reviewed-history-recovery-v1',
368
+ 'milestone-progress-projection-v1',
369
+ 'bounded-plan-integrity-recovery-v1',
370
+ 'task-mechanical-feasibility-v1',
124
371
  'strict-reviewer-v1',
125
372
  'legacy-snapshot-v1',
126
373
  'plan-risk-audit-sidecar-v1',
@@ -128,6 +375,8 @@ function workflowCapabilities() {
128
375
  'step-remediation-circuit-breaker-sidecar-v1',
129
376
  'milestone-scope-change-sidecar-v1',
130
377
  'milestone-membership-integrity-v1',
378
+ 'milestone-task-dependency-dag-v1',
379
+ 'milestone-initial-plan-transaction-v1',
131
380
  'task-c1-handoff-sidecar-v1',
132
381
  'semantic-plan-risk-audit-v2',
133
382
  'guarded-remediation-hard-stop-v1',
@@ -136,6 +385,7 @@ function workflowCapabilities() {
136
385
  'alpha6-adoption-posture-v1',
137
386
  'alpha6-strict-review-rescue-v1',
138
387
  'milestone-initial-assembly-v1',
388
+ 'milestone-initial-assembly-navigation-v2',
139
389
  'milestone-autonomy-contract-v1',
140
390
  'milestone-autonomy-content-refresh-v1',
141
391
  'milestone-autonomous-membership-evolution-v1',
@@ -144,12 +394,18 @@ function workflowCapabilities() {
144
394
  'corrective-decision-context-recovery-v1',
145
395
  'remediation-mode-recovery-v1',
146
396
  'plan-proof-obligations-v1',
147
- 'terminal-task-replacement-transaction-v1',
397
+ 'structural-task-replacement-disabled-v1',
148
398
  'project-composite-transaction-journal-v1',
399
+ 'corrective-yield-journal-v1',
400
+ 'corrective-replan-journal-v1',
401
+ 'corrective-replan-human-gate-v1',
402
+ 'corrective-replan-protocol-v2',
149
403
  ];
150
404
  }
151
405
  async function dispatch(args) {
152
406
  const [noun, action] = args.positionals;
407
+ if (args.options.has('help'))
408
+ return cliHelp(args);
153
409
  const repo = repository(args);
154
410
  if (noun === 'gateway' && action === 'handshake') {
155
411
  return {
@@ -162,19 +418,19 @@ async function dispatch(args) {
162
418
  }
163
419
  const workflow = new WorkflowService();
164
420
  if (noun === 'doctor') {
165
- const context = workflow.context(repo);
166
- const integration = integrationDiagnostics(context.identity.repositoryRoot);
421
+ const identity = resolveRepositoryIdentity(repo);
422
+ const integration = integrationDiagnostics(identity.repositoryRoot);
167
423
  const nodeSupported = Number(process.versions.node.split('.')[0]) >= 22;
168
424
  return {
169
425
  ok: nodeSupported && integration.localDependency.current,
170
426
  node: process.versions.node,
171
427
  requiredNode: '>=22',
172
- repositoryRoot: context.identity.repositoryRoot,
173
- projectId: context.identity.projectId,
174
- stateRoot: context.store.root,
175
- branch: currentBranch(context.identity.repositoryRoot),
176
- clean: isClean(context.identity.repositoryRoot),
177
- changedFiles: changedFiles(context.identity.repositoryRoot),
428
+ repositoryRoot: identity.repositoryRoot,
429
+ projectId: identity.projectId,
430
+ stateRoot: workflow.store.root,
431
+ branch: currentBranch(identity.repositoryRoot),
432
+ clean: isClean(identity.repositoryRoot),
433
+ changedFiles: changedFiles(identity.repositoryRoot),
178
434
  integration,
179
435
  limitations: [
180
436
  'CLI diagnostics cannot prove that Codex enforced a role, model, sandbox, or read-only reviewer.',
@@ -185,12 +441,18 @@ async function dispatch(args) {
185
441
  if (noun === 'status')
186
442
  return workflow.status(repo);
187
443
  if (noun === 'next')
188
- return workflow.next(repo);
444
+ return workflow.next(repo, option(args, 'task') ?? null);
189
445
  if (noun === 'update' && action === 'preflight')
190
446
  return workflow.updatePreflight(repo);
191
447
  if (noun === 'update' && action === 'rescue-preflight') {
192
448
  return workflow.alpha6StrictReviewRescuePreflight(repo);
193
449
  }
450
+ if (noun === 'update' && action === 'dependency-provenance-preflight') {
451
+ return workflow.dependencyProvenanceRecoveryPreflight(repo, required(args, 'id'));
452
+ }
453
+ if (noun === 'update' && action === 'dependency-provenance-recover') {
454
+ return workflow.recoverDependencyProvenance(repo, required(args, 'id'), revision(args), required(args, 'actor'), required(args, 'reason'));
455
+ }
194
456
  if (noun === 'delegation' && action === 'prepare') {
195
457
  return workflow.prepareDelegation(repo, jsonFile(args));
196
458
  }
@@ -198,12 +460,12 @@ async function dispatch(args) {
198
460
  return workflow.grantDelegation(repo, jsonFile(args), required(args, 'confirmation-code'));
199
461
  }
200
462
  if (noun === 'delegation' && action === 'list') {
201
- const context = workflow.context(repo);
202
- return context.store.listDelegations(context.identity.projectId);
463
+ const identity = resolveRepositoryIdentity(repo);
464
+ return workflow.store.listDelegations(identity.projectId);
203
465
  }
204
466
  if (noun === 'delegation' && action === 'show') {
205
- const context = workflow.context(repo);
206
- return context.store.readDelegation(context.identity.projectId, required(args, 'id'));
467
+ const identity = resolveRepositoryIdentity(repo);
468
+ return workflow.store.readDelegation(identity.projectId, required(args, 'id'));
207
469
  }
208
470
  if (noun === 'delegation' && action === 'revoke') {
209
471
  return workflow.revokeDelegation(repo, required(args, 'id'), revision(args), required(args, 'actor'), required(args, 'reason'));
@@ -306,8 +568,8 @@ async function dispatch(args) {
306
568
  return workflow.updateDiscovery(repo, required(args, 'id'), revision(args), patch);
307
569
  }
308
570
  if (noun === 'discovery' && action === 'show') {
309
- const context = workflow.context(repo);
310
- return context.store.readDiscovery(context.identity.projectId, required(args, 'id'));
571
+ const identity = resolveRepositoryIdentity(repo);
572
+ return workflow.store.readDiscovery(identity.projectId, required(args, 'id'));
311
573
  }
312
574
  if (noun === 'discovery' && action === 'materialize') {
313
575
  const kind = option(args, 'kind') ?? 'task';
@@ -320,8 +582,8 @@ async function dispatch(args) {
320
582
  throw new WorkflowError('INVALID_ARGUMENT', '--kind must be task or milestone.');
321
583
  }
322
584
  if (noun === 'task' && action === 'show') {
323
- const context = workflow.context(repo);
324
- return context.store.readTask(context.identity.projectId, required(args, 'id'));
585
+ const identity = resolveRepositoryIdentity(repo);
586
+ return workflow.store.readTask(identity.projectId, required(args, 'id'));
325
587
  }
326
588
  if (noun === 'task' && action === 'replacement-materialize') {
327
589
  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');
@@ -351,7 +613,32 @@ async function dispatch(args) {
351
613
  return workflow.startTask(repo, required(args, 'id'), revision(args), owner);
352
614
  }
353
615
  if (noun === 'task' && action === 'run') {
354
- return workflow.runStep(repo, required(args, 'id'), required(args, 'step'), revision(args), option(args, 'owner') ?? 'worker', option(args, 'writer-token') ?? null);
616
+ const outcome = workflow.runStep(repo, required(args, 'id'), required(args, 'step'), revision(args), option(args, 'owner') ?? 'worker', option(args, 'writer-token') ?? null);
617
+ const { writerToken, ...envelope } = outcome.envelope;
618
+ if (outcome.writerCredential.disposition === 'issued' && !writerToken) {
619
+ throw new WorkflowError('STATE_CORRUPT', 'Fresh task run credential issuance did not return its protocol-v1 writer token.');
620
+ }
621
+ if (outcome.writerCredential.disposition === 'renewed' && writerToken !== null) {
622
+ throw new WorkflowError('STATE_CORRUPT', 'Renewed task run credential unexpectedly returned a writer token.');
623
+ }
624
+ return {
625
+ writerCredential: { disposition: outcome.writerCredential.disposition },
626
+ ...(writerToken ? {
627
+ writerLeaseReceipt: {
628
+ token: writerToken,
629
+ kind: 'writer-lease',
630
+ owner: outcome.lease.owner,
631
+ action: 'task step-complete',
632
+ option: '--writer-token',
633
+ source: 'task run',
634
+ sensitive: true,
635
+ oneTime: false,
636
+ },
637
+ } : {}),
638
+ task: outcome.task,
639
+ lease: outcome.lease,
640
+ envelope,
641
+ };
355
642
  }
356
643
  if (noun === 'task' && action === 'step-complete') {
357
644
  return workflow.completeStep(repo, required(args, 'id'), required(args, 'step'), revision(args), required(args, 'writer-token'), repeated(args, 'note'), option(args, 'actor'));
@@ -364,10 +651,10 @@ async function dispatch(args) {
364
651
  return workflow.recordReview(repo, required(args, 'id'), revision(args), review, option(args, 'actor'), option(args, 'writer-token') ?? null);
365
652
  }
366
653
  if (noun === 'task' && action === 'review-launch') {
367
- const context = workflow.context(repo);
654
+ const identity = resolveRepositoryIdentity(repo);
368
655
  const id = required(args, 'id');
369
656
  const expectedRevision = revision(args);
370
- const task = context.store.readTask(context.identity.projectId, id);
657
+ const task = workflow.store.readTask(identity.projectId, id);
371
658
  if (task.revision !== expectedRevision) {
372
659
  throw new WorkflowError('STATE_CONFLICT', `State revision conflict for ${id}`, {
373
660
  expectedRevision,
@@ -375,30 +662,119 @@ async function dispatch(args) {
375
662
  });
376
663
  }
377
664
  const envelope = workflow.taskContext(repo, id, 'independent-reviewer');
378
- const launch = launchStrictReviewer(context.identity.repositoryRoot, task, context.store.taskRoot(task.projectId, task.id), envelope);
665
+ const launch = launchStrictReviewer(identity.repositoryRoot, task, workflow.store.taskRoot(task.projectId, task.id), envelope);
666
+ // The independent reviewer identity belongs to the strict reviewer payload. CLI --actor
667
+ // remains the lifecycle mutation actor, such as the current C1 claimant.
379
668
  const saved = workflow.recordReview(repo, id, expectedRevision, launch.review, option(args, 'actor'), option(args, 'writer-token') ?? null);
380
669
  return { launch, task: saved };
381
670
  }
671
+ if (noun === 'task' && action === 'review-packet') {
672
+ return workflow.prepareExternalTaskReview(repo, required(args, 'id'), revision(args));
673
+ }
674
+ if (noun === 'task' && action === 'review-sealed-record') {
675
+ return workflow.recordExternalTaskReview(repo, required(args, 'id'), revision(args), jsonFile(args), required(args, 'actor'), option(args, 'writer-token') ?? null);
676
+ }
382
677
  if (noun === 'task' && action === 'step-review') {
678
+ // Strict Step Review launches and records the isolated reviewer inside Core. CLI --actor
679
+ // remains the lifecycle actor from next, typically the active C1 claimant.
383
680
  return workflow.reviewStep(repo, required(args, 'id'), required(args, 'step'), revision(args), undefined, option(args, 'actor'), option(args, 'writer-token') ?? null);
384
681
  }
682
+ if (noun === 'task' && action === 'step-review-packet') {
683
+ return workflow.prepareExternalStepReview(repo, required(args, 'id'), required(args, 'step'), revision(args));
684
+ }
685
+ if (noun === 'task' && action === 'step-review-record') {
686
+ return workflow.recordExternalStepReview(repo, required(args, 'id'), required(args, 'step'), revision(args), jsonFile(args), required(args, 'actor'), option(args, 'writer-token') ?? null);
687
+ }
385
688
  if (noun === 'task' && action === 'corrective-decision-recover') {
386
689
  return workflow.recoverStepCorrectiveDecision(repo, required(args, 'id'), required(args, 'step'), revision(args), required(args, 'actor'), option(args, 'writer-token') ?? null);
387
690
  }
388
691
  if (noun === 'task' && action === 'remediation-mode-recover') {
389
692
  return workflow.recoverRemediationMode(repo, required(args, 'id'), required(args, 'step'), revision(args), required(args, 'actor'), option(args, 'writer-token') ?? null);
390
693
  }
694
+ if (noun === 'task' && action === 'plan-integrity-recover') {
695
+ return workflow.recoverPlanIntegrity(repo, required(args, 'id'), required(args, 'step'), revision(args), required(args, 'actor'), option(args, 'writer-token') ?? null);
696
+ }
391
697
  if (noun === 'task' && action === 'corrective-decision') {
392
698
  return workflow.recordStepCorrectiveDecision(repo, required(args, 'id'), required(args, 'step'), revision(args), jsonFile(args), option(args, 'actor'), option(args, 'writer-token') ?? null);
393
699
  }
394
- if (noun === 'task' && (action === 'handoff' || action === 'handoff-prepare')) {
395
- return 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);
700
+ if (noun === 'task' && action === 'corrective-yield') {
701
+ return workflow.executeCorrectiveYield(repo, required(args, 'id'), revision(args), required(args, 'actor'), required(args, 'writer-token'), required(args, 'reason'));
702
+ }
703
+ if (noun === 'task' && action === 'corrective-yield-recover') {
704
+ return workflow.recoverCorrectiveYield(repo, required(args, 'id'), required(args, 'transaction-id'));
705
+ }
706
+ if (noun === 'task' && action === 'corrective-replan-prepare') {
707
+ return workflow.prepareCorrectiveReplan(repo, required(args, 'id'), jsonFile(args));
708
+ }
709
+ if (noun === 'task' && action === 'corrective-replan-confirm') {
710
+ return workflow.confirmCorrectiveReplan(repo, required(args, 'id'), jsonFile(args), jsonFile(args, 'gate-file'), required(args, 'confirmation-code'));
711
+ }
712
+ if (noun === 'task' && action === 'corrective-replan-execute') {
713
+ return workflow.executeCorrectiveReplan(repo, required(args, 'id'), jsonFile(args), jsonFile(args, 'credential-file'));
714
+ }
715
+ if (noun === 'task' && action === 'corrective-replan-recover') {
716
+ return workflow.recoverCorrectiveReplan(repo, required(args, 'id'), required(args, 'transaction-id'));
717
+ }
718
+ if (noun === 'task' && (action === 'handoff' || action === 'handoff-prepare' || action === 'handoff-replace')) {
719
+ const replacePending = action === 'handoff-replace';
720
+ const outcome = workflow.handoffTask(repo, required(args, 'id'), revision(args), required(args, 'actor'), replacePending
721
+ ? required(args, 'target-actor')
722
+ : 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);
723
+ const { claimToken, ...bundle } = outcome.bundle;
724
+ return {
725
+ credentialHandoff: {
726
+ token: claimToken,
727
+ kind: 'claim-token',
728
+ targetActor: outcome.bundle.delegate,
729
+ action: 'task claim',
730
+ option: '--claim-token',
731
+ source: replacePending ? 'task handoff-replace' : 'task handoff-prepare',
732
+ sensitive: true,
733
+ oneTime: true,
734
+ },
735
+ task: outcome.task,
736
+ event: outcome.event,
737
+ bundle,
738
+ };
396
739
  }
397
740
  if (noun === 'task' && action === 'handoff-show') {
398
741
  return workflow.showTaskHandoff(repo, required(args, 'id'));
399
742
  }
400
743
  if (noun === 'task' && action === 'claim') {
401
- return workflow.claimTask(repo, required(args, 'id'), revision(args), required(args, 'actor'), required(args, 'claim-token'), option(args, 'writer-token') ?? null);
744
+ const outcome = workflow.claimTask(repo, required(args, 'id'), revision(args), required(args, 'actor'), required(args, 'claim-token'), option(args, 'writer-token') ?? null);
745
+ return {
746
+ writerCredential: { disposition: outcome.writerCredential.disposition },
747
+ ...(outcome.writerCredential.disposition === 'issued' ? {
748
+ writerLeaseReceipt: {
749
+ token: outcome.writerCredential.token,
750
+ kind: 'writer-lease',
751
+ owner: outcome.lease.owner,
752
+ action: 'task run',
753
+ option: '--writer-token',
754
+ source: 'task claim',
755
+ sensitive: true,
756
+ oneTime: false,
757
+ },
758
+ } : {}),
759
+ task: outcome.task,
760
+ event: outcome.event,
761
+ lease: outcome.lease,
762
+ };
763
+ }
764
+ if (noun === 'task' && action === 'writer-credential-replace') {
765
+ const outcome = workflow.replaceClaimedWriterCredential(repo, required(args, 'id'), revision(args), required(args, 'actor'));
766
+ return {
767
+ writerCredential: { disposition: outcome.writerCredential.disposition },
768
+ writerLeaseReceipt: {
769
+ token: outcome.writerCredential.token,
770
+ kind: 'writer-lease',
771
+ source: 'task writer-credential-replace',
772
+ sensitive: true,
773
+ oneTime: false,
774
+ },
775
+ task: outcome.task,
776
+ lease: outcome.lease,
777
+ };
402
778
  }
403
779
  if (noun === 'task' && (action === 'handback' || action === 'handback-create')) {
404
780
  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'
@@ -421,8 +797,11 @@ async function dispatch(args) {
421
797
  return workflow.confirmExternalMerge(repo, required(args, 'id'), revision(args), required(args, 'writer-token'), option(args, 'actor'));
422
798
  }
423
799
  if (noun === 'milestone' && action === 'show') {
424
- const context = workflow.context(repo);
425
- return context.store.readMilestone(context.identity.projectId, required(args, 'id'));
800
+ const identity = resolveRepositoryIdentity(repo);
801
+ return workflow.store.readMilestone(identity.projectId, required(args, 'id'));
802
+ }
803
+ if (noun === 'milestone' && action === 'progress') {
804
+ return workflow.milestoneProgress(repo, required(args, 'id'));
426
805
  }
427
806
  if (noun === 'milestone' && action === 'plan-set') {
428
807
  return workflow.setMilestonePlan(repo, required(args, 'id'), revision(args), jsonFile(args));
@@ -455,39 +834,100 @@ async function dispatch(args) {
455
834
  return workflow.cancelMilestone(repo, required(args, 'id'), revision(args), required(args, 'reason'));
456
835
  }
457
836
  if (noun === 'locks' && (action === 'inspect' || action === 'repair')) {
458
- const context = workflow.context(repo);
459
837
  const id = required(args, 'id');
460
- const lease = action === 'inspect' ? context.locks.inspect(id) : context.locks.repairStale(id);
461
- return lease ? {
462
- schemaVersion: lease.schemaVersion,
463
- entityId: lease.entityId,
464
- tokenFingerprint: createHash('sha256').update(lease.token).digest('hex').slice(0, 16),
465
- owner: lease.owner,
466
- pid: lease.pid,
467
- hostname: lease.hostname,
468
- acquiredAt: lease.acquiredAt,
469
- heartbeatAt: lease.heartbeatAt,
470
- expiresAt: lease.expiresAt,
471
- repaired: action === 'repair',
472
- } : null;
838
+ if (action === 'repair')
839
+ return workflow.repairStaleWriterLease(repo, id);
840
+ const inspection = workflow.inspectWriterLease(repo, id);
841
+ return inspection ? { ...inspection, repaired: false } : null;
473
842
  }
474
843
  throw new WorkflowError('INVALID_ARGUMENT', 'Unknown command.', {
475
844
  command: args.positionals.join(' '),
476
845
  hint: 'Use doctor, status, next, update preflight, state <action>, delegation <action>, project-memory <action>, discovery <action>, task <action>, milestone <action>, or locks <action>.',
477
846
  });
478
847
  }
848
+ function credentialAllowancesForResult(args, value) {
849
+ const [noun, action] = args.positionals;
850
+ if (!isRecord(value))
851
+ return [];
852
+ if (noun === 'task' && (action === 'run' || action === 'claim' || action === 'writer-credential-replace')) {
853
+ const disposition = isRecord(value.writerCredential) ? value.writerCredential.disposition : null;
854
+ const receipt = isRecord(value.writerLeaseReceipt) ? value.writerLeaseReceipt : null;
855
+ if (disposition === 'issued'
856
+ && receipt?.kind === 'writer-lease'
857
+ && receipt.source === `task ${action}`
858
+ && receipt.sensitive === true) {
859
+ return [{ path: '$.writerLeaseReceipt.token' }];
860
+ }
861
+ return [];
862
+ }
863
+ if (noun === 'task' && (action === 'handoff' || action === 'handoff-prepare' || action === 'handoff-replace')) {
864
+ const receipt = isRecord(value.credentialHandoff) ? value.credentialHandoff : null;
865
+ if (receipt?.kind === 'claim-token'
866
+ && receipt.source === (action === 'handoff-replace' ? 'task handoff-replace' : 'task handoff-prepare')
867
+ && receipt.sensitive === true
868
+ && receipt.oneTime === true) {
869
+ return [{ path: '$.credentialHandoff.token' }];
870
+ }
871
+ }
872
+ return [];
873
+ }
874
+ function rawCredentialInputs(argv) {
875
+ const values = [];
876
+ for (let index = 0; index < argv.length; index += 1) {
877
+ const argument = argv[index];
878
+ for (const optionName of ['--writer-token', '--claim-token', '--confirmation-code']) {
879
+ if (argument === optionName && argv[index + 1])
880
+ values.push(argv[index + 1]);
881
+ if (argument.startsWith(`${optionName}=`))
882
+ values.push(argument.slice(optionName.length + 1));
883
+ }
884
+ }
885
+ return [...new Set(values.filter(Boolean))];
886
+ }
887
+ function isRecord(value) {
888
+ return typeof value === 'object' && value !== null;
889
+ }
479
890
  async function main() {
891
+ const argv = process.argv.slice(2);
892
+ const sensitiveInputs = rawCredentialInputs(argv);
480
893
  try {
481
- const value = await dispatch(parseArguments(process.argv.slice(2)));
894
+ const args = parseArguments(argv);
895
+ const value = await dispatch(args);
896
+ assertCliSuccessCredentialSafety(value, credentialAllowancesForResult(args, value), sensitiveInputs);
482
897
  process.stdout.write(`${JSON.stringify({ ok: true, value }, null, 2)}\n`);
483
898
  }
484
899
  catch (error) {
900
+ if (error instanceof UnsafeCredentialOutputError) {
901
+ process.stderr.write(`${JSON.stringify({
902
+ ok: false,
903
+ error: {
904
+ code: 'STATE_CORRUPT',
905
+ message: error.message,
906
+ details: { credentialPaths: error.paths },
907
+ },
908
+ }, null, 2)}\n`);
909
+ process.exitCode = 2;
910
+ return;
911
+ }
485
912
  if (error instanceof WorkflowError) {
486
- process.stderr.write(`${JSON.stringify({ ok: false, error: { code: error.code, message: error.message, details: error.details } }, null, 2)}\n`);
913
+ process.stderr.write(`${JSON.stringify({
914
+ ok: false,
915
+ error: {
916
+ code: error.code,
917
+ message: projectCliErrorMessage(error.message, sensitiveInputs),
918
+ details: projectCliErrorValue(error.details, sensitiveInputs),
919
+ },
920
+ }, null, 2)}\n`);
487
921
  process.exitCode = 2;
488
922
  return;
489
923
  }
490
- process.stderr.write(`${JSON.stringify({ ok: false, error: { code: 'UNEXPECTED', message: error instanceof Error ? error.message : String(error) } }, null, 2)}\n`);
924
+ process.stderr.write(`${JSON.stringify({
925
+ ok: false,
926
+ error: {
927
+ code: 'UNEXPECTED',
928
+ message: projectCliErrorMessage(error instanceof Error ? error.message : String(error), sensitiveInputs),
929
+ },
930
+ }, null, 2)}\n`);
491
931
  process.exitCode = 1;
492
932
  }
493
933
  }