@pixel613/spec 1.0.1
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/LICENSE +21 -0
- package/README.md +174 -0
- package/dist/bin/pxs.d.ts +2 -0
- package/dist/bin/pxs.js +5 -0
- package/dist/bin/pxs.js.map +1 -0
- package/dist/src/backends/claude.d.ts +9 -0
- package/dist/src/backends/claude.js +80 -0
- package/dist/src/backends/claude.js.map +1 -0
- package/dist/src/backends/codex.d.ts +9 -0
- package/dist/src/backends/codex.js +72 -0
- package/dist/src/backends/codex.js.map +1 -0
- package/dist/src/backends/factory.d.ts +2 -0
- package/dist/src/backends/factory.js +14 -0
- package/dist/src/backends/factory.js.map +1 -0
- package/dist/src/backends/interface.d.ts +15 -0
- package/dist/src/backends/interface.js +2 -0
- package/dist/src/backends/interface.js.map +1 -0
- package/dist/src/cli.d.ts +2 -0
- package/dist/src/cli.js +79 -0
- package/dist/src/cli.js.map +1 -0
- package/dist/src/commands/clarify.d.ts +5 -0
- package/dist/src/commands/clarify.js +46 -0
- package/dist/src/commands/clarify.js.map +1 -0
- package/dist/src/commands/implement.d.ts +9 -0
- package/dist/src/commands/implement.js +244 -0
- package/dist/src/commands/implement.js.map +1 -0
- package/dist/src/commands/init.d.ts +6 -0
- package/dist/src/commands/init.js +177 -0
- package/dist/src/commands/init.js.map +1 -0
- package/dist/src/commands/new.d.ts +5 -0
- package/dist/src/commands/new.js +143 -0
- package/dist/src/commands/new.js.map +1 -0
- package/dist/src/commands/refine.d.ts +8 -0
- package/dist/src/commands/refine.js +158 -0
- package/dist/src/commands/refine.js.map +1 -0
- package/dist/src/commands/review.d.ts +4 -0
- package/dist/src/commands/review.js +70 -0
- package/dist/src/commands/review.js.map +1 -0
- package/dist/src/commands/status.d.ts +1 -0
- package/dist/src/commands/status.js +53 -0
- package/dist/src/commands/status.js.map +1 -0
- package/dist/src/discovery/project.d.ts +7 -0
- package/dist/src/discovery/project.js +90 -0
- package/dist/src/discovery/project.js.map +1 -0
- package/dist/src/git/operations.d.ts +10 -0
- package/dist/src/git/operations.js +56 -0
- package/dist/src/git/operations.js.map +1 -0
- package/dist/src/parsers/arguments.d.ts +18 -0
- package/dist/src/parsers/arguments.js +43 -0
- package/dist/src/parsers/arguments.js.map +1 -0
- package/dist/src/parsers/plan.d.ts +23 -0
- package/dist/src/parsers/plan.js +117 -0
- package/dist/src/parsers/plan.js.map +1 -0
- package/dist/src/parsers/spec.d.ts +10 -0
- package/dist/src/parsers/spec.js +46 -0
- package/dist/src/parsers/spec.js.map +1 -0
- package/dist/src/state/manager.d.ts +24 -0
- package/dist/src/state/manager.js +103 -0
- package/dist/src/state/manager.js.map +1 -0
- package/dist/src/state/types.d.ts +47 -0
- package/dist/src/state/types.js +21 -0
- package/dist/src/state/types.js.map +1 -0
- package/dist/src/utils/display.d.ts +7 -0
- package/dist/src/utils/display.js +42 -0
- package/dist/src/utils/display.js.map +1 -0
- package/dist/src/utils/prompt.d.ts +31 -0
- package/dist/src/utils/prompt.js +81 -0
- package/dist/src/utils/prompt.js.map +1 -0
- package/package.json +52 -0
- package/templates/agents-md-snippet.md +20 -0
- package/templates/architectures/clean/csharp-aspnet.md +56 -0
- package/templates/architectures/clean/go-gin.md +50 -0
- package/templates/architectures/clean/go-std.md +49 -0
- package/templates/architectures/clean/python-fastapi.md +49 -0
- package/templates/architectures/clean/typescript-express.md +60 -0
- package/templates/architectures/clean/typescript-nestjs.md +61 -0
- package/templates/architectures/ddd/csharp-aspnet.md +55 -0
- package/templates/architectures/ddd/go-gin.md +53 -0
- package/templates/architectures/ddd/python-fastapi.md +52 -0
- package/templates/architectures/ddd/typescript-nestjs.md +62 -0
- package/templates/architectures/hexagonal/csharp-aspnet.md +45 -0
- package/templates/architectures/hexagonal/go-gin.md +47 -0
- package/templates/architectures/hexagonal/python-fastapi.md +43 -0
- package/templates/architectures/hexagonal/typescript-nestjs.md +44 -0
- package/templates/architectures/layered/csharp-aspnet.md +45 -0
- package/templates/architectures/layered/go-gin.md +41 -0
- package/templates/architectures/layered/python-fastapi.md +42 -0
- package/templates/architectures/layered/typescript-nestjs.md +48 -0
- package/templates/architectures/modular/csharp-aspnet.md +45 -0
- package/templates/architectures/modular/go-gin.md +47 -0
- package/templates/architectures/modular/python-fastapi.md +45 -0
- package/templates/architectures/modular/typescript-nestjs.md +48 -0
- package/templates/claude-commands/sf.clarify.md +18 -0
- package/templates/claude-commands/sf.implement.md +79 -0
- package/templates/claude-commands/sf.new.md +22 -0
- package/templates/claude-commands/sf.refine.md +47 -0
- package/templates/claude-commands/sf.review.md +17 -0
- package/templates/claude-commands/sf.status.md +12 -0
- package/templates/workflow/config.yaml +17 -0
- package/templates/workflow/prompts/clarify.md +39 -0
- package/templates/workflow/prompts/final-review.md +30 -0
- package/templates/workflow/prompts/implement-tdd.md +35 -0
- package/templates/workflow/prompts/implement.md +43 -0
- package/templates/workflow/prompts/refine.md +52 -0
- package/templates/workflow/prompts/review.md +34 -0
- package/templates/workflow/prompts/test.md +14 -0
- package/templates/workflow/templates/spec-template.md +13 -0
|
@@ -0,0 +1,244 @@
|
|
|
1
|
+
import fs from 'node:fs';
|
|
2
|
+
import path from 'node:path';
|
|
3
|
+
import inquirer from 'inquirer';
|
|
4
|
+
import { StateManager } from '../state/manager.js';
|
|
5
|
+
import { createBackend } from '../backends/factory.js';
|
|
6
|
+
import { parsePlan } from '../parsers/plan.js';
|
|
7
|
+
import { assemblePrompt } from '../utils/prompt.js';
|
|
8
|
+
import { gitBranch, gitCommit, gitDiff, gitDiffBranch, gitCheckout, gitMerge } from '../git/operations.js';
|
|
9
|
+
import * as display from '../utils/display.js';
|
|
10
|
+
export async function implementCommand(name, args, options) {
|
|
11
|
+
const state = new StateManager();
|
|
12
|
+
state.ensureWorkflow();
|
|
13
|
+
state.checkPhaseGuard('implement', name);
|
|
14
|
+
const feature = state.getFeature(name);
|
|
15
|
+
const config = state.readConfig();
|
|
16
|
+
const backendName = options.backend ?? config.backend.default;
|
|
17
|
+
const backend = createBackend(backendName);
|
|
18
|
+
if (!(await backend.isAvailable())) {
|
|
19
|
+
display.error(`Backend "${backendName}" not available.`);
|
|
20
|
+
return;
|
|
21
|
+
}
|
|
22
|
+
// Read plan
|
|
23
|
+
const planPath = state.planPath(name);
|
|
24
|
+
if (!fs.existsSync(planPath)) {
|
|
25
|
+
display.error(`Plan not found. Run \`pxs refine ${name}\` first.`);
|
|
26
|
+
return;
|
|
27
|
+
}
|
|
28
|
+
const planContent = fs.readFileSync(planPath, 'utf-8');
|
|
29
|
+
const plan = parsePlan(planContent);
|
|
30
|
+
// Pre-flight: create branch if first run
|
|
31
|
+
if (feature.phase === 'ready_to_implement') {
|
|
32
|
+
const branchName = feature.branch || `${feature.type}/${name}`;
|
|
33
|
+
display.info(`Creating branch: ${branchName}`);
|
|
34
|
+
try {
|
|
35
|
+
gitBranch(branchName);
|
|
36
|
+
}
|
|
37
|
+
catch {
|
|
38
|
+
display.warn(`Branch ${branchName} may already exist, checking out...`);
|
|
39
|
+
gitCheckout(branchName);
|
|
40
|
+
}
|
|
41
|
+
feature.phase = 'implementing';
|
|
42
|
+
feature.branch = branchName;
|
|
43
|
+
state.upsertFeature(feature);
|
|
44
|
+
}
|
|
45
|
+
// Determine test strategy
|
|
46
|
+
const testConfig = parseTestOptions(options.test);
|
|
47
|
+
let sessionId = feature.session?.id ?? '';
|
|
48
|
+
// Execute tasks
|
|
49
|
+
for (let i = 0; i < feature.tasks.length; i++) {
|
|
50
|
+
const task = feature.tasks[i];
|
|
51
|
+
if (task.status === 'complete' || task.status === 'skipped')
|
|
52
|
+
continue;
|
|
53
|
+
const taskSpec = plan.tasks[i];
|
|
54
|
+
if (!taskSpec)
|
|
55
|
+
continue;
|
|
56
|
+
display.heading(`Task ${i + 1}: ${task.name}`);
|
|
57
|
+
// Update status
|
|
58
|
+
task.status = 'in_progress';
|
|
59
|
+
feature.current_task = i + 1;
|
|
60
|
+
state.upsertFeature(feature);
|
|
61
|
+
// Build prompt
|
|
62
|
+
const templateName = testConfig.tdd ? 'implement-tdd' : 'implement';
|
|
63
|
+
const previousDiff = i > 0 ? getDiffSummary() : '';
|
|
64
|
+
const prompt = assemblePrompt({
|
|
65
|
+
templateName,
|
|
66
|
+
vars: {
|
|
67
|
+
task_content: taskSpec.raw,
|
|
68
|
+
previous_diff: previousDiff,
|
|
69
|
+
},
|
|
70
|
+
agents: args.agents,
|
|
71
|
+
skills: args.skills,
|
|
72
|
+
extraText: args.text,
|
|
73
|
+
});
|
|
74
|
+
// Execute
|
|
75
|
+
const result = sessionId
|
|
76
|
+
? await backend.resume(sessionId, prompt)
|
|
77
|
+
: await backend.execute(prompt);
|
|
78
|
+
sessionId = result.sessionId;
|
|
79
|
+
feature.session = { backend: backendName, id: sessionId };
|
|
80
|
+
// Commit implementation
|
|
81
|
+
try {
|
|
82
|
+
gitCommit(`${feature.type}(${name}): task-${i + 1} ${task.name}`);
|
|
83
|
+
}
|
|
84
|
+
catch {
|
|
85
|
+
display.warn('Nothing to commit or commit failed.');
|
|
86
|
+
}
|
|
87
|
+
// Post-hoc tests (if not TDD)
|
|
88
|
+
if (testConfig.postHoc) {
|
|
89
|
+
display.info('Generating tests...');
|
|
90
|
+
const diff = getDiffSummary();
|
|
91
|
+
const testType = testConfig.intg ? 'integration' : 'unit';
|
|
92
|
+
const testPrompt = assemblePrompt({
|
|
93
|
+
templateName: 'test',
|
|
94
|
+
vars: {
|
|
95
|
+
test_type: testType,
|
|
96
|
+
git_diff: diff,
|
|
97
|
+
task_content: taskSpec.raw,
|
|
98
|
+
},
|
|
99
|
+
});
|
|
100
|
+
await backend.resume(sessionId, testPrompt);
|
|
101
|
+
try {
|
|
102
|
+
gitCommit(`test(${name}): task-${i + 1} ${task.name}`);
|
|
103
|
+
}
|
|
104
|
+
catch {
|
|
105
|
+
display.warn('No test changes to commit.');
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
// AI Review
|
|
109
|
+
display.info('Running AI review...');
|
|
110
|
+
const diff = getDiffSummary();
|
|
111
|
+
const reviewPrompt = assemblePrompt({
|
|
112
|
+
templateName: 'review',
|
|
113
|
+
vars: {
|
|
114
|
+
git_diff: diff,
|
|
115
|
+
task_content: taskSpec.raw,
|
|
116
|
+
},
|
|
117
|
+
agents: args.agents,
|
|
118
|
+
skills: args.skills,
|
|
119
|
+
});
|
|
120
|
+
const reviewResult = await backend.resume(sessionId, reviewPrompt);
|
|
121
|
+
sessionId = reviewResult.sessionId;
|
|
122
|
+
// Save review
|
|
123
|
+
fs.mkdirSync(state.reviewsDir(), { recursive: true });
|
|
124
|
+
fs.writeFileSync(state.reviewPath(name, i + 1), reviewResult.output, 'utf-8');
|
|
125
|
+
task.status = 'review_pending';
|
|
126
|
+
state.upsertFeature(feature);
|
|
127
|
+
// Present to user
|
|
128
|
+
console.log('\n' + reviewResult.output + '\n');
|
|
129
|
+
const { choice } = await inquirer.prompt([
|
|
130
|
+
{
|
|
131
|
+
type: 'list',
|
|
132
|
+
name: 'choice',
|
|
133
|
+
message: `Task ${i + 1} review:`,
|
|
134
|
+
choices: ['approve', 'request-change', 'add-test', 'skip'],
|
|
135
|
+
},
|
|
136
|
+
]);
|
|
137
|
+
switch (choice) {
|
|
138
|
+
case 'approve':
|
|
139
|
+
task.status = 'complete';
|
|
140
|
+
state.upsertFeature(feature);
|
|
141
|
+
display.success(`Task ${i + 1} approved.`);
|
|
142
|
+
break;
|
|
143
|
+
case 'skip':
|
|
144
|
+
task.status = 'skipped';
|
|
145
|
+
state.upsertFeature(feature);
|
|
146
|
+
display.info(`Task ${i + 1} skipped.`);
|
|
147
|
+
break;
|
|
148
|
+
case 'request-change':
|
|
149
|
+
task.status = 'in_progress';
|
|
150
|
+
state.upsertFeature(feature);
|
|
151
|
+
display.info('Re-run `pxs implement` to retry this task.');
|
|
152
|
+
return;
|
|
153
|
+
case 'add-test':
|
|
154
|
+
display.info('Generating additional tests...');
|
|
155
|
+
task.status = 'complete';
|
|
156
|
+
state.upsertFeature(feature);
|
|
157
|
+
break;
|
|
158
|
+
}
|
|
159
|
+
}
|
|
160
|
+
// All tasks complete
|
|
161
|
+
const allDone = feature.tasks.every((t) => t.status === 'complete' || t.status === 'skipped');
|
|
162
|
+
if (allDone) {
|
|
163
|
+
feature.phase = 'completed';
|
|
164
|
+
state.upsertFeature(feature);
|
|
165
|
+
display.heading('All Tasks Complete');
|
|
166
|
+
for (const t of feature.tasks) {
|
|
167
|
+
console.log(` ${display.taskIcon(t.status)} ${t.name}`);
|
|
168
|
+
}
|
|
169
|
+
// Final branch code review
|
|
170
|
+
if (!options.skipReview) {
|
|
171
|
+
display.info('Running final branch code review...');
|
|
172
|
+
try {
|
|
173
|
+
const branchDiff = gitDiffBranch('main');
|
|
174
|
+
const specContent = fs.existsSync(state.specPath(name))
|
|
175
|
+
? fs.readFileSync(state.specPath(name), 'utf-8')
|
|
176
|
+
: '(spec not found)';
|
|
177
|
+
const finalReviewPrompt = assemblePrompt({
|
|
178
|
+
templateName: 'final-review',
|
|
179
|
+
vars: {
|
|
180
|
+
branch_diff: branchDiff,
|
|
181
|
+
spec_content: specContent,
|
|
182
|
+
plan_content: planContent,
|
|
183
|
+
},
|
|
184
|
+
agents: args.agents,
|
|
185
|
+
skills: args.skills,
|
|
186
|
+
extraText: args.text,
|
|
187
|
+
});
|
|
188
|
+
const finalReviewResult = await backend.resume(sessionId, finalReviewPrompt);
|
|
189
|
+
sessionId = finalReviewResult.sessionId;
|
|
190
|
+
// Save final review
|
|
191
|
+
fs.mkdirSync(state.reviewsDir(), { recursive: true });
|
|
192
|
+
const finalReviewPath = path.join(state.reviewsDir(), `${name}-final.md`);
|
|
193
|
+
fs.writeFileSync(finalReviewPath, finalReviewResult.output, 'utf-8');
|
|
194
|
+
display.heading('Final Code Review');
|
|
195
|
+
console.log('\n' + finalReviewResult.output + '\n');
|
|
196
|
+
}
|
|
197
|
+
catch (err) {
|
|
198
|
+
display.warn(`Final review failed: ${err instanceof Error ? err.message : err}`);
|
|
199
|
+
}
|
|
200
|
+
}
|
|
201
|
+
const { merge } = await inquirer.prompt([
|
|
202
|
+
{
|
|
203
|
+
type: 'list',
|
|
204
|
+
name: 'merge',
|
|
205
|
+
message: 'What would you like to do?',
|
|
206
|
+
choices: ['merge', 'squash-merge', 'keep-branch'],
|
|
207
|
+
},
|
|
208
|
+
]);
|
|
209
|
+
if (merge === 'merge' || merge === 'squash-merge') {
|
|
210
|
+
const originalBranch = 'main'; // TODO: detect original branch
|
|
211
|
+
gitCheckout(originalBranch);
|
|
212
|
+
gitMerge(feature.branch, merge === 'squash-merge');
|
|
213
|
+
feature.phase = 'merged';
|
|
214
|
+
state.upsertFeature(feature);
|
|
215
|
+
display.success(`Merged ${feature.branch} into ${originalBranch}.`);
|
|
216
|
+
}
|
|
217
|
+
else {
|
|
218
|
+
display.info(`Branch ${feature.branch} kept. Merge manually when ready.`);
|
|
219
|
+
}
|
|
220
|
+
}
|
|
221
|
+
}
|
|
222
|
+
function getDiffSummary() {
|
|
223
|
+
try {
|
|
224
|
+
return gitDiff('HEAD~1');
|
|
225
|
+
}
|
|
226
|
+
catch {
|
|
227
|
+
return '(no previous diff available)';
|
|
228
|
+
}
|
|
229
|
+
}
|
|
230
|
+
function parseTestOptions(test) {
|
|
231
|
+
if (test === undefined || test === false) {
|
|
232
|
+
return { tdd: false, intg: false, postHoc: false };
|
|
233
|
+
}
|
|
234
|
+
if (test === true || (Array.isArray(test) && test.length === 0)) {
|
|
235
|
+
return { tdd: false, intg: false, postHoc: true };
|
|
236
|
+
}
|
|
237
|
+
const arr = test;
|
|
238
|
+
return {
|
|
239
|
+
tdd: arr.includes('tdd'),
|
|
240
|
+
intg: arr.includes('intg'),
|
|
241
|
+
postHoc: !arr.includes('tdd'),
|
|
242
|
+
};
|
|
243
|
+
}
|
|
244
|
+
//# sourceMappingURL=implement.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"implement.js","sourceRoot":"","sources":["../../../src/commands/implement.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,177 @@
|
|
|
1
|
+
import fs from 'node:fs';
|
|
2
|
+
import path from 'node:path';
|
|
3
|
+
import { fileURLToPath } from 'node:url';
|
|
4
|
+
import { detectProject } from '../discovery/project.js';
|
|
5
|
+
import * as display from '../utils/display.js';
|
|
6
|
+
const __dirname = path.dirname(fileURLToPath(import.meta.url));
|
|
7
|
+
// Walk up from __dirname to find the project root containing templates/
|
|
8
|
+
function findTemplatesDir() {
|
|
9
|
+
let dir = __dirname;
|
|
10
|
+
for (let i = 0; i < 5; i++) {
|
|
11
|
+
const candidate = path.join(dir, 'templates');
|
|
12
|
+
if (fs.existsSync(candidate))
|
|
13
|
+
return candidate;
|
|
14
|
+
dir = path.dirname(dir);
|
|
15
|
+
}
|
|
16
|
+
// Fallback: 3 levels up from dist/src/commands/ to package root
|
|
17
|
+
return path.resolve(__dirname, '..', '..', '..', 'templates');
|
|
18
|
+
}
|
|
19
|
+
const TEMPLATES_DIR = findTemplatesDir();
|
|
20
|
+
// Resolve shorthand --lang values to full lang_framework IDs
|
|
21
|
+
const LANG_SHORTHANDS = {
|
|
22
|
+
go: 'go-std',
|
|
23
|
+
typescript: 'typescript-express',
|
|
24
|
+
ts: 'typescript-express',
|
|
25
|
+
nestjs: 'typescript-nestjs',
|
|
26
|
+
express: 'typescript-express',
|
|
27
|
+
csharp: 'csharp-aspnet',
|
|
28
|
+
'c#': 'csharp-aspnet',
|
|
29
|
+
dotnet: 'csharp-aspnet',
|
|
30
|
+
python: 'python-fastapi',
|
|
31
|
+
fastapi: 'python-fastapi',
|
|
32
|
+
django: 'python-django',
|
|
33
|
+
gin: 'go-gin',
|
|
34
|
+
chi: 'go-chi',
|
|
35
|
+
};
|
|
36
|
+
export function resolveLangFramework(lang) {
|
|
37
|
+
return LANG_SHORTHANDS[lang.toLowerCase()] ?? lang;
|
|
38
|
+
}
|
|
39
|
+
export async function initCommand(options) {
|
|
40
|
+
const cwd = process.cwd();
|
|
41
|
+
const workflowDir = path.join(cwd, '.workflow');
|
|
42
|
+
if (fs.existsSync(workflowDir) && !options.force) {
|
|
43
|
+
display.error('.workflow/ already exists. Use --force to overwrite.');
|
|
44
|
+
return;
|
|
45
|
+
}
|
|
46
|
+
display.heading('Initializing pxs workflow');
|
|
47
|
+
// Detect project
|
|
48
|
+
const project = detectProject(cwd);
|
|
49
|
+
display.info(`Detected: ${project.language || 'unknown'} / ${project.framework || 'unknown'}`);
|
|
50
|
+
// Create .workflow directories
|
|
51
|
+
const dirs = [
|
|
52
|
+
'.workflow/prompts',
|
|
53
|
+
'.workflow/templates',
|
|
54
|
+
'.workflow/specs',
|
|
55
|
+
'.workflow/plans',
|
|
56
|
+
'.workflow/reviews',
|
|
57
|
+
'.claude/commands',
|
|
58
|
+
];
|
|
59
|
+
for (const dir of dirs) {
|
|
60
|
+
fs.mkdirSync(path.join(cwd, dir), { recursive: true });
|
|
61
|
+
}
|
|
62
|
+
// Copy workflow templates
|
|
63
|
+
copyDir(path.join(TEMPLATES_DIR, 'workflow'), workflowDir);
|
|
64
|
+
// Resolve architecture and lang_framework
|
|
65
|
+
const architecture = options.arch ?? 'none';
|
|
66
|
+
const langFramework = options.lang
|
|
67
|
+
? resolveLangFramework(options.lang)
|
|
68
|
+
: project.lang_framework;
|
|
69
|
+
// Handle --arch: copy architecture template to .workflow/architecture.md
|
|
70
|
+
if (options.arch) {
|
|
71
|
+
const archMdPath = path.join(workflowDir, 'architecture.md');
|
|
72
|
+
if (options.arch === 'custom') {
|
|
73
|
+
// For custom, the next positional arg would be a path — but Commander captures it as the arch value.
|
|
74
|
+
// Actually, `--arch custom` means the user provides a separate file. We check process.argv for a path after 'custom'.
|
|
75
|
+
const customPath = findCustomArchPath();
|
|
76
|
+
if (customPath && fs.existsSync(customPath)) {
|
|
77
|
+
fs.copyFileSync(customPath, archMdPath);
|
|
78
|
+
display.success(`Copied custom architecture from ${customPath}`);
|
|
79
|
+
}
|
|
80
|
+
else {
|
|
81
|
+
display.error('Custom architecture file not found. Usage: pxs init --arch custom <path>');
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
else {
|
|
85
|
+
// Look up template: templates/architectures/<arch>/<lang_framework>.md
|
|
86
|
+
const templatePath = path.join(TEMPLATES_DIR, 'architectures', options.arch, `${langFramework}.md`);
|
|
87
|
+
if (fs.existsSync(templatePath)) {
|
|
88
|
+
fs.copyFileSync(templatePath, archMdPath);
|
|
89
|
+
display.success(`Architecture: ${options.arch} (${langFramework})`);
|
|
90
|
+
}
|
|
91
|
+
else {
|
|
92
|
+
display.error(`Architecture template not found: ${options.arch}/${langFramework}.md — skipping architecture.md`);
|
|
93
|
+
const archDir = path.join(TEMPLATES_DIR, 'architectures', options.arch);
|
|
94
|
+
if (fs.existsSync(archDir)) {
|
|
95
|
+
const available = fs.readdirSync(archDir).filter(f => f.endsWith('.md')).map(f => f.replace('.md', ''));
|
|
96
|
+
if (available.length > 0) {
|
|
97
|
+
display.info(`Available: ${available.join(', ')}`);
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
// Substitute project info in config.yaml
|
|
104
|
+
const configPath = path.join(workflowDir, 'config.yaml');
|
|
105
|
+
if (fs.existsSync(configPath)) {
|
|
106
|
+
let config = fs.readFileSync(configPath, 'utf-8');
|
|
107
|
+
config = config.replace(/name: ""/, `name: "${project.name}"`);
|
|
108
|
+
config = config.replace(/language: ""/, `language: "${project.language}"`);
|
|
109
|
+
config = config.replace(/framework: ""/, `framework: "${project.framework}"`);
|
|
110
|
+
config = config.replace(/architecture: none/, `architecture: ${architecture}`);
|
|
111
|
+
config = config.replace(/lang_framework: ""/, `lang_framework: "${langFramework}"`);
|
|
112
|
+
fs.writeFileSync(configPath, config, 'utf-8');
|
|
113
|
+
}
|
|
114
|
+
// Copy claude commands (rename sf.* to pxs.*)
|
|
115
|
+
const claudeCommandsDir = path.join(TEMPLATES_DIR, 'claude-commands');
|
|
116
|
+
const targetCommandsDir = path.join(cwd, '.claude', 'commands');
|
|
117
|
+
if (fs.existsSync(claudeCommandsDir)) {
|
|
118
|
+
const files = fs.readdirSync(claudeCommandsDir);
|
|
119
|
+
for (const file of files) {
|
|
120
|
+
const targetName = file.replace(/^sf\./, 'pxs.');
|
|
121
|
+
fs.copyFileSync(path.join(claudeCommandsDir, file), path.join(targetCommandsDir, targetName));
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
// Append to AGENTS.md
|
|
125
|
+
const agentsSnippetPath = path.join(TEMPLATES_DIR, 'agents-md-snippet.md');
|
|
126
|
+
if (fs.existsSync(agentsSnippetPath)) {
|
|
127
|
+
const snippet = fs.readFileSync(agentsSnippetPath, 'utf-8');
|
|
128
|
+
const agentsPath = path.join(cwd, 'AGENTS.md');
|
|
129
|
+
if (fs.existsSync(agentsPath)) {
|
|
130
|
+
const existing = fs.readFileSync(agentsPath, 'utf-8');
|
|
131
|
+
if (!existing.includes('SF Spec-Driven Workflow')) {
|
|
132
|
+
fs.appendFileSync(agentsPath, '\n\n' + snippet, 'utf-8');
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
else {
|
|
136
|
+
fs.writeFileSync(agentsPath, snippet, 'utf-8');
|
|
137
|
+
}
|
|
138
|
+
}
|
|
139
|
+
display.success('Created .workflow/ directory structure');
|
|
140
|
+
display.success('Created .claude/commands/pxs.*.md slash commands');
|
|
141
|
+
display.success('Created AGENTS.md');
|
|
142
|
+
display.info('Run `pxs new <name>` to create your first spec.');
|
|
143
|
+
}
|
|
144
|
+
/**
|
|
145
|
+
* Find the custom architecture file path from process.argv.
|
|
146
|
+
* When user runs: pxs init --arch custom ./my-arch.md
|
|
147
|
+
* Commander captures "custom" as --arch value, but the file path remains in argv.
|
|
148
|
+
*/
|
|
149
|
+
function findCustomArchPath() {
|
|
150
|
+
const argv = process.argv;
|
|
151
|
+
const archIdx = argv.findIndex((a) => a === '--arch');
|
|
152
|
+
// The path should be 2 positions after --arch (--arch custom <path>)
|
|
153
|
+
if (archIdx >= 0 && archIdx + 2 < argv.length) {
|
|
154
|
+
const candidate = argv[archIdx + 2];
|
|
155
|
+
if (candidate && !candidate.startsWith('-')) {
|
|
156
|
+
return path.resolve(candidate);
|
|
157
|
+
}
|
|
158
|
+
}
|
|
159
|
+
return undefined;
|
|
160
|
+
}
|
|
161
|
+
function copyDir(src, dest) {
|
|
162
|
+
if (!fs.existsSync(src))
|
|
163
|
+
return;
|
|
164
|
+
fs.mkdirSync(dest, { recursive: true });
|
|
165
|
+
const entries = fs.readdirSync(src, { withFileTypes: true });
|
|
166
|
+
for (const entry of entries) {
|
|
167
|
+
const srcPath = path.join(src, entry.name);
|
|
168
|
+
const destPath = path.join(dest, entry.name);
|
|
169
|
+
if (entry.isDirectory()) {
|
|
170
|
+
copyDir(srcPath, destPath);
|
|
171
|
+
}
|
|
172
|
+
else {
|
|
173
|
+
fs.copyFileSync(srcPath, destPath);
|
|
174
|
+
}
|
|
175
|
+
}
|
|
176
|
+
}
|
|
177
|
+
//# sourceMappingURL=init.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"init.js","sourceRoot":"","sources":["../../../src/commands/init.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,143 @@
|
|
|
1
|
+
import fs from 'node:fs';
|
|
2
|
+
import inquirer from 'inquirer';
|
|
3
|
+
import { StateManager } from '../state/manager.js';
|
|
4
|
+
import { createBackend } from '../backends/factory.js';
|
|
5
|
+
import * as display from '../utils/display.js';
|
|
6
|
+
export async function newCommand(name, options) {
|
|
7
|
+
const state = new StateManager();
|
|
8
|
+
state.ensureWorkflow();
|
|
9
|
+
const specPath = state.specPath(name);
|
|
10
|
+
// Check if spec already exists
|
|
11
|
+
if (fs.existsSync(specPath)) {
|
|
12
|
+
const { overwrite } = await inquirer.prompt([
|
|
13
|
+
{
|
|
14
|
+
type: 'confirm',
|
|
15
|
+
name: 'overwrite',
|
|
16
|
+
message: `Spec "${name}" already exists. Overwrite?`,
|
|
17
|
+
default: false,
|
|
18
|
+
},
|
|
19
|
+
]);
|
|
20
|
+
if (!overwrite) {
|
|
21
|
+
display.info('Aborted.');
|
|
22
|
+
return;
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
// Ensure specs dir exists
|
|
26
|
+
fs.mkdirSync(state.specsDir(), { recursive: true });
|
|
27
|
+
if (options.jira && options.jira.length > 0) {
|
|
28
|
+
await createFromJira(name, options.jira, state);
|
|
29
|
+
}
|
|
30
|
+
else if (options.desc) {
|
|
31
|
+
await createFromDesc(name, options.desc, state);
|
|
32
|
+
}
|
|
33
|
+
else if (options.interactive) {
|
|
34
|
+
await createInteractive(name, state);
|
|
35
|
+
}
|
|
36
|
+
else {
|
|
37
|
+
createBlank(name, state);
|
|
38
|
+
}
|
|
39
|
+
// Update state
|
|
40
|
+
state.upsertFeature({
|
|
41
|
+
feature: name,
|
|
42
|
+
type: 'feat',
|
|
43
|
+
branch: '',
|
|
44
|
+
phase: 'spec_created',
|
|
45
|
+
total_tasks: 0,
|
|
46
|
+
current_task: 0,
|
|
47
|
+
tasks: [],
|
|
48
|
+
});
|
|
49
|
+
display.success(`Spec created: ${state.specPath(name)}`);
|
|
50
|
+
display.info(`Edit the spec, then run \`pxs refine ${name}\``);
|
|
51
|
+
}
|
|
52
|
+
function createBlank(name, state) {
|
|
53
|
+
const templatePath = state.templatesDir() + '/spec-template.md';
|
|
54
|
+
let template;
|
|
55
|
+
if (fs.existsSync(templatePath)) {
|
|
56
|
+
template = fs.readFileSync(templatePath, 'utf-8');
|
|
57
|
+
template = template.replace('<name>', name);
|
|
58
|
+
}
|
|
59
|
+
else {
|
|
60
|
+
template = `# Feature: ${name}
|
|
61
|
+
|
|
62
|
+
## Context
|
|
63
|
+
<!-- 2-3 sentences of project background -->
|
|
64
|
+
|
|
65
|
+
## Requirements
|
|
66
|
+
<!-- Numbered list with acceptance criteria -->
|
|
67
|
+
|
|
68
|
+
## Constraints
|
|
69
|
+
<!-- Technical limitations, compatibility requirements -->
|
|
70
|
+
|
|
71
|
+
## Notes
|
|
72
|
+
<!-- Additional notes -->
|
|
73
|
+
`;
|
|
74
|
+
}
|
|
75
|
+
fs.writeFileSync(state.specPath(name), template, 'utf-8');
|
|
76
|
+
}
|
|
77
|
+
async function createFromDesc(name, desc, state) {
|
|
78
|
+
display.info('Generating spec from description...');
|
|
79
|
+
try {
|
|
80
|
+
const config = state.readConfig();
|
|
81
|
+
const backend = createBackend(config.backend.default);
|
|
82
|
+
if (!(await backend.isAvailable())) {
|
|
83
|
+
display.error(`Backend "${config.backend.default}" is not available. Install claude or codex.`);
|
|
84
|
+
createBlank(name, state);
|
|
85
|
+
display.warn('Created blank spec instead.');
|
|
86
|
+
return;
|
|
87
|
+
}
|
|
88
|
+
const prompt = `Create a detailed feature spec in markdown format for the following feature:
|
|
89
|
+
|
|
90
|
+
Name: ${name}
|
|
91
|
+
Description: ${desc}
|
|
92
|
+
|
|
93
|
+
Output format:
|
|
94
|
+
# Feature: ${name}
|
|
95
|
+
|
|
96
|
+
## Context
|
|
97
|
+
(2-3 sentences of background)
|
|
98
|
+
|
|
99
|
+
## Requirements
|
|
100
|
+
(Numbered list with acceptance criteria)
|
|
101
|
+
|
|
102
|
+
## Constraints
|
|
103
|
+
(Technical limitations)
|
|
104
|
+
|
|
105
|
+
## Notes
|
|
106
|
+
(Additional notes)`;
|
|
107
|
+
const result = await backend.execute(prompt);
|
|
108
|
+
fs.writeFileSync(state.specPath(name), result.output, 'utf-8');
|
|
109
|
+
}
|
|
110
|
+
catch (err) {
|
|
111
|
+
display.warn(`AI generation failed: ${err}. Creating blank spec.`);
|
|
112
|
+
createBlank(name, state);
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
async function createFromJira(name, tickets, state) {
|
|
116
|
+
display.error('Jira MCP integration requires an MCP connection. Please ensure Jira MCP is configured.');
|
|
117
|
+
display.info('Creating blank spec instead. Add Jira content manually.');
|
|
118
|
+
createBlank(name, state);
|
|
119
|
+
}
|
|
120
|
+
async function createInteractive(name, state) {
|
|
121
|
+
const answers = await inquirer.prompt([
|
|
122
|
+
{ type: 'input', name: 'context', message: 'Project context (2-3 sentences):' },
|
|
123
|
+
{ type: 'editor', name: 'requirements', message: 'Requirements (one per line):' },
|
|
124
|
+
{ type: 'input', name: 'constraints', message: 'Constraints:' },
|
|
125
|
+
{ type: 'input', name: 'notes', message: 'Additional notes:' },
|
|
126
|
+
]);
|
|
127
|
+
const spec = `# Feature: ${name}
|
|
128
|
+
|
|
129
|
+
## Context
|
|
130
|
+
${answers.context}
|
|
131
|
+
|
|
132
|
+
## Requirements
|
|
133
|
+
${answers.requirements}
|
|
134
|
+
|
|
135
|
+
## Constraints
|
|
136
|
+
${answers.constraints}
|
|
137
|
+
|
|
138
|
+
## Notes
|
|
139
|
+
${answers.notes}
|
|
140
|
+
`;
|
|
141
|
+
fs.writeFileSync(state.specPath(name), spec, 'utf-8');
|
|
142
|
+
}
|
|
143
|
+
//# sourceMappingURL=new.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"new.js","sourceRoot":"","sources":["../../../src/commands/new.ts"],"names":[],"mappings":"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"}
|