codex-workflow-v2 2.0.0-beta.12 → 2.0.0-beta.12.2

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 (33) hide show
  1. package/README.md +5 -3
  2. package/dist/src/alpha6/remediation.d.ts +8 -3
  3. package/dist/src/alpha6/remediation.js +374 -9
  4. package/dist/src/alpha6/remediation.js.map +1 -1
  5. package/dist/src/alpha7/corrective-recovery.d.ts +8 -1
  6. package/dist/src/alpha7/corrective-recovery.js +144 -26
  7. package/dist/src/alpha7/corrective-recovery.js.map +1 -1
  8. package/dist/src/cli.js +19 -0
  9. package/dist/src/cli.js.map +1 -1
  10. package/dist/src/contracts.d.ts +42 -0
  11. package/dist/src/dependency-provenance.js +5 -3
  12. package/dist/src/dependency-provenance.js.map +1 -1
  13. package/dist/src/version.d.ts +1 -1
  14. package/dist/src/version.js +1 -1
  15. package/dist/src/version.js.map +1 -1
  16. package/dist/src/workflow.d.ts +5 -1
  17. package/dist/src/workflow.js +158 -19
  18. package/dist/src/workflow.js.map +1 -1
  19. package/docs/autonomy-guardrails.md +35 -1
  20. package/docs/pdf/codex-workflow-v2-architecture-ru.pdf +0 -0
  21. package/docs/pdf/codex-workflow-v2-chat-only-guide-ru.pdf +0 -0
  22. package/docs/pdf/codex-workflow-v2-technical-reference-ru.pdf +0 -0
  23. package/docs/pdf/sources/codex-workflow-v2-architecture-ru.md +23 -5
  24. package/docs/pdf/sources/codex-workflow-v2-chat-only-guide-ru.md +17 -8
  25. package/docs/pdf/sources/codex-workflow-v2-technical-reference-ru.md +32 -14
  26. package/docs/release.md +9 -1
  27. package/docs/updating-existing-project.md +38 -0
  28. package/docs/validation-report.md +84 -80
  29. package/package.json +1 -1
  30. package/plugins/codex-workflow-gateway/.codex-plugin/plugin.json +1 -1
  31. package/plugins/codex-workflow-gateway/references/protocol.md +21 -1
  32. package/plugins/codex-workflow-gateway/skills/codex-workflow-gateway/SKILL.md +24 -0
  33. package/schemas/stop-escalate-override-event.schema.json +45 -0
@@ -13,14 +13,14 @@ import { inspectLocalDependency, inspectWorkflowVersions } from './diagnostics.j
13
13
  import { appendTaskClaim, appendTaskHandback, appendTaskHandoff, appendTaskWriterCredentialReplacement, assertTaskClaimAllowed, assertTaskMutationAllowedByC1, defaultTaskWorkerActor, readTaskC1Posture, } from './alpha6/handoff.js';
14
14
  import { applyAdoptionPosture, assertAdoptionBaselinePreserved, buildAdoptionPreparation, initializeProjectRegistrationAdoption, readCurrentAdoptionPosture, } from './alpha6/adoption.js';
15
15
  import { appendCurrentPlanRiskAudit, appendReboundPlanRiskAudit, readCurrentPlanRiskAudit, validatePlanRiskAuditCandidate, } from './alpha6/plan-risk.js';
16
- import { appendCorrectiveDecisionEvent, appendPlanIntegrityRecoveryDecision, appendRemediationEvent, appendRemediationModeRecovery, assertCorrectiveAuditorIndependence, assertGuardedRemediationAttemptAllowed, defaultCorrectiveAuditorActor, findCurrentGuardedRemediationPosture, findRemediationModeRecoveryCandidate, findFailedGuardedStepRequiringCorrectiveDecision, readGuardedRemediationPostureForStep, readCorrectiveDecisionEvents, readRemediationEvents, } from './alpha6/remediation.js';
16
+ import { appendCorrectiveDecisionEvent, appendPlanIntegrityRecoveryDecision, appendRemediationEvent, appendRemediationModeRecovery, appendStopEscalateOverride, assertCorrectiveAuditorIndependence, assertGuardedRemediationAttemptAllowed, defaultCorrectiveAuditorActor, findCurrentGuardedRemediationPosture, findRemediationModeRecoveryCandidate, findFailedGuardedStepRequiringCorrectiveDecision, readGuardedRemediationPostureForStep, readCorrectiveDecisionEvents, readRemediationEvents, prepareStopEscalateOverride, stopEscalateOverrideDecisionEventIds, } from './alpha6/remediation.js';
17
17
  import { assessPlanIntegrityRecovery, defaultPlanIntegrityRecoveryActor, } from './alpha6/plan-integrity.js';
