codex-orchestrator 2.0.3 → 2.0.4
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 +28 -427
- package/README.md +135 -37
- package/dist/src/index.d.ts +1 -1
- package/dist/src/index.d.ts.map +1 -1
- package/dist/src/v2/adapters/gh-issue-adapter.d.ts.map +1 -1
- package/dist/src/v2/adapters/gh-issue-adapter.js +6 -7
- package/dist/src/v2/adapters/gh-issue-adapter.js.map +1 -1
- package/dist/src/v2/cli-contract.d.ts +3 -3
- package/dist/src/v2/cli-contract.d.ts.map +1 -1
- package/dist/src/v2/cli-contract.js +1 -3
- package/dist/src/v2/cli-contract.js.map +1 -1
- package/dist/src/v2/cli.d.ts +24 -0
- package/dist/src/v2/cli.d.ts.map +1 -0
- package/dist/src/v2/{candidate-cli.js → cli.js} +18 -29
- package/dist/src/v2/cli.js.map +1 -0
- package/dist/src/v2/code-review-report.d.ts +1 -1
- package/dist/src/v2/code-review-report.d.ts.map +1 -1
- package/dist/src/v2/code-review-report.js +2 -2
- package/dist/src/v2/code-review-report.js.map +1 -1
- 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/config.d.ts +2 -2
- package/dist/src/v2/config.d.ts.map +1 -1
- package/dist/src/v2/config.js.map +1 -1
- package/dist/src/v2/contained-report-operation.d.ts +2 -2
- package/dist/src/v2/contained-report-operation.d.ts.map +1 -1
- package/dist/src/v2/contained-report-operation.js +1 -1
- package/dist/src/v2/contained-report-operation.js.map +1 -1
- package/dist/src/v2/containment.d.ts +4 -0
- package/dist/src/v2/containment.d.ts.map +1 -1
- package/dist/src/v2/containment.js +9 -0
- package/dist/src/v2/containment.js.map +1 -1
- package/dist/src/v2/direct-delivery.d.ts +5 -10
- package/dist/src/v2/direct-delivery.d.ts.map +1 -1
- package/dist/src/v2/direct-delivery.js +25 -90
- package/dist/src/v2/direct-delivery.js.map +1 -1
- package/dist/src/v2/proof-report.d.ts.map +1 -1
- package/dist/src/v2/proof-report.js +55 -29
- package/dist/src/v2/proof-report.js.map +1 -1
- package/dist/src/v2/run-issue.d.ts +6 -9
- package/dist/src/v2/run-issue.d.ts.map +1 -1
- package/dist/src/v2/run-issue.js +98 -43
- package/dist/src/v2/run-issue.js.map +1 -1
- package/dist/src/v2/run-store.d.ts +4 -4
- package/dist/src/v2/run-store.d.ts.map +1 -1
- package/dist/src/v2/run-store.js +25 -40
- package/dist/src/v2/run-store.js.map +1 -1
- package/dist/src/v2/runtime.d.ts +3 -3
- package/dist/src/v2/runtime.d.ts.map +1 -1
- package/dist/src/v2/runtime.js +125 -47
- package/dist/src/v2/runtime.js.map +1 -1
- package/dist/src/v2/setup-cli.d.ts.map +1 -1
- package/dist/src/v2/setup-cli.js +4 -11
- package/dist/src/v2/setup-cli.js.map +1 -1
- package/dist/src/v2/setup-runtime.d.ts.map +1 -1
- package/dist/src/v2/setup-runtime.js +1 -61
- package/dist/src/v2/setup-runtime.js.map +1 -1
- package/dist/src/v2/setup-store.d.ts +0 -5
- package/dist/src/v2/setup-store.d.ts.map +1 -1
- package/dist/src/v2/setup-store.js +3 -106
- package/dist/src/v2/setup-store.js.map +1 -1
- package/dist/src/v2/setup.d.ts +6 -46
- package/dist/src/v2/setup.d.ts.map +1 -1
- package/dist/src/v2/setup.js +11 -293
- package/dist/src/v2/setup.js.map +1 -1
- package/dist/src/v2/workflow-assets.d.ts +19 -11
- package/dist/src/v2/workflow-assets.d.ts.map +1 -1
- package/dist/src/v2/workflow-assets.js +132 -40
- package/dist/src/v2/workflow-assets.js.map +1 -1
- package/docs/deep-dive.md +272 -56
- package/internal-workflow/docs/agents/bugfix-quality-gate.md +11 -0
- package/internal-workflow/docs/agents/coding-skill-routing.md +116 -196
- package/internal-workflow/docs/agents/review-gates.md +32 -39
- package/internal-workflow/docs/agents/review-protocol.md +75 -147
- package/internal-workflow/evals/coding-skill-evals.json +66 -0
- package/internal-workflow/manifest.json +1 -1
- package/internal-workflow/operations/acceptance-proof/SKILL.md +7 -1
- package/internal-workflow/operations/ambiguity-review/SKILL.md +2 -0
- package/internal-workflow/operations/code-review/SKILL.md +21 -1
- package/internal-workflow/operations/implementation/SKILL.md +22 -1
- package/internal-workflow/operations/spec-author/SKILL.md +10 -1
- package/internal-workflow/operations/spec-review/SKILL.md +10 -1
- package/internal-workflow/operations/triage/SKILL.md +10 -1
- package/internal-workflow/schemas/code-review-v1.json +1 -1
- package/internal-workflow/schemas/proof-report-v1.json +1 -1
- package/internal-workflow/skills/agent-auto/SKILL.md +6 -1
- package/internal-workflow/skills/code-debugger/SKILL.md +122 -0
- package/internal-workflow/skills/code-debugger/agents/openai.yaml +7 -0
- package/internal-workflow/skills/code-review/SKILL.md +33 -11
- package/internal-workflow/skills/code-review/references/cleanup-lens.md +52 -0
- package/internal-workflow/skills/implementation-spec-maker/SKILL.md +15 -6
- package/internal-workflow/skills/implementation-spec-maker/references/spec-template.md +2 -2
- package/internal-workflow/skills/implementation-spec-review/SKILL.md +108 -204
- package/internal-workflow/skills/implementation-spec-review/evals/evals.json +24 -0
- package/internal-workflow/skills/implementation-spec-review/references/review-loop.md +93 -0
- package/internal-workflow/skills/small-task-implementer/SKILL.md +15 -8
- package/internal-workflow/skills/spec-implementer/SKILL.md +101 -172
- package/internal-workflow/skills/spec-implementer/evals/evals.json +30 -0
- package/internal-workflow/skills/spec-implementer/references/review-loop.md +94 -0
- package/internal-workflow/skills/tdd/SKILL.md +15 -2
- package/internal-workflow/skills/tdd/agents/openai.yaml +2 -2
- package/package.json +9 -6
- package/dist/src/v2/adapters/target-activity-fence.d.ts +0 -23
- package/dist/src/v2/adapters/target-activity-fence.d.ts.map +0 -1
- package/dist/src/v2/adapters/target-activity-fence.js +0 -249
- package/dist/src/v2/adapters/target-activity-fence.js.map +0 -1
- package/dist/src/v2/candidate-cli.d.ts +0 -26
- package/dist/src/v2/candidate-cli.d.ts.map +0 -1
- package/dist/src/v2/candidate-cli.js.map +0 -1
- package/dist/src/v2/legacy-cutover.d.ts +0 -52
- package/dist/src/v2/legacy-cutover.d.ts.map +0 -1
- package/dist/src/v2/legacy-cutover.js +0 -87
- package/dist/src/v2/legacy-cutover.js.map +0 -1
- package/internal-workflow/docs/agents/artifact-review-loop.md +0 -267
- package/internal-workflow/docs/agents/implementation-review-loop.md +0 -302
- package/internal-workflow/operations/cleanup-review/SKILL.md +0 -3
- package/internal-workflow/operations/spec-implementation/SKILL.md +0 -3
- package/internal-workflow/profiles/implementer_deep.toml +0 -9
- package/internal-workflow/profiles/researcher_standard.toml +0 -9
- package/internal-workflow/profiles/reviewer_fast.toml +0 -9
- package/internal-workflow/skills/cleanup-review/SKILL.md +0 -84
- package/internal-workflow/skills/cleanup-review/agents/openai.yaml +0 -6
- package/internal-workflow/skills/codebase-design/DEEPENING.md +0 -35
- package/internal-workflow/skills/codebase-design/DESIGN-IT-TWICE.md +0 -50
- package/internal-workflow/skills/codebase-design/SKILL.md +0 -82
- package/internal-workflow/skills/codebase-design/agents/openai.yaml +0 -6
- package/internal-workflow/skills/research/SKILL.md +0 -107
- package/internal-workflow/skills/research/agents/openai.yaml +0 -6
- package/internal-workflow/skills/ui-evidence-proof/SKILL.md +0 -123
- package/internal-workflow/skills/ui-evidence-proof/agents/openai.yaml +0 -6
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"setup-store.js","sourceRoot":"","sources":["../../../src/v2/setup-store.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,
|
|
1
|
+
{"version":3,"file":"setup-store.js","sourceRoot":"","sources":["../../../src/v2/setup-store.ts"],"names":[],"mappings":"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"}
|
package/dist/src/v2/setup.d.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import { type
|
|
1
|
+
import { type AgentAutoConfig } from './config.js';
|
|
2
2
|
import { SetupStore } from './setup-store.js';
|
|
3
|
-
export type SetupOperation = 'configure' | 'prepare-labels' | '
|
|
3
|
+
export type SetupOperation = 'configure' | 'prepare-labels' | 'doctor' | 'status';
|
|
4
4
|
export interface SetupIntent {
|
|
5
5
|
targetRoot: string;
|
|
6
6
|
operation: SetupOperation;
|
|
@@ -16,18 +16,9 @@ export type SetupAction = {
|
|
|
16
16
|
} | {
|
|
17
17
|
kind: 'write-config';
|
|
18
18
|
path: '.codex-orchestrator/config.json';
|
|
19
|
-
} | {
|
|
20
|
-
kind: 'migrate-config-v1-to-v2';
|
|
21
|
-
path: '.codex-orchestrator/config.json';
|
|
22
19
|
} | {
|
|
23
20
|
kind: 'create-label';
|
|
24
21
|
name: string;
|
|
25
|
-
} | {
|
|
26
|
-
kind: 'backup-legacy';
|
|
27
|
-
path: string;
|
|
28
|
-
} | {
|
|
29
|
-
kind: 'commit-fresh';
|
|
30
|
-
path: '.codex-orchestrator/config.json';
|
|
31
22
|
};
|
|
32
23
|
export interface SetupDiagnostic {
|
|
33
24
|
code: string;
|
|
@@ -39,7 +30,7 @@ export interface SetupFailure {
|
|
|
39
30
|
summary: string;
|
|
40
31
|
}
|
|
41
32
|
export type SetupOutcome = {
|
|
42
|
-
status: 'created' | 'unchanged' | 'labels-prepared'
|
|
33
|
+
status: 'created' | 'unchanged' | 'labels-prepared';
|
|
43
34
|
} | {
|
|
44
35
|
status: 'planned';
|
|
45
36
|
actions: SetupAction[];
|
|
@@ -53,7 +44,7 @@ export type SetupOutcome = {
|
|
|
53
44
|
missing: string[];
|
|
54
45
|
cause: SetupFailure;
|
|
55
46
|
} | {
|
|
56
|
-
status: '
|
|
47
|
+
status: 'blocked-active' | 'repository-mismatch' | 'unsupported-schema';
|
|
57
48
|
reason: string;
|
|
58
49
|
} | {
|
|
59
50
|
status: 'transport-failed' | 'io-failed';
|
|
@@ -68,23 +59,6 @@ export interface SetupDependencies {
|
|
|
68
59
|
};
|
|
69
60
|
baseBranch?: string;
|
|
70
61
|
}>;
|
|
71
|
-
inspectRetained(input: {
|
|
72
|
-
targetRoot: string;
|
|
73
|
-
legacy: {
|
|
74
|
-
workspaceRoot: string;
|
|
75
|
-
stateDir: string;
|
|
76
|
-
};
|
|
77
|
-
v2: {
|
|
78
|
-
workspaceRoot: string;
|
|
79
|
-
stateDir: string;
|
|
80
|
-
proofDir: string;
|
|
81
|
-
};
|
|
82
|
-
}): Promise<{
|
|
83
|
-
worktreePaths: string[];
|
|
84
|
-
localRefs: string[];
|
|
85
|
-
remoteRefs: string[];
|
|
86
|
-
collisions: string[];
|
|
87
|
-
}>;
|
|
88
62
|
};
|
|
89
63
|
labels: {
|
|
90
64
|
listPage(input: {
|
|
@@ -100,16 +74,11 @@ export interface SetupDependencies {
|
|
|
100
74
|
create(input: {
|
|
101
75
|
owner: string;
|
|
102
76
|
repo: string;
|
|
103
|
-
label:
|
|
77
|
+
label: AgentAutoConfig['github']['labels'][keyof AgentAutoConfig['github']['labels']];
|
|
104
78
|
}): Promise<'created' | 'already-exists' | {
|
|
105
79
|
status: 'failed';
|
|
106
80
|
failure: SetupFailure;
|
|
107
81
|
}>;
|
|
108
|
-
listOpenIssueNumbersWithLabel(input: {
|
|
109
|
-
owner: string;
|
|
110
|
-
repo: string;
|
|
111
|
-
label: string;
|
|
112
|
-
}): Promise<number[]>;
|
|
113
82
|
};
|
|
114
83
|
ownership: {
|
|
115
84
|
acquire(repository: {
|
|
@@ -118,16 +87,13 @@ export interface SetupDependencies {
|
|
|
118
87
|
}): Promise<{
|
|
119
88
|
release(): Promise<void>;
|
|
120
89
|
}>;
|
|
121
|
-
|
|
90
|
+
inspectOwner(repository: {
|
|
122
91
|
owner: string;
|
|
123
92
|
repo: string;
|
|
124
93
|
}): Promise<{
|
|
125
94
|
status: 'absent' | 'inactive' | 'active' | 'ambiguous';
|
|
126
95
|
reason?: string;
|
|
127
96
|
}>;
|
|
128
|
-
acquireLegacyFence(targetRoot: string): Promise<{
|
|
129
|
-
release(): Promise<void>;
|
|
130
|
-
}>;
|
|
131
97
|
};
|
|
132
98
|
now?: () => string;
|
|
133
99
|
}
|
|
@@ -140,11 +106,5 @@ export declare class Setup {
|
|
|
140
106
|
private prepareLabels;
|
|
141
107
|
private inspect;
|
|
142
108
|
private listAllLabels;
|
|
143
|
-
private fresh;
|
|
144
|
-
private replayCommittedFresh;
|
|
145
|
-
private readManifests;
|
|
146
|
-
private buildManifest;
|
|
147
|
-
private copyBackupIfNeeded;
|
|
148
|
-
private copyConfigBackupIfNeeded;
|
|
149
109
|
}
|
|
150
110
|
//# sourceMappingURL=setup.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"setup.d.ts","sourceRoot":"","sources":["../../../src/v2/setup.ts"],"names":[],"mappings":"AAIA,OAAO,EAAwB,KAAK,
|
|
1
|
+
{"version":3,"file":"setup.d.ts","sourceRoot":"","sources":["../../../src/v2/setup.ts"],"names":[],"mappings":"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"}
|
package/dist/src/v2/setup.js
CHANGED
|
@@ -1,8 +1,7 @@
|
|
|
1
1
|
import { lstat, realpath } from 'node:fs/promises';
|
|
2
|
-
import {
|
|
2
|
+
import { resolve } from 'node:path';
|
|
3
3
|
import { canonicalJson } from './containment.js';
|
|
4
4
|
import { parseAgentAutoConfig } from './config.js';
|
|
5
|
-
import { detectLegacyConfig, parseCutoverManifest, sha256, } from './legacy-cutover.js';
|
|
6
5
|
import { SetupStore } from './setup-store.js';
|
|
7
6
|
const CONFIG_PATH = '.codex-orchestrator/config.json';
|
|
8
7
|
const IGNORE_PATH = '.gitignore';
|
|
@@ -45,7 +44,7 @@ export class Setup {
|
|
|
45
44
|
if (intent.operation === 'doctor' || intent.operation === 'status') {
|
|
46
45
|
return await this.inspect(targetRoot, observed.repository);
|
|
47
46
|
}
|
|
48
|
-
return
|
|
47
|
+
return { status: 'unsupported-schema', reason: 'Setup operation is unsupported.' };
|
|
49
48
|
}
|
|
50
49
|
catch {
|
|
51
50
|
return { status: 'io-failed', detail: failure('setup-operation', 'Setup operation could not complete safely.') };
|
|
@@ -59,60 +58,7 @@ export class Setup {
|
|
|
59
58
|
config = parseAgentAutoConfig(JSON.parse(existing.toString('utf8')));
|
|
60
59
|
}
|
|
61
60
|
catch {
|
|
62
|
-
|
|
63
|
-
if (migration.status === 'migratable') {
|
|
64
|
-
if (!sameRepository(migration.config.github, repository)
|
|
65
|
-
|| (intent.repository && !sameRepository(migration.config.github, intent.repository))) {
|
|
66
|
-
return { status: 'repository-mismatch', reason: 'Persisted repository does not match target origin.' };
|
|
67
|
-
}
|
|
68
|
-
if (intent.dryRun) {
|
|
69
|
-
return { status: 'planned', actions: [{ kind: 'migrate-config-v1-to-v2', path: CONFIG_PATH }] };
|
|
70
|
-
}
|
|
71
|
-
const owner = await this.dependencies.ownership.inspectV2Owner(repository).catch(() => ({
|
|
72
|
-
status: 'ambiguous', reason: 'V2 owner state could not be inspected.',
|
|
73
|
-
}));
|
|
74
|
-
if (owner.status === 'active' || owner.status === 'ambiguous') {
|
|
75
|
-
return { status: 'blocked-active', reason: owner.reason ?? 'An active or ambiguous V2 owner blocks Config V1 migration.' };
|
|
76
|
-
}
|
|
77
|
-
let running;
|
|
78
|
-
try {
|
|
79
|
-
running = await this.dependencies.labels.listOpenIssueNumbersWithLabel({
|
|
80
|
-
...repository, label: migration.runningLabel,
|
|
81
|
-
});
|
|
82
|
-
}
|
|
83
|
-
catch {
|
|
84
|
-
return { status: 'transport-failed', detail: failure('migration-running-read', 'Migration could not prove remote running claims are absent.') };
|
|
85
|
-
}
|
|
86
|
-
if (running.length > 0)
|
|
87
|
-
return { status: 'blocked-active', reason: 'Open Config V1 running claims block migration.' };
|
|
88
|
-
const lock = await this.dependencies.ownership.acquire(repository);
|
|
89
|
-
try {
|
|
90
|
-
const recheck = await this.store.readOptional(resolve(targetRoot, CONFIG_PATH));
|
|
91
|
-
if (!recheck || !recheck.equals(existing)) {
|
|
92
|
-
return { status: 'blocked-active', reason: 'Configuration changed while waiting for setup ownership.' };
|
|
93
|
-
}
|
|
94
|
-
let lockedRunning;
|
|
95
|
-
try {
|
|
96
|
-
lockedRunning = await this.dependencies.labels.listOpenIssueNumbersWithLabel({
|
|
97
|
-
...repository, label: migration.runningLabel,
|
|
98
|
-
});
|
|
99
|
-
}
|
|
100
|
-
catch {
|
|
101
|
-
return { status: 'transport-failed', detail: failure('migration-running-read', 'Migration could not prove remote running claims are absent under setup ownership.') };
|
|
102
|
-
}
|
|
103
|
-
if (lockedRunning.length > 0)
|
|
104
|
-
return { status: 'blocked-active', reason: 'Open Config V1 running claims block migration.' };
|
|
105
|
-
await this.store.writeAtomic(resolve(targetRoot, CONFIG_PATH), `${canonicalJson(migration.config)}\n`, 0o644);
|
|
106
|
-
return { status: 'migrated' };
|
|
107
|
-
}
|
|
108
|
-
finally {
|
|
109
|
-
await lock.release();
|
|
110
|
-
}
|
|
111
|
-
}
|
|
112
|
-
if (migration.status === 'collision') {
|
|
113
|
-
return { status: 'unsupported-schema', reason: 'Config V1 label names collide with agent:waiting-human.' };
|
|
114
|
-
}
|
|
115
|
-
return classifyNonV2Config(existing);
|
|
61
|
+
return unsupportedConfig();
|
|
116
62
|
}
|
|
117
63
|
if (!sameRepository(config.github, repository) || (intent.repository && !sameRepository(config.github, intent.repository))) {
|
|
118
64
|
return { status: 'repository-mismatch', reason: 'Persisted repository does not match target origin.' };
|
|
@@ -139,7 +85,7 @@ export class Setup {
|
|
|
139
85
|
: { status: 'repository-mismatch', reason: 'Persisted repository changed while waiting for setup ownership.' };
|
|
140
86
|
}
|
|
141
87
|
catch {
|
|
142
|
-
return
|
|
88
|
+
return unsupportedConfig();
|
|
143
89
|
}
|
|
144
90
|
}
|
|
145
91
|
if (nextIgnore.changed)
|
|
@@ -164,7 +110,7 @@ export class Setup {
|
|
|
164
110
|
config = parseAgentAutoConfig(JSON.parse(existing.toString('utf8')));
|
|
165
111
|
}
|
|
166
112
|
catch {
|
|
167
|
-
return
|
|
113
|
+
return unsupportedConfig();
|
|
168
114
|
}
|
|
169
115
|
if (!sameRepository(config.github, repository)) {
|
|
170
116
|
return { status: 'repository-mismatch', reason: 'Persisted repository does not match target origin.' };
|
|
@@ -208,7 +154,7 @@ export class Setup {
|
|
|
208
154
|
}
|
|
209
155
|
}
|
|
210
156
|
catch {
|
|
211
|
-
return
|
|
157
|
+
return unsupportedConfig();
|
|
212
158
|
}
|
|
213
159
|
}
|
|
214
160
|
else {
|
|
@@ -275,15 +221,9 @@ export class Setup {
|
|
|
275
221
|
config = parseAgentAutoConfig(JSON.parse(bytes.toString('utf8')));
|
|
276
222
|
}
|
|
277
223
|
catch {
|
|
278
|
-
if (parseConfigV1Migration(bytes).status === 'migratable') {
|
|
279
|
-
return { status: 'legacy-detected', reason: 'Config V1 requires setup migration.' };
|
|
280
|
-
}
|
|
281
|
-
const classified = classifyNonV2Config(bytes);
|
|
282
|
-
const legacy = classified.status === 'legacy-detected';
|
|
283
224
|
return {
|
|
284
225
|
status: 'inspected', disposition: 'blocked', diagnostics: [{
|
|
285
|
-
code:
|
|
286
|
-
summary: legacy ? 'Legacy configuration requires setup --fresh.' : 'Configuration schema is unsupported.',
|
|
226
|
+
code: 'unsupported-schema', status: 'block', summary: 'Configuration schema is unsupported.',
|
|
287
227
|
}],
|
|
288
228
|
};
|
|
289
229
|
}
|
|
@@ -294,7 +234,7 @@ export class Setup {
|
|
|
294
234
|
diagnostics.push(repositoryMatch
|
|
295
235
|
? { code: 'repository', status: 'pass', summary: 'Configured repository matches target origin.' }
|
|
296
236
|
: { code: 'repository', status: 'block', summary: 'Configured repository does not match target origin.' });
|
|
297
|
-
const owner = await this.dependencies.ownership.
|
|
237
|
+
const owner = await this.dependencies.ownership.inspectOwner(repository).catch(() => ({ status: 'ambiguous' }));
|
|
298
238
|
diagnostics.push(owner.status === 'active' || owner.status === 'ambiguous'
|
|
299
239
|
? { code: 'owner', status: 'block', summary: 'An active or ambiguous V2 owner blocks setup.' }
|
|
300
240
|
: { code: 'owner', status: 'pass', summary: 'No active V2 owner blocks setup.' });
|
|
@@ -330,177 +270,6 @@ export class Setup {
|
|
|
330
270
|
}
|
|
331
271
|
throw new Error('label pagination exceeded bound');
|
|
332
272
|
}
|
|
333
|
-
async fresh(targetRoot, intent, repository, baseBranch) {
|
|
334
|
-
const configPath = resolve(targetRoot, CONFIG_PATH);
|
|
335
|
-
let sourceBytes;
|
|
336
|
-
try {
|
|
337
|
-
sourceBytes = await this.store.readOptional(configPath);
|
|
338
|
-
}
|
|
339
|
-
catch {
|
|
340
|
-
return { status: 'io-failed', detail: failure('fresh-config-read', 'Fresh could not read target configuration safely.') };
|
|
341
|
-
}
|
|
342
|
-
if (!sourceBytes)
|
|
343
|
-
return { status: 'unsupported-schema', reason: 'Fresh requires a recognized Legacy configuration.' };
|
|
344
|
-
try {
|
|
345
|
-
const v2 = parseAgentAutoConfig(JSON.parse(sourceBytes.toString('utf8')));
|
|
346
|
-
if (!sameRepository(v2.github, repository))
|
|
347
|
-
return { status: 'repository-mismatch', reason: 'Persisted repository does not match target origin.' };
|
|
348
|
-
return this.replayCommittedFresh(targetRoot, repository, sourceBytes);
|
|
349
|
-
}
|
|
350
|
-
catch {
|
|
351
|
-
// Detect-only parsing below owns the Legacy boundary.
|
|
352
|
-
}
|
|
353
|
-
const detected = detectLegacyConfig(sourceBytes);
|
|
354
|
-
if (detected.status !== 'recognized')
|
|
355
|
-
return { status: 'unsupported-schema', reason: 'Fresh configuration schema is unsupported.' };
|
|
356
|
-
const legacy = detected.record;
|
|
357
|
-
if (!sameRepository(legacy.repository, repository) || (intent.repository && !sameRepository(legacy.repository, intent.repository))) {
|
|
358
|
-
return { status: 'repository-mismatch', reason: 'Legacy repository does not match target origin.' };
|
|
359
|
-
}
|
|
360
|
-
if (intent.dryRun) {
|
|
361
|
-
return { status: 'planned', actions: [
|
|
362
|
-
{ kind: 'backup-legacy', path: '.codex-orchestrator/v2/legacy-backups' },
|
|
363
|
-
{ kind: 'commit-fresh', path: CONFIG_PATH },
|
|
364
|
-
] };
|
|
365
|
-
}
|
|
366
|
-
let ownerLock;
|
|
367
|
-
let legacyFence;
|
|
368
|
-
try {
|
|
369
|
-
const owner = await this.dependencies.ownership.inspectV2Owner(repository);
|
|
370
|
-
if (owner.status === 'active' || owner.status === 'ambiguous') {
|
|
371
|
-
return { status: 'blocked-active', reason: owner.reason ?? 'An active or ambiguous V2 owner blocks fresh.' };
|
|
372
|
-
}
|
|
373
|
-
ownerLock = await this.dependencies.ownership.acquire(repository);
|
|
374
|
-
legacyFence = await this.dependencies.ownership.acquireLegacyFence(targetRoot);
|
|
375
|
-
let running;
|
|
376
|
-
try {
|
|
377
|
-
running = await this.dependencies.labels.listOpenIssueNumbersWithLabel({ ...repository, label: legacy.runningLabel });
|
|
378
|
-
}
|
|
379
|
-
catch {
|
|
380
|
-
return { status: 'transport-failed', detail: failure('fresh-running-read', 'Fresh could not prove remote running claims are absent.') };
|
|
381
|
-
}
|
|
382
|
-
if (running.length > 0)
|
|
383
|
-
return { status: 'blocked-active', reason: 'Open Legacy running claims block fresh.' };
|
|
384
|
-
const config = await defaultConfig(targetRoot, repository, baseBranch, this.store);
|
|
385
|
-
const roots = [config.runner.workspaceRoot, config.runner.stateDir, config.proof.artifactDir];
|
|
386
|
-
for (const root of roots) {
|
|
387
|
-
if (!await this.store.isAbsentOrEmptyDirectory(resolve(targetRoot, root))) {
|
|
388
|
-
return { status: 'blocked-active', reason: `V2 destination root is not empty: ${root}` };
|
|
389
|
-
}
|
|
390
|
-
}
|
|
391
|
-
let retained;
|
|
392
|
-
try {
|
|
393
|
-
retained = await this.dependencies.repository.inspectRetained({
|
|
394
|
-
targetRoot,
|
|
395
|
-
legacy: { workspaceRoot: legacy.workspaceRoot, stateDir: legacy.stateDir },
|
|
396
|
-
v2: { workspaceRoot: config.runner.workspaceRoot, stateDir: config.runner.stateDir, proofDir: config.proof.artifactDir },
|
|
397
|
-
});
|
|
398
|
-
}
|
|
399
|
-
catch {
|
|
400
|
-
return { status: 'io-failed', detail: failure('fresh-retained-read', 'Fresh could not inspect retained worktrees and refs.') };
|
|
401
|
-
}
|
|
402
|
-
if (retained.collisions.length > 0)
|
|
403
|
-
return { status: 'blocked-active', reason: 'Retained worktree or ref collision blocks fresh.' };
|
|
404
|
-
const configBytes = `${canonicalJson(config)}\n`;
|
|
405
|
-
const manifest = await this.buildManifest(targetRoot, legacy, configBytes, retained);
|
|
406
|
-
const manifestDirectory = resolve(targetRoot, '.codex-orchestrator/v2/fresh-cutover');
|
|
407
|
-
const manifestPath = resolve(manifestDirectory, `${manifest.transactionId}.json`);
|
|
408
|
-
const existingManifests = await this.readManifests(manifestDirectory);
|
|
409
|
-
if (existingManifests.some((entry) => entry.transactionId !== manifest.transactionId)) {
|
|
410
|
-
return { status: 'blocked-active', reason: 'Ambiguous fresh-cutover manifests block authority switch.' };
|
|
411
|
-
}
|
|
412
|
-
const existingManifest = existingManifests[0];
|
|
413
|
-
if (existingManifest && canonicalJson(existingManifest) !== canonicalJson(manifest)) {
|
|
414
|
-
return { status: 'blocked-active', reason: 'Fresh-cutover manifest does not match current Legacy evidence.' };
|
|
415
|
-
}
|
|
416
|
-
if (!existingManifest)
|
|
417
|
-
await this.store.writeAtomic(manifestPath, `${canonicalJson(manifest)}\n`, 0o600);
|
|
418
|
-
await this.copyConfigBackupIfNeeded(resolve(targetRoot, CONFIG_PATH), resolve(targetRoot, manifest.backup.configPath), manifest.source.configSha256);
|
|
419
|
-
await this.copyBackupIfNeeded(resolve(targetRoot, legacy.stateDir), resolve(targetRoot, manifest.backup.statePath), manifest.source.stateSha256);
|
|
420
|
-
const ignore = renderIgnore((await this.store.readOptional(resolve(targetRoot, IGNORE_PATH)))?.toString('utf8') ?? '', config);
|
|
421
|
-
if (ignore.changed)
|
|
422
|
-
await this.store.writeAtomic(resolve(targetRoot, IGNORE_PATH), ignore.bytes, 0o644);
|
|
423
|
-
await this.store.writeAtomic(configPath, configBytes, 0o644);
|
|
424
|
-
return { status: 'fresh-reset' };
|
|
425
|
-
}
|
|
426
|
-
catch {
|
|
427
|
-
return { status: 'io-failed', detail: failure('fresh-write', 'Fresh could not durably complete the cutover.') };
|
|
428
|
-
}
|
|
429
|
-
finally {
|
|
430
|
-
await legacyFence?.release().catch(() => undefined);
|
|
431
|
-
await ownerLock?.release().catch(() => undefined);
|
|
432
|
-
}
|
|
433
|
-
}
|
|
434
|
-
async replayCommittedFresh(targetRoot, repository, configBytes) {
|
|
435
|
-
let manifests;
|
|
436
|
-
try {
|
|
437
|
-
manifests = await this.readManifests(resolve(targetRoot, '.codex-orchestrator/v2/fresh-cutover'));
|
|
438
|
-
}
|
|
439
|
-
catch {
|
|
440
|
-
return { status: 'unsupported-schema', reason: 'Fresh-cutover manifest set is unreadable or ambiguous.' };
|
|
441
|
-
}
|
|
442
|
-
const matches = manifests.filter((manifest) => sameRepository(manifest.repository, repository)
|
|
443
|
-
&& manifest.destination.configSha256 === sha256(configBytes));
|
|
444
|
-
return matches.length === 1 && manifests.length === 1
|
|
445
|
-
? { status: 'fresh-reset' }
|
|
446
|
-
: { status: 'unsupported-schema', reason: 'Valid V2 configuration is not linked to one exact fresh-cutover manifest.' };
|
|
447
|
-
}
|
|
448
|
-
async readManifests(directory) {
|
|
449
|
-
const output = [];
|
|
450
|
-
for (const path of await this.store.listJsonFiles(directory)) {
|
|
451
|
-
const bytes = await this.store.readOptional(path);
|
|
452
|
-
if (!bytes)
|
|
453
|
-
throw new Error('fresh manifest disappeared');
|
|
454
|
-
output.push(parseCutoverManifest(JSON.parse(bytes.toString('utf8'))));
|
|
455
|
-
}
|
|
456
|
-
return output;
|
|
457
|
-
}
|
|
458
|
-
async buildManifest(targetRoot, legacy, configBytes, retained) {
|
|
459
|
-
const stateSha256 = await this.store.hashPath(resolve(targetRoot, legacy.stateDir));
|
|
460
|
-
const destination = {
|
|
461
|
-
workspaceRoot: '.codex-orchestrator/workspaces-v2', stateDir: '.codex-orchestrator/v2/state',
|
|
462
|
-
proofDir: '.codex-orchestrator/v2/proofs', configSha256: sha256(configBytes),
|
|
463
|
-
};
|
|
464
|
-
const inventory = {
|
|
465
|
-
worktreePaths: [...retained.worktreePaths].sort(), localRefs: [...retained.localRefs].sort(), remoteRefs: [...retained.remoteRefs].sort(),
|
|
466
|
-
};
|
|
467
|
-
const transactionId = sha256(canonicalJson({
|
|
468
|
-
repository: legacy.repository, configSha256: legacy.configSha256, stateSha256, destination, retained: inventory,
|
|
469
|
-
}));
|
|
470
|
-
const backupRoot = `.codex-orchestrator/v2/legacy-backups/${transactionId}`;
|
|
471
|
-
return {
|
|
472
|
-
schema: 'codex-orchestrator.agent-auto-fresh-cutover', version: 1, transactionId,
|
|
473
|
-
repository: legacy.repository,
|
|
474
|
-
source: { configPath: CONFIG_PATH, configSha256: legacy.configSha256, statePath: legacy.stateDir, stateSha256 },
|
|
475
|
-
destination,
|
|
476
|
-
retained: inventory,
|
|
477
|
-
backup: { root: backupRoot, configPath: `${backupRoot}/${basename(CONFIG_PATH)}`, statePath: `${backupRoot}/state` },
|
|
478
|
-
};
|
|
479
|
-
}
|
|
480
|
-
async copyBackupIfNeeded(source, destination, expectedHash) {
|
|
481
|
-
const destinationHash = await this.store.hashPath(destination);
|
|
482
|
-
if (destinationHash === expectedHash)
|
|
483
|
-
return;
|
|
484
|
-
const sourceHash = await this.store.hashPath(source);
|
|
485
|
-
if (sourceHash !== expectedHash)
|
|
486
|
-
throw new Error('fresh source hash changed');
|
|
487
|
-
const absentHash = await this.store.hashPath(`${destination}.known-absent-sentinel`);
|
|
488
|
-
if (destinationHash !== absentHash)
|
|
489
|
-
throw new Error('fresh backup destination contains different evidence');
|
|
490
|
-
await this.store.copyTree(source, destination);
|
|
491
|
-
}
|
|
492
|
-
async copyConfigBackupIfNeeded(source, destination, expectedHash) {
|
|
493
|
-
const destinationBytes = await this.store.readOptional(destination);
|
|
494
|
-
if (destinationBytes) {
|
|
495
|
-
if (sha256(destinationBytes) !== expectedHash)
|
|
496
|
-
throw new Error('fresh config backup contains different evidence');
|
|
497
|
-
return;
|
|
498
|
-
}
|
|
499
|
-
const sourceBytes = await this.store.readOptional(source);
|
|
500
|
-
if (!sourceBytes || sha256(sourceBytes) !== expectedHash)
|
|
501
|
-
throw new Error('fresh config source hash changed');
|
|
502
|
-
await this.store.writeAtomic(destination, sourceBytes, 0o600);
|
|
503
|
-
}
|
|
504
273
|
}
|
|
505
274
|
async function defaultConfig(targetRoot, repository, baseBranch, store) {
|
|
506
275
|
const packageJson = await store.readOptional(resolve(targetRoot, 'package.json'));
|
|
@@ -564,59 +333,8 @@ function renderIgnore(current, config) {
|
|
|
564
333
|
const entries = [config.runner.workspaceRoot, config.runner.stateDir, config.proof.artifactDir].map((path) => `${path}/`);
|
|
565
334
|
return { changed: true, bytes: `${prefix}${IGNORE_START}\n${entries.join('\n')}\n${IGNORE_END}\n` };
|
|
566
335
|
}
|
|
567
|
-
function
|
|
568
|
-
|
|
569
|
-
return detected.status === 'recognized'
|
|
570
|
-
? { status: 'legacy-detected', reason: detected.record.kind === 'experimental-skill-runtime-v2'
|
|
571
|
-
? 'Experimental runtime configuration requires setup --fresh.'
|
|
572
|
-
: 'Legacy configuration requires setup --fresh.' }
|
|
573
|
-
: { status: 'unsupported-schema', reason: 'Configuration schema is unsupported or unreadable.' };
|
|
574
|
-
}
|
|
575
|
-
function parseConfigV1Migration(bytes) {
|
|
576
|
-
let input;
|
|
577
|
-
try {
|
|
578
|
-
input = JSON.parse(bytes.toString('utf8'));
|
|
579
|
-
}
|
|
580
|
-
catch {
|
|
581
|
-
return { status: 'not-v1' };
|
|
582
|
-
}
|
|
583
|
-
if (typeof input !== 'object' || input === null || Array.isArray(input))
|
|
584
|
-
return { status: 'not-v1' };
|
|
585
|
-
const record = input;
|
|
586
|
-
if (record.schema !== 'codex-orchestrator.agent-auto' || record.version !== 1)
|
|
587
|
-
return { status: 'not-v1' };
|
|
588
|
-
const github = record.github;
|
|
589
|
-
if (typeof github !== 'object' || github === null || Array.isArray(github))
|
|
590
|
-
return { status: 'not-v1' };
|
|
591
|
-
const labels = github.labels;
|
|
592
|
-
if (typeof labels !== 'object' || labels === null || Array.isArray(labels))
|
|
593
|
-
return { status: 'not-v1' };
|
|
594
|
-
const labelRecord = labels;
|
|
595
|
-
if (Object.keys(labelRecord).sort().join(',') !== 'auto,blocked,review,running')
|
|
596
|
-
return { status: 'not-v1' };
|
|
597
|
-
const names = Object.values(labelRecord).map((label) => {
|
|
598
|
-
if (typeof label !== 'object' || label === null || Array.isArray(label))
|
|
599
|
-
return undefined;
|
|
600
|
-
return label.name;
|
|
601
|
-
});
|
|
602
|
-
if (names.includes('agent:waiting-human'))
|
|
603
|
-
return { status: 'collision' };
|
|
604
|
-
try {
|
|
605
|
-
const candidate = structuredClone(record);
|
|
606
|
-
candidate.version = 2;
|
|
607
|
-
const candidateGithub = candidate.github;
|
|
608
|
-
candidateGithub.labels = {
|
|
609
|
-
...candidateGithub.labels,
|
|
610
|
-
waitingHuman: {
|
|
611
|
-
name: 'agent:waiting-human', color: '5319e7', description: 'Waiting for an authorized product answer.',
|
|
612
|
-
},
|
|
613
|
-
};
|
|
614
|
-
const config = parseAgentAutoConfig(candidate);
|
|
615
|
-
return { status: 'migratable', config, runningLabel: config.github.labels.running.name };
|
|
616
|
-
}
|
|
617
|
-
catch {
|
|
618
|
-
return { status: 'not-v1' };
|
|
619
|
-
}
|
|
336
|
+
function unsupportedConfig() {
|
|
337
|
+
return { status: 'unsupported-schema', reason: 'Configuration schema is unsupported or unreadable.' };
|
|
620
338
|
}
|
|
621
339
|
function sameRepository(left, right) {
|
|
622
340
|
return left.owner.toLowerCase() === right.owner.toLowerCase() && left.repo.toLowerCase() === right.repo.toLowerCase();
|
|
@@ -624,7 +342,7 @@ function sameRepository(left, right) {
|
|
|
624
342
|
function failure(code, summary) { return { code, summary }; }
|
|
625
343
|
function isIntent(value) {
|
|
626
344
|
return typeof value?.targetRoot === 'string' && value.targetRoot.length > 0
|
|
627
|
-
&& ['configure', 'prepare-labels', '
|
|
345
|
+
&& ['configure', 'prepare-labels', 'doctor', 'status'].includes(value.operation)
|
|
628
346
|
&& typeof value.dryRun === 'boolean'
|
|
629
347
|
&& (value.repository === undefined || (typeof value.repository.owner === 'string' && value.repository.owner.length > 0
|
|
630
348
|
&& typeof value.repository.repo === 'string' && value.repository.repo.length > 0));
|