codex-workflow-v2 2.0.0-beta.13.8 → 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.
- package/README.md +27 -388
- package/dist/reviewer-runtime-build.json +96 -32
- package/dist/src/alpha6/adoption.d.ts +2 -0
- package/dist/src/alpha6/adoption.js +22 -0
- package/dist/src/alpha6/adoption.js.map +1 -1
- package/dist/src/alpha6/captured-check-evidence.d.ts +51 -0
- package/dist/src/alpha6/captured-check-evidence.js +152 -0
- package/dist/src/alpha6/captured-check-evidence.js.map +1 -0
- package/dist/src/alpha6/component-owner.d.ts +15 -1
- package/dist/src/alpha6/component-owner.js +44 -2
- package/dist/src/alpha6/component-owner.js.map +1 -1
- package/dist/src/alpha6/corrective-decision-boundary.d.ts +4 -0
- package/dist/src/alpha6/corrective-decision-boundary.js +47 -0
- package/dist/src/alpha6/corrective-decision-boundary.js.map +1 -0
- package/dist/src/alpha6/downstream-proof.d.ts +1 -25
- package/dist/src/alpha6/downstream-proof.js +0 -171
- package/dist/src/alpha6/downstream-proof.js.map +1 -1
- package/dist/src/alpha6/failed-step-planning-recovery.d.ts +10 -0
- package/dist/src/alpha6/failed-step-planning-recovery.js +93 -0
- package/dist/src/alpha6/failed-step-planning-recovery.js.map +1 -0
- package/dist/src/alpha6/literal-test-invocation.d.ts +2 -0
- package/dist/src/alpha6/literal-test-invocation.js +106 -0
- package/dist/src/alpha6/literal-test-invocation.js.map +1 -0
- package/dist/src/alpha6/milestone.d.ts +2 -0
- package/dist/src/alpha6/milestone.js +10 -1
- package/dist/src/alpha6/milestone.js.map +1 -1
- package/dist/src/alpha6/navigation-dirty-carryover.d.ts +11 -0
- package/dist/src/alpha6/navigation-dirty-carryover.js +130 -0
- package/dist/src/alpha6/navigation-dirty-carryover.js.map +1 -0
- package/dist/src/alpha6/plan-integrity.js +7 -5
- package/dist/src/alpha6/plan-integrity.js.map +1 -1
- package/dist/src/alpha6/plan-risk.d.ts +2 -0
- package/dist/src/alpha6/plan-risk.js +10 -3
- package/dist/src/alpha6/plan-risk.js.map +1 -1
- package/dist/src/alpha6/remediation.d.ts +6 -21
- package/dist/src/alpha6/remediation.js +161 -476
- package/dist/src/alpha6/remediation.js.map +1 -1
- package/dist/src/alpha6/root-cause-replan-carryover.d.ts +4 -1
- package/dist/src/alpha6/root-cause-replan-carryover.js +29 -5
- package/dist/src/alpha6/root-cause-replan-carryover.js.map +1 -1
- package/dist/src/beta1/project-transaction.d.ts +3 -1
- package/dist/src/beta1/project-transaction.js +6 -2
- package/dist/src/beta1/project-transaction.js.map +1 -1
- package/dist/src/checks/runner.d.ts +26 -0
- package/dist/src/checks/runner.js +223 -0
- package/dist/src/checks/runner.js.map +1 -0
- package/dist/src/checks/task-sync.d.ts +10 -0
- package/dist/src/checks/task-sync.js +41 -0
- package/dist/src/checks/task-sync.js.map +1 -0
- package/dist/src/checks/worker.d.ts +1 -0
- package/dist/src/checks/worker.js +154 -0
- package/dist/src/checks/worker.js.map +1 -0
- package/dist/src/cli-actions.d.ts +2 -2
- package/dist/src/cli-actions.js +3 -15
- package/dist/src/cli-actions.js.map +1 -1
- package/dist/src/cli.js +14 -98
- package/dist/src/cli.js.map +1 -1
- package/dist/src/contracts.d.ts +35 -32
- package/dist/src/dependency-provenance.d.ts +2 -2
- package/dist/src/dependency-provenance.js +12 -69
- package/dist/src/dependency-provenance.js.map +1 -1
- package/dist/src/domain/base-sync-conflict.d.ts +13 -0
- package/dist/src/domain/base-sync-conflict.js +32 -0
- package/dist/src/domain/base-sync-conflict.js.map +1 -0
- package/dist/src/domain/step-start-admission.d.ts +4 -0
- package/dist/src/domain/step-start-admission.js +9 -0
- package/dist/src/domain/step-start-admission.js.map +1 -0
- package/dist/src/domain/virgin-registration.d.ts +3 -0
- package/dist/src/domain/virgin-registration.js +65 -0
- package/dist/src/domain/virgin-registration.js.map +1 -0
- package/dist/src/errors.d.ts +1 -1
- package/dist/src/errors.js.map +1 -1
- package/dist/src/gateway-handshake.js +0 -8
- package/dist/src/gateway-handshake.js.map +1 -1
- package/dist/src/git.d.ts +3 -1
- package/dist/src/git.js +41 -14
- package/dist/src/git.js.map +1 -1
- package/dist/src/graph.js +25 -3
- package/dist/src/graph.js.map +1 -1
- package/dist/src/index.d.ts +1 -0
- package/dist/src/lifecycle/corrective-replan.js +3 -3
- package/dist/src/lifecycle/corrective-replan.js.map +1 -1
- package/dist/src/navigation-actions.d.ts +9 -0
- package/dist/src/navigation-actions.js +72 -0
- package/dist/src/navigation-actions.js.map +1 -0
- package/dist/src/navigation-update-artifact.d.ts +5 -0
- package/dist/src/navigation-update-artifact.js +227 -0
- package/dist/src/navigation-update-artifact.js.map +1 -0
- package/dist/src/navigation-update.d.ts +39 -0
- package/dist/src/navigation-update.js +82 -0
- package/dist/src/navigation-update.js.map +1 -0
- package/dist/src/observation.js +52 -29
- package/dist/src/observation.js.map +1 -1
- package/dist/src/observed-routes.js +5 -6
- package/dist/src/observed-routes.js.map +1 -1
- package/dist/src/pending-review-update.d.ts +0 -13
- package/dist/src/pending-review-update.js +1 -6
- package/dist/src/pending-review-update.js.map +1 -1
- package/dist/src/reviewer.d.ts +1 -1
- package/dist/src/reviewer.js +20 -17
- package/dist/src/reviewer.js.map +1 -1
- package/dist/src/runtime.d.ts +3 -0
- package/dist/src/runtime.js +6 -0
- package/dist/src/runtime.js.map +1 -0
- package/dist/src/state/corrective-replan-executor.d.ts +10 -0
- package/dist/src/state/corrective-replan-executor.js +37 -1
- package/dist/src/state/corrective-replan-executor.js.map +1 -1
- package/dist/src/state/corrective-replan-public-schema.js +15 -2
- package/dist/src/state/corrective-replan-public-schema.js.map +1 -1
- package/dist/src/state/corrective-replan-public.js +6 -5
- package/dist/src/state/corrective-replan-public.js.map +1 -1
- package/dist/src/state/corrective-replan-transaction.d.ts +1 -0
- package/dist/src/state/corrective-replan-transaction.js +12 -11
- package/dist/src/state/corrective-replan-transaction.js.map +1 -1
- package/dist/src/state/corrective-yield-executor.js +2 -2
- package/dist/src/state/corrective-yield-executor.js.map +1 -1
- package/dist/src/state/corrective-yield-transaction.d.ts +1 -0
- package/dist/src/state/corrective-yield-transaction.js +11 -10
- package/dist/src/state/corrective-yield-transaction.js.map +1 -1
- package/dist/src/state/lock.d.ts +4 -0
- package/dist/src/state/lock.js +21 -0
- package/dist/src/state/lock.js.map +1 -1
- package/dist/src/version.d.ts +1 -1
- package/dist/src/version.js +1 -1
- package/dist/src/version.js.map +1 -1
- package/dist/src/workflow-blocker-route.d.ts +8 -0
- package/dist/src/workflow-blocker-route.js +106 -0
- package/dist/src/workflow-blocker-route.js.map +1 -0
- package/dist/src/workflow.d.ts +48 -63
- package/dist/src/workflow.js +698 -1470
- package/dist/src/workflow.js.map +1 -1
- package/docs/autonomy-guardrails.md +26 -304
- package/docs/decisions.md +14 -112
- package/docs/development-flow.md +35 -238
- package/docs/project-memory.md +31 -50
- package/docs/release-app-evidence.md +190 -0
- package/docs/release.md +95 -363
- package/docs/updating-existing-project.md +19 -717
- package/package.json +11 -13
- package/plugins/codex-workflow-gateway/.codex-plugin/plugin.json +2 -2
- package/plugins/codex-workflow-gateway/references/chat-dispatch.md +73 -197
- package/plugins/codex-workflow-gateway/references/codebase-memory-routing.md +57 -0
- package/plugins/codex-workflow-gateway/references/protocol.md +42 -445
- package/plugins/codex-workflow-gateway/scripts/chat-dispatch.mjs +7 -1
- package/plugins/codex-workflow-gateway/scripts/chat-model-policy.mjs +10 -8
- package/plugins/codex-workflow-gateway/scripts/chat-registry.mjs +23 -5
- package/plugins/codex-workflow-gateway/skills/codex-workflow-gateway/SKILL.md +66 -740
- package/references/state-machine.md +4 -4
- package/roles/technical-planner.md +1 -1
- package/schemas/corrective-decision-event.schema.json +3 -1
- package/schemas/project-knowledge-map.schema.json +3 -1
- package/schemas/remediation-event.schema.json +10 -1
- package/schemas/task.schema.json +46 -2
- package/schemas/transition-payloads.schema.json +16 -1
- package/src/alpha6/adoption.ts +1123 -0
- package/src/alpha6/captured-check-evidence.ts +132 -0
- package/src/alpha6/check-support-anchor.ts +128 -0
- package/src/alpha6/component-owner.ts +168 -0
- package/src/alpha6/corrective-decision-boundary.ts +39 -0
- package/src/alpha6/downstream-proof.ts +520 -0
- package/src/alpha6/failed-step-planning-recovery.ts +88 -0
- package/src/alpha6/handoff.ts +1443 -0
- package/src/alpha6/journal.ts +473 -0
- package/src/alpha6/literal-test-invocation.ts +84 -0
- package/src/alpha6/mechanical-feasibility.ts +488 -0
- package/src/alpha6/milestone.ts +2192 -0
- package/src/alpha6/navigation-dirty-carryover.ts +154 -0
- package/src/alpha6/npm-check-contract.ts +47 -0
- package/src/alpha6/plan-integrity.ts +298 -0
- package/src/alpha6/plan-risk.ts +1480 -0
- package/src/alpha6/preexecution-replan.ts +187 -0
- package/src/alpha6/remediation-cause.ts +98 -0
- package/src/alpha6/remediation.ts +2438 -0
- package/src/alpha6/review.ts +1198 -0
- package/src/alpha6/root-cause-replan-carryover.ts +491 -0
- package/src/alpha6/store-sidecars.ts +335 -0
- package/src/alpha7/autonomy.ts +411 -0
- package/src/alpha7/corrective-recovery.ts +1332 -0
- package/src/artifacts.ts +130 -0
- package/src/beta1/project-transaction.ts +355 -0
- package/src/change-explanation.ts +153 -0
- package/src/checks/runner.ts +245 -0
- package/src/checks/task-sync.ts +41 -0
- package/src/checks/worker.ts +149 -0
- package/src/cli-actions.ts +107 -0
- package/src/cli.ts +1457 -0
- package/src/contracts.ts +1494 -0
- package/src/credential-output.ts +89 -0
- package/src/credential-transport.ts +215 -0
- package/src/delegation.ts +190 -0
- package/src/dependency-provenance.ts +472 -0
- package/src/diagnostics.ts +93 -0
- package/src/domain/base-sync-conflict.ts +35 -0
- package/src/domain/completed-step-carryover.ts +76 -0
- package/src/domain/discovery.ts +27 -0
- package/src/domain/plan-semantics.ts +58 -0
- package/src/domain/step-start-admission.ts +10 -0
- package/src/domain/validation.ts +177 -0
- package/src/domain/virgin-registration.ts +46 -0
- package/src/errors.ts +24 -0
- package/src/fs-utils.ts +61 -0
- package/src/gateway-handshake.ts +95 -0
- package/src/git.ts +183 -0
- package/src/graph.ts +342 -0
- package/src/historical-step-provenance.ts +136 -0
- package/src/index.ts +23 -0
- package/src/lifecycle/canonical-hash.ts +28 -0
- package/src/lifecycle/catalog.ts +202 -0
- package/src/lifecycle/compiler-inspection.ts +29 -0
- package/src/lifecycle/core-static-readiness.ts +132 -0
- package/src/lifecycle/corrective-replan-authority.ts +136 -0
- package/src/lifecycle/corrective-replan-binding-manifest.ts +51 -0
- package/src/lifecycle/corrective-replan-credential-core.ts +408 -0
- package/src/lifecycle/corrective-replan-credential-schema.ts +54 -0
- package/src/lifecycle/corrective-replan-credentials.ts +48 -0
- package/src/lifecycle/corrective-replan.ts +843 -0
- package/src/lifecycle/evaluator.ts +48 -0
- package/src/lifecycle/fingerprint.ts +488 -0
- package/src/lifecycle/immutable.ts +8 -0
- package/src/lifecycle/implementation-table.ts +118 -0
- package/src/lifecycle/index.ts +8 -0
- package/src/lifecycle/schema-artifact.ts +263 -0
- package/src/lifecycle/semantic-registry.ts +572 -0
- package/src/lifecycle/types.ts +838 -0
- package/src/memory.ts +273 -0
- package/src/migration.ts +161 -0
- package/src/navigation-actions.ts +70 -0
- package/src/navigation-update-artifact.ts +198 -0
- package/src/navigation-update.ts +121 -0
- package/src/observation.ts +225 -0
- package/src/observed-routes.ts +660 -0
- package/src/operational-contract.ts +125 -0
- package/src/pending-review-update.ts +175 -0
- package/src/repository.ts +99 -0
- package/src/reviewer.ts +1879 -0
- package/src/runtime.ts +6 -0
- package/src/state/corrective-replan-executor.ts +818 -0
- package/src/state/corrective-replan-public-schema.ts +83 -0
- package/src/state/corrective-replan-public.ts +908 -0
- package/src/state/corrective-replan-transaction.ts +949 -0
- package/src/state/corrective-yield-executor.ts +327 -0
- package/src/state/corrective-yield-transaction.ts +730 -0
- package/src/state/lock.ts +902 -0
- package/src/state/store.ts +567 -0
- package/src/transition-core.ts +330 -0
- package/src/ulid.ts +24 -0
- package/src/version.ts +2 -0
- package/src/workflow-blocker-route.ts +109 -0
- package/src/workflow.ts +10172 -0
- package/docs/alpha7.1-implementation-brief.md +0 -268
- package/docs/alpha7.2-corrective-context-refresh-brief.md +0 -484
- package/docs/alpha7.2.1-remediation-recovery-brief.md +0 -86
- package/docs/beta1-stabilization-brief.md +0 -165
- package/docs/beta11-plan-integrity-recovery-brief.md +0 -38
- package/docs/beta13.2-signal-review-recovery.md +0 -38
- package/docs/beta2-initial-assembly-navigation-brief.md +0 -616
- package/docs/change-model.md +0 -118
- package/docs/delegated-approval.md +0 -254
- package/docs/lifecycle/state-machine-stabilization.md +0 -641
- package/docs/pdf/README.md +0 -24
- package/docs/pdf/codex-workflow-v2-architecture-ru.pdf +0 -0
- package/docs/pdf/codex-workflow-v2-chat-only-guide-ru.pdf +0 -0
- package/docs/pdf/codex-workflow-v2-technical-reference-ru.pdf +0 -0
- package/docs/pdf/requirements.txt +0 -1
- package/docs/pdf/sources/codex-workflow-v2-architecture-ru.md +0 -478
- package/docs/pdf/sources/codex-workflow-v2-chat-only-guide-ru.md +0 -508
- package/docs/pdf/sources/codex-workflow-v2-technical-reference-ru.md +0 -778
- package/docs/pending-review-update.md +0 -15
- package/docs/problem-briefs/01-pre-implementation-integrity.md +0 -482
- package/docs/problem-briefs/02-minimal-step-integrity.md +0 -411
- package/docs/problem-briefs/03-minimal-agent-context-integrity.md +0 -358
- package/docs/problem-briefs/04-task-dependency-and-structural-replacement-integrity.md +0 -573
- package/docs/problem-briefs/BRIEF-TEMPLATE.md +0 -56
- package/docs/problem-briefs/README.md +0 -120
- package/docs/problem-briefs/evidence/p01-mechanical-feasibility-corpus.md +0 -90
- package/docs/problem-briefs/evidence/signal-v4-pre-m3-replay.md +0 -246
- package/docs/split-required-recovery.md +0 -47
- package/docs/stable-release-defect-register.md +0 -730
- package/docs/validation-report.md +0 -182
- package/scripts/generate-pdf-docs.py +0 -524
- 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
|
+
}
|