18
18
  import { assertMechanicalFeasibilityFresh, evaluateMechanicalFeasibility, hashMechanicalFeasibilityEvidence, } from './alpha6/mechanical-feasibility.js';
19
19
  import { assessMilestoneInitialAssembly, applyInitialMilestonePlanTransaction, applyMilestoneScopeChangeTransaction, assertMilestoneDependenciesDeclared, assertMilestoneTaskRunnable, assessMilestoneTaskDependencies, assertMilestoneMembershipIntegrity, assertMilestoneScopeChangeStatusAllowed, inspectMilestoneWithIntegrity, normalizeMilestonePlan, prepareMilestoneScopeChangeCandidate, prepareMilestoneScopeChangeBundle, readMilestoneForScopeChange, readMilestoneWithIntegrity, } from './alpha6/milestone.js';
20
20
  import { applyProjectTransaction, recoverProjectTransactions, runRollbackProjectTransaction, } from './beta1/project-transaction.js';
21
21
  import { buildCurrentStrictStepReviewCycle, countUnverifiedStrictStepReviews, ensurePendingStrictStepReview, isStepReviewRequired, latestFailedStepReviewRouting, latestPassedVerifiedStepReviewEvent, recordStrictStepReview, verifiedHistoricalStepReviewCommits, } from './alpha6/review.js';
22
22
  import { applyMilestoneAutonomyContract, assertAutonomousPlanEvolution, prepareMilestoneAutonomyContract, readMilestoneAutonomyEvents, requireActiveMilestoneAutonomy, } from './alpha7/autonomy.js';
23
- import { appendCorrectiveDecisionRecovery, readValidatedCorrectiveDecisionRecoveryForNavigation, requireCorrectiveDecisionRecoveryForRun, } from './alpha7/corrective-recovery.js';
23
+ import { appendCorrectiveDecisionRecovery, readValidatedCorrectiveDecisionRecoveryForNavigation, readValidatedStopOverrideContextRebindIfApplicable, requireCorrectiveDecisionRecoveryForRun, } from './alpha7/corrective-recovery.js';
24
24
  import { applyKnowledgeSelections, hashKnowledgeMap, inspectKnowledgeMap, normalizeRelativePath, reconcileKnowledgeMap, scanProjectKnowledge, selectKnowledgeSources, } from './memory.js';
25
25
  import { canonicalJsonStringify, sha256Hex } from './alpha6/store-sidecars.js';
26
26
  import { ensureDirectory } from './fs-utils.js';
@@ -110,6 +110,31 @@ export class WorkflowService {
110
110
  repaired: true,
111
111
  };
112
112
  }
