codex-workflow-v2 2.0.0-beta.13.9 → 2.0.0-beta.14

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 (271) hide show
  1. package/README.md +27 -388
  2. package/dist/reviewer-runtime-build.json +89 -29
  3. package/dist/src/alpha6/adoption.d.ts +2 -0
  4. package/dist/src/alpha6/adoption.js +22 -0
  5. package/dist/src/alpha6/adoption.js.map +1 -1
  6. package/dist/src/alpha6/captured-check-evidence.d.ts +51 -0
  7. package/dist/src/alpha6/captured-check-evidence.js +152 -0
  8. package/dist/src/alpha6/captured-check-evidence.js.map +1 -0
  9. package/dist/src/alpha6/component-owner.d.ts +15 -1
  10. package/dist/src/alpha6/component-owner.js +44 -2
  11. package/dist/src/alpha6/component-owner.js.map +1 -1
  12. package/dist/src/alpha6/corrective-decision-boundary.d.ts +4 -0
  13. package/dist/src/alpha6/corrective-decision-boundary.js +47 -0
  14. package/dist/src/alpha6/corrective-decision-boundary.js.map +1 -0
  15. package/dist/src/alpha6/downstream-proof.d.ts +1 -25
  16. package/dist/src/alpha6/downstream-proof.js +0 -171
  17. package/dist/src/alpha6/downstream-proof.js.map +1 -1
  18. package/dist/src/alpha6/literal-test-invocation.d.ts +2 -0
  19. package/dist/src/alpha6/literal-test-invocation.js +106 -0
  20. package/dist/src/alpha6/literal-test-invocation.js.map +1 -0
  21. package/dist/src/alpha6/milestone.d.ts +2 -0
  22. package/dist/src/alpha6/milestone.js +10 -1
  23. package/dist/src/alpha6/milestone.js.map +1 -1
  24. package/dist/src/alpha6/navigation-dirty-carryover.d.ts +11 -0
  25. package/dist/src/alpha6/navigation-dirty-carryover.js +130 -0
  26. package/dist/src/alpha6/navigation-dirty-carryover.js.map +1 -0
  27. package/dist/src/alpha6/plan-integrity.js +7 -5
  28. package/dist/src/alpha6/plan-integrity.js.map +1 -1
  29. package/dist/src/alpha6/remediation.d.ts +6 -21
  30. package/dist/src/alpha6/remediation.js +161 -476
  31. package/dist/src/alpha6/remediation.js.map +1 -1
  32. package/dist/src/alpha6/root-cause-replan-carryover.d.ts +4 -1
  33. package/dist/src/alpha6/root-cause-replan-carryover.js +29 -5
  34. package/dist/src/alpha6/root-cause-replan-carryover.js.map +1 -1
  35. package/dist/src/beta1/project-transaction.d.ts +3 -1
  36. package/dist/src/beta1/project-transaction.js +6 -2
  37. package/dist/src/beta1/project-transaction.js.map +1 -1
  38. package/dist/src/checks/runner.d.ts +26 -0
  39. package/dist/src/checks/runner.js +223 -0
  40. package/dist/src/checks/runner.js.map +1 -0
  41. package/dist/src/checks/task-sync.d.ts +10 -0
  42. package/dist/src/checks/task-sync.js +41 -0
  43. package/dist/src/checks/task-sync.js.map +1 -0
  44. package/dist/src/checks/worker.d.ts +1 -0
  45. package/dist/src/checks/worker.js +154 -0
  46. package/dist/src/checks/worker.js.map +1 -0
  47. package/dist/src/cli-actions.d.ts +2 -2
  48. package/dist/src/cli-actions.js +3 -15
  49. package/dist/src/cli-actions.js.map +1 -1
  50. package/dist/src/cli.js +14 -98
  51. package/dist/src/cli.js.map +1 -1
  52. package/dist/src/contracts.d.ts +35 -32
  53. package/dist/src/dependency-provenance.d.ts +2 -2
  54. package/dist/src/dependency-provenance.js +12 -69
  55. package/dist/src/dependency-provenance.js.map +1 -1
  56. package/dist/src/domain/base-sync-conflict.d.ts +13 -0
  57. package/dist/src/domain/base-sync-conflict.js +32 -0
  58. package/dist/src/domain/base-sync-conflict.js.map +1 -0
  59. package/dist/src/domain/step-start-admission.d.ts +4 -0
  60. package/dist/src/domain/step-start-admission.js +9 -0
  61. package/dist/src/domain/step-start-admission.js.map +1 -0
  62. package/dist/src/domain/virgin-registration.d.ts +3 -0
  63. package/dist/src/domain/virgin-registration.js +65 -0
  64. package/dist/src/domain/virgin-registration.js.map +1 -0
  65. package/dist/src/errors.d.ts +1 -1
  66. package/dist/src/errors.js.map +1 -1
  67. package/dist/src/gateway-handshake.js +0 -8
  68. package/dist/src/gateway-handshake.js.map +1 -1
  69. package/dist/src/git.d.ts +3 -1
  70. package/dist/src/git.js +41 -14
  71. package/dist/src/git.js.map +1 -1
  72. package/dist/src/graph.js +25 -3
  73. package/dist/src/graph.js.map +1 -1
  74. package/dist/src/index.d.ts +1 -0
  75. package/dist/src/navigation-actions.d.ts +9 -0
  76. package/dist/src/navigation-actions.js +72 -0
  77. package/dist/src/navigation-actions.js.map +1 -0
  78. package/dist/src/navigation-update-artifact.d.ts +5 -0
  79. package/dist/src/navigation-update-artifact.js +227 -0
  80. package/dist/src/navigation-update-artifact.js.map +1 -0
  81. package/dist/src/navigation-update.d.ts +39 -0
  82. package/dist/src/navigation-update.js +82 -0
  83. package/dist/src/navigation-update.js.map +1 -0
  84. package/dist/src/observation.js +52 -29
  85. package/dist/src/observation.js.map +1 -1
  86. package/dist/src/observed-routes.js +5 -6
  87. package/dist/src/observed-routes.js.map +1 -1
  88. package/dist/src/pending-review-update.d.ts +0 -13
  89. package/dist/src/pending-review-update.js +1 -6
  90. package/dist/src/pending-review-update.js.map +1 -1
  91. package/dist/src/reviewer.d.ts +1 -1
  92. package/dist/src/reviewer.js +20 -17
  93. package/dist/src/reviewer.js.map +1 -1
  94. package/dist/src/runtime.d.ts +3 -0
  95. package/dist/src/runtime.js +6 -0
  96. package/dist/src/runtime.js.map +1 -0
  97. package/dist/src/state/corrective-replan-executor.d.ts +10 -0
  98. package/dist/src/state/corrective-replan-executor.js +37 -1
  99. package/dist/src/state/corrective-replan-executor.js.map +1 -1
  100. package/dist/src/state/corrective-replan-public-schema.js +15 -2
  101. package/dist/src/state/corrective-replan-public-schema.js.map +1 -1
  102. package/dist/src/state/corrective-replan-public.js +1 -1
  103. package/dist/src/state/corrective-replan-public.js.map +1 -1
  104. package/dist/src/state/corrective-replan-transaction.d.ts +1 -0
  105. package/dist/src/state/corrective-replan-transaction.js +12 -11
  106. package/dist/src/state/corrective-replan-transaction.js.map +1 -1
  107. package/dist/src/state/corrective-yield-transaction.d.ts +1 -0
  108. package/dist/src/state/corrective-yield-transaction.js +11 -10
  109. package/dist/src/state/corrective-yield-transaction.js.map +1 -1
  110. package/dist/src/state/lock.d.ts +4 -0
  111. package/dist/src/state/lock.js +21 -0
  112. package/dist/src/state/lock.js.map +1 -1
  113. package/dist/src/version.d.ts +1 -1
  114. package/dist/src/version.js +1 -1
  115. package/dist/src/version.js.map +1 -1
  116. package/dist/src/workflow-blocker-route.d.ts +8 -0
  117. package/dist/src/workflow-blocker-route.js +106 -0
  118. package/dist/src/workflow-blocker-route.js.map +1 -0
  119. package/dist/src/workflow.d.ts +48 -63
  120. package/dist/src/workflow.js +666 -1460
  121. package/dist/src/workflow.js.map +1 -1
  122. package/docs/autonomy-guardrails.md +26 -304
  123. package/docs/decisions.md +14 -112
  124. package/docs/development-flow.md +35 -238
  125. package/docs/project-memory.md +31 -50
  126. package/docs/release-app-evidence.md +190 -0
  127. package/docs/release.md +95 -388
  128. package/docs/updating-existing-project.md +19 -717
  129. package/package.json +11 -13
  130. package/plugins/codex-workflow-gateway/.codex-plugin/plugin.json +2 -2
  131. package/plugins/codex-workflow-gateway/references/chat-dispatch.md +73 -197
  132. package/plugins/codex-workflow-gateway/references/codebase-memory-routing.md +57 -0
  133. package/plugins/codex-workflow-gateway/references/protocol.md +42 -445
  134. package/plugins/codex-workflow-gateway/scripts/chat-dispatch.mjs +7 -1
  135. package/plugins/codex-workflow-gateway/scripts/chat-model-policy.mjs +10 -8
  136. package/plugins/codex-workflow-gateway/scripts/chat-registry.mjs +23 -5
  137. package/plugins/codex-workflow-gateway/skills/codex-workflow-gateway/SKILL.md +66 -757
  138. package/references/state-machine.md +4 -4
  139. package/roles/technical-planner.md +1 -1
  140. package/schemas/corrective-decision-event.schema.json +3 -1
  141. package/schemas/project-knowledge-map.schema.json +3 -1
  142. package/schemas/remediation-event.schema.json +10 -1
  143. package/schemas/task.schema.json +46 -2
  144. package/schemas/transition-payloads.schema.json +16 -1
  145. package/src/alpha6/adoption.ts +1123 -0
  146. package/src/alpha6/captured-check-evidence.ts +132 -0
  147. package/src/alpha6/check-support-anchor.ts +128 -0
  148. package/src/alpha6/component-owner.ts +168 -0
  149. package/src/alpha6/corrective-decision-boundary.ts +39 -0
  150. package/src/alpha6/downstream-proof.ts +520 -0
  151. package/src/alpha6/failed-step-planning-recovery.ts +88 -0
  152. package/src/alpha6/handoff.ts +1443 -0
  153. package/src/alpha6/journal.ts +473 -0
  154. package/src/alpha6/literal-test-invocation.ts +84 -0
  155. package/src/alpha6/mechanical-feasibility.ts +488 -0
  156. package/src/alpha6/milestone.ts +2192 -0
  157. package/src/alpha6/navigation-dirty-carryover.ts +154 -0
  158. package/src/alpha6/npm-check-contract.ts +47 -0
  159. package/src/alpha6/plan-integrity.ts +298 -0
  160. package/src/alpha6/plan-risk.ts +1480 -0
  161. package/src/alpha6/preexecution-replan.ts +187 -0
  162. package/src/alpha6/remediation-cause.ts +98 -0
  163. package/src/alpha6/remediation.ts +2438 -0
  164. package/src/alpha6/review.ts +1198 -0
  165. package/src/alpha6/root-cause-replan-carryover.ts +491 -0
  166. package/src/alpha6/store-sidecars.ts +335 -0
  167. package/src/alpha7/autonomy.ts +411 -0
  168. package/src/alpha7/corrective-recovery.ts +1332 -0
  169. package/src/artifacts.ts +130 -0
  170. package/src/beta1/project-transaction.ts +355 -0
  171. package/src/change-explanation.ts +153 -0
  172. package/src/checks/runner.ts +245 -0
  173. package/src/checks/task-sync.ts +41 -0
  174. package/src/checks/worker.ts +149 -0
  175. package/src/cli-actions.ts +107 -0
  176. package/src/cli.ts +1457 -0
  177. package/src/contracts.ts +1494 -0
  178. package/src/credential-output.ts +89 -0
  179. package/src/credential-transport.ts +215 -0
  180. package/src/delegation.ts +190 -0
  181. package/src/dependency-provenance.ts +472 -0
  182. package/src/diagnostics.ts +93 -0
  183. package/src/domain/base-sync-conflict.ts +35 -0
  184. package/src/domain/completed-step-carryover.ts +76 -0
  185. package/src/domain/discovery.ts +27 -0
  186. package/src/domain/plan-semantics.ts +58 -0
  187. package/src/domain/step-start-admission.ts +10 -0
  188. package/src/domain/validation.ts +177 -0
  189. package/src/domain/virgin-registration.ts +46 -0
  190. package/src/errors.ts +24 -0
  191. package/src/fs-utils.ts +61 -0
  192. package/src/gateway-handshake.ts +95 -0
  193. package/src/git.ts +183 -0
  194. package/src/graph.ts +342 -0
  195. package/src/historical-step-provenance.ts +136 -0
  196. package/src/index.ts +23 -0
  197. package/src/lifecycle/canonical-hash.ts +28 -0
  198. package/src/lifecycle/catalog.ts +202 -0
  199. package/src/lifecycle/compiler-inspection.ts +29 -0
  200. package/src/lifecycle/core-static-readiness.ts +132 -0
  201. package/src/lifecycle/corrective-replan-authority.ts +136 -0
  202. package/src/lifecycle/corrective-replan-binding-manifest.ts +51 -0
  203. package/src/lifecycle/corrective-replan-credential-core.ts +408 -0
  204. package/src/lifecycle/corrective-replan-credential-schema.ts +54 -0
  205. package/src/lifecycle/corrective-replan-credentials.ts +48 -0
  206. package/src/lifecycle/corrective-replan.ts +843 -0
  207. package/src/lifecycle/evaluator.ts +48 -0
  208. package/src/lifecycle/fingerprint.ts +488 -0
  209. package/src/lifecycle/immutable.ts +8 -0
  210. package/src/lifecycle/implementation-table.ts +118 -0
  211. package/src/lifecycle/index.ts +8 -0
  212. package/src/lifecycle/schema-artifact.ts +263 -0
  213. package/src/lifecycle/semantic-registry.ts +572 -0
  214. package/src/lifecycle/types.ts +838 -0
  215. package/src/memory.ts +273 -0
  216. package/src/migration.ts +161 -0
  217. package/src/navigation-actions.ts +70 -0
  218. package/src/navigation-update-artifact.ts +198 -0
  219. package/src/navigation-update.ts +121 -0
  220. package/src/observation.ts +225 -0
  221. package/src/observed-routes.ts +660 -0
  222. package/src/operational-contract.ts +125 -0
  223. package/src/pending-review-update.ts +175 -0
  224. package/src/repository.ts +99 -0
  225. package/src/reviewer.ts +1879 -0
  226. package/src/runtime.ts +6 -0
  227. package/src/state/corrective-replan-executor.ts +818 -0
  228. package/src/state/corrective-replan-public-schema.ts +83 -0
  229. package/src/state/corrective-replan-public.ts +908 -0
  230. package/src/state/corrective-replan-transaction.ts +949 -0
  231. package/src/state/corrective-yield-executor.ts +327 -0
  232. package/src/state/corrective-yield-transaction.ts +730 -0
  233. package/src/state/lock.ts +902 -0
  234. package/src/state/store.ts +567 -0
  235. package/src/transition-core.ts +330 -0
  236. package/src/ulid.ts +24 -0
  237. package/src/version.ts +2 -0
  238. package/src/workflow-blocker-route.ts +109 -0
  239. package/src/workflow.ts +10172 -0
  240. package/docs/alpha7.1-implementation-brief.md +0 -268
  241. package/docs/alpha7.2-corrective-context-refresh-brief.md +0 -484
  242. package/docs/alpha7.2.1-remediation-recovery-brief.md +0 -86
  243. package/docs/beta1-stabilization-brief.md +0 -165
  244. package/docs/beta11-plan-integrity-recovery-brief.md +0 -38
  245. package/docs/beta13.2-signal-review-recovery.md +0 -38
  246. package/docs/beta2-initial-assembly-navigation-brief.md +0 -616
  247. package/docs/change-model.md +0 -118
  248. package/docs/delegated-approval.md +0 -254
  249. package/docs/lifecycle/state-machine-stabilization.md +0 -641
  250. package/docs/pdf/README.md +0 -24
  251. package/docs/pdf/codex-workflow-v2-architecture-ru.pdf +0 -0
  252. package/docs/pdf/codex-workflow-v2-chat-only-guide-ru.pdf +0 -0
  253. package/docs/pdf/codex-workflow-v2-technical-reference-ru.pdf +0 -0
  254. package/docs/pdf/requirements.txt +0 -1
  255. package/docs/pdf/sources/codex-workflow-v2-architecture-ru.md +0 -478
  256. package/docs/pdf/sources/codex-workflow-v2-chat-only-guide-ru.md +0 -506
  257. package/docs/pdf/sources/codex-workflow-v2-technical-reference-ru.md +0 -778
  258. package/docs/pending-review-update.md +0 -15
  259. package/docs/problem-briefs/01-pre-implementation-integrity.md +0 -482
  260. package/docs/problem-briefs/02-minimal-step-integrity.md +0 -411
  261. package/docs/problem-briefs/03-minimal-agent-context-integrity.md +0 -358
  262. package/docs/problem-briefs/04-task-dependency-and-structural-replacement-integrity.md +0 -573
  263. package/docs/problem-briefs/BRIEF-TEMPLATE.md +0 -56
  264. package/docs/problem-briefs/README.md +0 -120
  265. package/docs/problem-briefs/evidence/p01-mechanical-feasibility-corpus.md +0 -90
  266. package/docs/problem-briefs/evidence/signal-v4-pre-m3-replay.md +0 -246
  267. package/docs/split-required-recovery.md +0 -47
  268. package/docs/stable-release-defect-register.md +0 -730
  269. package/docs/validation-report.md +0 -182
  270. package/scripts/generate-pdf-docs.py +0 -524
  271. package/scripts/run-pdf-docs.mjs +0 -62
