codex-workflow-v2 2.0.0-beta.12.7 → 2.0.0-beta.12.9
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 +9 -1
- package/dist/src/alpha6/review.d.ts +6 -0
- package/dist/src/alpha6/review.js +12 -0
- package/dist/src/alpha6/review.js.map +1 -1
- package/dist/src/cli.js +37 -3
- package/dist/src/cli.js.map +1 -1
- package/dist/src/contracts.d.ts +37 -1
- package/dist/src/dependency-provenance.d.ts +2 -2
- package/dist/src/dependency-provenance.js +21 -5
- package/dist/src/dependency-provenance.js.map +1 -1
- package/dist/src/git.js +1 -0
- package/dist/src/git.js.map +1 -1
- package/dist/src/historical-step-provenance.d.ts +20 -0
- package/dist/src/historical-step-provenance.js +111 -0
- package/dist/src/historical-step-provenance.js.map +1 -0
- package/dist/src/state/corrective-replan-executor.js +5 -0
- package/dist/src/state/corrective-replan-executor.js.map +1 -1
- package/dist/src/version.d.ts +1 -1
- package/dist/src/version.js +1 -1
- package/dist/src/workflow.d.ts +7 -2
- package/dist/src/workflow.js +206 -11
- 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 +23 -6
- package/docs/pdf/sources/codex-workflow-v2-chat-only-guide-ru.md +28 -28
- package/docs/pdf/sources/codex-workflow-v2-technical-reference-ru.md +41 -26
- package/docs/release.md +9 -1
- package/docs/updating-existing-project.md +30 -0
- package/docs/validation-report.md +90 -96
- package/package.json +1 -1
- package/plugins/codex-workflow-gateway/.codex-plugin/plugin.json +1 -1
- package/plugins/codex-workflow-gateway/references/protocol.md +15 -0
- package/plugins/codex-workflow-gateway/skills/codex-workflow-gateway/SKILL.md +35 -0
- package/schemas/task.schema.json +43 -0
package/dist/src/workflow.js
CHANGED
|
@@ -3,6 +3,7 @@ import { createHash } from 'node:crypto';
|
|
|
3
3
|
import path from 'node:path';
|
|
4
4
|
import { PROTOCOL_VERSION, STATE_SCHEMA_VERSION, } from './contracts.js';
|
|
5
5
|
import { inspectDependencyProvenanceRecovery, } from './dependency-provenance.js';
|
|
6
|
+
import { inspectHistoricalStepProvenanceRecovery, omittedStepEvidenceCommits, } from './historical-step-provenance.js';
|
|
6
7
|
import { renderBrief, renderPlan, renderResult } from './artifacts.js';
|
|
7
8
|
import { assertDelegationCanAuthorize, hashDelegationPolicy, prepareDelegationGrantGate, } from './delegation.js';
|
|
8
9
|
import { assessDiscovery, mergeUnique } from './domain/discovery.js';
|
|
@@ -11,7 +12,7 @@ import { WorkflowError } from './errors.js';
|
|
|
11
12
|
import { bindGraphEvidence, createGraphRefreshRequest, fallbackGraphBinding, inspectGraphBinding, validateGraphRequestCurrent, } from './graph.js';
|
|
12
13
|
import { inspectLocalDependency, inspectWorkflowVersions } from './diagnostics.js';
|
|
13
14
|
import { appendTaskClaim, appendTaskHandback, appendTaskHandoff, appendTaskWriterCredentialReplacement, assertTaskClaimAllowed, assertTaskMutationAllowedByC1, defaultTaskWorkerActor, prepareTaskCorrectiveYield, readTaskC1Posture, } from './alpha6/handoff.js';
|
|
14
|
-
import { assessDownstreamProofCarryover, assessDownstreamProofReplanRecovery, assessDownstreamProofRecovery, downstreamProofInvalidationSidecar, downstreamProofReplanRecoverySidecar, prepareDownstreamProofInvalidation, prepareDownstreamProofReplanRecovery, readDownstreamProofInvalidations, readDownstreamProofReplanRecoveries, } from './alpha6/downstream-proof.js';
|
|
15
|
+
import { assessDownstreamProofCarryover, assessDownstreamProofReplanRecovery, assessDownstreamProofRecovery, downstreamProofInvalidationSidecar, downstreamProofReplanRecoverySidecar, prepareDownstreamProofInvalidation, prepareDownstreamProofReplanRecovery, readDownstreamProofInvalidations, readDownstreamProofReplanRecoveries, hashDirtyWorktree, } from './alpha6/downstream-proof.js';
|
|
15
16
|
import { applyAdoptionPosture, assertAdoptionBaselinePreserved, buildAdoptionPreparation, initializeProjectRegistrationAdoption, readCurrentAdoptionPosture, } from './alpha6/adoption.js';
|
|
16
17
|
import { appendCurrentPlanRiskAudit, appendReboundPlanRiskAudit, readCurrentPlanRiskAudit, readPlanRiskAuditEvents, validatePlanRiskAuditCandidate, } from './alpha6/plan-risk.js';
|
|
17
18
|
import { appendCorrectiveDecisionEvent, appendPlanIntegrityRecoveryDecision, appendRemediationEvent, appendRemediationModeRecovery, appendStopEscalateOverride, assertCorrectiveAuditorIndependence, assertGuardedRemediationAttemptAllowed, defaultCorrectiveAuditorActor, findCurrentGuardedRemediationPosture, findRemediationModeRecoveryCandidate, findFailedGuardedStepRequiringCorrectiveDecision, readGuardedRemediationPostureForStep, readCorrectiveDecisionEvents, readRemediationEvents, prepareStopEscalateOverride, stopEscalateOverrideDecisionEventIds, } from './alpha6/remediation.js';
|
|
@@ -19,7 +20,7 @@ import { assessPlanIntegrityRecovery, defaultPlanIntegrityRecoveryActor, } from
|
|
|
19
20
|
import { assertMechanicalFeasibilityFresh, evaluateMechanicalFeasibility, hashMechanicalFeasibilityEvidence, } from './alpha6/mechanical-feasibility.js';
|
|
20
21
|
import { assessMilestoneInitialAssembly, applyInitialMilestonePlanTransaction, applyMilestoneScopeChangeTransaction, assertMilestoneDependenciesDeclared, assertMilestoneTaskRunnable, assessMilestoneTaskDependencies, assertMilestoneMembershipIntegrity, assertMilestoneScopeChangeStatusAllowed, inspectMilestoneWithIntegrity, normalizeMilestonePlan, prepareMilestoneScopeChangeCandidate, prepareMilestoneScopeChangeBundle, readMilestoneForScopeChange, readMilestoneWithIntegrity, } from './alpha6/milestone.js';
|
|
21
22
|
import { applyProjectTransaction, recoverProjectTransactions, runRollbackProjectTransaction, } from './beta1/project-transaction.js';
|
|
22
|
-
import { buildCurrentStrictStepReviewCycle, countUnverifiedStrictStepReviews, ensurePendingStrictStepReview, isStepReviewRequired, latestFailedStepReviewRouting, latestPassedVerifiedStepReviewEvent, recordStrictStepReview, verifiedHistoricalStepReviewCommits, } from './alpha6/review.js';
|
|
23
|
+
import { buildCurrentStrictStepReviewCycle, countUnverifiedStrictStepReviews, ensurePendingStrictStepReview, isStepReviewRequired, latestFailedStepReviewRouting, latestPassedVerifiedStepReviewEvent, recordStrictStepReview, verifiedHistoricalStepReviewCommits, verifiedHistoricalStepReviewBindings, } from './alpha6/review.js';
|
|
23
24
|
import { applyMilestoneAutonomyContract, assertAutonomousPlanEvolution, prepareMilestoneAutonomyContract, readMilestoneAutonomyEvents, requireActiveMilestoneAutonomy, } from './alpha7/autonomy.js';
|
|
24
25
|
import { appendCorrectiveDecisionRecovery, readValidatedCorrectiveDecisionRecoveryForNavigation, readValidatedStopOverrideContextRebindIfApplicable, requireCorrectiveDecisionRecoveryForRun, } from './alpha7/corrective-recovery.js';
|
|
25
26
|
import { applyKnowledgeSelections, hashKnowledgeMap, inspectKnowledgeMap, normalizeRelativePath, reconcileKnowledgeMap, scanProjectKnowledge, selectKnowledgeSources, } from './memory.js';
|
|
@@ -1399,6 +1400,10 @@ export class WorkflowService {
|
|
|
1399
1400
|
status: dependenciesComplete(step, completedIds) ? 'planned' : 'blocked',
|
|
1400
1401
|
evidence: null,
|
|
1401
1402
|
}));
|
|
1403
|
+
const invalidatedStepCommits = [...new Set([
|
|
1404
|
+
...(task.invalidatedStepCommits ?? []),
|
|
1405
|
+
...omittedStepEvidenceCommits(task, plannedSteps),
|
|
1406
|
+
])];
|
|
1402
1407
|
if (task.status === 'needs_fix' &&
|
|
1403
1408
|
task.review.status === 'failed' &&
|
|
1404
1409
|
plannedSteps.every((step) => step.status === 'completed')) {
|
|
@@ -1437,6 +1442,7 @@ export class WorkflowService {
|
|
|
1437
1442
|
knowledgeMapHash: plan.knowledgeMapHash,
|
|
1438
1443
|
graphUse: plan.graphUse,
|
|
1439
1444
|
steps: plannedSteps,
|
|
1445
|
+
invalidatedStepCommits,
|
|
1440
1446
|
authorizations,
|
|
1441
1447
|
review: emptyReview(),
|
|
1442
1448
|
resultHash: null,
|
|
@@ -2733,16 +2739,23 @@ export class WorkflowService {
|
|
|
2733
2739
|
assertCorrectiveAuditorIndependence(this.store, task, stepId, correctiveAudit.auditor);
|
|
2734
2740
|
return appendCorrectiveDecisionEvent(this.store, task, stepId, correctiveAudit, planRiskAudit, task.planHash, this.now());
|
|
2735
2741
|
}
|
|
2736
|
-
setTaskResult(repository, taskId, expectedRevision, summary, limitations) {
|
|
2737
|
-
const
|
|
2742
|
+
setTaskResult(repository, taskId, expectedRevision, summary, limitations, writerToken, actor) {
|
|
2743
|
+
const context = this.#mutationContext(repository);
|
|
2744
|
+
const { identity } = context;
|
|
2738
2745
|
const task = this.store.readTask(identity.projectId, taskId);
|
|
2739
2746
|
assertExpectedRevision(task, expectedRevision);
|
|
2740
2747
|
if (task.status !== 'validating' || task.review.status !== 'passed') {
|
|
2741
2748
|
throw new WorkflowError('TRANSITION_BLOCKED', 'Result requires a passing independent review.');
|
|
2742
2749
|
}
|
|
2743
2750
|
this.assertReviewFresh(identity.repositoryRoot, task);
|
|
2751
|
+
const lease = context.locks.heartbeat(taskId, writerToken);
|
|
2752
|
+
this.assertTaskMutationAllowedByHandoff(task, actor ?? null, lease.token);
|
|
2744
2753
|
const root = this.store.taskRoot(task.projectId, task.id);
|
|
2745
2754
|
const stagedResult = this.store.stageArtifact(root, 'result.md', renderResult(task, summary, limitations));
|
|
2755
|
+
// Human final acceptance is an intentionally unbounded pause. Release the
|
|
2756
|
+
// execution lease before entering that gate so elapsed human time cannot
|
|
2757
|
+
// turn a successful Task into a repository-wide stale-lock repair route.
|
|
2758
|
+
context.locks.release(taskId, lease.token);
|
|
2746
2759
|
const saved = this.store.writeTask({ ...task, status: 'awaiting_final_acceptance', resultHash: stagedResult.hash, blockReason: null }, expectedRevision);
|
|
2747
2760
|
this.store.publishArtifact(stagedResult);
|
|
2748
2761
|
return saved;
|
|
@@ -3005,6 +3018,137 @@ export class WorkflowService {
|
|
|
3005
3018
|
throw new WorkflowError('NOT_FOUND', `Task ${taskId} was not found in this repository.`);
|
|
3006
3019
|
return this.inspectDependencyProvenanceCandidate(snapshot, task);
|
|
3007
3020
|
}
|
|
3021
|
+
historicalStepProvenanceRecoveryPreflight(repository, taskId) {
|
|
3022
|
+
const snapshot = this.observationSnapshot(repository);
|
|
3023
|
+
if (snapshot.observation.kind !== 'assessment') {
|
|
3024
|
+
throw new WorkflowError('TRANSITION_BLOCKED', 'Historical Step provenance recovery requires a coherent observation boundary.', {
|
|
3025
|
+
observation: snapshot.observation,
|
|
3026
|
+
});
|
|
3027
|
+
}
|
|
3028
|
+
const task = snapshot.tasks.find((candidate) => candidate.id === taskId);
|
|
3029
|
+
if (!task)
|
|
3030
|
+
throw new WorkflowError('NOT_FOUND', `Task ${taskId} was not found in this repository.`);
|
|
3031
|
+
return this.inspectHistoricalStepProvenanceCandidate(snapshot, task);
|
|
3032
|
+
}
|
|
3033
|
+
historicalStepDependencyRecoveryPreflight(repository, taskId) {
|
|
3034
|
+
const snapshot = this.observationSnapshot(repository);
|
|
3035
|
+
if (snapshot.observation.kind !== 'assessment') {
|
|
3036
|
+
throw new WorkflowError('TRANSITION_BLOCKED', 'Historical Step dependency recovery requires a coherent observation boundary.', {
|
|
3037
|
+
observation: snapshot.observation,
|
|
3038
|
+
});
|
|
3039
|
+
}
|
|
3040
|
+
const task = snapshot.tasks.find((candidate) => candidate.id === taskId);
|
|
3041
|
+
if (!task)
|
|
3042
|
+
throw new WorkflowError('NOT_FOUND', `Task ${taskId} was not found in this repository.`);
|
|
3043
|
+
let candidateParent = null;
|
|
3044
|
+
try {
|
|
3045
|
+
candidateParent = runGit(snapshot.identity.repositoryRoot, ['rev-parse', 'HEAD^']);
|
|
3046
|
+
}
|
|
3047
|
+
catch {
|
|
3048
|
+
candidateParent = null;
|
|
3049
|
+
}
|
|
3050
|
+
const assessment = candidateParent
|
|
3051
|
+
? this.inspectHistoricalStepProvenanceCandidate(snapshot, task, {
|
|
3052
|
+
historyBoundary: 'HEAD^',
|
|
3053
|
+
preservedHeadCommit: candidateParent,
|
|
3054
|
+
})
|
|
3055
|
+
: null;
|
|
3056
|
+
if (!assessment?.eligible
|
|
3057
|
+
|| !assessment.activeStepId
|
|
3058
|
+
|| !assessment.commitSha
|
|
3059
|
+
|| !task.planHash) {
|
|
3060
|
+
const ordinary = this.inspectDependencyProvenanceCandidate(snapshot, task);
|
|
3061
|
+
return {
|
|
3062
|
+
...ordinary,
|
|
3063
|
+
eligible: false,
|
|
3064
|
+
action: null,
|
|
3065
|
+
historicalStepProvenance: null,
|
|
3066
|
+
blockers: [...new Set([
|
|
3067
|
+
...ordinary.blockers,
|
|
3068
|
+
...(assessment?.blockers ?? []),
|
|
3069
|
+
'The dependency candidate parent must contain exactly one accepted and strictly reviewed historical Step commit omitted by the current corrective Plan.',
|
|
3070
|
+
])],
|
|
3071
|
+
};
|
|
3072
|
+
}
|
|
3073
|
+
let dirtyWorktreeHash;
|
|
3074
|
+
try {
|
|
3075
|
+
dirtyWorktreeHash = hashDirtyWorktree(snapshot.identity.repositoryRoot, assessment.dirtyFiles);
|
|
3076
|
+
}
|
|
3077
|
+
catch (error) {
|
|
3078
|
+
const ordinary = this.inspectDependencyProvenanceCandidate(snapshot, task);
|
|
3079
|
+
return {
|
|
3080
|
+
...ordinary,
|
|
3081
|
+
eligible: false,
|
|
3082
|
+
action: null,
|
|
3083
|
+
historicalStepProvenance: null,
|
|
3084
|
+
blockers: [...new Set([
|
|
3085
|
+
...ordinary.blockers,
|
|
3086
|
+
error instanceof Error ? error.message : String(error),
|
|
3087
|
+
])],
|
|
3088
|
+
};
|
|
3089
|
+
}
|
|
3090
|
+
return this.inspectDependencyProvenanceCandidate(snapshot, task, null, null, {
|
|
3091
|
+
activeStepId: assessment.activeStepId,
|
|
3092
|
+
planHash: task.planHash,
|
|
3093
|
+
dirtyFiles: assessment.dirtyFiles,
|
|
3094
|
+
dirtyWorktreeHash,
|
|
3095
|
+
retainedCommitSha: assessment.commitSha,
|
|
3096
|
+
});
|
|
3097
|
+
}
|
|
3098
|
+
recoverHistoricalStepProvenance(repository, taskId, expectedRevision, commitSha, actor, reason) {
|
|
3099
|
+
const normalizedActor = actor.trim();
|
|
3100
|
+
const normalizedReason = reason.trim();
|
|
3101
|
+
if (!normalizedActor)
|
|
3102
|
+
throw new WorkflowError('INVALID_ARGUMENT', 'Historical Step provenance recovery requires an actor.');
|
|
3103
|
+
if (!normalizedReason)
|
|
3104
|
+
throw new WorkflowError('INVALID_ARGUMENT', 'Historical Step provenance recovery requires a reason.');
|
|
3105
|
+
const context = this.#mutationContext(repository);
|
|
3106
|
+
const current = context.store.readTask(context.identity.projectId, taskId);
|
|
3107
|
+
const prior = current.historicalStepProvenanceRecoveries?.find((record) => record.commitSha === commitSha);
|
|
3108
|
+
if (prior && (current.invalidatedStepCommits ?? []).includes(commitSha)) {
|
|
3109
|
+
validateTaskHistory(context.identity.repositoryRoot, current);
|
|
3110
|
+
return current;
|
|
3111
|
+
}
|
|
3112
|
+
assertExpectedRevision(current, expectedRevision);
|
|
3113
|
+
const preflight = this.historicalStepProvenanceRecoveryPreflight(repository, taskId);
|
|
3114
|
+
if (!preflight.eligible || preflight.commitSha !== commitSha || !preflight.sourceFinalAcceptanceRecordedAt) {
|
|
3115
|
+
throw new WorkflowError('GIT_PRECONDITION_FAILED', 'The bounded historical Step provenance recovery preflight failed.', {
|
|
3116
|
+
taskId,
|
|
3117
|
+
requestedCommit: commitSha,
|
|
3118
|
+
candidateCommit: preflight.commitSha,
|
|
3119
|
+
blockers: preflight.blockers,
|
|
3120
|
+
});
|
|
3121
|
+
}
|
|
3122
|
+
const sourceAcceptance = current.authorizations.find((authorization) => authorization.kind === 'final_acceptance'
|
|
3123
|
+
&& ['approved', 'superseded'].includes(authorization.decision)
|
|
3124
|
+
&& authorization.headCommit === commitSha
|
|
3125
|
+
&& authorization.recordedAt === preflight.sourceFinalAcceptanceRecordedAt
|
|
3126
|
+
&& authorization.planHash
|
|
3127
|
+
&& authorization.resultHash
|
|
3128
|
+
&& authorization.evidenceHash);
|
|
3129
|
+
if (!sourceAcceptance?.planHash || !sourceAcceptance.resultHash || !sourceAcceptance.evidenceHash) {
|
|
3130
|
+
throw new WorkflowError('STATE_CONFLICT', 'The source final acceptance changed after historical provenance preflight.');
|
|
3131
|
+
}
|
|
3132
|
+
const saved = context.store.writeTask({
|
|
3133
|
+
...current,
|
|
3134
|
+
invalidatedStepCommits: [...new Set([...(current.invalidatedStepCommits ?? []), commitSha])],
|
|
3135
|
+
historicalStepProvenanceRecoveries: [
|
|
3136
|
+
...(current.historicalStepProvenanceRecoveries ?? []),
|
|
3137
|
+
{
|
|
3138
|
+
commitSha,
|
|
3139
|
+
actor: normalizedActor,
|
|
3140
|
+
reason: normalizedReason,
|
|
3141
|
+
recordedAt: this.now().toISOString(),
|
|
3142
|
+
sourceFinalAcceptanceRecordedAt: sourceAcceptance.recordedAt,
|
|
3143
|
+
sourcePlanHash: sourceAcceptance.planHash,
|
|
3144
|
+
sourceResultHash: sourceAcceptance.resultHash,
|
|
3145
|
+
sourceEvidenceHash: sourceAcceptance.evidenceHash,
|
|
3146
|
+
},
|
|
3147
|
+
],
|
|
3148
|
+
}, expectedRevision);
|
|
3149
|
+
validateTaskHistory(context.identity.repositoryRoot, saved);
|
|
3150
|
+
return saved;
|
|
3151
|
+
}
|
|
3008
3152
|
activeDownstreamProofDependencyRecoveryPreflight(repository, taskId) {
|
|
3009
3153
|
const snapshot = this.observationSnapshot(repository);
|
|
3010
3154
|
if (snapshot.observation.kind !== 'assessment') {
|
|
@@ -3152,6 +3296,9 @@ export class WorkflowService {
|
|
|
3152
3296
|
recoverDownstreamProofReplanDependencyProvenance(repository, taskId, expectedRevision, actor, reason) {
|
|
3153
3297
|
return this.recoverDependencyProvenanceCandidate(repository, taskId, expectedRevision, actor, reason, 'downstream-replan');
|
|
3154
3298
|
}
|
|
3299
|
+
recoverHistoricalStepDependencyProvenance(repository, taskId, expectedRevision, actor, reason) {
|
|
3300
|
+
return this.recoverDependencyProvenanceCandidate(repository, taskId, expectedRevision, actor, reason, 'historical-step');
|
|
3301
|
+
}
|
|
3155
3302
|
recoverDependencyProvenanceCandidate(repository, taskId, expectedRevision, actor, reason, recoveryMode) {
|
|
3156
3303
|
const normalizedActor = actor.trim();
|
|
3157
3304
|
const normalizedReason = reason.trim();
|
|
@@ -3166,7 +3313,9 @@ export class WorkflowService {
|
|
|
3166
3313
|
&& record.packageVersion === PACKAGE_VERSION
|
|
3167
3314
|
&& (recoveryMode === 'downstream-replan'
|
|
3168
3315
|
? Boolean(record.downstreamProofReplan)
|
|
3169
|
-
:
|
|
3316
|
+
: recoveryMode === 'historical-step'
|
|
3317
|
+
? Boolean(record.historicalStepProvenance)
|
|
3318
|
+
: Boolean(record.activeDownstreamProof) === recoveryMode));
|
|
3170
3319
|
if (prior && current.systemCommits.includes(currentHead))
|
|
3171
3320
|
return current;
|
|
3172
3321
|
assertExpectedRevision(current, expectedRevision);
|
|
@@ -3176,9 +3325,11 @@ export class WorkflowService {
|
|
|
3176
3325
|
throw new WorkflowError('NOT_FOUND', `Task ${taskId} was not found in this repository.`);
|
|
3177
3326
|
const preflight = recoveryMode === 'downstream-replan'
|
|
3178
3327
|
? this.downstreamProofReplanDependencyRecoveryPreflight(repository, taskId)
|
|
3179
|
-
: recoveryMode
|
|
3180
|
-
? this.
|
|
3181
|
-
:
|
|
3328
|
+
: recoveryMode === 'historical-step'
|
|
3329
|
+
? this.historicalStepDependencyRecoveryPreflight(repository, taskId)
|
|
3330
|
+
: recoveryMode
|
|
3331
|
+
? this.activeDownstreamProofDependencyRecoveryPreflight(repository, taskId)
|
|
3332
|
+
: this.inspectDependencyProvenanceCandidate(snapshot, task);
|
|
3182
3333
|
if (!preflight.eligible || !preflight.commitSha || !preflight.parentCommitSha) {
|
|
3183
3334
|
throw new WorkflowError('GIT_PRECONDITION_FAILED', 'The bounded dependency provenance recovery preflight failed.', {
|
|
3184
3335
|
taskId,
|
|
@@ -3206,6 +3357,9 @@ export class WorkflowService {
|
|
|
3206
3357
|
...(preflight.downstreamProofReplan
|
|
3207
3358
|
? { downstreamProofReplan: preflight.downstreamProofReplan }
|
|
3208
3359
|
: {}),
|
|
3360
|
+
...(preflight.historicalStepProvenance
|
|
3361
|
+
? { historicalStepProvenance: preflight.historicalStepProvenance }
|
|
3362
|
+
: {}),
|
|
3209
3363
|
},
|
|
3210
3364
|
],
|
|
3211
3365
|
}, expectedRevision);
|
|
@@ -3608,6 +3762,33 @@ export class WorkflowService {
|
|
|
3608
3762
|
const activeTask = requestedTask
|
|
3609
3763
|
?? status.tasks.find((task) => taskIsActionableFromRepositoryNext(task, milestonesById, tasksById));
|
|
3610
3764
|
if (activeTask) {
|
|
3765
|
+
const historicalStepProvenanceRecovery = this.historicalStepProvenanceRecoveryPreflight(repositoryRoot, activeTask.id);
|
|
3766
|
+
if (historicalStepProvenanceRecovery.eligible) {
|
|
3767
|
+
return withAdoption({
|
|
3768
|
+
scope: 'task',
|
|
3769
|
+
id: activeTask.id,
|
|
3770
|
+
status: activeTask.status,
|
|
3771
|
+
action: 'task historical-step-provenance-recover',
|
|
3772
|
+
revision: activeTask.revision,
|
|
3773
|
+
historicalStepProvenanceRecovery,
|
|
3774
|
+
});
|
|
3775
|
+
}
|
|
3776
|
+
const historicalStepDependencyRecovery = this.historicalStepDependencyRecoveryPreflight(repositoryRoot, activeTask.id);
|
|
3777
|
+
if (historicalStepDependencyRecovery.eligible) {
|
|
3778
|
+
return withAdoption({
|
|
3779
|
+
scope: 'task',
|
|
3780
|
+
id: activeTask.id,
|
|
3781
|
+
status: activeTask.status,
|
|
3782
|
+
action: 'update historical-step-dependency-recover',
|
|
3783
|
+
revision: activeTask.revision,
|
|
3784
|
+
dependencyProvenanceRecovery: historicalStepDependencyRecovery,
|
|
3785
|
+
compatibilityBoundary: {
|
|
3786
|
+
preservesWorktree: true,
|
|
3787
|
+
prerequisite: 'The active Milestone base and Task branch contain only the exact target dependency commits; the candidate parent still binds the reviewed historical Step commit.',
|
|
3788
|
+
continuation: 'Register the dependency commit and historical provenance atomically, then follow fresh next.',
|
|
3789
|
+
},
|
|
3790
|
+
});
|
|
3791
|
+
}
|
|
3611
3792
|
const dependencyRecovery = this.dependencyProvenanceRecoveryPreflight(repositoryRoot, activeTask.id);
|
|
3612
3793
|
if (dependencyRecovery.eligible) {
|
|
3613
3794
|
return withAdoption({
|
|
@@ -5056,7 +5237,7 @@ export class WorkflowService {
|
|
|
5056
5237
|
},
|
|
5057
5238
|
};
|
|
5058
5239
|
}
|
|
5059
|
-
inspectDependencyProvenanceCandidate(snapshot, task, activeDownstreamProof = null, downstreamProofReplan = null) {
|
|
5240
|
+
inspectDependencyProvenanceCandidate(snapshot, task, activeDownstreamProof = null, downstreamProofReplan = null, historicalStepProvenance = null) {
|
|
5060
5241
|
const versions = inspectWorkflowVersions(snapshot.identity.repositoryRoot, [task.baseBranch]);
|
|
5061
5242
|
const now = this.now().getTime();
|
|
5062
5243
|
return inspectDependencyProvenanceRecovery(snapshot.identity.repositoryRoot, task, {
|
|
@@ -5076,7 +5257,20 @@ export class WorkflowService {
|
|
|
5076
5257
|
currentBranch: versions.currentBranch,
|
|
5077
5258
|
baseBranch: versions.milestoneBases.find((base) => base.branch === task.baseBranch)?.version ?? null,
|
|
5078
5259
|
},
|
|
5079
|
-
}, activeDownstreamProof, downstreamProofReplan);
|
|
5260
|
+
}, activeDownstreamProof, downstreamProofReplan, historicalStepProvenance);
|
|
5261
|
+
}
|
|
5262
|
+
inspectHistoricalStepProvenanceCandidate(snapshot, task, options = {}) {
|
|
5263
|
+
const now = this.now().getTime();
|
|
5264
|
+
return inspectHistoricalStepProvenanceRecovery(snapshot.identity.repositoryRoot, task, {
|
|
5265
|
+
activeLeaseCount: snapshot.leases.filter((lease) => Date.parse(lease.expiresAt) > now).length,
|
|
5266
|
+
staleLeaseCount: snapshot.leases.filter((lease) => Date.parse(lease.expiresAt) <= now).length,
|
|
5267
|
+
pendingTransactionCount: snapshot.observation.pendingProjectTransactions.length
|
|
5268
|
+
+ snapshot.observation.pendingMilestoneTransactions.length
|
|
5269
|
+
+ snapshot.observation.pendingTaskTransactions.length,
|
|
5270
|
+
corruptTransactionCount: snapshot.observation.corruptTaskTransactions.length,
|
|
5271
|
+
coreOperationCount: snapshot.observation.coreTaskOperations.length,
|
|
5272
|
+
verifiedHistoricalStepBindings: verifiedHistoricalStepReviewBindings(this.store, task),
|
|
5273
|
+
}, options);
|
|
5080
5274
|
}
|
|
5081
5275
|
withTaskNavigationContracts(task, next) {
|
|
5082
5276
|
const action = typeof next.action === 'string' ? next.action : null;
|
|
@@ -5114,7 +5308,7 @@ export class WorkflowService {
|
|
|
5114
5308
|
return activeLeaseOwner;
|
|
5115
5309
|
const authorizationKind = ['task merge', 'task merge-confirm'].includes(action)
|
|
5116
5310
|
? 'final_acceptance'
|
|
5117
|
-
: ['task step-complete', 'task downstream-proof-recover', 'task submit'].includes(action)
|
|
5311
|
+
: ['task step-complete', 'task downstream-proof-recover', 'task submit', 'task result-set'].includes(action)
|
|
5118
5312
|
? 'execution'
|
|
5119
5313
|
: null;
|
|
5120
5314
|
if (!authorizationKind)
|
|
@@ -5902,6 +6096,7 @@ function writerTokenContractForAction(action, claimedC1Posture = false) {
|
|
|
5902
6096
|
'task step-complete',
|
|
5903
6097
|
'task downstream-proof-recover',
|
|
5904
6098
|
'task submit',
|
|
6099
|
+
'task result-set',
|
|
5905
6100
|
'task merge',
|
|
5906
6101
|
'task merge-confirm',
|
|
5907
6102
|
];
|