113
+ prepareTaskStopOverride(repository, taskId, stepId, expectedRevision, actor, reason) {
114
+ const snapshot = this.observationSnapshot(repository);
115
+ if (snapshot.observation.kind !== 'assessment') {
116
+ throw new WorkflowError('TRANSITION_BLOCKED', 'Stop override requires a coherent observation boundary.', {
117
+ observation: snapshot.observation,
118
+ });
119
+ }
120
+ const task = snapshot.tasks.find((candidate) => candidate.id === taskId) ?? null;
121
+ if (!task)
122
+ throw new WorkflowError('NOT_FOUND', `Task ${taskId} was not found in this repository.`);
123
+ this.assertStopOverrideRepositoryBoundary(snapshot.identity, task);
124
+ return prepareStopEscalateOverride(this.store, task, stepId, expectedRevision, actor, reason, headCommit(snapshot.identity.repositoryRoot));
125
+ }
126
+ applyTaskStopOverride(repository, taskId, stepId, expectedRevision, actor, reason, confirmationCode) {
127
+ const snapshot = this.observationSnapshot(repository);
128
+ if (snapshot.observation.kind !== 'assessment') {
129
+ throw new WorkflowError('TRANSITION_BLOCKED', 'Stop override requires a coherent observation boundary.', {
130
+ observation: snapshot.observation,
131
+ });
132
+ }
133
+ const context = this.#mutationContext(repository);
134
+ const task = context.store.readTask(context.identity.projectId, taskId);
135
+ this.assertStopOverrideRepositoryBoundary(context.identity, task, context.locks.list());
136
+ return appendStopEscalateOverride(context.store, task, stepId, expectedRevision, actor, reason, headCommit(context.identity.repositoryRoot), confirmationCode, this.now());
137
+ }
113
138
  prepareCorrectiveReplan(repository, taskId, candidate) {
114
139
  return this.correctiveReplanController(repository).prepare({ taskId, candidate });
115
140
  }
@@ -1038,7 +1063,9 @@ export class WorkflowService {
1038
1063
  const passedBoundary = latestPassedVerifiedStepReviewEvent(this.store, task, event.stepId);
1039
1064
  return !passedBoundary || passedBoundary.recordedAt <= event.recordedAt;
1040
1065
  });
1041
- const currentHardBlockingDecisions = currentPlanCorrectiveDecisions.filter((event) => event.decision === 'split-required' || event.decision === 'stop-escalate');
1066
+ const overriddenStopDecisionEventIds = stopEscalateOverrideDecisionEventIds(this.store, task);
1067
+ const currentHardBlockingDecisions = currentPlanCorrectiveDecisions.filter((event) => event.decision === 'split-required'
1068
+ || (event.decision === 'stop-escalate' && !overriddenStopDecisionEventIds.has(event.eventId)));
1042
1069
  const currentPlanRiskAudit = task.status === 'needs_fix' || currentReplanDecisions.length > 0
1043
1070
  ? readCurrentPlanRiskAudit(this.store, task)
1044
1071
  : null;
@@ -1758,8 +1785,11 @@ export class WorkflowService {
1758
1785
  throw new WorkflowError('TRANSITION_BLOCKED', `Task ${taskId} cannot run a Step while ${task.status}.`);
1759
1786
  }
1760
1787
  this.assertExecutionAuthorizationFresh(task, context.identity.repositoryRoot);
1788
+ const overriddenStopDecisionEventIds = stopEscalateOverrideDecisionEventIds(this.store, task);
1761
1789
  const currentPlanBlockingDecisions = readCorrectiveDecisionEvents(this.store, task)
1762
- .filter((event) => event.planHash === task.planHash && event.decision !== 'continue-fix');
1790
+ .filter((event) => event.planHash === task.planHash
1791
+ && event.decision !== 'continue-fix'
1792
+ && !(event.decision === 'stop-escalate' && overriddenStopDecisionEventIds.has(event.eventId)));
1763
1793
  if (currentPlanBlockingDecisions.length > 0) {
1764
1794
  throw new WorkflowError('TRANSITION_BLOCKED', `Task ${taskId} cannot run any Step while the current Plan has active blocking corrective decisions.`, {
1765
1795
  taskId,
@@ -1797,7 +1827,10 @@ export class WorkflowService {
1797
1827
  const recovery = staleDecision?.decision === 'continue-fix'
1798
1828
  ? requireCorrectiveDecisionRecoveryForRun(this.store, task, stepId, actor, writerToken)
1799
1829
  : null;
1800
- const gate = assertGuardedRemediationAttemptAllowed(this.store, task, stepId, planRiskAudit, recovery?.correctiveDecisionEventId ?? null);
1830
+ const stopOverrideContextRebind = staleDecision?.decision === 'stop-escalate'
1831
+ ? readValidatedStopOverrideContextRebindIfApplicable(this.store, task, stepId)
1832
+ : null;
1833
+ const gate = assertGuardedRemediationAttemptAllowed(this.store, task, stepId, planRiskAudit, recovery?.correctiveDecisionEventId ?? null, stopOverrideContextRebind?.stopDecision.eventId ?? null);
1801
1834
  resumesCorrectiveReplan = gate.posture === 'replan-ready';
1802
1835
  }
1803
1836
  const knowledgeMap = this.assertTaskKnowledgeBinding(context.identity.repositoryRoot, task);
@@ -2035,7 +2068,7 @@ export class WorkflowService {
2035
2068
  checksHash: sha256Hex(canonicalJsonStringify(checks)),
2036
2069
  reviewEventHash: null,
2037
2070
  reviewerAttestationHash: null,
2038
- }, planRiskAudit, this.now());
2071
+ }, planRiskAudit, this.now(), this.stopOverrideContextRebindDecisionId(task, stepId));
2039
2072
  }
