codex-orchestrator 2.0.10 → 2.0.11
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/CHANGELOG.md +37 -0
- package/README.md +26 -1
- package/dist/src/index.d.ts +3 -2
- package/dist/src/index.d.ts.map +1 -1
- package/dist/src/index.js +1 -1
- package/dist/src/index.js.map +1 -1
- package/dist/src/v2/acceptance-proof.d.ts +29 -16
- package/dist/src/v2/acceptance-proof.d.ts.map +1 -1
- package/dist/src/v2/acceptance-proof.js +159 -129
- package/dist/src/v2/acceptance-proof.js.map +1 -1
- package/dist/src/v2/adapters/command.d.ts +1 -0
- package/dist/src/v2/adapters/command.d.ts.map +1 -1
- package/dist/src/v2/adapters/command.js +1 -1
- package/dist/src/v2/adapters/command.js.map +1 -1
- package/dist/src/v2/adapters/gh-pull-request-adapter.js +1 -0
- package/dist/src/v2/adapters/gh-pull-request-adapter.js.map +1 -1
- package/dist/src/v2/adapters/pull-requests.d.ts +1 -0
- package/dist/src/v2/adapters/pull-requests.d.ts.map +1 -1
- package/dist/src/v2/adapters/pull-requests.js +1 -0
- package/dist/src/v2/adapters/pull-requests.js.map +1 -1
- package/dist/src/v2/adapters/worktree.js +3 -3
- package/dist/src/v2/adapters/worktree.js.map +1 -1
- package/dist/src/v2/atomic-store.d.ts +15 -0
- package/dist/src/v2/atomic-store.d.ts.map +1 -1
- package/dist/src/v2/atomic-store.js +55 -8
- package/dist/src/v2/atomic-store.js.map +1 -1
- package/dist/src/v2/candidate.d.ts +152 -0
- package/dist/src/v2/candidate.d.ts.map +1 -0
- package/dist/src/v2/candidate.js +129 -0
- package/dist/src/v2/candidate.js.map +1 -0
- package/dist/src/v2/checked-change.d.ts +37 -6
- package/dist/src/v2/checked-change.d.ts.map +1 -1
- package/dist/src/v2/checked-change.js +71 -0
- package/dist/src/v2/checked-change.js.map +1 -1
- package/dist/src/v2/cli.d.ts +6 -0
- package/dist/src/v2/cli.d.ts.map +1 -1
- package/dist/src/v2/cli.js +57 -21
- package/dist/src/v2/cli.js.map +1 -1
- package/dist/src/v2/codex-process.d.ts +1 -0
- package/dist/src/v2/codex-process.d.ts.map +1 -1
- package/dist/src/v2/codex-process.js +12 -1
- package/dist/src/v2/codex-process.js.map +1 -1
- package/dist/src/v2/contained-report-operation.d.ts +196 -30
- package/dist/src/v2/contained-report-operation.d.ts.map +1 -1
- package/dist/src/v2/contained-report-operation.js +464 -150
- package/dist/src/v2/contained-report-operation.js.map +1 -1
- package/dist/src/v2/direct-delivery.d.ts +10 -28
- package/dist/src/v2/direct-delivery.d.ts.map +1 -1
- package/dist/src/v2/direct-delivery.js +44 -114
- package/dist/src/v2/direct-delivery.js.map +1 -1
- package/dist/src/v2/implementation-reviewer.d.ts +4 -24
- package/dist/src/v2/implementation-reviewer.d.ts.map +1 -1
- package/dist/src/v2/implementation-reviewer.js +29 -35
- package/dist/src/v2/implementation-reviewer.js.map +1 -1
- package/dist/src/v2/owner-control-lock.d.ts +13 -1
- package/dist/src/v2/owner-control-lock.d.ts.map +1 -1
- package/dist/src/v2/owner-control-lock.js +66 -7
- package/dist/src/v2/owner-control-lock.js.map +1 -1
- package/dist/src/v2/proof-report.d.ts +2 -1
- package/dist/src/v2/proof-report.d.ts.map +1 -1
- package/dist/src/v2/proof-report.js +6 -40
- package/dist/src/v2/proof-report.js.map +1 -1
- package/dist/src/v2/proof-store.d.ts +19 -7
- package/dist/src/v2/proof-store.d.ts.map +1 -1
- package/dist/src/v2/proof-store.js +162 -41
- package/dist/src/v2/proof-store.js.map +1 -1
- package/dist/src/v2/review-feedback-coordinator.d.ts +7 -1
- package/dist/src/v2/review-feedback-coordinator.d.ts.map +1 -1
- package/dist/src/v2/review-feedback-coordinator.js +97 -70
- package/dist/src/v2/review-feedback-coordinator.js.map +1 -1
- package/dist/src/v2/review-feedback.d.ts +0 -18
- package/dist/src/v2/review-feedback.d.ts.map +1 -1
- package/dist/src/v2/review-feedback.js +9 -34
- package/dist/src/v2/review-feedback.js.map +1 -1
- package/dist/src/v2/route-coordinator.d.ts +7 -12
- package/dist/src/v2/route-coordinator.d.ts.map +1 -1
- package/dist/src/v2/route-coordinator.js +33 -128
- package/dist/src/v2/route-coordinator.js.map +1 -1
- package/dist/src/v2/route-decision.d.ts +0 -9
- package/dist/src/v2/route-decision.d.ts.map +1 -1
- package/dist/src/v2/route-decision.js +7 -27
- package/dist/src/v2/route-decision.js.map +1 -1
- package/dist/src/v2/run-issue.d.ts +64 -26
- package/dist/src/v2/run-issue.d.ts.map +1 -1
- package/dist/src/v2/run-issue.js +1298 -620
- package/dist/src/v2/run-issue.js.map +1 -1
- package/dist/src/v2/run-store.d.ts +39 -25
- package/dist/src/v2/run-store.d.ts.map +1 -1
- package/dist/src/v2/run-store.js +469 -88
- package/dist/src/v2/run-store.js.map +1 -1
- package/dist/src/v2/runtime.d.ts +61 -36
- package/dist/src/v2/runtime.d.ts.map +1 -1
- package/dist/src/v2/runtime.js +992 -402
- package/dist/src/v2/runtime.js.map +1 -1
- package/dist/src/v2/spec-coordinator.d.ts +16 -28
- package/dist/src/v2/spec-coordinator.d.ts.map +1 -1
- package/dist/src/v2/spec-coordinator.js +81 -43
- package/dist/src/v2/spec-coordinator.js.map +1 -1
- package/dist/src/v2/spec-delivery.d.ts +3 -34
- package/dist/src/v2/spec-delivery.d.ts.map +1 -1
- package/dist/src/v2/spec-delivery.js +42 -107
- package/dist/src/v2/spec-delivery.js.map +1 -1
- package/docs/deep-dive.md +52 -14
- package/internal-workflow/evals/coding-skill-evals.json +58 -17
- package/internal-workflow/manifest.json +1 -1
- package/internal-workflow/schemas/proof-report-v1.json +1 -1
- package/internal-workflow/skills/code-review/SKILL.md +18 -0
- package/internal-workflow/skills/spec-implementer/SKILL.md +8 -1
- package/package.json +1 -1
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { acceptSpecReview, acceptSpecRevision, createInitialSpecDelivery, freezeApprovedSpec,
|
|
1
|
+
import { acceptSpecReview, acceptSpecRevision, createInitialSpecDelivery, freezeApprovedSpec, recoverMalformedSpecReport, reserveSpecAuthorSession, reserveSpecReviewerSession, } from './spec-delivery.js';
|
|
2
2
|
export class SpecCoordinator {
|
|
3
3
|
dependencies;
|
|
4
4
|
constructor(dependencies) {
|
|
@@ -33,56 +33,94 @@ export class SpecCoordinator {
|
|
|
33
33
|
current = frozen;
|
|
34
34
|
continue;
|
|
35
35
|
}
|
|
36
|
-
const author = current.
|
|
37
|
-
const mode =
|
|
36
|
+
const author = current.stage === 'authoring' || current.stage === 'author-repair';
|
|
37
|
+
const mode = author ? (current.stage === 'authoring' ? 'author' : 'repair')
|
|
38
|
+
: (current.stage === 'review-full' ? 'full' : 'closure');
|
|
38
39
|
let active = current;
|
|
39
|
-
const
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
const next = launchSpecInvocation(active, actor);
|
|
49
|
-
if (!await this.dependencies.state.compareAndSwap(active, next))
|
|
50
|
-
throw new Error('spec launched state conflict');
|
|
51
|
-
active = next;
|
|
52
|
-
};
|
|
53
|
-
const result = current.invocation
|
|
54
|
-
? await this.dependencies.operation.recover({ context, state: current, signal })
|
|
55
|
-
: author
|
|
56
|
-
? await this.dependencies.operation.author({ context, state: current, mode: mode, signal, onPrepared, onLaunched })
|
|
57
|
-
: await this.dependencies.operation.review({ context, state: current, mode: mode, signal, onPrepared, onLaunched });
|
|
40
|
+
const authorSessionId = author ? current.authorSessionId ?? this.dependencies.createAuthorSessionId() : undefined;
|
|
41
|
+
const reviewerSessionId = author ? undefined : current.review.reviewerSessionId ?? this.dependencies.createReviewerSessionId();
|
|
42
|
+
const reviewState = author ? undefined : reserveSpecReviewerSession(current, reviewerSessionId);
|
|
43
|
+
const authorState = author ? reserveSpecAuthorSession(current, authorSessionId) : undefined;
|
|
44
|
+
const result = author
|
|
45
|
+
? await this.dependencies.operation.author({ context, state: authorState, mode: mode, authorSessionId: authorSessionId,
|
|
46
|
+
signal, invocationState: this.dependencies.state.authorInvocation(authorSessionId) })
|
|
47
|
+
: await this.dependencies.operation.review({ context, state: reviewState, mode: mode, reviewerSessionId: reviewerSessionId,
|
|
48
|
+
signal, invocationState: this.dependencies.state.reviewInvocation(reviewerSessionId) });
|
|
58
49
|
if (result.status === 'retryable') {
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
continue;
|
|
68
|
-
}
|
|
69
|
-
catch {
|
|
70
|
-
const exhausted = { ...structuredClone(active), stage: 'exhausted' };
|
|
71
|
-
delete exhausted.invocation;
|
|
72
|
-
if (!await this.dependencies.state.compareAndSwap(active, exhausted))
|
|
73
|
-
return { status: 'retryable', code: 'spec-exhaustion-state-conflict' };
|
|
74
|
-
return { status: 'blocked', kind: 'exhausted', code: 'spec-retry-budget-exhausted', evidence: [] };
|
|
75
|
-
}
|
|
50
|
+
return result;
|
|
51
|
+
}
|
|
52
|
+
if (result.status === 'invalid') {
|
|
53
|
+
const settlement = await this.settleInvalid(author ? 'author' : 'review', result.attemptId);
|
|
54
|
+
if (settlement.status === 'returned')
|
|
55
|
+
return settlement.result;
|
|
56
|
+
current = settlement.state;
|
|
57
|
+
continue;
|
|
76
58
|
}
|
|
77
59
|
if (result.status !== 'completed')
|
|
78
60
|
return result.status === 'blocked' ? { ...result, evidence: [] } : result;
|
|
79
|
-
const
|
|
80
|
-
|
|
81
|
-
:
|
|
82
|
-
|
|
61
|
+
const refreshed = await this.dependencies.state.read();
|
|
62
|
+
if (!refreshed)
|
|
63
|
+
return { status: 'retryable', code: 'spec-state-missing' };
|
|
64
|
+
active = refreshed;
|
|
65
|
+
const attemptId = author
|
|
66
|
+
? result.value.author.attemptId
|
|
67
|
+
: result.value.reviewer.attemptId;
|
|
68
|
+
let next;
|
|
69
|
+
try {
|
|
70
|
+
next = author
|
|
71
|
+
? acceptSpecRevision(active, result.value)
|
|
72
|
+
: acceptSpecReview(active, result.value, result.reportSha256 ?? '0'.repeat(64));
|
|
73
|
+
}
|
|
74
|
+
catch {
|
|
75
|
+
const settlement = await this.settleInvalid(author ? 'author' : 'review', attemptId);
|
|
76
|
+
if (settlement.status === 'returned')
|
|
77
|
+
return settlement.result;
|
|
78
|
+
current = settlement.state;
|
|
79
|
+
continue;
|
|
80
|
+
}
|
|
81
|
+
let saved;
|
|
82
|
+
try {
|
|
83
|
+
saved = author
|
|
84
|
+
? await this.dependencies.state.settleAuthor(active, next, attemptId)
|
|
85
|
+
: await this.dependencies.state.settleReview(active, next, attemptId);
|
|
86
|
+
}
|
|
87
|
+
catch {
|
|
88
|
+
return { status: 'retryable', code: 'spec-result-state-conflict' };
|
|
89
|
+
}
|
|
90
|
+
if (!saved)
|
|
83
91
|
return { status: 'retryable', code: 'spec-result-state-conflict' };
|
|
84
92
|
current = next;
|
|
85
93
|
}
|
|
86
94
|
}
|
|
95
|
+
async settleInvalid(owner, attemptId) {
|
|
96
|
+
const active = await this.dependencies.state.read();
|
|
97
|
+
if (!active)
|
|
98
|
+
return { status: 'returned', result: { status: 'retryable', code: 'spec-state-missing' } };
|
|
99
|
+
let next;
|
|
100
|
+
let exhausted = false;
|
|
101
|
+
try {
|
|
102
|
+
next = recoverMalformedSpecReport(active, owner);
|
|
103
|
+
}
|
|
104
|
+
catch {
|
|
105
|
+
next = { ...structuredClone(active), stage: 'exhausted' };
|
|
106
|
+
exhausted = true;
|
|
107
|
+
}
|
|
108
|
+
let settled;
|
|
109
|
+
try {
|
|
110
|
+
settled = owner === 'author'
|
|
111
|
+
? await this.dependencies.state.settleAuthor(active, next, attemptId)
|
|
112
|
+
: await this.dependencies.state.settleReview(active, next, attemptId);
|
|
113
|
+
}
|
|
114
|
+
catch {
|
|
115
|
+
return { status: 'returned', result: { status: 'retryable', code: exhausted
|
|
116
|
+
? 'spec-exhaustion-state-conflict' : 'spec-recovery-state-conflict' } };
|
|
117
|
+
}
|
|
118
|
+
if (!settled)
|
|
119
|
+
return { status: 'returned', result: { status: 'retryable', code: exhausted
|
|
120
|
+
? 'spec-exhaustion-state-conflict' : 'spec-recovery-state-conflict' } };
|
|
121
|
+
return exhausted
|
|
122
|
+
? { status: 'returned', result: { status: 'blocked', kind: 'exhausted', code: 'spec-retry-budget-exhausted', evidence: [] } }
|
|
123
|
+
: { status: 'continued', state: next };
|
|
124
|
+
}
|
|
87
125
|
}
|
|
88
126
|
//# sourceMappingURL=spec-coordinator.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"spec-coordinator.js","sourceRoot":"","sources":["../../../src/v2/spec-coordinator.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,gBAAgB,EAAE,kBAAkB,EAAE,yBAAyB,EAAE,kBAAkB,EACnF,
|
|
1
|
+
{"version":3,"file":"spec-coordinator.js","sourceRoot":"","sources":["../../../src/v2/spec-coordinator.ts"],"names":[],"mappings":"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"}
|
|
@@ -40,20 +40,6 @@ export interface SpecReviewReportV1 {
|
|
|
40
40
|
acceptedRisks: SpecAcceptedRiskV1[];
|
|
41
41
|
coverageInvalidated: boolean;
|
|
42
42
|
}
|
|
43
|
-
export interface SpecInvocationV1 {
|
|
44
|
-
purpose: 'author' | 'review';
|
|
45
|
-
mode: 'author' | 'repair' | 'full' | 'closure';
|
|
46
|
-
attemptId: string;
|
|
47
|
-
sessionId: string;
|
|
48
|
-
targetRevision: number;
|
|
49
|
-
targetSha256: string | null;
|
|
50
|
-
closureRequestSha256: string | null;
|
|
51
|
-
status: 'prepared' | 'launched';
|
|
52
|
-
pid: number | null;
|
|
53
|
-
processGroupId: number | null;
|
|
54
|
-
reportPath: string | null;
|
|
55
|
-
revisionPath: string | null;
|
|
56
|
-
}
|
|
57
43
|
export interface FrozenSpecReceiptV1 {
|
|
58
44
|
version: 1;
|
|
59
45
|
issueNumber: number;
|
|
@@ -77,6 +63,7 @@ export interface SpecDeliveryV1 {
|
|
|
77
63
|
authorSessionId: string | null;
|
|
78
64
|
review: {
|
|
79
65
|
reviewer: SpecActorV1 | null;
|
|
66
|
+
reviewerSessionId: string | null;
|
|
80
67
|
mode: 'full' | 'closure' | null;
|
|
81
68
|
coverage: string[];
|
|
82
69
|
defects: CodeReviewDefectV1[];
|
|
@@ -89,15 +76,12 @@ export interface SpecDeliveryV1 {
|
|
|
89
76
|
budgets: {
|
|
90
77
|
author: {
|
|
91
78
|
reportRepairs: 0 | 1;
|
|
92
|
-
transportRetries: 0 | 1;
|
|
93
79
|
};
|
|
94
80
|
review: {
|
|
95
81
|
reportRepairs: 0 | 1;
|
|
96
|
-
transportRetries: 0 | 1;
|
|
97
82
|
};
|
|
98
83
|
repairCycles: 0 | 1;
|
|
99
84
|
};
|
|
100
|
-
invocation?: SpecInvocationV1;
|
|
101
85
|
frozen?: FrozenSpecReceiptV1;
|
|
102
86
|
}
|
|
103
87
|
export declare function createInitialSpecDelivery(input: {
|
|
@@ -115,28 +99,13 @@ export declare function createSpecRevision(input: {
|
|
|
115
99
|
}): SpecRevisionV1;
|
|
116
100
|
export declare function hashSpecRevision(revision: Omit<SpecRevisionV1, 'revisionSha256'> | SpecRevisionV1): string;
|
|
117
101
|
export declare function validateSpecRevision(value: unknown, previous: SpecRevisionV1 | null): SpecRevisionV1;
|
|
118
|
-
export declare function
|
|
119
|
-
purpose: 'author' | 'review';
|
|
120
|
-
mode: 'author' | 'repair' | 'full' | 'closure';
|
|
121
|
-
attemptId: string;
|
|
122
|
-
sessionId: string;
|
|
123
|
-
reportPath?: string;
|
|
124
|
-
revisionPath?: string;
|
|
125
|
-
}): SpecDeliveryV1;
|
|
126
|
-
export declare function launchSpecInvocation(state: SpecDeliveryV1, input: {
|
|
127
|
-
attemptId: string;
|
|
128
|
-
pid: number;
|
|
129
|
-
processGroupId: number;
|
|
130
|
-
}): SpecDeliveryV1;
|
|
102
|
+
export declare function reserveSpecAuthorSession(state: SpecDeliveryV1, sessionId: string): SpecDeliveryV1;
|
|
131
103
|
export declare function acceptSpecRevision(state: SpecDeliveryV1, revision: SpecRevisionV1): SpecDeliveryV1;
|
|
132
104
|
export declare function acceptSpecReview(state: SpecDeliveryV1, report: SpecReviewReportV1, reportSha256: string): SpecDeliveryV1;
|
|
105
|
+
export declare function reserveSpecReviewerSession(state: SpecDeliveryV1, reviewerSessionId: string): SpecDeliveryV1;
|
|
133
106
|
export declare function hashSpecClosureRequest(state: SpecDeliveryV1): string;
|
|
134
107
|
export declare function consumeSpecReportRepair(state: SpecDeliveryV1, owner: 'author' | 'review'): SpecDeliveryV1;
|
|
135
108
|
export declare function recoverMalformedSpecReport(state: SpecDeliveryV1, owner: 'author' | 'review'): SpecDeliveryV1;
|
|
136
|
-
export declare function recoverSpecInvocation(state: SpecDeliveryV1, input: {
|
|
137
|
-
attemptId: string;
|
|
138
|
-
processGroupAbsent: boolean;
|
|
139
|
-
}): SpecDeliveryV1;
|
|
140
109
|
export declare function freezeApprovedSpec(state: SpecDeliveryV1): SpecDeliveryV1;
|
|
141
110
|
export declare function validateFrozenSpecReceipt(value: unknown, state: SpecDeliveryV1): FrozenSpecReceiptV1;
|
|
142
111
|
export declare function validateSpecDelivery(value: unknown): SpecDeliveryV1;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"spec-delivery.d.ts","sourceRoot":"","sources":["../../../src/v2/spec-delivery.ts"],"names":[],"mappings":"AAGA,OAAO,EAA6B,KAAK,kBAAkB,EAAE,MAAM,yBAAyB,CAAC;AAO7F,MAAM,WAAW,cAAc;IAAG,IAAI,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,MAAM,CAAC;IAAC,WAAW,EAAE,MAAM,CAAA;CAAE;AACrF,MAAM,WAAW,WAAW;IAAG,SAAS,EAAE,MAAM,CAAC;IAAC,SAAS,EAAE,MAAM,CAAA;CAAE;AACrE,MAAM,WAAW,cAAc;IAC7B,OAAO,EAAE,CAAC,CAAC;IACX,QAAQ,EAAE,MAAM,CAAC;IACjB,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,CAAC;IAChB,aAAa,EAAE,MAAM,CAAC;IACtB,QAAQ,EAAE,cAAc,EAAE,CAAC;IAC3B,MAAM,EAAE,WAAW,CAAC;IACpB,sBAAsB,EAAE,MAAM,GAAG,IAAI,CAAC;IACtC,cAAc,EAAE,MAAM,CAAC;CACxB;AACD,MAAM,WAAW,kBAAkB;IACjC,QAAQ,EAAE,MAAM,CAAC;IACjB,SAAS,EAAE,MAAM,CAAC;IAClB,MAAM,EAAE,MAAM,CAAC;IACf,UAAU,EAAE,MAAM,CAAC;CACpB;AACD,MAAM,WAAW,kBAAkB;IACjC,OAAO,EAAE,CAAC,CAAC;IACX,cAAc,EAAE,MAAM,CAAC;IACvB,YAAY,EAAE,MAAM,CAAC;IACrB,IAAI,EAAE,MAAM,GAAG,SAAS,CAAC;IACzB,OAAO,EAAE,UAAU,GAAG,YAAY,GAAG,UAAU,CAAC;IAChD,QAAQ,EAAE,WAAW,CAAC;IACtB,QAAQ,EAAE,MAAM,EAAE,CAAC;IACnB,OAAO,EAAE,kBAAkB,EAAE,CAAC;IAC9B,iBAAiB,EAAE,MAAM,EAAE,CAAC;IAC5B,iBAAiB,EAAE,MAAM,EAAE,CAAC;IAC5B,oBAAoB,EAAE,MAAM,GAAG,IAAI,CAAC;IACpC,aAAa,EAAE,kBAAkB,EAAE,CAAC;IACpC,mBAAmB,EAAE,OAAO,CAAC;CAC9B;AACD,MAAM,WAAW,
|
|
1
|
+
{"version":3,"file":"spec-delivery.d.ts","sourceRoot":"","sources":["../../../src/v2/spec-delivery.ts"],"names":[],"mappings":"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"}
|
|
@@ -11,8 +11,8 @@ export function createInitialSpecDelivery(input) {
|
|
|
11
11
|
hash(input.workflowGenerationSha256, 'workflow generation hash');
|
|
12
12
|
return {
|
|
13
13
|
version: 1, ...input, stage: 'authoring', revisions: [], authorSessionId: null,
|
|
14
|
-
review: { reviewer: null, mode: null, coverage: [], defects: [], affectedDefectIds: [], affectedContracts: [], closureRequestSha256: null, acceptedRisks: [], acceptedReportSha256: null },
|
|
15
|
-
budgets: { author: { reportRepairs: 0
|
|
14
|
+
review: { reviewer: null, reviewerSessionId: null, mode: null, coverage: [], defects: [], affectedDefectIds: [], affectedContracts: [], closureRequestSha256: null, acceptedRisks: [], acceptedReportSha256: null },
|
|
15
|
+
budgets: { author: { reportRepairs: 0 }, review: { reportRepairs: 0 }, repairCycles: 0 },
|
|
16
16
|
};
|
|
17
17
|
}
|
|
18
18
|
export function createSpecRevision(input) {
|
|
@@ -56,42 +56,18 @@ export function validateSpecRevision(value, previous) {
|
|
|
56
56
|
throw new Error('spec revision hash is invalid');
|
|
57
57
|
return structuredClone(value);
|
|
58
58
|
}
|
|
59
|
-
export function
|
|
59
|
+
export function reserveSpecAuthorSession(state, sessionId) {
|
|
60
60
|
validateSpecDelivery(state);
|
|
61
|
-
if (state.
|
|
62
|
-
throw new Error('spec
|
|
63
|
-
|
|
64
|
-
if (
|
|
65
|
-
throw new Error('spec invocation does not match stage');
|
|
66
|
-
actor({ attemptId: input.attemptId, sessionId: input.sessionId }, 'spec invocation actor');
|
|
67
|
-
if (input.purpose === 'review') {
|
|
68
|
-
if (input.sessionId === state.authorSessionId || state.revisions.some((revision) => revision.author.attemptId === input.attemptId))
|
|
69
|
-
throw new Error('spec reviewer is not independent');
|
|
70
|
-
if (state.review.reviewer && state.review.reviewer.sessionId !== input.sessionId)
|
|
71
|
-
throw new Error('Closure reviewer identity changed');
|
|
72
|
-
}
|
|
73
|
-
else if (state.authorSessionId && state.authorSessionId !== input.sessionId)
|
|
61
|
+
if (state.stage !== 'authoring' && state.stage !== 'author-repair')
|
|
62
|
+
throw new Error('spec stage does not accept an author session');
|
|
63
|
+
text(sessionId, 'spec author session ID');
|
|
64
|
+
if (state.authorSessionId !== null && state.authorSessionId !== sessionId)
|
|
74
65
|
throw new Error('spec author session changed');
|
|
75
|
-
|
|
76
|
-
const { reportPath = null, revisionPath = null, ...actorInput } = input;
|
|
77
|
-
const invocation = {
|
|
78
|
-
...actorInput, targetRevision: target?.revision ?? 1, targetSha256: target?.revisionSha256 ?? null,
|
|
79
|
-
closureRequestSha256: input.mode === 'closure' ? state.review.closureRequestSha256 : null,
|
|
80
|
-
status: 'prepared', pid: null, processGroupId: null, reportPath, revisionPath,
|
|
81
|
-
};
|
|
82
|
-
return { ...structuredClone(state), invocation };
|
|
83
|
-
}
|
|
84
|
-
export function launchSpecInvocation(state, input) {
|
|
85
|
-
if (!state.invocation || state.invocation.status !== 'prepared' || state.invocation.attemptId !== input.attemptId)
|
|
86
|
-
throw new Error('prepared spec invocation mismatch');
|
|
87
|
-
positive(input.pid, 'spec process PID');
|
|
88
|
-
positive(input.processGroupId, 'spec process group ID');
|
|
89
|
-
return { ...structuredClone(state), invocation: { ...state.invocation, status: 'launched', pid: input.pid, processGroupId: input.processGroupId } };
|
|
66
|
+
return validateSpecDelivery({ ...structuredClone(state), authorSessionId: sessionId });
|
|
90
67
|
}
|
|
91
68
|
export function acceptSpecRevision(state, revision) {
|
|
92
|
-
if (
|
|
93
|
-
|
|
94
|
-
if (revision.author.attemptId !== state.invocation.attemptId || revision.author.sessionId !== state.invocation.sessionId)
|
|
69
|
+
if ((state.stage !== 'authoring' && state.stage !== 'author-repair') || state.authorSessionId === null
|
|
70
|
+
|| revision.author.sessionId !== state.authorSessionId)
|
|
95
71
|
throw new Error('spec revision author correlation mismatch');
|
|
96
72
|
const previous = state.revisions.at(-1) ?? null;
|
|
97
73
|
const validated = validateSpecRevision(revision, previous);
|
|
@@ -101,27 +77,27 @@ export function acceptSpecRevision(state, revision) {
|
|
|
101
77
|
: state.review.defects;
|
|
102
78
|
const next = {
|
|
103
79
|
...structuredClone(state), stage: state.stage === 'authoring' ? 'review-full' : 'review-closure',
|
|
104
|
-
revisions: [...state.revisions, validated],
|
|
80
|
+
revisions: [...state.revisions, validated],
|
|
105
81
|
review: { ...structuredClone(state.review), defects },
|
|
106
82
|
};
|
|
107
|
-
delete next.invocation;
|
|
108
83
|
if (next.stage === 'review-closure')
|
|
109
84
|
next.review.closureRequestSha256 = hashSpecClosureRequest(next);
|
|
110
85
|
return validateSpecDelivery(next);
|
|
111
86
|
}
|
|
112
87
|
export function acceptSpecReview(state, report, reportSha256) {
|
|
113
88
|
hash(reportSha256, 'spec review report hash');
|
|
114
|
-
if (!state.invocation || state.invocation.purpose !== 'review' || state.invocation.status !== 'launched')
|
|
115
|
-
throw new Error('spec review invocation is not launched');
|
|
116
89
|
const target = state.revisions.at(-1);
|
|
117
90
|
validateReviewReport(report);
|
|
118
91
|
validateCodeReviewDefects(report.defects, report.targetRevision);
|
|
119
92
|
if (report.acceptedRisks.length !== 0)
|
|
120
93
|
throw new Error('reviewer cannot authorize accepted risks');
|
|
121
94
|
if (report.targetRevision !== target.revision || report.targetSha256 !== target.revisionSha256
|
|
122
|
-
|| report.mode !== state.
|
|
123
|
-
|| report.reviewer.sessionId
|
|
124
|
-
||
|
|
95
|
+
|| report.mode !== (state.stage === 'review-full' ? 'full' : 'closure')
|
|
96
|
+
|| report.reviewer.sessionId === state.authorSessionId
|
|
97
|
+
|| state.revisions.some((revision) => revision.author.attemptId === report.reviewer.attemptId)
|
|
98
|
+
|| (state.review.reviewerSessionId !== null && report.reviewer.sessionId !== state.review.reviewerSessionId)
|
|
99
|
+
|| (state.review.reviewer !== null && report.reviewer.sessionId !== state.review.reviewer.sessionId)
|
|
100
|
+
|| report.closureRequestSha256 !== (state.stage === 'review-closure' ? state.review.closureRequestSha256 : null))
|
|
125
101
|
throw new Error('spec review correlation mismatch');
|
|
126
102
|
for (const required of MANDATORY_COVERAGE)
|
|
127
103
|
if (!report.coverage.includes(required))
|
|
@@ -133,7 +109,6 @@ export function acceptSpecReview(state, report, reportSha256) {
|
|
|
133
109
|
next.review.closureRequestSha256 = null;
|
|
134
110
|
next.review.affectedDefectIds = [];
|
|
135
111
|
next.review.affectedContracts = [];
|
|
136
|
-
delete next.invocation;
|
|
137
112
|
return validateSpecDelivery(next);
|
|
138
113
|
}
|
|
139
114
|
const defects = report.mode === 'closure' ? mergeClosureDefects(state, report) : structuredClone(report.defects);
|
|
@@ -151,7 +126,7 @@ export function acceptSpecReview(state, report, reportSha256) {
|
|
|
151
126
|
: report.verdict === 'needs-work' && state.budgets.repairCycles === 0 ? 'author-repair'
|
|
152
127
|
: report.verdict === 'needs-work' ? 'exhausted' : 'rejected',
|
|
153
128
|
review: {
|
|
154
|
-
reviewer: structuredClone(report.reviewer), mode: report.mode, coverage: sorted(report.coverage),
|
|
129
|
+
reviewer: structuredClone(report.reviewer), reviewerSessionId: report.reviewer.sessionId, mode: report.mode, coverage: sorted(report.coverage),
|
|
155
130
|
defects: defects.sort((a, b) => a.id.localeCompare(b.id)),
|
|
156
131
|
affectedDefectIds: report.verdict === 'needs-work' ? sorted(report.defects.filter((defect) => ['open', 'reopened'].includes(defect.status)).map((defect) => defect.id)) : [],
|
|
157
132
|
affectedContracts: report.verdict === 'needs-work' ? sorted(report.affectedContracts) : [],
|
|
@@ -162,7 +137,19 @@ export function acceptSpecReview(state, report, reportSha256) {
|
|
|
162
137
|
repairCycles: report.verdict === 'needs-work' && state.budgets.repairCycles === 0 ? 1 : state.budgets.repairCycles,
|
|
163
138
|
},
|
|
164
139
|
};
|
|
165
|
-
|
|
140
|
+
return validateSpecDelivery(next);
|
|
141
|
+
}
|
|
142
|
+
export function reserveSpecReviewerSession(state, reviewerSessionId) {
|
|
143
|
+
validateSpecDelivery(state);
|
|
144
|
+
text(reviewerSessionId, 'spec reviewer session ID');
|
|
145
|
+
if (state.stage !== 'review-full' && state.stage !== 'review-closure')
|
|
146
|
+
throw new Error('spec stage does not accept a reviewer session');
|
|
147
|
+
if (reviewerSessionId === state.authorSessionId)
|
|
148
|
+
throw new Error('spec reviewer is not independent');
|
|
149
|
+
if (state.review.reviewerSessionId !== null && state.review.reviewerSessionId !== reviewerSessionId)
|
|
150
|
+
throw new Error('spec reviewer session changed');
|
|
151
|
+
const next = structuredClone(state);
|
|
152
|
+
next.review.reviewerSessionId = reviewerSessionId;
|
|
166
153
|
return validateSpecDelivery(next);
|
|
167
154
|
}
|
|
168
155
|
export function hashSpecClosureRequest(state) {
|
|
@@ -181,24 +168,7 @@ export function consumeSpecReportRepair(state, owner) {
|
|
|
181
168
|
return { ...structuredClone(state), budgets: { ...structuredClone(state.budgets), [owner]: { ...state.budgets[owner], reportRepairs: 1 } } };
|
|
182
169
|
}
|
|
183
170
|
export function recoverMalformedSpecReport(state, owner) {
|
|
184
|
-
|
|
185
|
-
throw new Error('malformed spec report owner mismatch');
|
|
186
|
-
const next = consumeSpecReportRepair(state, owner);
|
|
187
|
-
delete next.invocation;
|
|
188
|
-
return validateSpecDelivery(next);
|
|
189
|
-
}
|
|
190
|
-
export function recoverSpecInvocation(state, input) {
|
|
191
|
-
if (!state.invocation || state.invocation.attemptId !== input.attemptId)
|
|
192
|
-
throw new Error('spec recovery invocation mismatch');
|
|
193
|
-
if (!input.processGroupAbsent)
|
|
194
|
-
throw new Error('spec process is still active');
|
|
195
|
-
const owner = state.invocation.purpose === 'author' ? 'author' : 'review';
|
|
196
|
-
if (state.budgets[owner].transportRetries !== 0)
|
|
197
|
-
throw new Error(`${owner} transport retry budget exhausted`);
|
|
198
|
-
const next = structuredClone(state);
|
|
199
|
-
next.budgets[owner].transportRetries = 1;
|
|
200
|
-
delete next.invocation;
|
|
201
|
-
return validateSpecDelivery(next);
|
|
171
|
+
return validateSpecDelivery(consumeSpecReportRepair(state, owner));
|
|
202
172
|
}
|
|
203
173
|
export function freezeApprovedSpec(state) {
|
|
204
174
|
validateSpecDelivery(state);
|
|
@@ -230,7 +200,7 @@ export function validateFrozenSpecReceipt(value, state) {
|
|
|
230
200
|
return structuredClone(value);
|
|
231
201
|
}
|
|
232
202
|
export function validateSpecDelivery(value) {
|
|
233
|
-
const optional = ['
|
|
203
|
+
const optional = ['frozen'].filter((key) => own(value, key));
|
|
234
204
|
exact(value, ['version', 'issueNumber', 'runId', 'workflowGenerationSha256', 'stage', 'revisions', 'authorSessionId', 'review', 'budgets', ...optional], 'spec delivery');
|
|
235
205
|
if (value.version !== 1)
|
|
236
206
|
throw new Error('spec delivery version is invalid');
|
|
@@ -245,12 +215,10 @@ export function validateSpecDelivery(value) {
|
|
|
245
215
|
for (const revision of value.revisions)
|
|
246
216
|
previous = validateSpecRevision(revision, previous);
|
|
247
217
|
exact(value.budgets, ['author', 'review', 'repairCycles'], 'spec budgets');
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
throw new Error('spec budget is invalid');
|
|
253
|
-
}
|
|
218
|
+
exact(value.budgets.author, ['reportRepairs'], 'author budget');
|
|
219
|
+
exact(value.budgets.review, ['reportRepairs'], 'review budget');
|
|
220
|
+
if (![value.budgets.author.reportRepairs, value.budgets.review.reportRepairs].every((count) => count === 0 || count === 1))
|
|
221
|
+
throw new Error('spec budget is invalid');
|
|
254
222
|
if (![0, 1].includes(value.budgets.repairCycles))
|
|
255
223
|
throw new Error('spec repair cycle budget is invalid');
|
|
256
224
|
validateReviewState(value.review);
|
|
@@ -261,8 +229,6 @@ export function validateSpecDelivery(value) {
|
|
|
261
229
|
throw new Error('spec stage requires a revision');
|
|
262
230
|
if (stage === 'approved' && (!value.review.reviewer || !value.review.acceptedReportSha256))
|
|
263
231
|
throw new Error('approved spec is missing review authority');
|
|
264
|
-
if (own(value, 'invocation'))
|
|
265
|
-
validateInvocation(value.invocation, value);
|
|
266
232
|
if (stage === 'frozen')
|
|
267
233
|
validateFrozenSpecReceipt(value.frozen, value);
|
|
268
234
|
else if (own(value, 'frozen'))
|
|
@@ -331,9 +297,13 @@ function validateReviewReport(value) {
|
|
|
331
297
|
}
|
|
332
298
|
}
|
|
333
299
|
function validateReviewState(value) {
|
|
334
|
-
exact(value, ['reviewer', 'mode', 'coverage', 'defects', 'affectedDefectIds', 'affectedContracts', 'closureRequestSha256', 'acceptedRisks', 'acceptedReportSha256'], 'spec review state');
|
|
300
|
+
exact(value, ['reviewer', 'reviewerSessionId', 'mode', 'coverage', 'defects', 'affectedDefectIds', 'affectedContracts', 'closureRequestSha256', 'acceptedRisks', 'acceptedReportSha256'], 'spec review state');
|
|
335
301
|
if (value.reviewer !== null)
|
|
336
302
|
actor(value.reviewer, 'persisted reviewer');
|
|
303
|
+
if (value.reviewerSessionId !== null)
|
|
304
|
+
text(value.reviewerSessionId, 'persisted reviewer session ID');
|
|
305
|
+
if (value.reviewer !== null && value.reviewer.sessionId !== value.reviewerSessionId)
|
|
306
|
+
throw new Error('persisted reviewer session correlation mismatch');
|
|
337
307
|
if (value.mode !== null && !['full', 'closure'].includes(value.mode))
|
|
338
308
|
throw new Error('persisted review mode is invalid');
|
|
339
309
|
strings(value.coverage, 'persisted coverage');
|
|
@@ -346,41 +316,6 @@ function validateReviewState(value) {
|
|
|
346
316
|
if (value.acceptedReportSha256 !== null)
|
|
347
317
|
hash(value.acceptedReportSha256, 'persisted report hash');
|
|
348
318
|
}
|
|
349
|
-
function validateInvocation(value, state) {
|
|
350
|
-
exact(value, ['purpose', 'mode', 'attemptId', 'sessionId', 'targetRevision', 'targetSha256', 'closureRequestSha256', 'status', 'pid', 'processGroupId', 'reportPath', 'revisionPath'], 'spec invocation');
|
|
351
|
-
const expected = stageInvocation(state.stage);
|
|
352
|
-
if (value.purpose !== expected.purpose || value.mode !== expected.mode)
|
|
353
|
-
throw new Error('spec invocation/stage mismatch');
|
|
354
|
-
actor({ attemptId: value.attemptId, sessionId: value.sessionId }, 'spec invocation actor');
|
|
355
|
-
const target = state.revisions.at(-1);
|
|
356
|
-
if (value.targetRevision !== (target?.revision ?? 1) || value.targetSha256 !== (target?.revisionSha256 ?? null))
|
|
357
|
-
throw new Error('spec invocation target mismatch');
|
|
358
|
-
if (value.closureRequestSha256 !== (value.mode === 'closure' ? state.review.closureRequestSha256 : null))
|
|
359
|
-
throw new Error('spec invocation Closure mismatch');
|
|
360
|
-
if (value.status === 'prepared' && (value.pid !== null || value.processGroupId !== null))
|
|
361
|
-
throw new Error('prepared spec invocation has process identity');
|
|
362
|
-
if (value.status === 'launched') {
|
|
363
|
-
positive(value.pid, 'spec invocation PID');
|
|
364
|
-
positive(value.processGroupId, 'spec invocation process group');
|
|
365
|
-
}
|
|
366
|
-
if (value.reportPath !== null)
|
|
367
|
-
text(value.reportPath, 'spec invocation report path');
|
|
368
|
-
if (value.revisionPath !== null)
|
|
369
|
-
text(value.revisionPath, 'spec invocation revision path');
|
|
370
|
-
if (value.purpose === 'review' && value.revisionPath !== null)
|
|
371
|
-
throw new Error('spec review invocation has revision path');
|
|
372
|
-
}
|
|
373
|
-
function stageInvocation(stage) {
|
|
374
|
-
if (stage === 'authoring')
|
|
375
|
-
return { purpose: 'author', mode: 'author' };
|
|
376
|
-
if (stage === 'author-repair')
|
|
377
|
-
return { purpose: 'author', mode: 'repair' };
|
|
378
|
-
if (stage === 'review-full')
|
|
379
|
-
return { purpose: 'review', mode: 'full' };
|
|
380
|
-
if (stage === 'review-closure')
|
|
381
|
-
return { purpose: 'review', mode: 'closure' };
|
|
382
|
-
throw new Error('spec stage does not accept an invocation');
|
|
383
|
-
}
|
|
384
319
|
function frozenDigest(payload) { return digest(`codex-orchestrator-frozen-spec-v1\0${canonicalJson(payload)}`); }
|
|
385
320
|
function digest(value) { return createHash('sha256').update(value, 'utf8').digest('hex'); }
|
|
386
321
|
function sorted(values) { return [...new Set(values)].sort(); }
|