codex-workflow-v2 2.0.0-beta.13.3 → 2.0.0-beta.13.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +1 -1
- package/dist/reviewer-runtime-build.json +17 -9
- package/dist/src/alpha6/plan-risk.d.ts +1 -0
- package/dist/src/alpha6/plan-risk.js +9 -6
- package/dist/src/alpha6/plan-risk.js.map +1 -1
- package/dist/src/alpha6/preexecution-replan.d.ts +38 -0
- package/dist/src/alpha6/preexecution-replan.js +130 -0
- package/dist/src/alpha6/preexecution-replan.js.map +1 -0
- package/dist/src/alpha6/remediation.d.ts +4 -3
- package/dist/src/alpha6/remediation.js +147 -21
- package/dist/src/alpha6/remediation.js.map +1 -1
- package/dist/src/cli-actions.d.ts +1 -1
- package/dist/src/cli-actions.js +1 -0
- package/dist/src/cli-actions.js.map +1 -1
- package/dist/src/cli.js +44 -0
- package/dist/src/cli.js.map +1 -1
- package/dist/src/domain/plan-semantics.d.ts +11 -0
- package/dist/src/domain/plan-semantics.js +49 -0
- package/dist/src/domain/plan-semantics.js.map +1 -0
- package/dist/src/version.d.ts +1 -1
- package/dist/src/version.js +1 -1
- package/dist/src/workflow.d.ts +19 -1
- package/dist/src/workflow.js +514 -80
- package/dist/src/workflow.js.map +1 -1
- 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/sources/codex-workflow-v2-architecture-ru.md +1 -1
- package/docs/pdf/sources/codex-workflow-v2-chat-only-guide-ru.md +2 -2
- package/docs/pdf/sources/codex-workflow-v2-technical-reference-ru.md +2 -2
- package/docs/release.md +43 -0
- package/package.json +1 -1
- package/plugins/codex-workflow-gateway/skills/codex-workflow-gateway/SKILL.md +35 -2
- package/schemas/preexecution-replan-event.schema.json +45 -0
|
@@ -1,10 +1,12 @@
|
|
|
1
1
|
import { closeSync, existsSync, openSync, readFileSync, unlinkSync } from 'node:fs';
|
|
2
2
|
import path from 'node:path';
|
|
3
|
+
import { normalizePlanKnowledgeBinding, readVerifiedPlanArtifact } from '../domain/plan-semantics.js';
|
|
3
4
|
import { pathAllowed } from '../domain/validation.js';
|
|
4
5
|
import { WorkflowError } from '../errors.js';
|
|
5
6
|
import { hashCanonical } from '../lifecycle/fingerprint.js';
|
|
6
7
|
import { createUlid } from '../ulid.js';
|
|
7
8
|
import { PACKAGE_VERSION } from '../version.js';
|
|
9
|
+
import { readPlanRiskAuditEvents } from './plan-risk.js';
|
|
8
10
|
import { assertHash64, canonicalJsonStringify, prepareSidecarAppend, sha256Hex, } from './store-sidecars.js';
|
|
9
11
|
import { readTaskC1Posture } from './handoff.js';
|
|
10
12
|
import { buildCurrentStrictStepReviewCycle, latestPassedVerifiedStepReviewEvent, readReviewerAttestations, readStepReviewEvents, } from './review.js';
|
|
@@ -83,7 +85,7 @@ function validateRemediationHistory(store, task) {
|
|
|
83
85
|
validateRemediationReviewReferences(store, task, remediationEvents);
|
|
84
86
|
validateCorrectiveDecisionCoverage(task, correctiveDecisionEvents, remediationEvents);
|
|
85
87
|
const recoveredEventIds = validateRemediationModeRecoveries(store, task, remediationEvents, correctiveDecisionEvents, modeRecoveries);
|
|
86
|
-
validateHistoricalRemediationModesForAllSteps(task, remediationEvents, correctiveDecisionEvents, recoveredEventIds, overriddenStopDecisionEventIds);
|
|
88
|
+
validateHistoricalRemediationModesForAllSteps(store, task, remediationEvents, correctiveDecisionEvents, recoveredEventIds, overriddenStopDecisionEventIds);
|
|
87
89
|
return {
|
|
88
90
|
remediationEvents,
|
|
89
91
|
correctiveDecisionEvents,
|
|
@@ -161,6 +163,7 @@ export function prepareRemediationEvent(store, task, stepId, failureKind, failur
|
|
|
161
163
|
const recoveredDecisionEventId = findCorrectiveRecoveryDecisionIdForFailure(store, task, stepId);
|
|
162
164
|
const allExisting = readRemediationEvents(store, task);
|
|
163
165
|
const existing = allExisting.filter((event) => event.stepId === stepId);
|
|
166
|
+
const correctiveDecisions = readCorrectiveDecisionEvents(store, task);
|
|
164
167
|
const matching = existing.filter((event) => remediationEventMatchesFailure(event, failureKind, failureEvidence));
|
|
165
168
|
if (matching.length > 1) {
|
|
166
169
|
throw new WorkflowError('STATE_CORRUPT', 'Multiple remediation events match the same failure identity.', {
|
|
@@ -181,10 +184,13 @@ export function prepareRemediationEvent(store, task, stepId, failureKind, failur
|
|
|
181
184
|
});
|
|
182
185
|
}
|
|
183
186
|
const priorEvents = existing.filter((event) => event.attemptOrdinal < reused.attemptOrdinal);
|
|
184
|
-
const
|
|
187
|
+
const cycle = selectCurrentPlanRemediationCycle(store, task, priorEvents, correctiveDecisions);
|
|
188
|
+
const gate = deriveAttemptGateFromHistory(task, stepId, planRiskAudit, cycle.remediationEvents, cycle.correctiveDecisions, {
|
|
185
189
|
recoveredDecisionEventId,
|
|
186
190
|
reboundStopOverrideDecisionEventId,
|
|
187
191
|
overriddenStopDecisionEventIds: stopEscalateOverrideDecisionEventIds(store, task),
|
|
192
|
+
priorRemediationEvents: cycle.priorRemediationEvents,
|
|
193
|
+
nextAttemptOrdinal: reused.attemptOrdinal,
|
|
188
194
|
});
|
|
189
195
|
if (reused.attemptOrdinal !== gate.nextAttemptOrdinal || reused.mode !== gate.mode || reused.guardedCategory !== gate.guardedCategory) {
|
|
190
196
|
throw new WorkflowError('STATE_CORRUPT', 'Existing remediation event conflicts with the current guarded retry binding.', {
|
|
@@ -199,10 +205,13 @@ export function prepareRemediationEvent(store, task, stepId, failureKind, failur
|
|
|
199
205
|
}
|
|
200
206
|
return { event: reused, postimage: null };
|
|
201
207
|
}
|
|
202
|
-
const
|
|
208
|
+
const cycle = selectCurrentPlanRemediationCycle(store, task, existing, correctiveDecisions);
|
|
209
|
+
const gate = deriveAttemptGateFromHistory(task, stepId, planRiskAudit, cycle.remediationEvents, cycle.correctiveDecisions, {
|
|
203
210
|
recoveredDecisionEventId,
|
|
204
211
|
reboundStopOverrideDecisionEventId,
|
|
205
212
|
overriddenStopDecisionEventIds: stopEscalateOverrideDecisionEventIds(store, task),
|
|
213
|
+
priorRemediationEvents: cycle.priorRemediationEvents,
|
|
214
|
+
nextAttemptOrdinal: existing.length + 1,
|
|
206
215
|
});
|
|
207
216
|
const prepared = prepareSidecarAppend(allExisting, {
|
|
208
217
|
eventId: `RME-${createUlid(now.getTime())}`,
|
|
@@ -832,6 +841,8 @@ export function assertGuardedRemediationAttemptAllowed(store, task, stepId, plan
|
|
|
832
841
|
recoveredDecisionEventId,
|
|
833
842
|
reboundStopOverrideDecisionEventId,
|
|
834
843
|
overriddenStopDecisionEventIds: stopEscalateOverrideDecisionEventIds(store, task),
|
|
844
|
+
priorRemediationEvents: history.priorRemediationEvents,
|
|
845
|
+
nextAttemptOrdinal: history.nextAttemptOrdinal,
|
|
835
846
|
});
|
|
836
847
|
}
|
|
837
848
|
export function readGuardedRemediationPostureForStep(store, task, stepId, planRiskAudit) {
|
|
@@ -849,12 +860,16 @@ export function readGuardedRemediationPostureForStep(store, task, stepId, planRi
|
|
|
849
860
|
const earlyPlanIntegrityDecision = remediationEvents.length === 1
|
|
850
861
|
? findCurrentCorrectiveDecision(task, stepId, 2, history.correctiveDecisions)
|
|
851
862
|
: null;
|
|
863
|
+
const currentDecision = findCurrentCorrectiveDecision(task, stepId, history.nextAttemptOrdinal, history.correctiveDecisions);
|
|
852
864
|
if (remediationEvents.length < 2 && earlyPlanIntegrityDecision?.recoveryBasis !== 'plan-integrity'
|
|
853
|
-
&&
|
|
865
|
+
&& currentDecision === null
|
|
866
|
+
&& deriveCurrentCauseDecision(remediationEvents, history.priorRemediationEvents) !== 'root-cause-replan')
|
|
854
867
|
return null;
|
|
855
868
|
if (step.status === 'failed' || step.status === 'planned') {
|
|
856
869
|
return deriveAttemptGateFromHistory(task, stepId, planRiskAudit, remediationEvents, history.correctiveDecisions, {
|
|
857
870
|
overriddenStopDecisionEventIds: stopEscalateOverrideDecisionEventIds(store, task),
|
|
871
|
+
priorRemediationEvents: history.priorRemediationEvents,
|
|
872
|
+
nextAttemptOrdinal: history.nextAttemptOrdinal,
|
|
858
873
|
});
|
|
859
874
|
}
|
|
860
875
|
if (task.status !== 'blocked' || step.status !== 'in_progress' || !step.evidence)
|
|
@@ -864,19 +879,99 @@ export function readGuardedRemediationPostureForStep(store, task, stepId, planRi
|
|
|
864
879
|
return null;
|
|
865
880
|
return deriveAttemptGateFromHistory(task, stepId, planRiskAudit, remediationEvents, history.correctiveDecisions, {
|
|
866
881
|
overriddenStopDecisionEventIds: stopEscalateOverrideDecisionEventIds(store, task),
|
|
882
|
+
priorRemediationEvents: history.priorRemediationEvents,
|
|
883
|
+
nextAttemptOrdinal: history.nextAttemptOrdinal,
|
|
867
884
|
});
|
|
868
885
|
}
|
|
869
886
|
function readOpenGuardedRemediationHistory(store, task, stepId) {
|
|
870
|
-
const
|
|
871
|
-
const
|
|
887
|
+
const allStepRemediations = readRemediationEvents(store, task).filter((event) => event.stepId === stepId);
|
|
888
|
+
const allStepDecisions = readCorrectiveDecisionEvents(store, task).filter((event) => event.stepId === stepId);
|
|
872
889
|
const passedBoundary = latestPassedVerifiedStepReviewEvent(store, task, stepId);
|
|
873
|
-
|
|
874
|
-
|
|
890
|
+
const remediationEvents = passedBoundary
|
|
891
|
+
? allStepRemediations.filter((event) => event.recordedAt > passedBoundary.recordedAt)
|
|
892
|
+
: allStepRemediations;
|
|
893
|
+
const correctiveDecisions = passedBoundary
|
|
894
|
+
? allStepDecisions.filter((event) => event.recordedAt > passedBoundary.recordedAt)
|
|
895
|
+
: allStepDecisions;
|
|
875
896
|
return {
|
|
876
|
-
|
|
877
|
-
|
|
897
|
+
...selectCurrentPlanRemediationCycle(store, task, remediationEvents, correctiveDecisions),
|
|
898
|
+
nextAttemptOrdinal: allStepRemediations.length + 1,
|
|
878
899
|
};
|
|
879
900
|
}
|
|
901
|
+
function selectCurrentPlanRemediationCycle(store, task, remediationEvents, correctiveDecisions) {
|
|
902
|
+
const unchanged = () => ({
|
|
903
|
+
remediationEvents: [...remediationEvents],
|
|
904
|
+
priorRemediationEvents: [],
|
|
905
|
+
correctiveDecisions: [...correctiveDecisions],
|
|
906
|
+
});
|
|
907
|
+
if (remediationEvents.length === 0 || !task.planHash)
|
|
908
|
+
return unchanged();
|
|
909
|
+
const audits = readPlanRiskAuditEvents(store, task);
|
|
910
|
+
const currentAudit = [...audits].reverse().find((event) => event.planHash === task.planHash
|
|
911
|
+
&& event.taskRevision <= task.revision
|
|
912
|
+
&& event.decision !== 'split-required'
|
|
913
|
+
&& event.decision !== 'stop-escalate') ?? null;
|
|
914
|
+
if (!currentAudit)
|
|
915
|
+
return unchanged();
|
|
916
|
+
const taskRoot = store.taskRoot(task.projectId, task.id);
|
|
917
|
+
let currentSemanticHash;
|
|
918
|
+
try {
|
|
919
|
+
currentSemanticHash = normalizePlanKnowledgeBinding(readVerifiedPlanArtifact(taskRoot, task.planHash, task.planHash), 'current').semanticHash;
|
|
920
|
+
}
|
|
921
|
+
catch {
|
|
922
|
+
return unchanged();
|
|
923
|
+
}
|
|
924
|
+
const reviews = readStepReviewEvents(store, task);
|
|
925
|
+
const bindings = remediationEvents.map((event) => resolveRemediationPlanCycleBinding(taskRoot, task.planHash, event, reviews, audits));
|
|
926
|
+
if (bindings.some((binding) => binding === null))
|
|
927
|
+
return unchanged();
|
|
928
|
+
let cycleStart = remediationEvents.length;
|
|
929
|
+
while (cycleStart > 0 && bindings[cycleStart - 1].semanticHash === currentSemanticHash)
|
|
930
|
+
cycleStart -= 1;
|
|
931
|
+
if (cycleStart === remediationEvents.length
|
|
932
|
+
&& currentAudit.taskRevision <= bindings.at(-1).sourceTaskRevision)
|
|
933
|
+
return unchanged();
|
|
934
|
+
return {
|
|
935
|
+
remediationEvents: remediationEvents.slice(cycleStart),
|
|
936
|
+
priorRemediationEvents: remediationEvents.slice(0, cycleStart),
|
|
937
|
+
// Corrective decisions remain globally authoritative. The semantic cycle scopes
|
|
938
|
+
// cause counting only; filtering decisions could discard stop/split authority.
|
|
939
|
+
correctiveDecisions: [...correctiveDecisions],
|
|
940
|
+
};
|
|
941
|
+
}
|
|
942
|
+
function resolveRemediationPlanCycleBinding(taskRoot, currentPlanHash, event, reviews, audits) {
|
|
943
|
+
let planHash = null;
|
|
944
|
+
let sourceTaskRevision = null;
|
|
945
|
+
if (event.failureEvidence.reviewEventHash) {
|
|
946
|
+
const review = reviews.find((candidate) => candidate.eventHash === event.failureEvidence.reviewEventHash) ?? null;
|
|
947
|
+
if (!review)
|
|
948
|
+
return null;
|
|
949
|
+
planHash = review.planHash;
|
|
950
|
+
sourceTaskRevision = review.taskRevision;
|
|
951
|
+
}
|
|
952
|
+
else if (event.failureEvidence.executionTaskRevision !== undefined) {
|
|
953
|
+
sourceTaskRevision = event.failureEvidence.executionTaskRevision;
|
|
954
|
+
planHash = [...audits].reverse().find((audit) => audit.taskRevision <= sourceTaskRevision)?.planHash ?? null;
|
|
955
|
+
}
|
|
956
|
+
if (!planHash || sourceTaskRevision === null
|
|
957
|
+
|| !audits.some((audit) => audit.planHash === planHash && audit.taskRevision <= sourceTaskRevision))
|
|
958
|
+
return null;
|
|
959
|
+
try {
|
|
960
|
+
return {
|
|
961
|
+
semanticHash: normalizePlanKnowledgeBinding(readVerifiedPlanArtifact(taskRoot, planHash, currentPlanHash), 'remediation ' + event.eventId).semanticHash,
|
|
962
|
+
planHash,
|
|
963
|
+
sourceTaskRevision,
|
|
964
|
+
};
|
|
965
|
+
}
|
|
966
|
+
catch {
|
|
967
|
+
return null;
|
|
968
|
+
}
|
|
969
|
+
}
|
|
970
|
+
export function deriveCurrentCauseDecisionForTask(store, task, stepId, remediationEvents) {
|
|
971
|
+
const decisions = readCorrectiveDecisionEvents(store, task).filter((event) => event.stepId === stepId);
|
|
972
|
+
const cycle = selectCurrentPlanRemediationCycle(store, task, remediationEvents, decisions);
|
|
973
|
+
return deriveCurrentCauseDecision(cycle.remediationEvents, cycle.priorRemediationEvents);
|
|
974
|
+
}
|
|
880
975
|
export function findCurrentGuardedRemediationPosture(store, task, planRiskAudit) {
|
|
881
976
|
const matches = planRiskAudit.reviewRequiredStepIds
|
|
882
977
|
.map((stepId) => readGuardedRemediationPostureForStep(store, task, stepId, planRiskAudit))
|
|
@@ -900,10 +995,10 @@ export function findFailedGuardedStepRequiringCorrectiveDecision(store, task, pl
|
|
|
900
995
|
: null;
|
|
901
996
|
}
|
|
902
997
|
function deriveAttemptGateFromHistory(task, stepId, planRiskAudit, remediationEvents, correctiveDecisions, options = {}) {
|
|
903
|
-
const attemptCount = remediationEvents.length;
|
|
904
|
-
const nextAttemptOrdinal = attemptCount + 1;
|
|
998
|
+
const attemptCount = remediationEvents.length + (options.priorRemediationEvents?.length ?? 0);
|
|
999
|
+
const nextAttemptOrdinal = options.nextAttemptOrdinal ?? attemptCount + 1;
|
|
905
1000
|
const guardedCategory = requireGuardedCategory(planRiskAudit, stepId);
|
|
906
|
-
const rollingCauseDecision = deriveCurrentCauseDecision(remediationEvents);
|
|
1001
|
+
const rollingCauseDecision = deriveCurrentCauseDecision(remediationEvents, options.priorRemediationEvents ?? []);
|
|
907
1002
|
const currentCorrectiveDecision = findCurrentCorrectiveDecision(task, stepId, nextAttemptOrdinal, correctiveDecisions);
|
|
908
1003
|
const planIntegrityDecision = currentCorrectiveDecision;
|
|
909
1004
|
if (planIntegrityDecision?.recoveryBasis === 'plan-integrity'
|
|
@@ -1075,17 +1170,22 @@ function deriveAttemptGateFromHistory(task, stepId, planRiskAudit, remediationEv
|
|
|
1075
1170
|
// Current execution must respect a proved Plan obstruction immediately. Keep the
|
|
1076
1171
|
// historical rolling classifier unchanged: older valid histories may have been
|
|
1077
1172
|
// recorded before this gate existed and must not be reclassified as corrupt.
|
|
1078
|
-
export function deriveCurrentCauseDecision(remediationEvents) {
|
|
1173
|
+
export function deriveCurrentCauseDecision(remediationEvents, priorRemediationEvents = []) {
|
|
1174
|
+
// A verified replacement clears the active cause, not the global attempt
|
|
1175
|
+
// count or an explicit corrective decision's dirty-work continuation authority.
|
|
1176
|
+
if (remediationEvents.length === 0 && priorRemediationEvents.length > 0
|
|
1177
|
+
&& priorRemediationEvents.every((event) => event.causeBindings !== undefined))
|
|
1178
|
+
return 'same-task-fix';
|
|
1079
1179
|
if (remediationEvents.at(-1)?.causeBindings?.some(cause => cause.authority === 'external-reviewer' && cause.planConflict))
|
|
1080
1180
|
return 'root-cause-replan';
|
|
1081
|
-
return deriveRollingCauseDecision(remediationEvents);
|
|
1181
|
+
return deriveRollingCauseDecision(remediationEvents, priorRemediationEvents);
|
|
1082
1182
|
}
|
|
1083
|
-
export function deriveRollingCauseDecision(remediationEvents) {
|
|
1183
|
+
export function deriveRollingCauseDecision(remediationEvents, priorRemediationEvents = []) {
|
|
1084
1184
|
if (remediationEvents.length === 0 || remediationEvents.some((event) => event.causeBindings === undefined))
|
|
1085
1185
|
return null;
|
|
1086
1186
|
const latest = remediationEvents.at(-1);
|
|
1087
|
-
const priorFingerprints = new Set(remediationEvents.slice(0, -1)
|
|
1088
|
-
.flatMap((event) => event.causeBindings
|
|
1187
|
+
const priorFingerprints = new Set([...priorRemediationEvents, ...remediationEvents.slice(0, -1)]
|
|
1188
|
+
.flatMap((event) => event.causeBindings?.map((cause) => cause.causeFingerprint) ?? []));
|
|
1089
1189
|
const authoritativeRepeat = latest.causeBindings.some((cause) => priorFingerprints.has(cause.causeFingerprint)
|
|
1090
1190
|
&& (cause.authority === 'mechanical' || (cause.authority === 'external-reviewer' && cause.planConflict)));
|
|
1091
1191
|
return authoritativeRepeat ? 'root-cause-replan' : 'same-task-fix';
|
|
@@ -1995,10 +2095,36 @@ function validateCorrectiveDecisionCoverage(task, decisions, remediationEvents)
|
|
|
1995
2095
|
}
|
|
1996
2096
|
}
|
|
1997
2097
|
}
|
|
1998
|
-
function validateHistoricalRemediationModes(task, stepId, remediationEvents, correctiveDecisions, recoveredEventIds, overriddenStopDecisionEventIds) {
|
|
2098
|
+
function validateHistoricalRemediationModes(store, task, stepId, remediationEvents, correctiveDecisions, recoveredEventIds, overriddenStopDecisionEventIds) {
|
|
1999
2099
|
const causeAwareHistory = remediationEvents.length > 0
|
|
2000
2100
|
&& remediationEvents.every((event) => event.causeBindings !== undefined);
|
|
2001
2101
|
if (causeAwareHistory) {
|
|
2102
|
+
const audits = readPlanRiskAuditEvents(store, task);
|
|
2103
|
+
const reviews = readStepReviewEvents(store, task);
|
|
2104
|
+
const taskRoot = store.taskRoot(task.projectId, task.id);
|
|
2105
|
+
const cycleBindings = task.planHash
|
|
2106
|
+
? remediationEvents.map((event) => resolveRemediationPlanCycleBinding(taskRoot, task.planHash, event, reviews, audits))
|
|
2107
|
+
: remediationEvents.map(() => null);
|
|
2108
|
+
if (cycleBindings.every((binding) => binding !== null)) {
|
|
2109
|
+
let cycleStart = 0;
|
|
2110
|
+
for (let index = 0; index < remediationEvents.length; index += 1) {
|
|
2111
|
+
if (index > 0 && cycleBindings[index].semanticHash !== cycleBindings[index - 1].semanticHash) {
|
|
2112
|
+
cycleStart = index;
|
|
2113
|
+
}
|
|
2114
|
+
const cyclePrefix = remediationEvents.slice(cycleStart, index + 1);
|
|
2115
|
+
const priorCycles = remediationEvents.slice(0, cycleStart);
|
|
2116
|
+
if (deriveRollingCauseDecision(cyclePrefix, priorCycles) === 'root-cause-replan'
|
|
2117
|
+
&& index < remediationEvents.length - 1
|
|
2118
|
+
&& cycleBindings[index + 1].semanticHash === cycleBindings[index].semanticHash) {
|
|
2119
|
+
throw new WorkflowError('STATE_CORRUPT', 'Remediation continued after an authoritative cause required semantic replan.', {
|
|
2120
|
+
taskId: task.id,
|
|
2121
|
+
stepId,
|
|
2122
|
+
eventId: remediationEvents[index].eventId,
|
|
2123
|
+
});
|
|
2124
|
+
}
|
|
2125
|
+
}
|
|
2126
|
+
return;
|
|
2127
|
+
}
|
|
2002
2128
|
for (let index = 0; index < remediationEvents.length; index += 1) {
|
|
2003
2129
|
const prefix = remediationEvents.slice(0, index + 1);
|
|
2004
2130
|
if (deriveRollingCauseDecision(prefix) === 'root-cause-replan' && index < remediationEvents.length - 1) {
|
|
@@ -2053,13 +2179,13 @@ function validateHistoricalRemediationModes(task, stepId, remediationEvents, cor
|
|
|
2053
2179
|
}
|
|
2054
2180
|
}
|
|
2055
2181
|
}
|
|
2056
|
-
function validateHistoricalRemediationModesForAllSteps(task, remediationEvents, correctiveDecisions, recoveredEventIds, overriddenStopDecisionEventIds) {
|
|
2182
|
+
function validateHistoricalRemediationModesForAllSteps(store, task, remediationEvents, correctiveDecisions, recoveredEventIds, overriddenStopDecisionEventIds) {
|
|
2057
2183
|
const stepIds = new Set(remediationEvents.map((event) => event.stepId));
|
|
2058
2184
|
for (const stepId of stepIds) {
|
|
2059
2185
|
const stepEvents = remediationEvents
|
|
2060
2186
|
.filter((event) => event.stepId === stepId)
|
|
2061
2187
|
.sort((left, right) => left.attemptOrdinal - right.attemptOrdinal);
|
|
2062
|
-
validateHistoricalRemediationModes(task, stepId, stepEvents, correctiveDecisions, recoveredEventIds, overriddenStopDecisionEventIds);
|
|
2188
|
+
validateHistoricalRemediationModes(store, task, stepId, stepEvents, correctiveDecisions, recoveredEventIds, overriddenStopDecisionEventIds);
|
|
2063
2189
|
}
|
|
2064
2190
|
}
|
|
2065
2191
|
function validateCorrectiveDecisionAudit(audit) {
|