2040
2073
  const steps = task.steps.map((candidate) => candidate.id === stepId ? { ...candidate, status: 'failed' } : candidate);
2041
2074
  return this.store.writeTask({ ...task, status: 'needs_fix', steps, blockReason: `${stepId} checks failed.` }, expectedRevision);
@@ -2155,7 +2188,7 @@ export class WorkflowService {
2155
2188
  checksHash: currentCycle.reviewRecordedEvent.checksHash,
2156
2189
  reviewEventHash: currentCycle.reviewRecordedEvent.eventHash,
2157
2190
  reviewerAttestationHash: currentCycle.reviewerAttestationEvent.eventHash,
2158
- }, planRiskAudit, this.now());
2191
+ }, planRiskAudit, this.now(), this.stopOverrideContextRebindDecisionId(task, stepId));
2159
2192
  }
2160
2193
  return this.store.writeTask(applyStrictStepReviewResolution(task, stepId, currentCycle.resolution), expectedRevision);
2161
2194
  }
@@ -2183,7 +2216,7 @@ export class WorkflowService {
2183
2216
  checksHash: reviewRecordedEvent.checksHash,
2184
2217
  reviewEventHash: reviewRecordedEvent.eventHash,
2185
2218
  reviewerAttestationHash: reviewerAttestationEvent.eventHash,
2186
- }, planRiskAudit, this.now());
2219
+ }, planRiskAudit, this.now(), this.stopOverrideContextRebindDecisionId(task, stepId));
2187
2220
  }
2188
2221
  return this.store.writeTask(applyStrictStepReviewResolution(task, stepId, recorded.resolution, launch.review.summary), expectedRevision);
2189
2222
  }
@@ -2255,7 +2288,7 @@ export class WorkflowService {
2255
2288
  checksHash: recorded.reviewRecordedEvent.checksHash,
2256
2289
  reviewEventHash: recorded.reviewRecordedEvent.eventHash,
2257
2290
  reviewerAttestationHash: recorded.reviewerAttestationEvent.eventHash,
2258
- }, readCurrentPlanRiskAudit(this.store, task), this.now());
2291
+ }, readCurrentPlanRiskAudit(this.store, task), this.now(), this.stopOverrideContextRebindDecisionId(task, stepId));
2259
2292
  }
2260
2293
  const saved = this.store.writeTask(applyStrictStepReviewResolution(task, stepId, recorded.resolution, review.summary), expectedRevision);
