codex-workflow-v2 2.0.0-beta.1 → 2.0.0-beta.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.
@@ -74,6 +74,18 @@ export interface Alpha6StrictReviewRescuePreflight {
74
74
  expectedRevision?: number;
75
75
  }>;
76
76
  }
77
+ interface MilestoneInitialAssemblyOption {
78
+ action: 'linked-task-assembly' | 'milestone plan-set';
79
+ commands: string[];
80
+ description: string;
81
+ }
82
+ interface MilestoneInitialAssemblyNavigation {
83
+ milestoneId: string;
84
+ revision: number;
85
+ linkedTaskIds: string[];
86
+ executionAvailable: false;
87
+ options: MilestoneInitialAssemblyOption[];
88
+ }
77
89
  export declare class WorkflowService {
78
90
  readonly store: FileStateStore;
79
91
  private readonly now;
@@ -158,6 +170,7 @@ export declare class WorkflowService {
158
170
  discoveries: DiscoveryState[];
159
171
  tasks: TaskState[];
160
172
  milestones: MilestoneState[];
173
+ milestoneInitialAssembly: MilestoneInitialAssemblyNavigation[];
161
174
  delegations: DelegationGrant[];
162
175
  adoption: AdoptionPreparation;
163
176
  };
@@ -188,6 +201,7 @@ export declare class WorkflowService {
188
201
  private delegatedAuthorization;
189
202
  private assertHandoffGrant;
190
203
  private nextForTaskWithDelegation;
204
+ private taskPlanContract;
191
205
  private assertTaskContextChangeAllowed;
192
206
  private taskHasTerminalCorrectiveDecision;
193
207
  private taskTerminalCorrectivePosture;
@@ -200,6 +214,9 @@ export declare class WorkflowService {
200
214
  private readMilestoneCurrent;
201
215
  private readMilestoneScopeChangeCurrent;
202
216
  private listMilestonesCurrent;
217
+ private taskGitNavigationOverride;
218
+ private withTaskNavigationContracts;
219
+ private describeMilestoneInitialAssembly;
203
220
  private prepareMilestoneScopeChangeCandidate;
204
221
  private proveWriterLeaseTokenForHandoff;
205
222
  private proveOptionalWriterLeaseToken;
@@ -217,3 +234,4 @@ export declare class WorkflowService {
217
234
  private validateKnowledgeTargets;
218
235
  private assertReviewFresh;
219
236
  }
237
+ export {};
@@ -13,7 +13,7 @@ import { appendTaskClaim, appendTaskHandback, appendTaskHandoff, assertTaskMutat
13
13
  import { applyAdoptionPosture, assertAdoptionBaselinePreserved, buildAdoptionPreparation, initializeProjectRegistrationAdoption, readCurrentAdoptionPosture, } from './alpha6/adoption.js';
14
14
  import { appendCurrentPlanRiskAudit, appendReboundPlanRiskAudit, readCurrentPlanRiskAudit, validatePlanRiskAuditCandidate, } from './alpha6/plan-risk.js';
15
15
  import { appendCorrectiveDecisionEvent, appendRemediationEvent, appendRemediationModeRecovery, assertCorrectiveAuditorIndependence, assertGuardedRemediationAttemptAllowed, defaultCorrectiveAuditorActor, findCurrentGuardedRemediationPosture, findRemediationModeRecoveryCandidate, findFailedGuardedStepRequiringCorrectiveDecision, readGuardedRemediationPostureForStep, readCorrectiveDecisionEvents, readRemediationEvents, } from './alpha6/remediation.js';
16
- import { applyMilestoneScopeChangeTransaction, assertMilestoneMembershipIntegrity, assertMilestoneScopeChangeStatusAllowed, normalizeMilestonePlan, prepareMilestoneScopeChangeCandidate, prepareMilestoneScopeChangeBundle, readMilestoneForScopeChange, readMilestoneWithIntegrity, } from './alpha6/milestone.js';
16
+ import { assessMilestoneInitialAssembly, applyMilestoneScopeChangeTransaction, assertMilestoneMembershipIntegrity, assertMilestoneScopeChangeStatusAllowed, normalizeMilestonePlan, prepareMilestoneScopeChangeCandidate, prepareMilestoneScopeChangeBundle, readMilestoneForScopeChange, readMilestoneWithIntegrity, } from './alpha6/milestone.js';
17
17
  import { applyProjectTransaction, recoverProjectTransactions, runRollbackProjectTransaction, } from './beta1/project-transaction.js';
18
18
  import { buildCurrentStrictStepReviewCycle, ensurePendingStrictStepReview, isStepReviewRequired, recordStrictStepReview, } from './alpha6/review.js';
19
19
  import { applyMilestoneAutonomyContract, assertAutonomousPlanEvolution, prepareMilestoneAutonomyContract, readMilestoneAutonomyEvents, requireActiveMilestoneAutonomy, } from './alpha7/autonomy.js';
@@ -2154,11 +2154,15 @@ export class WorkflowService {
2154
2154
  const tasks = this.store.listTasks(identity.projectId);
2155
2155
  const rawMilestones = this.store.listMilestones(identity.projectId);
2156
2156
  const adoption = this.inspectAdoptionPreparation(identity, tasks, rawMilestones);
2157
+ const milestones = this.listMilestonesCurrent(identity.projectId, adoption.currentPosture);
2157
2158
  return {
2158
2159
  projectId: identity.projectId,
2159
2160
  discoveries: this.store.listDiscoveries(identity.projectId),
2160
2161
  tasks,
2161
- milestones: this.listMilestonesCurrent(identity.projectId, adoption.currentPosture),
2162
+ milestones,
2163
+ milestoneInitialAssembly: milestones
2164
+ .map((milestone) => this.describeMilestoneInitialAssembly(identity.projectId, milestone, tasks))
2165
+ .filter((value) => value !== null),
2162
2166
  delegations: this.store.listDelegations(identity.projectId),
2163
2167
  adoption,
2164
2168
  };
@@ -2588,6 +2592,31 @@ export class WorkflowService {
2588
2592
  }
2589
2593
  const activeMilestone = status.milestones.find((milestone) => !['accepted', 'cancelled'].includes(milestone.status));
2590
2594
  if (activeMilestone) {
2595
+ const initialAssembly = status.milestoneInitialAssembly
2596
+ .find((candidate) => candidate.milestoneId === activeMilestone.id) ?? null;
2597
+ if (initialAssembly) {
2598
+ const activeDiscovery = status.discoveries.find((discovery) => !['materialized', 'abandoned'].includes(discovery.status));
2599
+ if (activeDiscovery) {
2600
+ return withAdoption({
2601
+ scope: 'discovery',
2602
+ id: activeDiscovery.id,
2603
+ status: activeDiscovery.status,
2604
+ action: activeDiscovery.status === 'ready_to_materialize' ? 'discovery materialize' : 'discovery update',
2605
+ readiness: assessDiscovery(activeDiscovery),
2606
+ milestoneInitialAssembly: initialAssembly,
2607
+ });
2608
+ }
2609
+ return withAdoption({
2610
+ scope: 'milestone',
2611
+ id: activeMilestone.id,
2612
+ status: activeMilestone.status,
2613
+ action: 'milestone initial-assembly',
2614
+ revision: activeMilestone.revision,
2615
+ linkedTaskIds: initialAssembly.linkedTaskIds,
2616
+ executionAvailable: initialAssembly.executionAvailable,
2617
+ milestoneInitialAssembly: initialAssembly,
2618
+ });
2619
+ }
2591
2620
  if (activeMilestone.status === 'awaiting_final_acceptance') {
2592
2621
  const root = this.store.milestoneRoot(activeMilestone.projectId, activeMilestone.id);
2593
2622
  const evidence = JSON.parse(readFileSync(path.join(root, 'evidence.json'), 'utf8'));
@@ -2794,7 +2823,7 @@ export class WorkflowService {
2794
2823
  throw error;
2795
2824
  }
2796
2825
  }
2797
- const next = nextForTask(task);
2826
+ const next = this.taskGitNavigationOverride(task) ?? nextForTask(task);
2798
2827
  const handoffPosture = readTaskC1Posture(this.store, task);
2799
2828
  const strictStepReviewStep = planRiskAudit
2800
2829
  ? task.steps.find((step) => {
@@ -3051,13 +3080,31 @@ export class WorkflowService {
3051
3080
  ...(delegatedApprovalOptions.length > 0 ? { delegatedApprovalOptions } : {}),
3052
3081
  };
3053
3082
  if (handoffPosture.state === 'pending') {
3054
- return {
3083
+ return this.withTaskNavigationContracts(task, {
3055
3084
  ...result,
3056
3085
  action: 'task claim',
3057
3086
  blockedAction: next.action,
3058
- };
3087
+ });
3059
3088
  }
3060
- return result;
3089
+ const navigableResult = ['task plan-set', 'task plan-set with independent corrective audit']
3090
+ .includes(String(result.action))
3091
+ ? {
3092
+ ...result,
3093
+ taskPlanContract: this.taskPlanContract(projectId, task),
3094
+ }
3095
+ : result;
3096
+ return this.withTaskNavigationContracts(task, navigableResult);
3097
+ }
3098
+ taskPlanContract(projectId, task) {
3099
+ const map = this.store.readKnowledgeMap(projectId);
3100
+ return {
3101
+ requiredRequirementIds: [...task.requirements],
3102
+ requiredAcceptanceIds: [...task.acceptance],
3103
+ currentRisks: [...task.risks],
3104
+ exactInclusionRequired: true,
3105
+ briefHash: task.briefHash,
3106
+ knowledgeMap: knowledgeSummary(map),
3107
+ };
3061
3108
  }
3062
3109
  assertTaskContextChangeAllowed(task) {
3063
3110
  const posture = this.taskTerminalCorrectivePosture(task);
@@ -3205,6 +3252,70 @@ export class WorkflowService {
3205
3252
  ? milestone
3206
3253
  : readMilestoneWithIntegrity(this.store, projectId, milestone.id, (taskId) => this.store.readTask(projectId, taskId), () => this.store.listTasks(projectId))));
3207
3254
  }
3255
+ taskGitNavigationOverride(task) {
3256
+ if (task.status !== 'merging' || task.workspaceOwner !== 'local' || !task.baseCommit || !task.taskBranch) {
3257
+ return null;
3258
+ }
3259
+ const currentBase = runGit(task.repositoryRoot, ['rev-parse', task.baseBranch]);
3260
+ if (currentBase === task.baseCommit)
3261
+ return null;
3262
+ return {
3263
+ scope: 'task',
3264
+ id: task.id,
3265
+ status: task.status,
3266
+ action: 'task sync-base',
3267
+ revision: task.revision,
3268
+ baseSyncRequired: {
3269
+ baseBranch: task.baseBranch,
3270
+ recordedBaseCommit: task.baseCommit,
3271
+ currentBaseCommit: currentBase,
3272
+ },
3273
+ };
3274
+ }
3275
+ withTaskNavigationContracts(task, next) {
3276
+ const action = typeof next.action === 'string' ? next.action : null;
3277
+ if (!action)
3278
+ return next;
3279
+ const policy = gitMutationPolicyForAction(task, action);
3280
+ const claimedC1Posture = readTaskC1Posture(this.store, task).state === 'claimed';
3281
+ const writerTokenContract = writerTokenContractForAction(action, claimedC1Posture);
3282
+ return {
3283
+ ...next,
3284
+ ...(policy ? { gitMutationPolicy: policy } : {}),
3285
+ ...(writerTokenContract ? { writerTokenContract } : {}),
3286
+ };
3287
+ }
3288
+ describeMilestoneInitialAssembly(projectId, milestone, tasks) {
3289
+ const assessment = assessMilestoneInitialAssembly({
3290
+ store: this.store,
3291
+ projectId,
3292
+ milestone,
3293
+ listTasks: () => tasks,
3294
+ });
3295
+ if (!assessment.eligible)
3296
+ return null;
3297
+ const options = [
3298
+ {
3299
+ action: 'linked-task-assembly',
3300
+ commands: ['discovery start', 'discovery materialize'],
3301
+ description: 'Start or materialize the next linked Task Discovery for this Milestone before closing the initial membership Plan.',
3302
+ },
3303
+ ];
3304
+ if (assessment.orphanTaskIds.length > 0) {
3305
+ options.push({
3306
+ action: 'milestone plan-set',
3307
+ commands: ['milestone plan-set'],
3308
+ description: 'Record one complete initial Milestone Plan that classifies every currently linked Task.',
3309
+ });
3310
+ }
3311
+ return {
3312
+ milestoneId: milestone.id,
3313
+ revision: milestone.revision,
3314
+ linkedTaskIds: assessment.orphanTaskIds,
3315
+ executionAvailable: false,
3316
+ options,
3317
+ };
3318
+ }
3208
3319
  prepareMilestoneScopeChangeCandidate(projectId, milestone, plan, actor) {
3209
3320
  validateMilestonePlan(plan);
3210
3321
  return prepareMilestoneScopeChangeCandidate({
@@ -3860,13 +3971,13 @@ function nextForTask(task) {
3860
3971
  awaiting_execution_authorization: 'task authorize',
3861
3972
  ready: task.workspaceOwner ? (stepsComplete ? 'task submit' : 'task run') : 'task start',
3862
3973
  in_progress: activeStep ? 'task step-complete' : stepsComplete ? 'task submit' : 'task run',
3863
- validating: task.review.status === 'passed' ? 'task result-set' : 'task review-record',
3974
+ validating: task.review.status === 'passed' ? 'task result-set' : 'task review-launch',
3864
3975
  needs_fix: task.steps.some((step) => step.status === 'failed') ? 'task run' : 'task plan-set',
3865
3976
  awaiting_final_acceptance: 'task accept',
3866
3977
  merging: 'task merge',
3867
3978
  ready_to_merge: 'task merge-confirm',
3868
3979
  merged: 'none',
3869
- blocked: task.review.status === 'unverified' ? 'task review-record' : 'doctor',
3980
+ blocked: task.review.status === 'unverified' ? 'task review-launch' : 'doctor',
3870
3981
  cancelled: 'none',
3871
3982
  };
3872
3983
  const selectedStep = activeStep ?? failedStep ?? runnableStep;
@@ -3888,6 +3999,73 @@ function nextForTask(task) {
3888
3999
  : {}),
3889
4000
  };
3890
4001
  }
4002
+ function gitMutationPolicyForAction(task, action) {
4003
+ const metadataWrites = ['.git/index', '.git/index.lock', '.git/HEAD', '.git/refs', '.git/logs'];
4004
+ switch (action) {
4005
+ case 'task start':
4006
+ return {
4007
+ permission: 'git-metadata-write',
4008
+ requiredBeforeFirstCall: true,
4009
+ boundedToTransition: true,
4010
+ transition: 'task start',
4011
+ appliesWhen: { workspaceOwner: 'local' },
4012
+ metadataWrites,
4013
+ };
4014
+ case 'task step-complete':
4015
+ return {
4016
+ permission: 'git-metadata-write',
4017
+ requiredBeforeFirstCall: true,
4018
+ boundedToTransition: true,
4019
+ transition: 'task step-complete',
4020
+ metadataWrites,
4021
+ };
4022
+ case 'task merge':
4023
+ if (task.workspaceOwner !== 'local')
4024
+ return null;
4025
+ return {
4026
+ permission: 'git-metadata-write',
4027
+ requiredBeforeFirstCall: true,
4028
+ boundedToTransition: true,
4029
+ transition: 'task merge',
4030
+ metadataWrites,
4031
+ };
4032
+ case 'task sync-base':
4033
+ return {
4034
+ permission: 'git-metadata-write',
4035
+ requiredBeforeFirstCall: true,
4036
+ boundedToTransition: true,
4037
+ transition: 'task sync-base',
4038
+ metadataWrites,
4039
+ };
4040
+ default:
4041
+ return null;
4042
+ }
4043
+ }
4044
+ function writerTokenContractForAction(action, claimedC1Posture = false) {
4045
+ const alwaysLeaseBound = ['task step-complete', 'task submit', 'task merge', 'task merge-confirm'];
4046
+ const claimedC1LeaseBound = [
4047
+ 'task run',
4048
+ 'task step-review',
4049
+ 'task review-record',
4050
+ 'task review-launch',
4051
+ 'task corrective-decision-recover',
4052
+ 'task remediation-mode-recover',
4053
+ 'task corrective-decision',
4054
+ 'task handoff',
4055
+ 'task handoff-prepare',
4056
+ 'task handback',
4057
+ 'task handback-create',
4058
+ ];
4059
+ if (!alwaysLeaseBound.includes(action) && !(claimedC1Posture && claimedC1LeaseBound.includes(action))) {
4060
+ return null;
4061
+ }
4062
+ return {
4063
+ required: true,
4064
+ option: '--writer-token',
4065
+ source: 'active-writer-lease',
4066
+ sensitive: true,
4067
+ };
4068
+ }
3891
4069
  function knowledgeSummary(map) {
3892
4070
  return {
3893
4071
  revision: map.revision,