@@ -0,0 +1,187 @@
1
+ import type { AuthorizationEvent, PlanRiskAuditEvent, SidecarEventRecord, TaskState } from '../contracts.js';
2
+ import { WorkflowError } from '../errors.js';
3
+ import type { FileStateStore } from '../state/store.js';
4
+ import { createUlid } from '../ulid.js';
5
+ import {
6
+ assertHash64,
7
+ canonicalJsonStringify,
8
+ prepareSidecarAppend,
9
+ sha256Hex,
10
+ } from './store-sidecars.js';
11
+
12
+ const SIDECAR = 'preexecution-replans.jsonl';
13
+
14
+ export interface PreExecutionReplanEvent extends SidecarEventRecord {
15
+ taskId: string;
16
+ sourceTaskRevision: number;
17
+ resultTaskRevision: number;
18
+ briefHash: string;
19
+ sourcePlanHash: string;
20
+ knowledgeMapRevision: number;
21
+ knowledgeMapHash: string;
22
+ sourcePlanRiskAuditEventId: string;
23
+ sourcePlanRiskAuditEventHash: string;
24
+ obstructionPlanRiskAuditEventId: string;
25
+ obstructionPlanRiskAuditEventHash: string;
26
+ sourceExecutionAuthorizationHash: string;
27
+ sourceHeadCommit: string;
28
+ completedStepIds: string[];
29
+ completedStepsHash: string;
30
+ actor: string;
31
+ reason: string;
32
+ recordedAt: string;
33
+ }
34
+
35
+ export function preExecutionReplanSidecar(): string {
36
+ return SIDECAR;
37
+ }
38
+
39
+ export function hashExecutionAuthorization(authorization: AuthorizationEvent): string {
40
+ return sha256Hex(canonicalJsonStringify(authorization));
41
+ }
42
+
43
+ export function hashCompletedSteps(task: TaskState): string {
44
+ return sha256Hex(canonicalJsonStringify(
45
+ task.steps.filter((step) => step.status === 'completed'),
46
+ ));
47
+ }
48
+
49
+ export function preparePreExecutionReplanEvent(
50
+ store: FileStateStore,
51
+ task: TaskState,
52
+ input: {
53
+ sourceAudit: PlanRiskAuditEvent;
54
+ obstructionAudit: PlanRiskAuditEvent;
55
+ authorization: AuthorizationEvent;
56
+ sourceHeadCommit: string;
57
+ actor: string;
58
+ reason: string;
59
+ },
60
+ now: Date,
61
+ ): { event: PreExecutionReplanEvent; postimage: string } {
62
+ const actor = input.actor.trim();
63
+ const reason = input.reason.trim();
64
+ if (!actor) throw new WorkflowError('INVALID_ARGUMENT', 'Pre-execution replan actor is required.');
65
+ if (!reason) throw new WorkflowError('INVALID_ARGUMENT', 'Pre-execution replan reason is required.');
66
+ if (reason.length > 2048) throw new WorkflowError('INVALID_ARGUMENT', 'Pre-execution replan reason is too long.');
67
+ if (!task.planHash || task.knowledgeMapRevision === null || !task.knowledgeMapHash) {
68
+ throw new WorkflowError('STATE_CORRUPT', 'Pre-execution replan requires complete current Plan and Knowledge bindings.');
69
+ }
70
+ const existing = readPreExecutionReplanEvents(store, task);
71
+ const completedStepIds = task.steps.filter((step) => step.status === 'completed').map((step) => step.id);
72
+ const prepared = prepareSidecarAppend<PreExecutionReplanEvent>(existing, {
73
+ eventId: `PER-${createUlid(now.getTime())}`,
74
+ taskId: task.id,
75
+ sourceTaskRevision: task.revision,
76
+ resultTaskRevision: task.revision + 1,
77
+ briefHash: task.briefHash,
78
+ sourcePlanHash: task.planHash,
79
+ knowledgeMapRevision: task.knowledgeMapRevision,
80
+ knowledgeMapHash: task.knowledgeMapHash,
81
+ sourcePlanRiskAuditEventId: input.sourceAudit.eventId,
82
+ sourcePlanRiskAuditEventHash: input.sourceAudit.eventHash,
83
+ obstructionPlanRiskAuditEventId: input.obstructionAudit.eventId,
84
+ obstructionPlanRiskAuditEventHash: input.obstructionAudit.eventHash,
85
+ sourceExecutionAuthorizationHash: hashExecutionAuthorization(input.authorization),
86
+ sourceHeadCommit: input.sourceHeadCommit,
87
+ completedStepIds,
88
+ completedStepsHash: hashCompletedSteps(task),
89
+ actor,
90
+ reason,
91
+ recordedAt: now.toISOString(),
92
+ }, {
93
+ validateEvent: validateStoredPreExecutionReplanEvent,
94
+ });
95
+ return { event: prepared.event, postimage: prepared.content };
96
+ }
97
+
98
+ export function readPreExecutionReplanEvents(
99
+ store: FileStateStore,
100
+ task: TaskState,
101
+ ): PreExecutionReplanEvent[] {
102
+ return store.readSidecarEvents<PreExecutionReplanEvent>(
103
+ store.taskRoot(task.projectId, task.id),
104
+ SIDECAR,
105
+ { validateEvent: validateStoredPreExecutionReplanEvent },
106
+ );
107
+ }
108
+
109
+ export function readCurrentPreExecutionReplan(
110
+ store: FileStateStore,
111
+ task: TaskState,
112
+ ): PreExecutionReplanEvent | null {
113
+ const event = readPreExecutionReplanEvents(store, task).at(-1) ?? null;
114
+ if (!event || event.sourcePlanHash !== task.planHash || task.status === 'cancelled') return null;
115
+ if (task.revision < event.resultTaskRevision) {
116
+ throw new WorkflowError('STATE_CORRUPT', 'Pre-execution replan marker is newer than its Task state.', {
117
+ taskId: task.id,
118
+ eventId: event.eventId,
119
+ });
120
+ }
121
+ if (event.taskId !== task.id || event.briefHash !== task.briefHash
122
+ || event.knowledgeMapRevision !== task.knowledgeMapRevision
123
+ || event.knowledgeMapHash !== task.knowledgeMapHash) {
124
+ throw new WorkflowError('STATE_CORRUPT', 'Current pre-execution replan marker does not match Task authority.', {
125
+ taskId: task.id,
126
+ eventId: event.eventId,
127
+ });
128
+ }
129
+ if (event.completedStepsHash !== hashCompletedSteps(task)
130
+ || canonicalJsonStringify(event.completedStepIds)
131
+ !== canonicalJsonStringify(task.steps.filter((step) => step.status === 'completed').map((step) => step.id))) {
132
+ throw new WorkflowError('STATE_CORRUPT', 'Completed Step authority changed after pre-execution replan recording.', {
133
+ taskId: task.id,
134
+ eventId: event.eventId,
135
+ });
136
+ }
137
+ return event;
138
+ }
139
+
140
+ function validateStoredPreExecutionReplanEvent(
141
+ event: PreExecutionReplanEvent,
142
+ context: { file: string; line: number; eventId: string },
143
+ ): void {
144
+ const expectedKeys = [
145
+ 'actor', 'briefHash', 'completedStepIds', 'completedStepsHash', 'eventHash', 'eventId',
146
+ 'knowledgeMapHash', 'knowledgeMapRevision', 'obstructionPlanRiskAuditEventHash',
147
+ 'obstructionPlanRiskAuditEventId', 'previousEventHash', 'reason', 'recordedAt',
148
+ 'resultTaskRevision', 'sourceExecutionAuthorizationHash', 'sourceHeadCommit', 'sourcePlanHash',
149
+ 'sourcePlanRiskAuditEventHash', 'sourcePlanRiskAuditEventId', 'sourceTaskRevision', 'taskId',
150
+ ].sort();
151
+ if (!event || typeof event !== 'object' || Array.isArray(event)
152
+ || canonicalJsonStringify(Object.keys(event).sort()) !== canonicalJsonStringify(expectedKeys)) {
153
+ throw new WorkflowError('STATE_CORRUPT', 'Pre-execution replan event has an invalid shape.', context);
154
+ }
155
+ if (!/^PER-[0-9A-HJKMNP-TV-Z]{26}$/.test(event.eventId)
156
+ || !/^TASK-[0-9A-HJKMNP-TV-Z]{26}$/.test(event.taskId)
157
+ || !/^PRA-[0-9A-HJKMNP-TV-Z]{26}$/.test(event.sourcePlanRiskAuditEventId)
158
+ || !/^PRA-[0-9A-HJKMNP-TV-Z]{26}$/.test(event.obstructionPlanRiskAuditEventId)) {
159
+ throw new WorkflowError('STATE_CORRUPT', 'Pre-execution replan event identity binding is invalid.', context);
160
+ }
161
+ if (!Number.isSafeInteger(event.sourceTaskRevision) || event.sourceTaskRevision < 1
162
+ || event.resultTaskRevision !== event.sourceTaskRevision + 1
163
+ || !Number.isSafeInteger(event.knowledgeMapRevision) || event.knowledgeMapRevision < 1) {
164
+ throw new WorkflowError('STATE_CORRUPT', 'Pre-execution replan event revision binding is invalid.', context);
165
+ }
166
+ for (const [label, value] of [
167
+ ['briefHash', event.briefHash], ['sourcePlanHash', event.sourcePlanHash],
168
+ ['knowledgeMapHash', event.knowledgeMapHash],
169
+ ['sourcePlanRiskAuditEventHash', event.sourcePlanRiskAuditEventHash],
170
+ ['obstructionPlanRiskAuditEventHash', event.obstructionPlanRiskAuditEventHash],
171
+ ['sourceExecutionAuthorizationHash', event.sourceExecutionAuthorizationHash],
172
+ ['completedStepsHash', event.completedStepsHash],
173
+ ] as const) assertHash64(value, `Pre-execution replan ${label}`);
174
+ if (!/^[a-f0-9]{40}$/.test(event.sourceHeadCommit)) {
175
+ throw new WorkflowError('STATE_CORRUPT', 'Pre-execution replan source HEAD is invalid.', context);
176
+ }
177
+ if (!Array.isArray(event.completedStepIds)
178
+ || event.completedStepIds.some((stepId) => typeof stepId !== 'string' || !stepId.trim())
179
+ || new Set(event.completedStepIds).size !== event.completedStepIds.length) {
180
+ throw new WorkflowError('STATE_CORRUPT', 'Pre-execution replan completed Step ids are invalid.', context);
181
+ }
182
+ if (typeof event.actor !== 'string' || !event.actor.trim()
183
+ || typeof event.reason !== 'string' || !event.reason.trim() || event.reason.length > 2048
184
+ || typeof event.recordedAt !== 'string' || !Number.isFinite(Date.parse(event.recordedAt))) {
185
+ throw new WorkflowError('STATE_CORRUPT', 'Pre-execution replan provenance is invalid.', context);
186
+ }
187
+ }
@@ -0,0 +1,98 @@
1
+ import { createHash } from 'node:crypto';
2
+ import path from 'node:path';
3
+ import type { RemediationCauseBinding } from '../contracts.js';
4
+ import type { CheckResult } from '../git.js';
5
+ import { canonicalJsonStringify } from './store-sidecars.js';
6
+
7
+ const ANSI_ESCAPE = /\u001b\[[0-9;]*m/g;
8
+ const ISO_TIMESTAMP = /\b\d{4}-\d{2}-\d{2}[T ][0-9:.+-]+Z?\b/g;
9
+ const TEMP_PATH = /\/(?:private\/)?(?:tmp|var\/folders)\/[^\s:'"`]+/g;
10
+ const HEX_ID = /\b[a-f0-9]{40,64}\b/g;
11
+ const SOURCE_LOCATION = /:(?:\d+)(?::\d+)?\b/g;
12
+ const DIAGNOSTIC_CODE = /\b(?:[A-Z][A-Z0-9_]{2,}|TS\d{3,5}|ERR_[A-Z0-9_]+)\b/g;
13
+ const REPOSITORY_PATH = /(?:^|[\s('"`])([A-Za-z0-9_.-]+(?:\/[A-Za-z0-9_.-]+)+\.(?:cjs|js|json|mjs|sql|ts|tsx))(?=[:\s)'"`]|$)/g;
14
+
15
+ export interface NormalizedMechanicalFailure {
16
+ command: string;
17
+ exitCode: number;
18
+ diagnosticCodes: string[];
19
+ diagnosticShape: string[];
20
+ diagnosticPaths: string[];
21
+ causeFingerprint: string;
22
+ }
23
+
24
+ export function normalizeMechanicalFailures(
25
+ checks: readonly CheckResult[],
26
+ repositoryRoot: string,
27
+ ): NormalizedMechanicalFailure[] {
28
+ return checks.filter((check) => !check.passed).map((check) => {
29
+ const normalizedOutput = normalizeOutput(check.output, repositoryRoot);
30
+ const diagnosticCodes = [...new Set(normalizedOutput.match(DIAGNOSTIC_CODE) ?? [])].sort().slice(0, 16);
31
+ const diagnosticShape = [...new Set(normalizedOutput.split('\n')
32
+ .map((line) => line.trim().replace(/\s+/g, ' '))
33
+ .filter(Boolean)
34
+ .slice(0, 4)
35
+ .map((line) => line.slice(0, 240)))];
36
+ const diagnosticPaths = extractRepositoryPaths(check.output, repositoryRoot);
37
+ const causeMaterial = {
38
+ domain: 'codex-workflow/mechanical-remediation-cause/v1',
39
+ command: normalizeCommand(check.command),
40
+ exitCode: check.exitCode,
41
+ diagnosticCodes,
42
+ diagnosticShape,
43
+ };
44
+ return {
45
+ command: causeMaterial.command,
46
+ exitCode: causeMaterial.exitCode,
47
+ diagnosticCodes,
48
+ diagnosticShape,
49
+ diagnosticPaths,
50
+ causeFingerprint: createHash('sha256').update(canonicalJsonStringify(causeMaterial)).digest('hex'),
51
+ };
52
+ });
53
+ }
54
+
55
+ export function mechanicalCauseBindings(
56
+ failures: readonly NormalizedMechanicalFailure[],
57
+ ): RemediationCauseBinding[] {
58
+ return failures.map((failure) => ({
59
+ authority: 'mechanical',
60
+ causeId: `mechanical:${failure.causeFingerprint}`,
61
+ causeFingerprint: failure.causeFingerprint,
62
+ planConflict: false,
63
+ }));
64
+ }
65
+
66
+ export function reviewerCauseFingerprint(causeId: string): string {
67
+ return createHash('sha256').update(canonicalJsonStringify({
68
+ domain: 'codex-workflow/external-reviewer-cause/v1',
69
+ causeId: causeId.trim(),
70
+ })).digest('hex');
71
+ }
72
+
73
+ function normalizeOutput(output: string, repositoryRoot: string): string {
74
+ const normalizedRoot = path.resolve(repositoryRoot).replaceAll('\\', '/');
75
+ return output
76
+ .replace(ANSI_ESCAPE, '')
77
+ .replaceAll('\\', '/')
78
+ .replaceAll(normalizedRoot, '<repo>')
79
+ .replace(TEMP_PATH, '<tmp>')
80
+ .replace(ISO_TIMESTAMP, '<time>')
81
+ .replace(HEX_ID, '<hash>')
82
+ .replace(SOURCE_LOCATION, ':<loc>');
83
+ }
84
+
85
+ function normalizeCommand(command: string): string {
86
+ return command.trim().replace(/\s+/g, ' ');
87
+ }
88
+
89
+ function extractRepositoryPaths(output: string, repositoryRoot: string): string[] {
90
+ const normalizedRoot = path.resolve(repositoryRoot).replaceAll('\\', '/');
91
+ const normalized = output.replaceAll('\\', '/').replaceAll(`${normalizedRoot}/`, '');
92
+ const result = new Set<string>();
93
+ for (const match of normalized.matchAll(REPOSITORY_PATH)) {
94
+ const candidate = match[1]!;
95
+ if (!candidate.startsWith('../') && !path.posix.isAbsolute(candidate)) result.add(candidate);
96
+ }
97
+ return [...result].sort();
98
+ }