2261
2294
  return {
@@ -3926,6 +3959,39 @@ export class WorkflowService {
3926
3959
  case 'decision-required':
3927
3960
  if (guardedCorrectivePosture.correctiveDecision
3928
3961
  && guardedCorrectivePosture.correctiveDecision.planHash !== task.planHash) {
3962
+ if (guardedCorrectivePosture.correctiveDecision.decision === 'stop-escalate') {
3963
+ try {
3964
+ const assessment = readValidatedStopOverrideContextRebindIfApplicable(this.store, task, guardedCorrectivePosture.stepId);
3965
+ if (!assessment) {
3966
+ throw new WorkflowError('TRANSITION_BLOCKED', 'Stale stop decision has no validated stop-override context-rebind continuation.');
3967
+ }
3968
+ guardedCorrectiveOverlay = {
3969
+ action: 'task run',
3970
+ stepId: guardedCorrectivePosture.stepId,
3971
+ stopOverrideContextRebind: {
3972
+ state: 'validated',
3973
+ overrideEventId: assessment.override.eventId,
3974
+ stopDecisionEventId: assessment.stopDecision.eventId,
3975
+ sourcePlanHash: assessment.override.planHash,
3976
+ reboundPlanHash: task.planHash,
3977
+ semanticPlanHash: assessment.semanticPlanHash,
3978
+ appendOnly: true,
3979
+ },
3980
+ };
3981
+ }
3982
+ catch (error) {
3983
+ guardedCorrectiveOverlay = {
3984
+ action: 'doctor',
3985
+ stepId: guardedCorrectivePosture.stepId,
3986
+ blockedAction: 'task run',
3987
+ stopOverrideContextRebind: {
3988
+ state: 'blocked',
3989
+ reason: error instanceof Error ? error.message : String(error),
3990
+ },
3991
+ };
3992
+ }
3993
+ break;
3994
+ }
3929
3995
  try {
3930
3996
  const navigation = readValidatedCorrectiveDecisionRecoveryForNavigation(this.store, task, guardedCorrectivePosture.stepId);
3931
3997
  guardedCorrectiveOverlay = navigation.recovery
@@ -4039,16 +4105,50 @@ export class WorkflowService {
4039
4105
  }
4040
4106
  break;
4041
4107
  case 'stop-escalate':
4042
- guardedCorrectiveOverlay = {
4043
- action: 'doctor',
4044
- stepId: guardedCorrectivePosture.stepId,
4045
- correctiveDecisionGate: {
4046
- attemptCount: guardedCorrectivePosture.attemptCount,
4047
- decision: guardedCorrectivePosture.correctiveDecision?.decision ?? null,
4048
- decisionEventId: guardedCorrectivePosture.correctiveDecision?.eventId ?? null,
4049
- humanApprovalRequired: false,
4050
- },
4051
- };
4108
+ try {
4109
+ this.assertStopOverrideRepositoryBoundary(resolveRepositoryIdentity(repositoryRoot), task);
4110
+ prepareStopEscalateOverride(this.store, task, guardedCorrectivePosture.stepId, task.revision, 'user', 'navigation eligibility probe', headCommit(repositoryRoot));
4111
+ guardedCorrectiveOverlay = {
4112
+ action: 'task stop-override-prepare',
4113
+ blockedAction: 'task run',
4114
+ stepId: guardedCorrectivePosture.stepId,
4115
+ correctiveDecisionGate: {
4116
+ attemptCount: guardedCorrectivePosture.attemptCount,
4117
+ decision: guardedCorrectivePosture.correctiveDecision?.decision ?? null,
4118
+ decisionEventId: guardedCorrectivePosture.correctiveDecision?.eventId ?? null,
4119
+ humanApprovalRequired: true,
4120
+ delegatedApprovalAllowed: false,
4121
+ },
4122
+ stopOverride: {
4123
+ state: 'eligible',
4124
+ policy: 'beta11-attempt4-stop-compatibility-v1',
4125
+ prepareCommand: 'task stop-override-prepare',
4126
+ applyCommand: 'task stop-override-apply',
4127
+ expectedRevision: task.revision,
4128
+ appendOnly: true,
4129
+ preservesOriginalDecision: true,
4130
+ requiredAction: 'Prepare with an explicit human actor and reason, then apply the exact confirmation code in a later user turn.',
4131
+ },
4132
+ };
4133
+ }
4134
+ catch (error) {
4135
+ guardedCorrectiveOverlay = {
4136
+ action: 'doctor',
4137
+ blockedAction: 'task stop-override-prepare',
4138
+ stepId: guardedCorrectivePosture.stepId,
4139
+ correctiveDecisionGate: {
4140
+ attemptCount: guardedCorrectivePosture.attemptCount,
4141
+ decision: guardedCorrectivePosture.correctiveDecision?.decision ?? null,
4142
+ decisionEventId: guardedCorrectivePosture.correctiveDecision?.eventId ?? null,
4143
+ humanApprovalRequired: true,
4144
+ },
4145
+ stopOverride: {
4146
+ state: 'blocked',
4147
+ policy: 'beta11-attempt4-stop-compatibility-v1',
4148
+ reason: error instanceof Error ? error.message : String(error),
4149
+ },
4150
+ };
4151
+ }
4052
4152
  break;
4053
4153
  default:
4054
4154
  break;
@@ -4170,6 +4270,9 @@ export class WorkflowService {
4170
4270
  : 'Escalate outside this Task; stop-escalate cannot be resumed or rebound.',
4171
4271
  });
4172
4272
  }
4273
+ stopOverrideContextRebindDecisionId(task, stepId) {
4274
+ return readValidatedStopOverrideContextRebindIfApplicable(this.store, task, stepId)?.stopDecision.eventId ?? null;
4275
+ }
4173
4276
  taskHasTerminalCorrectiveDecision(task) {
4174
4277
  return this.taskTerminalCorrectivePosture(task) !== null;
4175
4278
  }
@@ -4184,6 +4287,42 @@ export class WorkflowService {
4184
4287
  ? posture
4185
4288
  : null;
4186
4289
  }
4290
+ assertStopOverrideRepositoryBoundary(identity, task, observedLeases) {
4291
+ const blockers = [];
4292
+ const dirty = changedFiles(identity.repositoryRoot);
4293
+ if (dirty.length > 0)
4294
+ blockers.push('Repository checkout must be clean.');
4295
+ if (task.workspaceOwner !== 'local')
4296
+ blockers.push('Stop override is limited to a local Task workspace.');
4297
+ if (!task.taskBranch || currentBranch(identity.repositoryRoot) !== task.taskBranch) {
4298
+ blockers.push('The current branch must be the recorded Task branch.');
4299
+ }
4300
+ if (task.steps.some((step) => step.status === 'in_progress'))
4301
+ blockers.push('No Step may be in progress.');
4302
+ const leases = observedLeases
4303
+ ?? new WriterLockManager(this.store.lockRoot(identity.projectId), this.now, this.store.root).list();
4304
+ if (leases.some((lease) => lease.entityId === task.id))
4305
+ blockers.push('No active or stale Task writer lease may exist.');
4306
+ const projectRoot = this.store.projectRoot(identity.projectId);
4307
+ const replanTransactions = inspectCorrectiveReplanTaskTransactions(projectRoot, this.store.root);
4308
+ const yieldTransactions = inspectCorrectiveYieldTaskTransactions(projectRoot, this.store.root);
4309
+ if (replanTransactions.pending.some((transaction) => transaction.taskId === task.id)
4310
+ || replanTransactions.corrupt.some((transaction) => transaction.taskId === task.id)
4311
+ || yieldTransactions.pending.some((transaction) => transaction.taskId === task.id)
4312
+ || yieldTransactions.corrupt.some((transaction) => transaction.taskId === task.id)) {
4313
+ blockers.push('No pending or corrupt Task transaction may exist.');
4314
+ }
4315
+ if (listCoreTaskOperationMutexes(this.store.lockRoot(identity.projectId), this.store.root)
4316
+ .some((operation) => operation.entityId === task.id)) {
4317
+ blockers.push('No Core Task operation may exist.');
4318
+ }
4319
+ if (blockers.length > 0) {
4320
+ throw new WorkflowError('TRANSITION_BLOCKED', 'Stop override repository preconditions are not satisfied.', {
4321
+ taskId: task.id,
4322
+ blockers,
4323
+ });
4324
+ }
4325
+ }
4187
4326
  delegatedApprovalOptions(projectId, transition, target) {
4188
4327
  return this.store.listDelegations(projectId)
4189
4328
  .filter((grant) => {