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.
@@ -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)