pmpt-cli 1.12.1 → 1.12.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/dist/commands/clone.js +8 -10
- package/dist/commands/diff.js +3 -2
- package/dist/commands/init.js +8 -10
- package/dist/commands/plan.js +9 -12
- package/dist/commands/publish.js +1 -0
- package/dist/commands/squash.js +2 -0
- package/dist/commands/update.js +8 -0
- package/dist/index.js +75 -4
- package/dist/lib/api.js +11 -0
- package/dist/lib/plan.js +23 -12
- package/package.json +1 -1
package/dist/commands/clone.js
CHANGED
|
@@ -190,22 +190,24 @@ export async function cmdClone(slug) {
|
|
|
190
190
|
// Copy AI prompt to clipboard
|
|
191
191
|
const aiContent = readFileSync(aiMdPath, 'utf-8');
|
|
192
192
|
const copied = copyToClipboard(aiContent);
|
|
193
|
+
p.log.info('Tips:');
|
|
194
|
+
p.log.message(' pmpt history — view version history');
|
|
195
|
+
p.log.message(' pmpt plan — view or edit AI prompt');
|
|
196
|
+
p.log.message(' pmpt save — save a new snapshot');
|
|
197
|
+
p.log.message('');
|
|
193
198
|
if (copied) {
|
|
194
|
-
p.log.message('');
|
|
195
|
-
p.log.success('AI prompt copied to clipboard!');
|
|
196
|
-
p.log.message('');
|
|
197
199
|
const banner = [
|
|
198
|
-
'',
|
|
199
200
|
'┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┓',
|
|
200
201
|
'┃ ┃',
|
|
201
202
|
'┃ 📋 NEXT STEP ┃',
|
|
202
203
|
'┃ ┃',
|
|
203
|
-
'┃
|
|
204
|
+
'┃ AI prompt is already copied to clipboard! ┃',
|
|
205
|
+
'┃ Open your AI coding tool and paste it: ┃',
|
|
204
206
|
'┃ ┃',
|
|
205
207
|
'┃ ⌘ + V (Mac) ┃',
|
|
206
208
|
'┃ Ctrl + V (Windows/Linux) ┃',
|
|
207
209
|
'┃ ┃',
|
|
208
|
-
'┃ Your
|
|
210
|
+
'┃ Your project context is ready! 🚀 ┃',
|
|
209
211
|
'┃ ┃',
|
|
210
212
|
'┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┛',
|
|
211
213
|
'',
|
|
@@ -216,9 +218,5 @@ export async function cmdClone(slug) {
|
|
|
216
218
|
p.log.warn('Could not copy to clipboard.');
|
|
217
219
|
p.log.info(`Read it at: ${aiMdPath}`);
|
|
218
220
|
}
|
|
219
|
-
p.log.info('Tips:');
|
|
220
|
-
p.log.message(' pmpt history — view version history');
|
|
221
|
-
p.log.message(' pmpt plan — view or edit AI prompt');
|
|
222
|
-
p.log.message(' pmpt save — save a new snapshot');
|
|
223
221
|
p.outro('Project cloned!');
|
|
224
222
|
}
|
package/dist/commands/diff.js
CHANGED
|
@@ -126,16 +126,17 @@ export function cmdDiff(v1, v2, pathOrOptions, maybeOptions) {
|
|
|
126
126
|
p.log.error('No snapshots found.');
|
|
127
127
|
process.exit(1);
|
|
128
128
|
}
|
|
129
|
+
const versionList = snapshots.map(s => `v${s.version}`).join(', ');
|
|
129
130
|
const fromIndex = snapshots.findIndex(s => s.version === fromVersion);
|
|
130
131
|
if (fromIndex === -1) {
|
|
131
|
-
p.log.error(`Version v${fromVersion} not found
|
|
132
|
+
p.log.error(`Version v${fromVersion} not found. Available: ${versionList}`);
|
|
132
133
|
process.exit(1);
|
|
133
134
|
}
|
|
134
135
|
let toIndex;
|
|
135
136
|
if (!diffAgainstWorking) {
|
|
136
137
|
toIndex = snapshots.findIndex(s => s.version === toVersion);
|
|
137
138
|
if (toIndex === -1) {
|
|
138
|
-
p.log.error(`Version v${toVersion} not found
|
|
139
|
+
p.log.error(`Version v${toVersion} not found. Available: ${versionList}`);
|
|
139
140
|
process.exit(1);
|
|
140
141
|
}
|
|
141
142
|
}
|
package/dist/commands/init.js
CHANGED
|
@@ -176,7 +176,7 @@ export async function cmdInit(path, options) {
|
|
|
176
176
|
const s2 = p.spinner();
|
|
177
177
|
s2.start('Scanning project and generating plan...');
|
|
178
178
|
const answers = scanResultToAnswers(scanResult, userDesc);
|
|
179
|
-
const { planPath, promptPath } = savePlanDocuments(projectPath, answers);
|
|
179
|
+
const { planPath, promptPath } = savePlanDocuments(projectPath, answers, origin);
|
|
180
180
|
const progress = initPlanProgress(projectPath);
|
|
181
181
|
progress.completed = true;
|
|
182
182
|
progress.answers = answers;
|
|
@@ -197,17 +197,19 @@ export async function cmdInit(path, options) {
|
|
|
197
197
|
// Copy to clipboard
|
|
198
198
|
const content = readFileSync(promptPath, 'utf-8');
|
|
199
199
|
const copied = copyToClipboard(content);
|
|
200
|
+
p.log.info('Tips:');
|
|
201
|
+
p.log.message(' pmpt plan — View or edit your AI prompt');
|
|
202
|
+
p.log.message(' pmpt save — Save a snapshot anytime');
|
|
203
|
+
p.log.message(' pmpt watch — Auto-save on file changes');
|
|
204
|
+
p.log.message('');
|
|
200
205
|
if (copied) {
|
|
201
|
-
p.log.message('');
|
|
202
|
-
p.log.success('AI prompt copied to clipboard!');
|
|
203
|
-
p.log.message('');
|
|
204
206
|
const banner = [
|
|
205
|
-
'',
|
|
206
207
|
'┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┓',
|
|
207
208
|
'┃ ┃',
|
|
208
209
|
'┃ 📋 NEXT STEP ┃',
|
|
209
210
|
'┃ ┃',
|
|
210
|
-
'┃
|
|
211
|
+
'┃ AI prompt is already copied to clipboard! ┃',
|
|
212
|
+
'┃ Open your AI coding tool and paste it: ┃',
|
|
211
213
|
'┃ ┃',
|
|
212
214
|
'┃ ⌘ + V (Mac) ┃',
|
|
213
215
|
'┃ Ctrl + V (Windows/Linux) ┃',
|
|
@@ -223,10 +225,6 @@ export async function cmdInit(path, options) {
|
|
|
223
225
|
p.log.warn('Could not copy to clipboard.');
|
|
224
226
|
p.log.info(`Read it at: ${promptPath}`);
|
|
225
227
|
}
|
|
226
|
-
p.log.info('Tips:');
|
|
227
|
-
p.log.message(' pmpt plan — View or edit your AI prompt');
|
|
228
|
-
p.log.message(' pmpt save — Save a snapshot anytime');
|
|
229
|
-
p.log.message(' pmpt watch — Auto-save on file changes');
|
|
230
228
|
p.outro('Ready to go!');
|
|
231
229
|
}
|
|
232
230
|
else if (scanChoice === 'manual') {
|
package/dist/commands/plan.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import * as p from '@clack/prompts';
|
|
2
2
|
import { resolve } from 'path';
|
|
3
3
|
import { existsSync, readFileSync } from 'fs';
|
|
4
|
-
import { isInitialized } from '../lib/config.js';
|
|
4
|
+
import { isInitialized, loadConfig } from '../lib/config.js';
|
|
5
5
|
import { copyToClipboard } from '../lib/clipboard.js';
|
|
6
6
|
import { cmdWatch } from './watch.js';
|
|
7
7
|
import { PLAN_QUESTIONS, getPlanProgress, initPlanProgress, savePlanProgress, savePlanDocuments, } from '../lib/plan.js';
|
|
@@ -88,16 +88,14 @@ export async function cmdPlan(path, options) {
|
|
|
88
88
|
if (action === 'copy') {
|
|
89
89
|
const copied = copyToClipboard(content);
|
|
90
90
|
if (copied) {
|
|
91
|
-
p.log.success('AI prompt copied to clipboard!');
|
|
92
91
|
p.log.message('');
|
|
93
|
-
// Eye-catching next step banner
|
|
94
92
|
const banner = [
|
|
95
|
-
'',
|
|
96
93
|
'┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┓',
|
|
97
94
|
'┃ ┃',
|
|
98
95
|
'┃ 📋 NEXT STEP ┃',
|
|
99
96
|
'┃ ┃',
|
|
100
|
-
'┃
|
|
97
|
+
'┃ AI prompt is already copied to clipboard! ┃',
|
|
98
|
+
'┃ Open your AI coding tool and paste it: ┃',
|
|
101
99
|
'┃ ┃',
|
|
102
100
|
'┃ ⌘ + V (Mac) ┃',
|
|
103
101
|
'┃ Ctrl + V (Windows/Linux) ┃',
|
|
@@ -159,9 +157,10 @@ export async function cmdPlan(path, options) {
|
|
|
159
157
|
p.outro('');
|
|
160
158
|
process.exit(1);
|
|
161
159
|
}
|
|
160
|
+
const config = loadConfig(projectPath);
|
|
162
161
|
const s = p.spinner();
|
|
163
162
|
s.start('Generating documents from answers file...');
|
|
164
|
-
const { planPath, promptPath } = savePlanDocuments(projectPath, answers);
|
|
163
|
+
const { planPath, promptPath } = savePlanDocuments(projectPath, answers, config?.origin);
|
|
165
164
|
progress.completed = true;
|
|
166
165
|
progress.answers = answers;
|
|
167
166
|
savePlanProgress(projectPath, progress);
|
|
@@ -197,9 +196,10 @@ export async function cmdPlan(path, options) {
|
|
|
197
196
|
answers[question.key] = answer;
|
|
198
197
|
}
|
|
199
198
|
// Generate documents
|
|
199
|
+
const config = loadConfig(projectPath);
|
|
200
200
|
const s = p.spinner();
|
|
201
201
|
s.start('Generating your AI prompt...');
|
|
202
|
-
const { planPath, promptPath } = savePlanDocuments(projectPath, answers);
|
|
202
|
+
const { planPath, promptPath } = savePlanDocuments(projectPath, answers, config?.origin);
|
|
203
203
|
// Update progress
|
|
204
204
|
progress.completed = true;
|
|
205
205
|
progress.answers = answers;
|
|
@@ -233,16 +233,13 @@ export async function cmdPlan(path, options) {
|
|
|
233
233
|
const copied = copyToClipboard(content);
|
|
234
234
|
if (copied) {
|
|
235
235
|
p.log.message('');
|
|
236
|
-
p.log.success('AI prompt copied to clipboard!');
|
|
237
|
-
p.log.message('');
|
|
238
|
-
// Eye-catching next step banner
|
|
239
236
|
const banner = [
|
|
240
|
-
'',
|
|
241
237
|
'┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┓',
|
|
242
238
|
'┃ ┃',
|
|
243
239
|
'┃ 📋 NEXT STEP ┃',
|
|
244
240
|
'┃ ┃',
|
|
245
|
-
'┃
|
|
241
|
+
'┃ AI prompt is already copied to clipboard! ┃',
|
|
242
|
+
'┃ Open your AI coding tool and paste it: ┃',
|
|
246
243
|
'┃ ┃',
|
|
247
244
|
'┃ ⌘ + V (Mac) ┃',
|
|
248
245
|
'┃ Ctrl + V (Windows/Linux) ┃',
|
package/dist/commands/publish.js
CHANGED
|
@@ -411,6 +411,7 @@ export async function cmdPublish(path, options) {
|
|
|
411
411
|
if (config) {
|
|
412
412
|
config.lastPublished = new Date().toISOString();
|
|
413
413
|
config.lastPublishedSlug = slug;
|
|
414
|
+
config.lastPublishedVersionCount = snapshots.length;
|
|
414
415
|
saveConfig(projectPath, config);
|
|
415
416
|
}
|
|
416
417
|
p.note([
|
package/dist/commands/squash.js
CHANGED
|
@@ -25,10 +25,12 @@ export async function cmdSquash(from, to, path) {
|
|
|
25
25
|
p.log.error('No snapshots found.');
|
|
26
26
|
process.exit(1);
|
|
27
27
|
}
|
|
28
|
+
const versionList = snapshots.map(s => `v${s.version}`).join(', ');
|
|
28
29
|
// Find snapshots to squash
|
|
29
30
|
const toSquash = snapshots.filter(s => s.version >= fromVersion && s.version <= toVersion);
|
|
30
31
|
if (toSquash.length < 2) {
|
|
31
32
|
p.log.error(`Need at least 2 versions to squash. Found ${toSquash.length} in range v${fromVersion}-v${toVersion}.`);
|
|
33
|
+
p.log.info(`Available versions: ${versionList}`);
|
|
32
34
|
process.exit(1);
|
|
33
35
|
}
|
|
34
36
|
p.intro('pmpt squash');
|
package/dist/commands/update.js
CHANGED
|
@@ -67,6 +67,13 @@ export async function cmdUpdate(path) {
|
|
|
67
67
|
p.outro('');
|
|
68
68
|
return;
|
|
69
69
|
}
|
|
70
|
+
// Check if already up to date
|
|
71
|
+
if (config?.lastPublishedVersionCount === snapshots.length) {
|
|
72
|
+
p.log.success('Already up to date — no new snapshots since last publish.');
|
|
73
|
+
p.log.info('Run `pmpt save` to create a new snapshot, then try again.');
|
|
74
|
+
p.outro('');
|
|
75
|
+
return;
|
|
76
|
+
}
|
|
70
77
|
// Quality gate
|
|
71
78
|
const docsDir = getDocsDir(projectPath);
|
|
72
79
|
const aiMdPath = join(docsDir, 'pmpt.ai.md');
|
|
@@ -136,6 +143,7 @@ export async function cmdUpdate(path) {
|
|
|
136
143
|
s.stop('Updated!');
|
|
137
144
|
if (config) {
|
|
138
145
|
config.lastPublished = new Date().toISOString();
|
|
146
|
+
config.lastPublishedVersionCount = snapshots.length;
|
|
139
147
|
saveConfig(projectPath, config);
|
|
140
148
|
}
|
|
141
149
|
p.note([
|
package/dist/index.js
CHANGED
|
@@ -42,10 +42,15 @@ import { cmdExplore } from './commands/browse.js';
|
|
|
42
42
|
import { cmdRecover } from './commands/recover.js';
|
|
43
43
|
import { cmdDiff } from './commands/diff.js';
|
|
44
44
|
import { cmdInternalSeed } from './commands/internal-seed.js';
|
|
45
|
+
import { trackCommand } from './lib/api.js';
|
|
45
46
|
import { createRequire } from 'module';
|
|
46
47
|
const require = createRequire(import.meta.url);
|
|
47
48
|
const { version } = require('../package.json');
|
|
48
49
|
const program = new Command();
|
|
50
|
+
// Track every command invocation (fire-and-forget)
|
|
51
|
+
program.hook('preAction', (thisCommand) => {
|
|
52
|
+
trackCommand(thisCommand.name());
|
|
53
|
+
});
|
|
49
54
|
program
|
|
50
55
|
.name('pmpt')
|
|
51
56
|
.description('pmpt — Record and share your AI-driven product development journey')
|
|
@@ -56,19 +61,24 @@ Examples:
|
|
|
56
61
|
$ pmpt plan Start product planning (5 questions → AI prompt)
|
|
57
62
|
$ pmpt save Save snapshot of docs folder
|
|
58
63
|
$ pmpt watch Auto-detect file changes
|
|
59
|
-
$ pmpt history
|
|
64
|
+
$ pmpt history (hist) View version history
|
|
60
65
|
$ pmpt diff v1 v2 Compare two versions
|
|
61
66
|
$ pmpt diff v3 Compare v3 to working copy
|
|
62
67
|
$ pmpt squash v2 v5 Merge versions v2-v5 into v2
|
|
63
68
|
$ pmpt export Export as .pmpt file (single JSON)
|
|
64
69
|
$ pmpt import <file.pmpt> Import from .pmpt file
|
|
65
70
|
$ pmpt login Authenticate with pmptwiki
|
|
66
|
-
$ pmpt publish
|
|
71
|
+
$ pmpt publish (pub) Publish project to pmptwiki
|
|
67
72
|
$ pmpt update Quick re-publish (content only)
|
|
68
73
|
$ pmpt clone <slug> Clone a project from pmptwiki
|
|
69
|
-
$ pmpt explore
|
|
74
|
+
$ pmpt explore (exp) Explore projects on pmptwiki.com
|
|
70
75
|
$ pmpt recover Recover damaged pmpt.md via AI
|
|
71
76
|
|
|
77
|
+
Workflow:
|
|
78
|
+
init → plan → save → publish Basic publishing flow
|
|
79
|
+
init → plan → watch Continuous development
|
|
80
|
+
login → publish → update Re-publish with updates
|
|
81
|
+
|
|
72
82
|
Documentation: https://pmptwiki.com
|
|
73
83
|
`);
|
|
74
84
|
// Project tracking commands
|
|
@@ -87,10 +97,12 @@ program
|
|
|
87
97
|
.action(cmdSave);
|
|
88
98
|
program
|
|
89
99
|
.command('status [path]')
|
|
100
|
+
.alias('st')
|
|
90
101
|
.description('Check project status and tracked files')
|
|
91
102
|
.action(cmdStatus);
|
|
92
103
|
program
|
|
93
104
|
.command('history [path]')
|
|
105
|
+
.alias('hist')
|
|
94
106
|
.description('View saved version history')
|
|
95
107
|
.option('-c, --compact', 'Show compact history (hide small changes)')
|
|
96
108
|
.action(cmdHistory);
|
|
@@ -123,9 +135,12 @@ program
|
|
|
123
135
|
.command('logout')
|
|
124
136
|
.description('Clear saved GitHub authentication')
|
|
125
137
|
.action(async () => {
|
|
138
|
+
const prompts = await import('@clack/prompts');
|
|
126
139
|
const { clearAuth } = await import('./lib/auth.js');
|
|
140
|
+
prompts.intro('pmpt logout');
|
|
127
141
|
clearAuth();
|
|
128
|
-
|
|
142
|
+
prompts.log.success('Logged out successfully.');
|
|
143
|
+
prompts.outro('');
|
|
129
144
|
});
|
|
130
145
|
// Platform commands
|
|
131
146
|
program
|
|
@@ -134,6 +149,7 @@ program
|
|
|
134
149
|
.action(cmdLogin);
|
|
135
150
|
program
|
|
136
151
|
.command('publish [path]')
|
|
152
|
+
.alias('pub')
|
|
137
153
|
.description('Publish project to pmptwiki platform')
|
|
138
154
|
.option('--non-interactive', 'Run without interactive prompts')
|
|
139
155
|
.option('--meta-file <file>', 'JSON file with slug, description, tags, category')
|
|
@@ -163,6 +179,7 @@ program
|
|
|
163
179
|
.action(cmdClone);
|
|
164
180
|
program
|
|
165
181
|
.command('explore')
|
|
182
|
+
.alias('exp')
|
|
166
183
|
.description('Open pmptwiki.com to explore and search projects')
|
|
167
184
|
.action(cmdExplore);
|
|
168
185
|
program
|
|
@@ -174,4 +191,58 @@ program
|
|
|
174
191
|
.command('internal-seed', { hidden: true })
|
|
175
192
|
.requiredOption('--spec <file>', 'Seed spec JSON file')
|
|
176
193
|
.action(cmdInternalSeed);
|
|
194
|
+
// "Did you mean?" helper
|
|
195
|
+
function levenshtein(a, b) {
|
|
196
|
+
const m = a.length, n = b.length;
|
|
197
|
+
const dp = Array.from({ length: m + 1 }, (_, i) => Array.from({ length: n + 1 }, (_, j) => (i === 0 ? j : j === 0 ? i : 0)));
|
|
198
|
+
for (let i = 1; i <= m; i++) {
|
|
199
|
+
for (let j = 1; j <= n; j++) {
|
|
200
|
+
dp[i][j] = a[i - 1] === b[j - 1]
|
|
201
|
+
? dp[i - 1][j - 1]
|
|
202
|
+
: 1 + Math.min(dp[i - 1][j], dp[i][j - 1], dp[i - 1][j - 1]);
|
|
203
|
+
}
|
|
204
|
+
}
|
|
205
|
+
return dp[m][n];
|
|
206
|
+
}
|
|
207
|
+
function suggestCommand(unknown) {
|
|
208
|
+
const available = program.commands
|
|
209
|
+
.filter(cmd => !cmd._hidden)
|
|
210
|
+
.flatMap(cmd => [cmd.name(), ...(cmd.aliases?.() ?? [])]);
|
|
211
|
+
let bestMatch = '';
|
|
212
|
+
let bestDist = Infinity;
|
|
213
|
+
for (const name of available) {
|
|
214
|
+
const dist = levenshtein(unknown, name);
|
|
215
|
+
if (dist < bestDist) {
|
|
216
|
+
bestDist = dist;
|
|
217
|
+
bestMatch = name;
|
|
218
|
+
}
|
|
219
|
+
}
|
|
220
|
+
console.error(`\n Unknown command: ${unknown}\n`);
|
|
221
|
+
if (bestDist <= 3 && bestMatch) {
|
|
222
|
+
console.error(` Did you mean \x1b[36mpmpt ${bestMatch}\x1b[0m?\n`);
|
|
223
|
+
}
|
|
224
|
+
console.error(` Run \x1b[36mpmpt --help\x1b[0m to see all commands.\n`);
|
|
225
|
+
process.exit(1);
|
|
226
|
+
}
|
|
227
|
+
// Handle unknown subcommands and Quick Start
|
|
228
|
+
program.on('command:*', (operands) => {
|
|
229
|
+
suggestCommand(operands[0]);
|
|
230
|
+
});
|
|
231
|
+
// Show Quick Start when no arguments provided
|
|
232
|
+
const args = process.argv.slice(2);
|
|
233
|
+
if (args.length === 0) {
|
|
234
|
+
console.log(`
|
|
235
|
+
pmpt v${version} — Record and share your AI-driven product development journey
|
|
236
|
+
|
|
237
|
+
Quick Start:
|
|
238
|
+
$ pmpt init 1. Initialize project
|
|
239
|
+
$ pmpt plan 2. Generate AI prompt (copied to clipboard)
|
|
240
|
+
$ pmpt save 3. Save snapshot after progress
|
|
241
|
+
$ pmpt publish 4. Share on pmptwiki.com
|
|
242
|
+
|
|
243
|
+
Run \x1b[36mpmpt --help\x1b[0m for all commands.
|
|
244
|
+
Documentation: https://pmptwiki.com
|
|
245
|
+
`);
|
|
246
|
+
process.exit(0);
|
|
247
|
+
}
|
|
177
248
|
program.parse();
|
package/dist/lib/api.js
CHANGED
|
@@ -92,3 +92,14 @@ export function trackClone(slug) {
|
|
|
92
92
|
body: JSON.stringify({ slug }),
|
|
93
93
|
}).catch(() => { });
|
|
94
94
|
}
|
|
95
|
+
/**
|
|
96
|
+
* Fire-and-forget CLI command usage tracking.
|
|
97
|
+
* Never throws — failures are silently ignored.
|
|
98
|
+
*/
|
|
99
|
+
export function trackCommand(command) {
|
|
100
|
+
fetch(`${API_BASE}/metrics/command`, {
|
|
101
|
+
method: 'POST',
|
|
102
|
+
headers: { 'Content-Type': 'application/json' },
|
|
103
|
+
body: JSON.stringify({ command }),
|
|
104
|
+
}).catch(() => { });
|
|
105
|
+
}
|
package/dist/lib/plan.js
CHANGED
|
@@ -42,7 +42,7 @@ export const PLAN_QUESTIONS = [
|
|
|
42
42
|
},
|
|
43
43
|
];
|
|
44
44
|
// Generate AI instruction file (pmpt.ai.md) — always English, AI-facing
|
|
45
|
-
export function generateAIPrompt(answers) {
|
|
45
|
+
export function generateAIPrompt(answers, origin) {
|
|
46
46
|
// Parse features (support comma, semicolon, or newline separators)
|
|
47
47
|
const features = answers.coreFeatures
|
|
48
48
|
.split(/[,;\n]/)
|
|
@@ -56,10 +56,28 @@ export function generateAIPrompt(answers) {
|
|
|
56
56
|
const techSection = answers.techStack
|
|
57
57
|
? `\n## Tech Stack Preferences\n${answers.techStack}\n`
|
|
58
58
|
: '';
|
|
59
|
+
const isAdopted = origin === 'adopted';
|
|
60
|
+
const workflowSteps = isAdopted
|
|
61
|
+
? `This is an **existing project** — you are joining mid-development.
|
|
62
|
+
|
|
63
|
+
1. First, explore the existing codebase and understand the current architecture.
|
|
64
|
+
2. Review what's already implemented vs what still needs to be done.
|
|
65
|
+
3. Suggest improvements or next steps based on the current state.
|
|
66
|
+
4. Continue development from where it left off.
|
|
67
|
+
|
|
68
|
+
Do NOT start from scratch. Build on the existing code.`
|
|
69
|
+
: `Please help me build this product based on the requirements above.
|
|
70
|
+
|
|
71
|
+
1. First, review the requirements and ask if anything is unclear.
|
|
72
|
+
2. Propose a technical architecture.
|
|
73
|
+
3. Outline the implementation steps.
|
|
74
|
+
4. Start coding from the first step.
|
|
75
|
+
|
|
76
|
+
I'll confirm progress at each step before moving to the next.`;
|
|
59
77
|
return `<!-- This file is for AI tools only. Do not edit manually. -->
|
|
60
78
|
<!-- Paste this into Claude Code, Codex, Cursor, or any AI coding tool. -->
|
|
61
79
|
|
|
62
|
-
# ${answers.projectName} — Product Development Request
|
|
80
|
+
# ${answers.projectName} — ${isAdopted ? 'Continue Development' : 'Product Development Request'}
|
|
63
81
|
|
|
64
82
|
## What I Want to Build
|
|
65
83
|
${answers.productIdea}
|
|
@@ -69,14 +87,7 @@ ${features}
|
|
|
69
87
|
${techSection}
|
|
70
88
|
---
|
|
71
89
|
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
1. First, review the requirements and ask if anything is unclear.
|
|
75
|
-
2. Propose a technical architecture.
|
|
76
|
-
3. Outline the implementation steps.
|
|
77
|
-
4. Start coding from the first step.
|
|
78
|
-
|
|
79
|
-
I'll confirm progress at each step before moving to the next.
|
|
90
|
+
${workflowSteps}
|
|
80
91
|
|
|
81
92
|
## Documentation Rule
|
|
82
93
|
|
|
@@ -186,7 +197,7 @@ export function initPlanProgress(projectPath) {
|
|
|
186
197
|
savePlanProgress(projectPath, progress);
|
|
187
198
|
return progress;
|
|
188
199
|
}
|
|
189
|
-
export function savePlanDocuments(projectPath, answers) {
|
|
200
|
+
export function savePlanDocuments(projectPath, answers, origin) {
|
|
190
201
|
const pmptDir = getPmptDir(projectPath);
|
|
191
202
|
mkdirSync(pmptDir, { recursive: true });
|
|
192
203
|
// Save plan to pmpt folder
|
|
@@ -199,7 +210,7 @@ export function savePlanDocuments(projectPath, answers) {
|
|
|
199
210
|
writeFileSync(pmptMdPath, pmptMdContent, 'utf-8');
|
|
200
211
|
// Save AI instruction file
|
|
201
212
|
const promptPath = join(pmptDir, 'pmpt.ai.md');
|
|
202
|
-
const promptContent = generateAIPrompt(answers);
|
|
213
|
+
const promptContent = generateAIPrompt(answers, origin);
|
|
203
214
|
writeFileSync(promptPath, promptContent, 'utf-8');
|
|
204
215
|
// Create initial snapshot
|
|
205
216
|
createFullSnapshot(projectPath);
|