codex-workflow-v2 2.0.0-beta.8 → 2.0.0-beta.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 +5 -2
- package/dist/src/cli.js +25 -1
- package/dist/src/cli.js.map +1 -1
- package/dist/src/contracts.d.ts +56 -0
- package/dist/src/dependency-provenance.d.ts +18 -0
- package/dist/src/dependency-provenance.js +179 -0
- package/dist/src/dependency-provenance.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 +5 -1
- package/dist/src/workflow.js +139 -1
- package/dist/src/workflow.js.map +1 -1
- package/docs/autonomy-guardrails.md +6 -6
- package/docs/delegated-approval.md +5 -3
- package/docs/development-flow.md +4 -4
- package/docs/release.md +4 -1
- package/docs/stable-release-defect-register.md +37 -1
- package/docs/updating-existing-project.md +7 -5
- package/docs/validation-report.md +70 -56
- package/package.json +1 -1
- package/plugins/codex-workflow-gateway/.codex-plugin/plugin.json +10 -3
- package/plugins/codex-workflow-gateway/references/protocol.md +14 -2
- package/plugins/codex-workflow-gateway/scripts/chat-registry.mjs +376 -0
- package/plugins/codex-workflow-gateway/skills/codex-workflow-gateway/SKILL.md +51 -14
- package/roles/delivery-coordinator.md +10 -5
- package/schemas/task.schema.json +19 -1
package/dist/src/workflow.js
CHANGED
|
@@ -2,6 +2,7 @@ import { appendFileSync, existsSync, lstatSync, readFileSync, readdirSync } from
|
|
|
2
2
|
import { createHash } from 'node:crypto';
|
|
3
3
|
import path from 'node:path';
|
|
4
4
|
import { PROTOCOL_VERSION, STATE_SCHEMA_VERSION, } from './contracts.js';
|
|
5
|
+
import { inspectDependencyProvenanceRecovery } from './dependency-provenance.js';
|
|
5
6
|
import { renderBrief, renderPlan, renderResult } from './artifacts.js';
|
|
6
7
|
import { assertDelegationCanAuthorize, hashDelegationPolicy, prepareDelegationGrantGate, } from './delegation.js';
|
|
7
8
|
import { assessDiscovery, mergeUnique } from './domain/discovery.js';
|
|
@@ -32,7 +33,7 @@ import { createCorrectiveYieldExecutor } from './state/corrective-yield-executor
|
|
|
32
33
|
import { createCorrectiveReplanPublicController, } from './state/corrective-replan-public.js';
|
|
33
34
|
import { inspectWorkflowObservationBoundary, } from './observation.js';
|
|
34
35
|
import { createEntityId } from './ulid.js';
|
|
35
|
-
import { PACKAGE_VERSION } from './version.js';
|
|
36
|
+
import { PACKAGE_NAME, PACKAGE_VERSION } from './version.js';
|
|
36
37
|
import { correctiveReplanBlockedNavigation, correctiveReplanNavigation, evaluateTaskCorrectiveReplanAvailability, evaluateTaskCorrectiveReplanCandidate, identifyCorrectiveReplanPosture, prepareCorrectiveReplanCandidate, TASK_CORRECTIVE_REPLAN_TRANSITION_ID, } from './lifecycle/corrective-replan.js';
|
|
37
38
|
const MAX_STRICT_REVIEW_INFRASTRUCTURE_FAILURES = 2;
|
|
38
39
|
export class WorkflowService {
|
|
@@ -2620,6 +2621,111 @@ export class WorkflowService {
|
|
|
2620
2621
|
observation: snapshot.observation,
|
|
2621
2622
|
};
|
|
2622
2623
|
}
|
|
2624
|
+
dependencyProvenanceRecoveryPreflight(repository, taskId) {
|
|
2625
|
+
const snapshot = this.observationSnapshot(repository);
|
|
2626
|
+
if (snapshot.observation.kind !== 'assessment') {
|
|
2627
|
+
throw new WorkflowError('TRANSITION_BLOCKED', 'Dependency provenance recovery requires a coherent observation boundary.', {
|
|
2628
|
+
observation: snapshot.observation,
|
|
2629
|
+
});
|
|
2630
|
+
}
|
|
2631
|
+
const task = snapshot.tasks.find((candidate) => candidate.id === taskId);
|
|
2632
|
+
if (!task)
|
|
2633
|
+
throw new WorkflowError('NOT_FOUND', `Task ${taskId} was not found in this repository.`);
|
|
2634
|
+
return this.inspectDependencyProvenanceCandidate(snapshot, task);
|
|
2635
|
+
}
|
|
2636
|
+
recoverDependencyProvenance(repository, taskId, expectedRevision, actor, reason) {
|
|
2637
|
+
const normalizedActor = actor.trim();
|
|
2638
|
+
const normalizedReason = reason.trim();
|
|
2639
|
+
if (!normalizedActor)
|
|
2640
|
+
throw new WorkflowError('INVALID_ARGUMENT', 'Dependency provenance recovery requires an actor.');
|
|
2641
|
+
if (!normalizedReason)
|
|
2642
|
+
throw new WorkflowError('INVALID_ARGUMENT', 'Dependency provenance recovery requires a reason.');
|
|
2643
|
+
const context = this.#mutationContext(repository);
|
|
2644
|
+
const current = context.store.readTask(context.identity.projectId, taskId);
|
|
2645
|
+
const currentHead = headCommit(context.identity.repositoryRoot);
|
|
2646
|
+
const prior = current.dependencyProvenanceRecoveries?.find((record) => record.commitSha === currentHead && record.packageVersion === PACKAGE_VERSION);
|
|
2647
|
+
if (prior && current.systemCommits.includes(currentHead))
|
|
2648
|
+
return current;
|
|
2649
|
+
assertExpectedRevision(current, expectedRevision);
|
|
2650
|
+
const snapshot = this.observationSnapshot(repository);
|
|
2651
|
+
const task = snapshot.tasks.find((candidate) => candidate.id === taskId);
|
|
2652
|
+
if (!task)
|
|
2653
|
+
throw new WorkflowError('NOT_FOUND', `Task ${taskId} was not found in this repository.`);
|
|
2654
|
+
const preflight = this.inspectDependencyProvenanceCandidate(snapshot, task);
|
|
2655
|
+
if (!preflight.eligible || !preflight.commitSha || !preflight.parentCommitSha) {
|
|
2656
|
+
throw new WorkflowError('GIT_PRECONDITION_FAILED', 'The bounded dependency provenance recovery preflight failed.', {
|
|
2657
|
+
taskId,
|
|
2658
|
+
blockers: preflight.blockers,
|
|
2659
|
+
});
|
|
2660
|
+
}
|
|
2661
|
+
return context.store.writeTask({
|
|
2662
|
+
...task,
|
|
2663
|
+
systemCommits: [...task.systemCommits, preflight.commitSha],
|
|
2664
|
+
dependencyProvenanceRecoveries: [
|
|
2665
|
+
...(task.dependencyProvenanceRecoveries ?? []),
|
|
2666
|
+
{
|
|
2667
|
+
commitSha: preflight.commitSha,
|
|
2668
|
+
parentCommitSha: preflight.parentCommitSha,
|
|
2669
|
+
packageName: PACKAGE_NAME,
|
|
2670
|
+
packageVersion: PACKAGE_VERSION,
|
|
2671
|
+
files: ['package-lock.json', 'package.json'],
|
|
2672
|
+
actor: normalizedActor,
|
|
2673
|
+
reason: normalizedReason,
|
|
2674
|
+
recordedAt: this.now().toISOString(),
|
|
2675
|
+
},
|
|
2676
|
+
],
|
|
2677
|
+
}, expectedRevision);
|
|
2678
|
+
}
|
|
2679
|
+
milestoneProgress(repository, milestoneId) {
|
|
2680
|
+
const snapshot = this.observationSnapshot(repository);
|
|
2681
|
+
if (snapshot.observation.kind !== 'assessment') {
|
|
2682
|
+
throw new WorkflowError('TRANSITION_BLOCKED', 'Milestone progress requires a coherent read-only observation boundary.', {
|
|
2683
|
+
observation: snapshot.observation,
|
|
2684
|
+
});
|
|
2685
|
+
}
|
|
2686
|
+
const milestone = snapshot.milestones.find((candidate) => candidate.id === milestoneId);
|
|
2687
|
+
if (!milestone)
|
|
2688
|
+
throw new WorkflowError('NOT_FOUND', `Milestone ${milestoneId} was not found in this repository.`);
|
|
2689
|
+
const tasksById = new Map(snapshot.tasks.map((task) => [task.id, task]));
|
|
2690
|
+
const tasks = milestone.memberships.map((membership, index) => {
|
|
2691
|
+
const task = tasksById.get(membership.taskId);
|
|
2692
|
+
if (!task)
|
|
2693
|
+
throw new WorkflowError('STATE_CORRUPT', `Milestone member ${membership.taskId} does not exist.`);
|
|
2694
|
+
const stepsCompleted = task.steps.filter((step) => ['completed', 'skipped'].includes(step.status)).length;
|
|
2695
|
+
return {
|
|
2696
|
+
ordinal: `T${String(index + 1).padStart(2, '0')}`,
|
|
2697
|
+
taskId: task.id,
|
|
2698
|
+
title: task.title,
|
|
2699
|
+
status: task.status,
|
|
2700
|
+
revision: task.revision,
|
|
2701
|
+
disposition: membership.disposition,
|
|
2702
|
+
membershipReason: membership.reason,
|
|
2703
|
+
replacementForTaskId: task.replacementForTaskId ?? null,
|
|
2704
|
+
replacedByTaskId: task.replacedByTaskId ?? null,
|
|
2705
|
+
stepsCompleted,
|
|
2706
|
+
stepsTotal: task.steps.length,
|
|
2707
|
+
steps: task.steps.map((step, stepIndex) => ({
|
|
2708
|
+
ordinal: `S${String(stepIndex + 1).padStart(2, '0')}`,
|
|
2709
|
+
stepId: step.id,
|
|
2710
|
+
title: step.title,
|
|
2711
|
+
status: step.status,
|
|
2712
|
+
})),
|
|
2713
|
+
};
|
|
2714
|
+
});
|
|
2715
|
+
const required = tasks.filter((task) => task.disposition === 'required');
|
|
2716
|
+
return {
|
|
2717
|
+
readOnly: true,
|
|
2718
|
+
projectId: snapshot.identity.projectId,
|
|
2719
|
+
milestoneId: milestone.id,
|
|
2720
|
+
milestoneTitle: milestone.title,
|
|
2721
|
+
milestoneStatus: milestone.status,
|
|
2722
|
+
milestoneRevision: milestone.revision,
|
|
2723
|
+
membershipRevision: milestone.membershipRevision,
|
|
2724
|
+
tasksCompleted: required.filter((task) => task.status === 'merged').length,
|
|
2725
|
+
tasksRequired: required.length,
|
|
2726
|
+
tasks,
|
|
2727
|
+
};
|
|
2728
|
+
}
|
|
2623
2729
|
alpha6StrictReviewRescuePreflight(repository) {
|
|
2624
2730
|
const context = this.#mutationContext(repository);
|
|
2625
2731
|
const dependency = inspectLocalDependency(context.identity.repositoryRoot);
|
|
@@ -2939,6 +3045,17 @@ export class WorkflowService {
|
|
|
2939
3045
|
const activeTask = requestedTask
|
|
2940
3046
|
?? status.tasks.find((task) => taskIsActionableFromRepositoryNext(task, milestonesById));
|
|
2941
3047
|
if (activeTask) {
|
|
3048
|
+
const dependencyRecovery = this.dependencyProvenanceRecoveryPreflight(repositoryRoot, activeTask.id);
|
|
3049
|
+
if (dependencyRecovery.eligible) {
|
|
3050
|
+
return withAdoption({
|
|
3051
|
+
scope: 'task',
|
|
3052
|
+
id: activeTask.id,
|
|
3053
|
+
status: activeTask.status,
|
|
3054
|
+
action: 'update dependency-provenance-recover',
|
|
3055
|
+
revision: activeTask.revision,
|
|
3056
|
+
dependencyProvenanceRecovery: dependencyRecovery,
|
|
3057
|
+
});
|
|
3058
|
+
}
|
|
2942
3059
|
const activeTaskMilestone = activeTask.milestoneId
|
|
2943
3060
|
? milestonesById.get(activeTask.milestoneId) ?? null
|
|
2944
3061
|
: null;
|
|
@@ -3961,6 +4078,27 @@ export class WorkflowService {
|
|
|
3961
4078
|
},
|
|
3962
4079
|
};
|
|
3963
4080
|
}
|
|
4081
|
+
inspectDependencyProvenanceCandidate(snapshot, task) {
|
|
4082
|
+
const versions = inspectWorkflowVersions(snapshot.identity.repositoryRoot, [task.baseBranch]);
|
|
4083
|
+
const now = this.now().getTime();
|
|
4084
|
+
return inspectDependencyProvenanceRecovery(snapshot.identity.repositoryRoot, task, {
|
|
4085
|
+
activeLeaseCount: snapshot.leases.filter((lease) => Date.parse(lease.expiresAt) > now).length,
|
|
4086
|
+
staleLeaseCount: snapshot.leases.filter((lease) => Date.parse(lease.expiresAt) <= now).length,
|
|
4087
|
+
pendingTransactionCount: snapshot.observation.pendingProjectTransactions.length
|
|
4088
|
+
+ snapshot.observation.pendingMilestoneTransactions.length
|
|
4089
|
+
+ snapshot.observation.pendingTaskTransactions.length,
|
|
4090
|
+
corruptTransactionCount: snapshot.observation.corruptTaskTransactions.length,
|
|
4091
|
+
coreOperationCount: snapshot.observation.coreTaskOperations.length,
|
|
4092
|
+
versions: {
|
|
4093
|
+
runtime: versions.runtime,
|
|
4094
|
+
declared: versions.declared,
|
|
4095
|
+
locked: versions.locked,
|
|
4096
|
+
installed: versions.installed,
|
|
4097
|
+
currentBranch: versions.currentBranch,
|
|
4098
|
+
baseBranch: versions.milestoneBases.find((base) => base.branch === task.baseBranch)?.version ?? null,
|
|
4099
|
+
},
|
|
4100
|
+
});
|
|
4101
|
+
}
|
|
3964
4102
|
withTaskNavigationContracts(task, next) {
|
|
3965
4103
|
const action = typeof next.action === 'string' ? next.action : null;
|
|
3966
4104
|
if (!action)
|