@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,158 @@
|
|
|
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 { assemblePrompt } from '../utils/prompt.js';
|
|
6
|
+
import { parsePlan } from '../parsers/plan.js';
|
|
7
|
+
import * as display from '../utils/display.js';
|
|
8
|
+
export async function refineCommand(name, args, options) {
|
|
9
|
+
const state = new StateManager();
|
|
10
|
+
state.ensureWorkflow();
|
|
11
|
+
state.checkPhaseGuard('refine', name);
|
|
12
|
+
const specPath = state.specPath(name);
|
|
13
|
+
if (!fs.existsSync(specPath)) {
|
|
14
|
+
display.error(`Spec "${name}" not found. Run \`pxs new ${name}\` first.`);
|
|
15
|
+
return;
|
|
16
|
+
}
|
|
17
|
+
const config = state.readConfig();
|
|
18
|
+
const backend = createBackend(config.backend.default);
|
|
19
|
+
if (!(await backend.isAvailable())) {
|
|
20
|
+
display.error(`Backend "${config.backend.default}" not available.`);
|
|
21
|
+
return;
|
|
22
|
+
}
|
|
23
|
+
let specContent = fs.readFileSync(specPath, 'utf-8');
|
|
24
|
+
const feature = state.getFeature(name);
|
|
25
|
+
let sessionId = feature.session?.id ?? '';
|
|
26
|
+
// Sub-flow 1: Clarify (unless skipped)
|
|
27
|
+
if (!options.skipClarify) {
|
|
28
|
+
display.heading('Phase 1: Requirement Clarification');
|
|
29
|
+
const clarifyPrompt = assemblePrompt({
|
|
30
|
+
templateName: 'clarify',
|
|
31
|
+
vars: { spec_content: specContent },
|
|
32
|
+
agents: args.agents,
|
|
33
|
+
skills: args.skills,
|
|
34
|
+
extraText: args.text,
|
|
35
|
+
});
|
|
36
|
+
const clarifyResult = sessionId
|
|
37
|
+
? await backend.resume(sessionId, clarifyPrompt)
|
|
38
|
+
: await backend.execute(clarifyPrompt);
|
|
39
|
+
sessionId = clarifyResult.sessionId;
|
|
40
|
+
console.log('\n' + clarifyResult.output);
|
|
41
|
+
feature.phase = 'clarifying';
|
|
42
|
+
feature.session = { backend: config.backend.default, id: sessionId };
|
|
43
|
+
state.upsertFeature(feature);
|
|
44
|
+
// Wait for user to answer questions (in CLI mode, AI handles the conversation)
|
|
45
|
+
const { proceed } = await inquirer.prompt([
|
|
46
|
+
{
|
|
47
|
+
type: 'confirm',
|
|
48
|
+
name: 'proceed',
|
|
49
|
+
message: 'Proceed to spec refinement?',
|
|
50
|
+
default: true,
|
|
51
|
+
},
|
|
52
|
+
]);
|
|
53
|
+
if (!proceed) {
|
|
54
|
+
display.info('Paused. Run `pxs refine` again when ready.');
|
|
55
|
+
return;
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
// Sub-flow 2: Refine spec
|
|
59
|
+
display.heading('Phase 2: Refine Spec');
|
|
60
|
+
specContent = fs.readFileSync(specPath, 'utf-8');
|
|
61
|
+
const refinePrompt = assemblePrompt({
|
|
62
|
+
templateName: 'refine',
|
|
63
|
+
vars: { spec_content: specContent },
|
|
64
|
+
agents: args.agents,
|
|
65
|
+
skills: args.skills,
|
|
66
|
+
extraText: args.text,
|
|
67
|
+
});
|
|
68
|
+
const refineResult = sessionId
|
|
69
|
+
? await backend.resume(sessionId, refinePrompt)
|
|
70
|
+
: await backend.execute(refinePrompt);
|
|
71
|
+
sessionId = refineResult.sessionId;
|
|
72
|
+
// Save refined spec
|
|
73
|
+
fs.writeFileSync(specPath, refineResult.output, 'utf-8');
|
|
74
|
+
display.success(`Refined spec saved to ${specPath}`);
|
|
75
|
+
console.log('\n' + refineResult.output.slice(0, 500) + '...\n');
|
|
76
|
+
feature.phase = 'spec_approved';
|
|
77
|
+
feature.session = { backend: config.backend.default, id: sessionId };
|
|
78
|
+
state.upsertFeature(feature);
|
|
79
|
+
const { approveSpec } = await inquirer.prompt([
|
|
80
|
+
{
|
|
81
|
+
type: 'list',
|
|
82
|
+
name: 'approveSpec',
|
|
83
|
+
message: 'Spec refinement:',
|
|
84
|
+
choices: ['approve', 'edit'],
|
|
85
|
+
},
|
|
86
|
+
]);
|
|
87
|
+
if (approveSpec === 'edit') {
|
|
88
|
+
display.info(`Edit ${specPath} and run \`pxs refine ${name} --skip-clarify\``);
|
|
89
|
+
return;
|
|
90
|
+
}
|
|
91
|
+
// Sub-flow 3: Decompose plan
|
|
92
|
+
display.heading('Phase 3: Decompose Plan');
|
|
93
|
+
specContent = fs.readFileSync(specPath, 'utf-8');
|
|
94
|
+
const planPrompt = `Decompose the following refined spec into an implementation plan with discrete tasks.
|
|
95
|
+
|
|
96
|
+
${specContent}
|
|
97
|
+
|
|
98
|
+
Output the plan in this exact format:
|
|
99
|
+
# Implementation Plan: ${name}
|
|
100
|
+
|
|
101
|
+
> type: feat
|
|
102
|
+
> branch: feat/${name}
|
|
103
|
+
> total_tasks: N
|
|
104
|
+
|
|
105
|
+
## Task 1: <title>
|
|
106
|
+
- **Files**:
|
|
107
|
+
- \`path/to/file\` (new|modify)
|
|
108
|
+
- **Description**: What to implement
|
|
109
|
+
- **Depends on**: None | Task N
|
|
110
|
+
- **Complexity**: Low | Medium | High
|
|
111
|
+
- **Acceptance**: Definition of done
|
|
112
|
+
|
|
113
|
+
(repeat for each task)`;
|
|
114
|
+
const planResult = sessionId
|
|
115
|
+
? await backend.resume(sessionId, planPrompt)
|
|
116
|
+
: await backend.execute(planPrompt);
|
|
117
|
+
sessionId = planResult.sessionId;
|
|
118
|
+
// Save plan
|
|
119
|
+
fs.mkdirSync(state.plansDir(), { recursive: true });
|
|
120
|
+
const planPath = state.planPath(name);
|
|
121
|
+
fs.writeFileSync(planPath, planResult.output, 'utf-8');
|
|
122
|
+
display.success(`Plan saved to ${planPath}`);
|
|
123
|
+
console.log('\n' + planResult.output + '\n');
|
|
124
|
+
// Parse plan for state
|
|
125
|
+
const plan = parsePlan(planResult.output);
|
|
126
|
+
feature.phase = 'plan_pending_approval';
|
|
127
|
+
feature.session = { backend: config.backend.default, id: sessionId };
|
|
128
|
+
state.upsertFeature(feature);
|
|
129
|
+
const { approvePlan } = await inquirer.prompt([
|
|
130
|
+
{
|
|
131
|
+
type: 'list',
|
|
132
|
+
name: 'approvePlan',
|
|
133
|
+
message: 'Implementation plan:',
|
|
134
|
+
choices: ['approve', 'edit', 're-split'],
|
|
135
|
+
},
|
|
136
|
+
]);
|
|
137
|
+
if (approvePlan === 'edit') {
|
|
138
|
+
display.info(`Edit ${planPath} and run \`pxs refine ${name} --skip-clarify\``);
|
|
139
|
+
return;
|
|
140
|
+
}
|
|
141
|
+
if (approvePlan === 're-split') {
|
|
142
|
+
display.info('Re-splitting not yet implemented. Edit the plan manually.');
|
|
143
|
+
return;
|
|
144
|
+
}
|
|
145
|
+
// Approve: update state
|
|
146
|
+
feature.type = plan.type;
|
|
147
|
+
feature.branch = plan.branch || `${plan.type}/${name}`;
|
|
148
|
+
feature.phase = 'ready_to_implement';
|
|
149
|
+
feature.total_tasks = plan.tasks.length;
|
|
150
|
+
feature.current_task = 0;
|
|
151
|
+
feature.tasks = plan.tasks.map((t) => ({
|
|
152
|
+
name: t.title,
|
|
153
|
+
status: 'pending',
|
|
154
|
+
}));
|
|
155
|
+
state.upsertFeature(feature);
|
|
156
|
+
display.success('Plan approved! Run `pxs implement ' + name + '` to start.');
|
|
157
|
+
}
|
|
158
|
+
//# sourceMappingURL=refine.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"refine.js","sourceRoot":"","sources":["../../../src/commands/refine.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
import fs from 'node:fs';
|
|
2
|
+
import path from 'node:path';
|
|
3
|
+
import { StateManager } from '../state/manager.js';
|
|
4
|
+
import * as display from '../utils/display.js';
|
|
5
|
+
export async function reviewCommand(name, options) {
|
|
6
|
+
const state = new StateManager();
|
|
7
|
+
state.ensureWorkflow();
|
|
8
|
+
state.checkPhaseGuard('review', name);
|
|
9
|
+
const feature = state.getFeature(name);
|
|
10
|
+
if (!feature) {
|
|
11
|
+
display.error(`Feature "${name}" not found.`);
|
|
12
|
+
return;
|
|
13
|
+
}
|
|
14
|
+
if (options.summary) {
|
|
15
|
+
display.heading(`Review Summary: ${name}`);
|
|
16
|
+
for (let i = 0; i < feature.tasks.length; i++) {
|
|
17
|
+
const t = feature.tasks[i];
|
|
18
|
+
const reviewPath = state.reviewPath(name, i + 1);
|
|
19
|
+
const hasReview = fs.existsSync(reviewPath);
|
|
20
|
+
console.log(` ${i + 1}. ${display.taskIcon(t.status)} ${t.name} ${hasReview ? '(reviewed)' : ''}`);
|
|
21
|
+
}
|
|
22
|
+
// Show final review status
|
|
23
|
+
const finalReviewPath = path.join(state.reviewsDir(), `${name}-final.md`);
|
|
24
|
+
if (fs.existsSync(finalReviewPath)) {
|
|
25
|
+
console.log(`\n Final branch review: exists`);
|
|
26
|
+
}
|
|
27
|
+
return;
|
|
28
|
+
}
|
|
29
|
+
if (options.step !== undefined) {
|
|
30
|
+
const reviewPath = state.reviewPath(name, options.step);
|
|
31
|
+
if (!fs.existsSync(reviewPath)) {
|
|
32
|
+
display.error(`Review for task ${options.step} not found.`);
|
|
33
|
+
return;
|
|
34
|
+
}
|
|
35
|
+
const content = fs.readFileSync(reviewPath, 'utf-8');
|
|
36
|
+
display.heading(`Review: ${name} - Task ${options.step}`);
|
|
37
|
+
console.log(content);
|
|
38
|
+
return;
|
|
39
|
+
}
|
|
40
|
+
// Default: if completed, show final review first
|
|
41
|
+
if (feature.phase === 'completed' || feature.phase === 'merged') {
|
|
42
|
+
const finalReviewPath = path.join(state.reviewsDir(), `${name}-final.md`);
|
|
43
|
+
if (fs.existsSync(finalReviewPath)) {
|
|
44
|
+
display.heading(`Final Branch Review: ${name}`);
|
|
45
|
+
console.log(fs.readFileSync(finalReviewPath, 'utf-8'));
|
|
46
|
+
return;
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
// Show most recent or pending review
|
|
50
|
+
const pendingIdx = feature.tasks.findIndex((t) => t.status === 'review_pending');
|
|
51
|
+
if (pendingIdx >= 0) {
|
|
52
|
+
const reviewPath = state.reviewPath(name, pendingIdx + 1);
|
|
53
|
+
if (fs.existsSync(reviewPath)) {
|
|
54
|
+
display.heading(`Pending Review: Task ${pendingIdx + 1}`);
|
|
55
|
+
console.log(fs.readFileSync(reviewPath, 'utf-8'));
|
|
56
|
+
return;
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
// Show last completed task's review
|
|
60
|
+
for (let i = feature.tasks.length - 1; i >= 0; i--) {
|
|
61
|
+
const reviewPath = state.reviewPath(name, i + 1);
|
|
62
|
+
if (fs.existsSync(reviewPath)) {
|
|
63
|
+
display.heading(`Latest Review: Task ${i + 1}`);
|
|
64
|
+
console.log(fs.readFileSync(reviewPath, 'utf-8'));
|
|
65
|
+
return;
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
display.info('No reviews found.');
|
|
69
|
+
}
|
|
70
|
+
//# sourceMappingURL=review.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"review.js","sourceRoot":"","sources":["../../../src/commands/review.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare function statusCommand(name?: string): Promise<void>;
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
import { StateManager } from '../state/manager.js';
|
|
2
|
+
import * as display from '../utils/display.js';
|
|
3
|
+
export async function statusCommand(name) {
|
|
4
|
+
const state = new StateManager();
|
|
5
|
+
if (!state.workflowExists()) {
|
|
6
|
+
display.error('Workflow not initialized. Run `pxs init` first.');
|
|
7
|
+
return;
|
|
8
|
+
}
|
|
9
|
+
const workflowState = state.readState();
|
|
10
|
+
if (!name) {
|
|
11
|
+
// List all features
|
|
12
|
+
if (workflowState.features.length === 0) {
|
|
13
|
+
display.info('No features tracked. Run `pxs new <name>` to start.');
|
|
14
|
+
return;
|
|
15
|
+
}
|
|
16
|
+
display.heading('Workflow Status');
|
|
17
|
+
display.table(['Feature', 'Type', 'Phase', 'Tasks', 'Branch'], workflowState.features.map((f) => {
|
|
18
|
+
const completedTasks = f.tasks.filter((t) => t.status === 'complete').length;
|
|
19
|
+
return [
|
|
20
|
+
f.feature,
|
|
21
|
+
f.type,
|
|
22
|
+
f.phase,
|
|
23
|
+
`${completedTasks}/${f.total_tasks}`,
|
|
24
|
+
f.branch || '-',
|
|
25
|
+
];
|
|
26
|
+
}));
|
|
27
|
+
}
|
|
28
|
+
else {
|
|
29
|
+
// Show specific feature
|
|
30
|
+
const feature = state.getFeature(name);
|
|
31
|
+
if (!feature) {
|
|
32
|
+
display.error(`Feature "${name}" not found.`);
|
|
33
|
+
return;
|
|
34
|
+
}
|
|
35
|
+
display.heading(`Feature: ${feature.feature}`);
|
|
36
|
+
console.log(` Type: ${feature.type}`);
|
|
37
|
+
console.log(` Branch: ${feature.branch || '-'}`);
|
|
38
|
+
console.log(` Phase: ${feature.phase}`);
|
|
39
|
+
if (feature.session) {
|
|
40
|
+
console.log(` Backend: ${feature.session.backend}`);
|
|
41
|
+
console.log(` Session: ${feature.session.id}`);
|
|
42
|
+
}
|
|
43
|
+
if (feature.tasks.length > 0) {
|
|
44
|
+
console.log('\n Tasks:');
|
|
45
|
+
for (let i = 0; i < feature.tasks.length; i++) {
|
|
46
|
+
const t = feature.tasks[i];
|
|
47
|
+
const icon = display.taskIcon(t.status);
|
|
48
|
+
console.log(` ${i + 1}. ${icon} ${t.name} (${t.status})`);
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
//# sourceMappingURL=status.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"status.js","sourceRoot":"","sources":["../../../src/commands/status.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
import fs from 'node:fs';
|
|
2
|
+
import path from 'node:path';
|
|
3
|
+
export function detectProject(cwd = process.cwd()) {
|
|
4
|
+
const info = {
|
|
5
|
+
name: path.basename(cwd),
|
|
6
|
+
language: '',
|
|
7
|
+
framework: '',
|
|
8
|
+
lang_framework: '',
|
|
9
|
+
};
|
|
10
|
+
// Node.js / TypeScript
|
|
11
|
+
const pkgPath = path.join(cwd, 'package.json');
|
|
12
|
+
if (fs.existsSync(pkgPath)) {
|
|
13
|
+
try {
|
|
14
|
+
const pkg = JSON.parse(fs.readFileSync(pkgPath, 'utf-8'));
|
|
15
|
+
info.name = pkg.name || info.name;
|
|
16
|
+
info.language = 'typescript';
|
|
17
|
+
info.framework = 'node';
|
|
18
|
+
info.lang_framework = detectNodeFramework(pkg);
|
|
19
|
+
}
|
|
20
|
+
catch {
|
|
21
|
+
// ignore parse error
|
|
22
|
+
}
|
|
23
|
+
return info;
|
|
24
|
+
}
|
|
25
|
+
// Go
|
|
26
|
+
const goModPath = path.join(cwd, 'go.mod');
|
|
27
|
+
if (fs.existsSync(goModPath)) {
|
|
28
|
+
const content = fs.readFileSync(goModPath, 'utf-8');
|
|
29
|
+
const moduleMatch = content.match(/^module\s+(.+)$/m);
|
|
30
|
+
if (moduleMatch) {
|
|
31
|
+
info.name = moduleMatch[1].trim();
|
|
32
|
+
}
|
|
33
|
+
info.language = 'go';
|
|
34
|
+
info.framework = 'go';
|
|
35
|
+
info.lang_framework = detectGoFramework(content);
|
|
36
|
+
return info;
|
|
37
|
+
}
|
|
38
|
+
// Python
|
|
39
|
+
const reqPath = path.join(cwd, 'requirements.txt');
|
|
40
|
+
if (fs.existsSync(reqPath)) {
|
|
41
|
+
const content = fs.readFileSync(reqPath, 'utf-8');
|
|
42
|
+
info.language = 'python';
|
|
43
|
+
info.framework = 'python';
|
|
44
|
+
info.lang_framework = detectPythonFramework(content);
|
|
45
|
+
return info;
|
|
46
|
+
}
|
|
47
|
+
// C# / .NET
|
|
48
|
+
const csprojFiles = fs.readdirSync(cwd).filter((f) => f.endsWith('.csproj'));
|
|
49
|
+
if (csprojFiles.length > 0) {
|
|
50
|
+
info.name = csprojFiles[0].replace('.csproj', '');
|
|
51
|
+
info.language = 'csharp';
|
|
52
|
+
info.framework = 'dotnet';
|
|
53
|
+
const content = fs.readFileSync(path.join(cwd, csprojFiles[0]), 'utf-8');
|
|
54
|
+
info.lang_framework = detectCsharpFramework(content);
|
|
55
|
+
return info;
|
|
56
|
+
}
|
|
57
|
+
return info;
|
|
58
|
+
}
|
|
59
|
+
function detectNodeFramework(pkg) {
|
|
60
|
+
const deps = {
|
|
61
|
+
...pkg.dependencies,
|
|
62
|
+
...pkg.devDependencies,
|
|
63
|
+
};
|
|
64
|
+
if (deps['@nestjs/core'])
|
|
65
|
+
return 'typescript-nestjs';
|
|
66
|
+
if (deps['express'])
|
|
67
|
+
return 'typescript-express';
|
|
68
|
+
return 'typescript-express';
|
|
69
|
+
}
|
|
70
|
+
function detectGoFramework(goMod) {
|
|
71
|
+
if (goMod.includes('github.com/gin-gonic/gin'))
|
|
72
|
+
return 'go-gin';
|
|
73
|
+
if (goMod.includes('github.com/go-chi/chi'))
|
|
74
|
+
return 'go-chi';
|
|
75
|
+
return 'go-std';
|
|
76
|
+
}
|
|
77
|
+
function detectPythonFramework(requirements) {
|
|
78
|
+
const lower = requirements.toLowerCase();
|
|
79
|
+
if (lower.includes('fastapi'))
|
|
80
|
+
return 'python-fastapi';
|
|
81
|
+
if (lower.includes('django'))
|
|
82
|
+
return 'python-django';
|
|
83
|
+
return 'python-std';
|
|
84
|
+
}
|
|
85
|
+
function detectCsharpFramework(csproj) {
|
|
86
|
+
if (csproj.includes('Microsoft.AspNetCore'))
|
|
87
|
+
return 'csharp-aspnet';
|
|
88
|
+
return 'csharp-dotnet';
|
|
89
|
+
}
|
|
90
|
+
//# sourceMappingURL=project.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"project.js","sourceRoot":"","sources":["../../../src/discovery/project.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
export declare function gitBranch(branchName: string, cwd?: string): void;
|
|
2
|
+
export declare function gitCheckout(branchName: string, cwd?: string): void;
|
|
3
|
+
export declare function gitCurrentBranch(cwd?: string): string;
|
|
4
|
+
export declare function gitCommit(message: string, cwd?: string): void;
|
|
5
|
+
export declare function gitDiff(from?: string, to?: string, cwd?: string): string;
|
|
6
|
+
export declare function gitStatus(cwd?: string): string;
|
|
7
|
+
export declare function gitMerge(branch: string, squash?: boolean, cwd?: string): void;
|
|
8
|
+
export declare function gitLog(n?: number, cwd?: string): string;
|
|
9
|
+
export declare function gitDiffBranch(base?: string, cwd?: string): string;
|
|
10
|
+
export declare function isGitRepo(cwd?: string): boolean;
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
import { execFileSync } from 'node:child_process';
|
|
2
|
+
function run(cmd, args, cwd) {
|
|
3
|
+
return execFileSync(cmd, args, {
|
|
4
|
+
cwd: cwd ?? process.cwd(),
|
|
5
|
+
encoding: 'utf-8',
|
|
6
|
+
}).trim();
|
|
7
|
+
}
|
|
8
|
+
export function gitBranch(branchName, cwd) {
|
|
9
|
+
run('git', ['checkout', '-b', branchName], cwd);
|
|
10
|
+
}
|
|
11
|
+
export function gitCheckout(branchName, cwd) {
|
|
12
|
+
run('git', ['checkout', branchName], cwd);
|
|
13
|
+
}
|
|
14
|
+
export function gitCurrentBranch(cwd) {
|
|
15
|
+
return run('git', ['rev-parse', '--abbrev-ref', 'HEAD'], cwd);
|
|
16
|
+
}
|
|
17
|
+
export function gitCommit(message, cwd) {
|
|
18
|
+
run('git', ['add', '-A'], cwd);
|
|
19
|
+
run('git', ['commit', '-m', message], cwd);
|
|
20
|
+
}
|
|
21
|
+
export function gitDiff(from, to, cwd) {
|
|
22
|
+
if (from && to) {
|
|
23
|
+
return run('git', ['diff', `${from}..${to}`], cwd);
|
|
24
|
+
}
|
|
25
|
+
if (from) {
|
|
26
|
+
return run('git', ['diff', from], cwd);
|
|
27
|
+
}
|
|
28
|
+
return run('git', ['diff', 'HEAD~1'], cwd);
|
|
29
|
+
}
|
|
30
|
+
export function gitStatus(cwd) {
|
|
31
|
+
return run('git', ['status', '--short'], cwd);
|
|
32
|
+
}
|
|
33
|
+
export function gitMerge(branch, squash = false, cwd) {
|
|
34
|
+
const args = ['merge'];
|
|
35
|
+
if (squash)
|
|
36
|
+
args.push('--squash');
|
|
37
|
+
args.push(branch);
|
|
38
|
+
run('git', args, cwd);
|
|
39
|
+
}
|
|
40
|
+
export function gitLog(n = 5, cwd) {
|
|
41
|
+
return run('git', ['log', '--oneline', `-${n}`], cwd);
|
|
42
|
+
}
|
|
43
|
+
export function gitDiffBranch(base = 'main', cwd) {
|
|
44
|
+
const mergeBase = run('git', ['merge-base', base, 'HEAD'], cwd);
|
|
45
|
+
return run('git', ['diff', mergeBase], cwd);
|
|
46
|
+
}
|
|
47
|
+
export function isGitRepo(cwd) {
|
|
48
|
+
try {
|
|
49
|
+
run('git', ['rev-parse', '--is-inside-work-tree'], cwd);
|
|
50
|
+
return true;
|
|
51
|
+
}
|
|
52
|
+
catch {
|
|
53
|
+
return false;
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
//# sourceMappingURL=operations.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"operations.js","sourceRoot":"","sources":["../../../src/git/operations.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
export interface ParsedArgs {
|
|
2
|
+
name: string;
|
|
3
|
+
agents: string[];
|
|
4
|
+
skills: string[];
|
|
5
|
+
text: string;
|
|
6
|
+
options: Record<string, string | boolean | string[]>;
|
|
7
|
+
}
|
|
8
|
+
/**
|
|
9
|
+
* Parse variadic CLI arguments into structured parts.
|
|
10
|
+
*
|
|
11
|
+
* Rules:
|
|
12
|
+
* - First word not starting with @, /, or -- is <name>
|
|
13
|
+
* - Words starting with @ are agent references (e.g., @architect)
|
|
14
|
+
* - Words starting with / are skill/MCP references (e.g., /mysql)
|
|
15
|
+
* - Words starting with -- are options (handled by commander, but we parse leftovers)
|
|
16
|
+
* - Remaining text is supplementary instructions
|
|
17
|
+
*/
|
|
18
|
+
export declare function parseArgs(args: string[]): ParsedArgs;
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Parse variadic CLI arguments into structured parts.
|
|
3
|
+
*
|
|
4
|
+
* Rules:
|
|
5
|
+
* - First word not starting with @, /, or -- is <name>
|
|
6
|
+
* - Words starting with @ are agent references (e.g., @architect)
|
|
7
|
+
* - Words starting with / are skill/MCP references (e.g., /mysql)
|
|
8
|
+
* - Words starting with -- are options (handled by commander, but we parse leftovers)
|
|
9
|
+
* - Remaining text is supplementary instructions
|
|
10
|
+
*/
|
|
11
|
+
export function parseArgs(args) {
|
|
12
|
+
const result = {
|
|
13
|
+
name: '',
|
|
14
|
+
agents: [],
|
|
15
|
+
skills: [],
|
|
16
|
+
text: '',
|
|
17
|
+
options: {},
|
|
18
|
+
};
|
|
19
|
+
const textParts = [];
|
|
20
|
+
let nameFound = false;
|
|
21
|
+
for (const arg of args) {
|
|
22
|
+
if (arg.startsWith('@')) {
|
|
23
|
+
result.agents.push(arg.slice(1));
|
|
24
|
+
}
|
|
25
|
+
else if (arg.startsWith('/')) {
|
|
26
|
+
result.skills.push(arg.slice(1));
|
|
27
|
+
}
|
|
28
|
+
else if (arg.startsWith('--')) {
|
|
29
|
+
// Skip option flags (handled by commander)
|
|
30
|
+
continue;
|
|
31
|
+
}
|
|
32
|
+
else if (!nameFound) {
|
|
33
|
+
result.name = arg;
|
|
34
|
+
nameFound = true;
|
|
35
|
+
}
|
|
36
|
+
else {
|
|
37
|
+
textParts.push(arg);
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
result.text = textParts.join(' ');
|
|
41
|
+
return result;
|
|
42
|
+
}
|
|
43
|
+
//# sourceMappingURL=arguments.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"arguments.js","sourceRoot":"","sources":["../../../src/parsers/arguments.ts"],"names":[],"mappings":"AAQA;;;;;;;;;GASG;AACH,MAAM,UAAU,SAAS,CAAC,IAAc;IACtC,MAAM,MAAM,GAAe;QACzB,IAAI,EAAE,EAAE;QACR,MAAM,EAAE,EAAE;QACV,MAAM,EAAE,EAAE;QACV,IAAI,EAAE,EAAE;QACR,OAAO,EAAE,EAAE;KACZ,CAAC;IAEF,MAAM,SAAS,GAAa,EAAE,CAAC;IAC/B,IAAI,SAAS,GAAG,KAAK,CAAC;IAEtB,KAAK,MAAM,GAAG,IAAI,IAAI,EAAE,CAAC;QACvB,IAAI,GAAG,CAAC,UAAU,CAAC,GAAG,CAAC,EAAE,CAAC;YACxB,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC;QACnC,CAAC;aAAM,IAAI,GAAG,CAAC,UAAU,CAAC,GAAG,CAAC,EAAE,CAAC;YAC/B,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC;QACnC,CAAC;aAAM,IAAI,GAAG,CAAC,UAAU,CAAC,IAAI,CAAC,EAAE,CAAC;YAChC,2CAA2C;YAC3C,SAAS;QACX,CAAC;aAAM,IAAI,CAAC,SAAS,EAAE,CAAC;YACtB,MAAM,CAAC,IAAI,GAAG,GAAG,CAAC;YAClB,SAAS,GAAG,IAAI,CAAC;QACnB,CAAC;aAAM,CAAC;YACN,SAAS,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;QACtB,CAAC;IACH,CAAC;IAED,MAAM,CAAC,IAAI,GAAG,SAAS,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;IAClC,OAAO,MAAM,CAAC;AAChB,CAAC"}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import type { FeatureType } from '../state/types.js';
|
|
2
|
+
export interface PlanTask {
|
|
3
|
+
number: number;
|
|
4
|
+
title: string;
|
|
5
|
+
files: string[];
|
|
6
|
+
description: string;
|
|
7
|
+
dependsOn: string;
|
|
8
|
+
complexity: string;
|
|
9
|
+
acceptance: string;
|
|
10
|
+
raw: string;
|
|
11
|
+
}
|
|
12
|
+
export interface ParsedPlan {
|
|
13
|
+
name: string;
|
|
14
|
+
type: FeatureType;
|
|
15
|
+
branch: string;
|
|
16
|
+
totalTasks: number;
|
|
17
|
+
tasks: PlanTask[];
|
|
18
|
+
raw: string;
|
|
19
|
+
}
|
|
20
|
+
/**
|
|
21
|
+
* Parse a plan markdown file into structured tasks.
|
|
22
|
+
*/
|
|
23
|
+
export declare function parsePlan(content: string): ParsedPlan;
|