@jojonax/codex-copilot 1.0.2 → 1.0.3
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/bin/cli.js +33 -22
- package/package.json +1 -1
- package/src/commands/init.js +82 -82
- package/src/commands/reset.js +10 -10
- package/src/commands/run.js +121 -115
- package/src/commands/status.js +15 -15
- package/src/utils/detect-prd.js +18 -18
- package/src/utils/git.js +17 -17
- package/src/utils/github.js +19 -19
- package/src/utils/logger.js +14 -13
- package/src/utils/prompt.js +7 -7
- package/src/utils/update-check.js +103 -0
package/bin/cli.js
CHANGED
|
@@ -1,31 +1,39 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
|
|
3
3
|
/**
|
|
4
|
-
* codex-copilot CLI - PRD →
|
|
4
|
+
* codex-copilot CLI - PRD → Auto Dev → PR → Review → Fix → Merge
|
|
5
5
|
*
|
|
6
|
-
*
|
|
7
|
-
* codex-copilot init #
|
|
8
|
-
* codex-copilot run #
|
|
9
|
-
* codex-copilot status #
|
|
10
|
-
* codex-copilot reset #
|
|
6
|
+
* Usage:
|
|
7
|
+
* codex-copilot init # Initialize project (auto-detect PRD, generate tasks)
|
|
8
|
+
* codex-copilot run # Start automated development loop
|
|
9
|
+
* codex-copilot status # View current progress
|
|
10
|
+
* codex-copilot reset # Reset state (start over)
|
|
11
11
|
*/
|
|
12
12
|
|
|
13
|
-
import { resolve } from 'path';
|
|
14
|
-
import { existsSync } from 'fs';
|
|
13
|
+
import { resolve, dirname } from 'path';
|
|
14
|
+
import { existsSync, readFileSync } from 'fs';
|
|
15
|
+
import { fileURLToPath } from 'url';
|
|
15
16
|
|
|
16
17
|
import { init } from '../src/commands/init.js';
|
|
17
18
|
import { run } from '../src/commands/run.js';
|
|
18
19
|
import { status } from '../src/commands/status.js';
|
|
19
20
|
import { reset } from '../src/commands/reset.js';
|
|
20
21
|
import { log } from '../src/utils/logger.js';
|
|
22
|
+
import { checkForUpdates } from '../src/utils/update-check.js';
|
|
21
23
|
|
|
22
24
|
const command = process.argv[2];
|
|
23
25
|
const projectDir = process.cwd();
|
|
24
26
|
|
|
27
|
+
// Read version from package.json
|
|
28
|
+
const __filename = fileURLToPath(import.meta.url);
|
|
29
|
+
const __dirname = dirname(__filename);
|
|
30
|
+
const pkg = JSON.parse(readFileSync(resolve(__dirname, '..', 'package.json'), 'utf-8'));
|
|
31
|
+
const version = pkg.version;
|
|
32
|
+
|
|
25
33
|
// Banner
|
|
26
34
|
console.log('');
|
|
27
35
|
console.log(' ╔══════════════════════════════════════════╗');
|
|
28
|
-
console.log(
|
|
36
|
+
console.log(` ║ 🤖 Codex-Copilot v${version.padEnd(18)}║`);
|
|
29
37
|
console.log(' ║ PRD-Driven Auto Development ║');
|
|
30
38
|
console.log(' ╚══════════════════════════════════════════╝');
|
|
31
39
|
console.log('');
|
|
@@ -39,7 +47,7 @@ async function main() {
|
|
|
39
47
|
|
|
40
48
|
case 'run':
|
|
41
49
|
if (!existsSync(resolve(projectDir, '.codex-copilot/tasks.json'))) {
|
|
42
|
-
log.error('
|
|
50
|
+
log.error('Not initialized. Run: codex-copilot init');
|
|
43
51
|
process.exit(1);
|
|
44
52
|
}
|
|
45
53
|
await run(projectDir);
|
|
@@ -47,7 +55,7 @@ async function main() {
|
|
|
47
55
|
|
|
48
56
|
case 'status':
|
|
49
57
|
if (!existsSync(resolve(projectDir, '.codex-copilot/tasks.json'))) {
|
|
50
|
-
log.error('
|
|
58
|
+
log.error('Not initialized. Run: codex-copilot init');
|
|
51
59
|
process.exit(1);
|
|
52
60
|
}
|
|
53
61
|
await status(projectDir);
|
|
@@ -58,26 +66,29 @@ async function main() {
|
|
|
58
66
|
break;
|
|
59
67
|
|
|
60
68
|
default:
|
|
61
|
-
console.log('
|
|
69
|
+
console.log(' Usage: codex-copilot <command>');
|
|
62
70
|
console.log('');
|
|
63
|
-
console.log('
|
|
64
|
-
console.log(' init
|
|
65
|
-
console.log(' run
|
|
66
|
-
console.log(' status
|
|
67
|
-
console.log(' reset
|
|
71
|
+
console.log(' Commands:');
|
|
72
|
+
console.log(' init Initialize project (auto-detect PRD, generate task queue)');
|
|
73
|
+
console.log(' run Start automated development loop');
|
|
74
|
+
console.log(' status View current task progress');
|
|
75
|
+
console.log(' reset Reset state and start over');
|
|
68
76
|
console.log('');
|
|
69
|
-
console.log('
|
|
70
|
-
console.log(' 1. cd
|
|
71
|
-
console.log(' 2. codex-copilot init (
|
|
72
|
-
console.log(' 3. codex-copilot run (
|
|
77
|
+
console.log(' Workflow:');
|
|
78
|
+
console.log(' 1. cd into your project directory');
|
|
79
|
+
console.log(' 2. codex-copilot init (auto-detect PRD and decompose tasks)');
|
|
80
|
+
console.log(' 3. codex-copilot run (start automated dev loop)');
|
|
73
81
|
console.log('');
|
|
74
82
|
break;
|
|
75
83
|
}
|
|
76
84
|
} catch (err) {
|
|
77
|
-
log.error(
|
|
85
|
+
log.error(`Execution failed: ${err.message}`);
|
|
78
86
|
if (process.env.DEBUG) console.error(err);
|
|
79
87
|
process.exit(1);
|
|
80
88
|
}
|
|
81
89
|
}
|
|
82
90
|
|
|
91
|
+
// Check for updates (non-blocking, cached 24h)
|
|
92
|
+
checkForUpdates(version);
|
|
93
|
+
|
|
83
94
|
main();
|
package/package.json
CHANGED
package/src/commands/init.js
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* codex-copilot init -
|
|
2
|
+
* codex-copilot init - Initialize project
|
|
3
3
|
*
|
|
4
|
-
* 1.
|
|
5
|
-
* 2.
|
|
6
|
-
* 3.
|
|
7
|
-
* 4.
|
|
4
|
+
* 1. Auto-detect PRD document
|
|
5
|
+
* 2. Let user confirm/select PRD
|
|
6
|
+
* 3. Generate CodeX-executable task decomposition prompt
|
|
7
|
+
* 4. Create .codex-copilot/ directory structure
|
|
8
8
|
*/
|
|
9
9
|
|
|
10
10
|
import { mkdirSync, writeFileSync, readFileSync, existsSync } from 'fs';
|
|
@@ -17,34 +17,34 @@ import { git } from '../utils/git.js';
|
|
|
17
17
|
import { github } from '../utils/github.js';
|
|
18
18
|
|
|
19
19
|
export async function init(projectDir) {
|
|
20
|
-
log.title('📋
|
|
20
|
+
log.title('📋 Initializing Codex-Copilot');
|
|
21
21
|
log.blank();
|
|
22
22
|
|
|
23
|
-
// =====
|
|
24
|
-
log.step('
|
|
23
|
+
// ===== Pre-flight checks =====
|
|
24
|
+
log.step('Checking environment...');
|
|
25
25
|
|
|
26
|
-
//
|
|
26
|
+
// Check if in a git repo
|
|
27
27
|
try {
|
|
28
28
|
git.currentBranch(projectDir);
|
|
29
|
-
log.info('Git
|
|
29
|
+
log.info('Git repository ✓');
|
|
30
30
|
} catch {
|
|
31
|
-
log.error('
|
|
31
|
+
log.error('Not a Git repository. Run: git init');
|
|
32
32
|
closePrompt();
|
|
33
33
|
process.exit(1);
|
|
34
34
|
}
|
|
35
35
|
|
|
36
|
-
//
|
|
36
|
+
// Check gh CLI
|
|
37
37
|
if (!github.checkGhAuth()) {
|
|
38
|
-
log.error('GitHub CLI
|
|
38
|
+
log.error('GitHub CLI not authenticated. Run: gh auth login');
|
|
39
39
|
closePrompt();
|
|
40
40
|
process.exit(1);
|
|
41
41
|
}
|
|
42
42
|
log.info('GitHub CLI ✓');
|
|
43
43
|
|
|
44
|
-
//
|
|
44
|
+
// Check GitHub remote
|
|
45
45
|
try {
|
|
46
46
|
const repo = git.getRepoInfo(projectDir);
|
|
47
|
-
log.info(`GitHub
|
|
47
|
+
log.info(`GitHub repo: ${repo.owner}/${repo.repo} ✓`);
|
|
48
48
|
} catch (err) {
|
|
49
49
|
log.error(err.message);
|
|
50
50
|
closePrompt();
|
|
@@ -53,57 +53,57 @@ export async function init(projectDir) {
|
|
|
53
53
|
|
|
54
54
|
log.blank();
|
|
55
55
|
|
|
56
|
-
// =====
|
|
57
|
-
log.step('
|
|
56
|
+
// ===== Detect PRD =====
|
|
57
|
+
log.step('Scanning for PRD documents...');
|
|
58
58
|
const candidates = detectPRD(projectDir);
|
|
59
59
|
|
|
60
60
|
let prdPath;
|
|
61
61
|
|
|
62
62
|
if (candidates.length === 0) {
|
|
63
|
-
log.warn('
|
|
64
|
-
const manualPath = await ask('
|
|
63
|
+
log.warn('No PRD document detected automatically');
|
|
64
|
+
const manualPath = await ask('Enter PRD file path (relative or absolute):');
|
|
65
65
|
prdPath = resolve(projectDir, manualPath);
|
|
66
|
-
//
|
|
66
|
+
// Prevent path traversal
|
|
67
67
|
if (!prdPath.startsWith(resolve(projectDir)) && !manualPath.startsWith('/')) {
|
|
68
|
-
log.error('PRD
|
|
68
|
+
log.error('PRD path is outside the project directory');
|
|
69
69
|
closePrompt();
|
|
70
70
|
process.exit(1);
|
|
71
71
|
}
|
|
72
72
|
if (!existsSync(prdPath)) {
|
|
73
|
-
log.error(
|
|
73
|
+
log.error(`File not found: ${prdPath}`);
|
|
74
74
|
closePrompt();
|
|
75
75
|
process.exit(1);
|
|
76
76
|
}
|
|
77
77
|
} else if (candidates.length === 1) {
|
|
78
78
|
prdPath = candidates[0].path;
|
|
79
|
-
log.info(
|
|
80
|
-
const ok = await confirm('
|
|
79
|
+
log.info(`Found PRD: ${candidates[0].relativePath}`);
|
|
80
|
+
const ok = await confirm('Use this file?');
|
|
81
81
|
if (!ok) {
|
|
82
|
-
const manualPath = await ask('
|
|
82
|
+
const manualPath = await ask('Enter PRD file path:');
|
|
83
83
|
prdPath = resolve(projectDir, manualPath);
|
|
84
84
|
}
|
|
85
85
|
} else {
|
|
86
|
-
log.info(
|
|
87
|
-
const choice = await select('
|
|
88
|
-
label: `${c.relativePath} (
|
|
86
|
+
log.info(`Found ${candidates.length} candidate PRD files:`);
|
|
87
|
+
const choice = await select('Select the PRD to use:', candidates.map(c => ({
|
|
88
|
+
label: `${c.relativePath} (score: ${c.score})`,
|
|
89
89
|
value: c.path,
|
|
90
90
|
})));
|
|
91
91
|
prdPath = choice.value;
|
|
92
92
|
}
|
|
93
93
|
|
|
94
|
-
log.info(
|
|
94
|
+
log.info(`Using PRD: ${prdPath}`);
|
|
95
95
|
log.blank();
|
|
96
96
|
|
|
97
|
-
// =====
|
|
97
|
+
// ===== Read PRD =====
|
|
98
98
|
const prdContent = readPRD(prdPath);
|
|
99
|
-
log.info(`PRD
|
|
99
|
+
log.info(`PRD size: ${(prdContent.length / 1024).toFixed(1)} KB`);
|
|
100
100
|
|
|
101
|
-
// =====
|
|
102
|
-
log.step('
|
|
101
|
+
// ===== Create .codex-copilot directory =====
|
|
102
|
+
log.step('Creating .codex-copilot/ directory...');
|
|
103
103
|
const copilotDir = resolve(projectDir, '.codex-copilot');
|
|
104
104
|
mkdirSync(copilotDir, { recursive: true });
|
|
105
105
|
|
|
106
|
-
//
|
|
106
|
+
// Write config file
|
|
107
107
|
const config = {
|
|
108
108
|
prd_path: prdPath,
|
|
109
109
|
base_branch: git.currentBranch(projectDir) || 'main',
|
|
@@ -114,7 +114,7 @@ export async function init(projectDir) {
|
|
|
114
114
|
};
|
|
115
115
|
writeFileSync(resolve(copilotDir, 'config.json'), JSON.stringify(config, null, 2));
|
|
116
116
|
|
|
117
|
-
//
|
|
117
|
+
// Write initial state
|
|
118
118
|
const state = {
|
|
119
119
|
current_task: 0,
|
|
120
120
|
current_pr: null,
|
|
@@ -123,28 +123,28 @@ export async function init(projectDir) {
|
|
|
123
123
|
};
|
|
124
124
|
writeFileSync(resolve(copilotDir, 'state.json'), JSON.stringify(state, null, 2));
|
|
125
125
|
|
|
126
|
-
//
|
|
127
|
-
const instructions = `# Codex-Copilot
|
|
126
|
+
// Write CodeX instruction template
|
|
127
|
+
const instructions = `# Codex-Copilot Development Instructions
|
|
128
128
|
|
|
129
|
-
##
|
|
130
|
-
|
|
129
|
+
## Role
|
|
130
|
+
You are an efficient automated development agent responsible for completing feature development according to task descriptions.
|
|
131
131
|
|
|
132
|
-
##
|
|
133
|
-
1.
|
|
134
|
-
2.
|
|
135
|
-
3. **Git
|
|
136
|
-
4.
|
|
137
|
-
5.
|
|
132
|
+
## Rules
|
|
133
|
+
1. **Follow the project tech stack**: Use the existing frameworks, tools, and code style
|
|
134
|
+
2. **Test first**: Ensure code compiles/runs before finishing
|
|
135
|
+
3. **Git conventions**: Commit message format \`feat(task-N): brief description\` or \`fix(task-N): brief description\`
|
|
136
|
+
4. **Don't modify unrelated files**: Only change files required by the current task
|
|
137
|
+
5. **Commit when done**: \`git add -A && git commit -m "..."\`
|
|
138
138
|
|
|
139
|
-
##
|
|
140
|
-
1.
|
|
141
|
-
2.
|
|
142
|
-
3.
|
|
143
|
-
4.
|
|
139
|
+
## Rules for fixing reviews
|
|
140
|
+
1. Read each review comment carefully
|
|
141
|
+
2. Distinguish between must-fix vs. suggestions
|
|
142
|
+
3. If you disagree with a comment, explain why in the commit message
|
|
143
|
+
4. Ensure fixes don't introduce new issues
|
|
144
144
|
`;
|
|
145
145
|
writeFileSync(resolve(copilotDir, 'codex-instructions.md'), instructions);
|
|
146
146
|
|
|
147
|
-
//
|
|
147
|
+
// Add .gitignore entries
|
|
148
148
|
const gitignorePath = resolve(projectDir, '.gitignore');
|
|
149
149
|
const gitignoreEntry = '\n# Codex-Copilot state\n.codex-copilot/state.json\n';
|
|
150
150
|
if (existsSync(gitignorePath)) {
|
|
@@ -154,49 +154,49 @@ export async function init(projectDir) {
|
|
|
154
154
|
}
|
|
155
155
|
}
|
|
156
156
|
|
|
157
|
-
log.info('.codex-copilot/
|
|
157
|
+
log.info('.codex-copilot/ directory created');
|
|
158
158
|
log.blank();
|
|
159
159
|
|
|
160
|
-
// =====
|
|
161
|
-
log.step('
|
|
160
|
+
// ===== Generate task decomposition prompt =====
|
|
161
|
+
log.step('Generating task decomposition prompt...');
|
|
162
162
|
|
|
163
163
|
const parsePrompt = buildParsePrompt(prdContent, copilotDir);
|
|
164
164
|
const promptPath = resolve(copilotDir, 'parse-prd-prompt.md');
|
|
165
165
|
writeFileSync(promptPath, parsePrompt);
|
|
166
166
|
|
|
167
|
-
log.info(
|
|
167
|
+
log.info('Task decomposition prompt saved to: .codex-copilot/parse-prd-prompt.md');
|
|
168
168
|
log.blank();
|
|
169
169
|
|
|
170
|
-
// =====
|
|
171
|
-
log.title('✅
|
|
170
|
+
// ===== Guide user to next steps =====
|
|
171
|
+
log.title('✅ Initialization complete!');
|
|
172
172
|
log.blank();
|
|
173
|
-
log.info('
|
|
173
|
+
log.info('Next steps:');
|
|
174
174
|
log.blank();
|
|
175
175
|
console.log(' ┌───────────────────────────────────────────────────┐');
|
|
176
|
-
console.log(' │ 1.
|
|
177
|
-
console.log(' │ 2.
|
|
176
|
+
console.log(' │ 1. Open CodeX Desktop │');
|
|
177
|
+
console.log(' │ 2. Paste the following file content into CodeX: │');
|
|
178
178
|
console.log(' │ .codex-copilot/parse-prd-prompt.md │');
|
|
179
|
-
console.log(' │ 3. CodeX
|
|
180
|
-
console.log(' │ 4.
|
|
179
|
+
console.log(' │ 3. CodeX will generate .codex-copilot/tasks.json │');
|
|
180
|
+
console.log(' │ 4. Confirm the task list, then run: │');
|
|
181
181
|
console.log(' │ codex-copilot run │');
|
|
182
182
|
console.log(' └───────────────────────────────────────────────────┘');
|
|
183
183
|
log.blank();
|
|
184
184
|
|
|
185
|
-
//
|
|
185
|
+
// Ask if user wants to auto-decompose (if codex CLI is available)
|
|
186
186
|
const hasCodexCLI = checkCodexCLI();
|
|
187
187
|
if (hasCodexCLI) {
|
|
188
|
-
log.info('
|
|
189
|
-
const autoparse = await confirm('
|
|
188
|
+
log.info('CodeX CLI detected!');
|
|
189
|
+
const autoparse = await confirm('Auto-invoke CodeX to decompose PRD?');
|
|
190
190
|
if (autoparse) {
|
|
191
|
-
log.step('
|
|
191
|
+
log.step('Invoking CodeX CLI to decompose PRD...');
|
|
192
192
|
try {
|
|
193
|
-
execSync(`
|
|
193
|
+
execSync(`cat .codex-copilot/parse-prd-prompt.md | codex exec --full-auto -`, {
|
|
194
194
|
cwd: projectDir,
|
|
195
195
|
stdio: 'inherit',
|
|
196
196
|
});
|
|
197
|
-
log.info('CodeX
|
|
197
|
+
log.info('CodeX decomposition complete!');
|
|
198
198
|
} catch {
|
|
199
|
-
log.warn('CodeX CLI
|
|
199
|
+
log.warn('CodeX CLI invocation failed. Please run manually.');
|
|
200
200
|
}
|
|
201
201
|
}
|
|
202
202
|
}
|
|
@@ -215,27 +215,27 @@ function checkCodexCLI() {
|
|
|
215
215
|
}
|
|
216
216
|
|
|
217
217
|
function buildParsePrompt(prdContent, copilotDir) {
|
|
218
|
-
return
|
|
218
|
+
return `Read the following PRD document and break it down into independent development tasks.
|
|
219
219
|
|
|
220
|
-
##
|
|
221
|
-
1.
|
|
222
|
-
2.
|
|
223
|
-
3.
|
|
224
|
-
4.
|
|
220
|
+
## Requirements
|
|
221
|
+
1. Each task should be completable in a single PR (moderate granularity — not too large, not too small)
|
|
222
|
+
2. Each task must have clear acceptance criteria
|
|
223
|
+
3. Tasks should be ordered by dependency (dependent tasks first)
|
|
224
|
+
4. The first task is usually "Project initialization / base framework setup"
|
|
225
225
|
|
|
226
|
-
##
|
|
227
|
-
|
|
226
|
+
## Output Format
|
|
227
|
+
Write the result to \`.codex-copilot/tasks.json\` in the following format:
|
|
228
228
|
|
|
229
229
|
\`\`\`json
|
|
230
230
|
{
|
|
231
|
-
"project": "
|
|
231
|
+
"project": "Project Name",
|
|
232
232
|
"total": 5,
|
|
233
233
|
"tasks": [
|
|
234
234
|
{
|
|
235
235
|
"id": 1,
|
|
236
|
-
"title": "
|
|
237
|
-
"description": "
|
|
238
|
-
"acceptance": ["
|
|
236
|
+
"title": "Task title (brief)",
|
|
237
|
+
"description": "Detailed task description with specific features and technical details",
|
|
238
|
+
"acceptance": ["Acceptance criteria 1", "Acceptance criteria 2"],
|
|
239
239
|
"branch": "feature/001-task-slug",
|
|
240
240
|
"status": "pending",
|
|
241
241
|
"depends_on": []
|
|
@@ -253,7 +253,7 @@ function buildParsePrompt(prdContent, copilotDir) {
|
|
|
253
253
|
}
|
|
254
254
|
\`\`\`
|
|
255
255
|
|
|
256
|
-
## PRD
|
|
256
|
+
## PRD Document Content
|
|
257
257
|
|
|
258
258
|
${prdContent}
|
|
259
259
|
`;
|
package/src/commands/reset.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* codex-copilot reset -
|
|
2
|
+
* codex-copilot reset - Reset state
|
|
3
3
|
*/
|
|
4
4
|
|
|
5
5
|
import { readFileSync, writeFileSync, existsSync, unlinkSync } from 'fs';
|
|
@@ -12,17 +12,17 @@ export async function reset(projectDir) {
|
|
|
12
12
|
const tasksPath = resolve(projectDir, '.codex-copilot/tasks.json');
|
|
13
13
|
|
|
14
14
|
if (!existsSync(statePath)) {
|
|
15
|
-
log.warn('
|
|
15
|
+
log.warn('Project not initialized, nothing to reset');
|
|
16
16
|
closePrompt();
|
|
17
17
|
return;
|
|
18
18
|
}
|
|
19
19
|
|
|
20
|
-
log.title('🔄
|
|
20
|
+
log.title('🔄 Resetting Codex-Copilot state');
|
|
21
21
|
log.blank();
|
|
22
22
|
|
|
23
|
-
const resetTasks = await confirm('
|
|
23
|
+
const resetTasks = await confirm('Also reset all task statuses to pending?', false);
|
|
24
24
|
|
|
25
|
-
//
|
|
25
|
+
// Reset state
|
|
26
26
|
const state = {
|
|
27
27
|
current_task: 0,
|
|
28
28
|
current_pr: null,
|
|
@@ -30,23 +30,23 @@ export async function reset(projectDir) {
|
|
|
30
30
|
status: 'initialized',
|
|
31
31
|
};
|
|
32
32
|
writeFileSync(statePath, JSON.stringify(state, null, 2));
|
|
33
|
-
log.info('
|
|
33
|
+
log.info('Execution state reset');
|
|
34
34
|
|
|
35
|
-
//
|
|
35
|
+
// Reset task statuses
|
|
36
36
|
if (resetTasks && existsSync(tasksPath)) {
|
|
37
37
|
const tasks = JSON.parse(readFileSync(tasksPath, 'utf-8'));
|
|
38
38
|
for (const task of tasks.tasks) {
|
|
39
39
|
task.status = 'pending';
|
|
40
40
|
}
|
|
41
41
|
writeFileSync(tasksPath, JSON.stringify(tasks, null, 2));
|
|
42
|
-
log.info('
|
|
42
|
+
log.info('Task statuses reset');
|
|
43
43
|
}
|
|
44
44
|
|
|
45
|
-
//
|
|
45
|
+
// Clean up temp files
|
|
46
46
|
const promptPath = resolve(projectDir, '.codex-copilot/_current_prompt.md');
|
|
47
47
|
if (existsSync(promptPath)) unlinkSync(promptPath);
|
|
48
48
|
|
|
49
49
|
log.blank();
|
|
50
|
-
log.info('✅
|
|
50
|
+
log.info('✅ Reset complete. You can now run: codex-copilot run');
|
|
51
51
|
closePrompt();
|
|
52
52
|
}
|