clavix 4.12.0 → 5.0.0
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/README.md +69 -61
- package/dist/templates/slash-commands/_canonical/archive.md +83 -121
- package/dist/templates/slash-commands/_canonical/execute.md +32 -42
- package/dist/templates/slash-commands/_canonical/implement.md +32 -44
- package/dist/templates/slash-commands/_canonical/improve.md +13 -52
- package/dist/templates/slash-commands/_components/agent-protocols/cli-reference.md +84 -180
- package/dist/templates/slash-commands/_components/agent-protocols/error-handling.md +2 -2
- package/dist/templates/slash-commands/_components/agent-protocols/file-formats.md +41 -59
- package/dist/templates/slash-commands/_components/sections/file-saving-protocol.md +20 -27
- package/dist/templates/slash-commands/_components/troubleshooting/file-not-saved.md +4 -5
- package/package.json +2 -2
- package/dist/cli/commands/analyze.d.ts +0 -17
- package/dist/cli/commands/analyze.js +0 -133
- package/dist/cli/commands/archive.d.ts +0 -36
- package/dist/cli/commands/archive.js +0 -266
- package/dist/cli/commands/deep.d.ts +0 -17
- package/dist/cli/commands/deep.js +0 -170
- package/dist/cli/commands/execute.d.ts +0 -15
- package/dist/cli/commands/execute.js +0 -168
- package/dist/cli/commands/fast.d.ts +0 -18
- package/dist/cli/commands/fast.js +0 -219
- package/dist/cli/commands/implement.d.ts +0 -24
- package/dist/cli/commands/implement.js +0 -289
- package/dist/cli/commands/improve.d.ts +0 -32
- package/dist/cli/commands/improve.js +0 -250
- package/dist/cli/commands/list.d.ts +0 -17
- package/dist/cli/commands/list.js +0 -217
- package/dist/cli/commands/plan.d.ts +0 -21
- package/dist/cli/commands/plan.js +0 -297
- package/dist/cli/commands/prd.d.ts +0 -24
- package/dist/cli/commands/prd.js +0 -321
- package/dist/cli/commands/prompts/clear.d.ts +0 -16
- package/dist/cli/commands/prompts/clear.js +0 -222
- package/dist/cli/commands/prompts/list.d.ts +0 -8
- package/dist/cli/commands/prompts/list.js +0 -88
- package/dist/cli/commands/show.d.ts +0 -21
- package/dist/cli/commands/show.js +0 -191
- package/dist/cli/commands/start.d.ts +0 -40
- package/dist/cli/commands/start.js +0 -210
- package/dist/cli/commands/summarize.d.ts +0 -17
- package/dist/cli/commands/summarize.js +0 -196
- package/dist/cli/commands/task-complete.d.ts +0 -27
- package/dist/cli/commands/task-complete.js +0 -269
- package/dist/cli/commands/verify.d.ts +0 -28
- package/dist/cli/commands/verify.js +0 -349
- package/dist/core/archive-manager.d.ts +0 -100
- package/dist/core/archive-manager.js +0 -302
- package/dist/core/basic-checklist-generator.d.ts +0 -35
- package/dist/core/basic-checklist-generator.js +0 -344
- package/dist/core/checklist-parser.d.ts +0 -48
- package/dist/core/checklist-parser.js +0 -238
- package/dist/core/config-manager.d.ts +0 -149
- package/dist/core/config-manager.js +0 -230
- package/dist/core/conversation-analyzer.d.ts +0 -86
- package/dist/core/conversation-analyzer.js +0 -387
- package/dist/core/conversation-quality-tracker.d.ts +0 -81
- package/dist/core/conversation-quality-tracker.js +0 -195
- package/dist/core/git-manager.d.ts +0 -126
- package/dist/core/git-manager.js +0 -282
- package/dist/core/intelligence/confidence-calculator.d.ts +0 -93
- package/dist/core/intelligence/confidence-calculator.js +0 -124
- package/dist/core/intelligence/index.d.ts +0 -11
- package/dist/core/intelligence/index.js +0 -15
- package/dist/core/intelligence/intent-detector.d.ts +0 -54
- package/dist/core/intelligence/intent-detector.js +0 -723
- package/dist/core/intelligence/pattern-library.d.ts +0 -104
- package/dist/core/intelligence/pattern-library.js +0 -330
- package/dist/core/intelligence/patterns/actionability-enhancer.d.ts +0 -27
- package/dist/core/intelligence/patterns/actionability-enhancer.js +0 -192
- package/dist/core/intelligence/patterns/alternative-phrasing-generator.d.ts +0 -29
- package/dist/core/intelligence/patterns/alternative-phrasing-generator.js +0 -239
- package/dist/core/intelligence/patterns/ambiguity-detector.d.ts +0 -22
- package/dist/core/intelligence/patterns/ambiguity-detector.js +0 -196
- package/dist/core/intelligence/patterns/assumption-explicitizer.d.ts +0 -30
- package/dist/core/intelligence/patterns/assumption-explicitizer.js +0 -296
- package/dist/core/intelligence/patterns/base-pattern.d.ts +0 -192
- package/dist/core/intelligence/patterns/base-pattern.js +0 -103
- package/dist/core/intelligence/patterns/completeness-validator.d.ts +0 -27
- package/dist/core/intelligence/patterns/completeness-validator.js +0 -221
- package/dist/core/intelligence/patterns/conciseness-filter.d.ts +0 -20
- package/dist/core/intelligence/patterns/conciseness-filter.js +0 -92
- package/dist/core/intelligence/patterns/context-precision.d.ts +0 -32
- package/dist/core/intelligence/patterns/context-precision.js +0 -389
- package/dist/core/intelligence/patterns/conversation-summarizer.d.ts +0 -30
- package/dist/core/intelligence/patterns/conversation-summarizer.js +0 -277
- package/dist/core/intelligence/patterns/dependency-identifier.d.ts +0 -23
- package/dist/core/intelligence/patterns/dependency-identifier.js +0 -166
- package/dist/core/intelligence/patterns/domain-context-enricher.d.ts +0 -21
- package/dist/core/intelligence/patterns/domain-context-enricher.js +0 -198
- package/dist/core/intelligence/patterns/edge-case-identifier.d.ts +0 -30
- package/dist/core/intelligence/patterns/edge-case-identifier.js +0 -269
- package/dist/core/intelligence/patterns/error-tolerance-enhancer.d.ts +0 -22
- package/dist/core/intelligence/patterns/error-tolerance-enhancer.js +0 -179
- package/dist/core/intelligence/patterns/implicit-requirement-extractor.d.ts +0 -24
- package/dist/core/intelligence/patterns/implicit-requirement-extractor.js +0 -259
- package/dist/core/intelligence/patterns/objective-clarifier.d.ts +0 -22
- package/dist/core/intelligence/patterns/objective-clarifier.js +0 -126
- package/dist/core/intelligence/patterns/output-format-enforcer.d.ts +0 -22
- package/dist/core/intelligence/patterns/output-format-enforcer.js +0 -151
- package/dist/core/intelligence/patterns/prd-structure-enforcer.d.ts +0 -23
- package/dist/core/intelligence/patterns/prd-structure-enforcer.js +0 -183
- package/dist/core/intelligence/patterns/prerequisite-identifier.d.ts +0 -23
- package/dist/core/intelligence/patterns/prerequisite-identifier.js +0 -221
- package/dist/core/intelligence/patterns/requirement-prioritizer.d.ts +0 -24
- package/dist/core/intelligence/patterns/requirement-prioritizer.js +0 -134
- package/dist/core/intelligence/patterns/scope-definer.d.ts +0 -26
- package/dist/core/intelligence/patterns/scope-definer.js +0 -236
- package/dist/core/intelligence/patterns/step-decomposer.d.ts +0 -31
- package/dist/core/intelligence/patterns/step-decomposer.js +0 -242
- package/dist/core/intelligence/patterns/structure-organizer.d.ts +0 -31
- package/dist/core/intelligence/patterns/structure-organizer.js +0 -218
- package/dist/core/intelligence/patterns/success-criteria-enforcer.d.ts +0 -22
- package/dist/core/intelligence/patterns/success-criteria-enforcer.js +0 -165
- package/dist/core/intelligence/patterns/success-metrics-enforcer.d.ts +0 -24
- package/dist/core/intelligence/patterns/success-metrics-enforcer.js +0 -165
- package/dist/core/intelligence/patterns/technical-context-enricher.d.ts +0 -25
- package/dist/core/intelligence/patterns/technical-context-enricher.js +0 -165
- package/dist/core/intelligence/patterns/topic-coherence-analyzer.d.ts +0 -26
- package/dist/core/intelligence/patterns/topic-coherence-analyzer.js +0 -300
- package/dist/core/intelligence/patterns/user-persona-enricher.d.ts +0 -24
- package/dist/core/intelligence/patterns/user-persona-enricher.js +0 -141
- package/dist/core/intelligence/patterns/validation-checklist-creator.d.ts +0 -31
- package/dist/core/intelligence/patterns/validation-checklist-creator.js +0 -242
- package/dist/core/intelligence/quality-assessor.d.ts +0 -71
- package/dist/core/intelligence/quality-assessor.js +0 -525
- package/dist/core/intelligence/types.d.ts +0 -111
- package/dist/core/intelligence/types.js +0 -3
- package/dist/core/intelligence/universal-optimizer.d.ts +0 -91
- package/dist/core/intelligence/universal-optimizer.js +0 -399
- package/dist/core/prd-generator.d.ts +0 -76
- package/dist/core/prd-generator.js +0 -173
- package/dist/core/prompt-manager.d.ts +0 -110
- package/dist/core/prompt-manager.js +0 -274
- package/dist/core/prompt-optimizer.d.ts +0 -268
- package/dist/core/prompt-optimizer.js +0 -959
- package/dist/core/question-engine.d.ts +0 -167
- package/dist/core/question-engine.js +0 -356
- package/dist/core/session-manager.d.ts +0 -139
- package/dist/core/session-manager.js +0 -365
- package/dist/core/task-manager.d.ts +0 -211
- package/dist/core/task-manager.js +0 -981
- package/dist/core/verification-hooks.d.ts +0 -67
- package/dist/core/verification-hooks.js +0 -309
- package/dist/core/verification-manager.d.ts +0 -107
- package/dist/core/verification-manager.js +0 -415
- package/dist/index 2.js +0 -13
- package/dist/index.d 2.ts +0 -4
- package/dist/types/session.d.ts +0 -78
- package/dist/types/session.js +0 -8
- package/dist/types/verification.d.ts +0 -205
- package/dist/types/verification.js +0 -9
|
@@ -1,217 +0,0 @@
|
|
|
1
|
-
import { Command, Flags } from '@oclif/core';
|
|
2
|
-
import chalk from 'chalk';
|
|
3
|
-
import fs from 'fs-extra';
|
|
4
|
-
import * as path from 'path';
|
|
5
|
-
import { SessionManager } from '../../core/session-manager.js';
|
|
6
|
-
export default class List extends Command {
|
|
7
|
-
static description = 'List sessions and outputs';
|
|
8
|
-
static examples = [
|
|
9
|
-
'<%= config.bin %> <%= command.id %>',
|
|
10
|
-
'<%= config.bin %> <%= command.id %> --sessions',
|
|
11
|
-
'<%= config.bin %> <%= command.id %> --outputs',
|
|
12
|
-
'<%= config.bin %> <%= command.id %> --project my-feature',
|
|
13
|
-
];
|
|
14
|
-
static flags = {
|
|
15
|
-
sessions: Flags.boolean({
|
|
16
|
-
char: 's',
|
|
17
|
-
description: 'List only sessions',
|
|
18
|
-
default: false,
|
|
19
|
-
}),
|
|
20
|
-
outputs: Flags.boolean({
|
|
21
|
-
char: 'o',
|
|
22
|
-
description: 'List only outputs',
|
|
23
|
-
default: false,
|
|
24
|
-
}),
|
|
25
|
-
archived: Flags.boolean({
|
|
26
|
-
char: 'a',
|
|
27
|
-
description: 'Include archived projects in outputs',
|
|
28
|
-
default: false,
|
|
29
|
-
}),
|
|
30
|
-
project: Flags.string({
|
|
31
|
-
char: 'p',
|
|
32
|
-
description: 'Filter by project name',
|
|
33
|
-
}),
|
|
34
|
-
limit: Flags.integer({
|
|
35
|
-
char: 'l',
|
|
36
|
-
description: 'Limit number of results',
|
|
37
|
-
default: 20,
|
|
38
|
-
}),
|
|
39
|
-
};
|
|
40
|
-
async run() {
|
|
41
|
-
const { flags } = await this.parse(List);
|
|
42
|
-
const clavixDir = path.join(process.cwd(), '.clavix');
|
|
43
|
-
if (!fs.existsSync(clavixDir)) {
|
|
44
|
-
this.error(chalk.red('No .clavix directory found.') +
|
|
45
|
-
'\n' +
|
|
46
|
-
chalk.yellow('Run ') +
|
|
47
|
-
chalk.cyan('clavix init') +
|
|
48
|
-
chalk.yellow(' to initialize Clavix in this project.'));
|
|
49
|
-
}
|
|
50
|
-
// If no specific flag is set, show both
|
|
51
|
-
const showSessions = flags.sessions || (!flags.outputs && !flags.sessions);
|
|
52
|
-
const showOutputs = flags.outputs || (!flags.outputs && !flags.sessions);
|
|
53
|
-
if (showSessions) {
|
|
54
|
-
await this.listSessions(flags.project, flags.limit);
|
|
55
|
-
}
|
|
56
|
-
if (showOutputs) {
|
|
57
|
-
if (showSessions) {
|
|
58
|
-
this.log(''); // Add spacing
|
|
59
|
-
}
|
|
60
|
-
await this.listOutputs(flags.project, flags.limit, flags.archived);
|
|
61
|
-
}
|
|
62
|
-
}
|
|
63
|
-
async listSessions(projectFilter, limit) {
|
|
64
|
-
this.log(chalk.bold.cyan('📋 Sessions\n'));
|
|
65
|
-
const sessionManager = new SessionManager();
|
|
66
|
-
const sessions = await sessionManager.listSessions();
|
|
67
|
-
if (sessions.length === 0) {
|
|
68
|
-
this.log(chalk.gray(' No sessions found.'));
|
|
69
|
-
this.log(chalk.gray(' Run ') + chalk.cyan('clavix start') + chalk.gray(' to create a new session.'));
|
|
70
|
-
return;
|
|
71
|
-
}
|
|
72
|
-
// Filter by project if specified
|
|
73
|
-
let filteredSessions = sessions;
|
|
74
|
-
if (projectFilter) {
|
|
75
|
-
filteredSessions = sessions.filter(s => s.projectName?.toLowerCase().includes(projectFilter.toLowerCase()));
|
|
76
|
-
}
|
|
77
|
-
// Sort by updated date (most recent first)
|
|
78
|
-
filteredSessions.sort((a, b) => new Date(b.updated).getTime() - new Date(a.updated).getTime());
|
|
79
|
-
// Apply limit
|
|
80
|
-
if (limit) {
|
|
81
|
-
filteredSessions = filteredSessions.slice(0, limit);
|
|
82
|
-
}
|
|
83
|
-
if (filteredSessions.length === 0) {
|
|
84
|
-
this.log(chalk.gray(` No sessions found matching "${projectFilter}".`));
|
|
85
|
-
return;
|
|
86
|
-
}
|
|
87
|
-
// Display sessions in a table-like format
|
|
88
|
-
filteredSessions.forEach((session, index) => {
|
|
89
|
-
const isActive = session.status === 'active';
|
|
90
|
-
const statusIcon = isActive ? '🟢' : '⚪';
|
|
91
|
-
const projectName = session.projectName || 'untitled';
|
|
92
|
-
const created = new Date(session.created).toLocaleDateString();
|
|
93
|
-
const updated = new Date(session.updated).toLocaleString();
|
|
94
|
-
const messageCount = session.messageCount || 0;
|
|
95
|
-
this.log(` ${statusIcon} ${chalk.bold(projectName)} ${chalk.gray(`(${session.id})`)}` +
|
|
96
|
-
`\n ${chalk.gray('Created:')} ${created} ${chalk.gray('│')} ` +
|
|
97
|
-
`${chalk.gray('Updated:')} ${updated}` +
|
|
98
|
-
`\n ${chalk.gray('Messages:')} ${messageCount} ${chalk.gray('│')} ` +
|
|
99
|
-
`${chalk.gray('Status:')} ${isActive ? chalk.green('active') : chalk.gray('completed')}` +
|
|
100
|
-
(index < filteredSessions.length - 1 ? '\n' : ''));
|
|
101
|
-
});
|
|
102
|
-
this.log('');
|
|
103
|
-
this.log(chalk.gray(` Showing ${filteredSessions.length} of ${sessions.length} sessions`));
|
|
104
|
-
if (sessions.length > filteredSessions.length && !limit) {
|
|
105
|
-
this.log(chalk.gray(` Use ${chalk.cyan('--limit N')} to show more results`));
|
|
106
|
-
}
|
|
107
|
-
}
|
|
108
|
-
async listOutputs(projectFilter, limit, includeArchived = false) {
|
|
109
|
-
this.log(chalk.bold.cyan('📁 Outputs\n'));
|
|
110
|
-
const outputsDir = path.join(process.cwd(), '.clavix', 'outputs');
|
|
111
|
-
if (!fs.existsSync(outputsDir)) {
|
|
112
|
-
this.log(chalk.gray(' No outputs found.'));
|
|
113
|
-
this.log(chalk.gray(' Run ') + chalk.cyan('clavix prd') + chalk.gray(' or ') + chalk.cyan('clavix summarize') + chalk.gray(' to generate outputs.'));
|
|
114
|
-
return;
|
|
115
|
-
}
|
|
116
|
-
const projectDirs = fs.readdirSync(outputsDir).filter(name => {
|
|
117
|
-
const fullPath = path.join(outputsDir, name);
|
|
118
|
-
// Skip archive directory in main listing
|
|
119
|
-
if (name === 'archive' && !includeArchived) {
|
|
120
|
-
return false;
|
|
121
|
-
}
|
|
122
|
-
return fs.statSync(fullPath).isDirectory();
|
|
123
|
-
});
|
|
124
|
-
if (projectDirs.length === 0) {
|
|
125
|
-
this.log(chalk.gray(' No outputs found.'));
|
|
126
|
-
return;
|
|
127
|
-
}
|
|
128
|
-
// Filter by project if specified
|
|
129
|
-
let filteredDirs = projectDirs;
|
|
130
|
-
if (projectFilter) {
|
|
131
|
-
filteredDirs = projectDirs.filter(dir => dir.toLowerCase().includes(projectFilter.toLowerCase()));
|
|
132
|
-
}
|
|
133
|
-
// Sort by modification time (most recent first)
|
|
134
|
-
filteredDirs.sort((a, b) => {
|
|
135
|
-
const aPath = path.join(outputsDir, a);
|
|
136
|
-
const bPath = path.join(outputsDir, b);
|
|
137
|
-
return fs.statSync(bPath).mtime.getTime() - fs.statSync(aPath).mtime.getTime();
|
|
138
|
-
});
|
|
139
|
-
// Apply limit
|
|
140
|
-
if (limit) {
|
|
141
|
-
filteredDirs = filteredDirs.slice(0, limit);
|
|
142
|
-
}
|
|
143
|
-
if (filteredDirs.length === 0) {
|
|
144
|
-
this.log(chalk.gray(` No outputs found matching "${projectFilter}".`));
|
|
145
|
-
return;
|
|
146
|
-
}
|
|
147
|
-
// Display outputs
|
|
148
|
-
filteredDirs.forEach((projectDir, index) => {
|
|
149
|
-
const projectPath = path.join(outputsDir, projectDir);
|
|
150
|
-
const files = fs.readdirSync(projectPath).filter(f => f.endsWith('.md'));
|
|
151
|
-
const modified = fs.statSync(projectPath).mtime.toLocaleDateString();
|
|
152
|
-
this.log(` 📄 ${chalk.bold(projectDir)}` +
|
|
153
|
-
`\n ${chalk.gray('Path:')} ${chalk.dim(path.relative(process.cwd(), projectPath))}` +
|
|
154
|
-
`\n ${chalk.gray('Files:')} ${files.join(', ')}` +
|
|
155
|
-
`\n ${chalk.gray('Modified:')} ${modified}` +
|
|
156
|
-
(index < filteredDirs.length - 1 ? '\n' : ''));
|
|
157
|
-
});
|
|
158
|
-
this.log('');
|
|
159
|
-
this.log(chalk.gray(` Showing ${filteredDirs.length} of ${projectDirs.length} output directories`));
|
|
160
|
-
if (projectDirs.length > filteredDirs.length && !limit) {
|
|
161
|
-
this.log(chalk.gray(` Use ${chalk.cyan('--limit N')} to show more results`));
|
|
162
|
-
}
|
|
163
|
-
// Show archived projects if flag is set
|
|
164
|
-
if (includeArchived) {
|
|
165
|
-
await this.listArchivedOutputs(projectFilter, limit);
|
|
166
|
-
}
|
|
167
|
-
}
|
|
168
|
-
async listArchivedOutputs(projectFilter, limit) {
|
|
169
|
-
const archiveDir = path.join(process.cwd(), '.clavix', 'outputs', 'archive');
|
|
170
|
-
if (!fs.existsSync(archiveDir)) {
|
|
171
|
-
return; // No archived projects
|
|
172
|
-
}
|
|
173
|
-
const archivedDirs = fs.readdirSync(archiveDir).filter(name => {
|
|
174
|
-
const fullPath = path.join(archiveDir, name);
|
|
175
|
-
return fs.statSync(fullPath).isDirectory();
|
|
176
|
-
});
|
|
177
|
-
if (archivedDirs.length === 0) {
|
|
178
|
-
return; // No archived projects
|
|
179
|
-
}
|
|
180
|
-
// Filter by project if specified
|
|
181
|
-
let filteredDirs = archivedDirs;
|
|
182
|
-
if (projectFilter) {
|
|
183
|
-
filteredDirs = archivedDirs.filter(dir => dir.toLowerCase().includes(projectFilter.toLowerCase()));
|
|
184
|
-
}
|
|
185
|
-
// Sort by modification time (most recent first)
|
|
186
|
-
filteredDirs.sort((a, b) => {
|
|
187
|
-
const aPath = path.join(archiveDir, a);
|
|
188
|
-
const bPath = path.join(archiveDir, b);
|
|
189
|
-
return fs.statSync(bPath).mtime.getTime() - fs.statSync(aPath).mtime.getTime();
|
|
190
|
-
});
|
|
191
|
-
// Apply limit
|
|
192
|
-
if (limit) {
|
|
193
|
-
filteredDirs = filteredDirs.slice(0, limit);
|
|
194
|
-
}
|
|
195
|
-
if (filteredDirs.length === 0) {
|
|
196
|
-
return; // No matching archived projects
|
|
197
|
-
}
|
|
198
|
-
// Display archived section header
|
|
199
|
-
this.log('');
|
|
200
|
-
this.log(chalk.bold.cyan('📦 Archived Outputs\n'));
|
|
201
|
-
// Display archived outputs
|
|
202
|
-
filteredDirs.forEach((projectDir, index) => {
|
|
203
|
-
const projectPath = path.join(archiveDir, projectDir);
|
|
204
|
-
const files = fs.readdirSync(projectPath).filter(f => f.endsWith('.md'));
|
|
205
|
-
const modified = fs.statSync(projectPath).mtime.toLocaleDateString();
|
|
206
|
-
this.log(` 📦 ${chalk.bold(projectDir)} ${chalk.gray('(archived)')}` +
|
|
207
|
-
`\n ${chalk.gray('Path:')} ${chalk.dim(path.relative(process.cwd(), projectPath))}` +
|
|
208
|
-
`\n ${chalk.gray('Files:')} ${files.join(', ')}` +
|
|
209
|
-
`\n ${chalk.gray('Modified:')} ${modified}` +
|
|
210
|
-
(index < filteredDirs.length - 1 ? '\n' : ''));
|
|
211
|
-
});
|
|
212
|
-
this.log('');
|
|
213
|
-
this.log(chalk.gray(` Showing ${filteredDirs.length} of ${archivedDirs.length} archived directories`));
|
|
214
|
-
this.log(chalk.gray(` Use ${chalk.cyan('clavix archive --restore <project>')} to restore a project`));
|
|
215
|
-
}
|
|
216
|
-
}
|
|
217
|
-
//# sourceMappingURL=list.js.map
|
|
@@ -1,21 +0,0 @@
|
|
|
1
|
-
import { Command } from '@oclif/core';
|
|
2
|
-
export default class Plan extends Command {
|
|
3
|
-
static description: string;
|
|
4
|
-
static examples: string[];
|
|
5
|
-
static flags: {
|
|
6
|
-
project: import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
|
|
7
|
-
'prd-path': import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
|
|
8
|
-
session: import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
|
|
9
|
-
'active-session': import("@oclif/core/interfaces").BooleanFlag<boolean>;
|
|
10
|
-
source: import("@oclif/core/interfaces").OptionFlag<string, import("@oclif/core/interfaces").CustomOptions>;
|
|
11
|
-
'max-tasks': import("@oclif/core/interfaces").OptionFlag<number, import("@oclif/core/interfaces").CustomOptions>;
|
|
12
|
-
overwrite: import("@oclif/core/interfaces").BooleanFlag<boolean>;
|
|
13
|
-
};
|
|
14
|
-
run(): Promise<void>;
|
|
15
|
-
private validateSessionFlags;
|
|
16
|
-
private prepareArtifactsFromSession;
|
|
17
|
-
private resolveProjectDirectory;
|
|
18
|
-
private sanitizeProjectName;
|
|
19
|
-
private isInteractive;
|
|
20
|
-
}
|
|
21
|
-
//# sourceMappingURL=plan.d.ts.map
|
|
@@ -1,297 +0,0 @@
|
|
|
1
|
-
import { Command, Flags } from '@oclif/core';
|
|
2
|
-
import chalk from 'chalk';
|
|
3
|
-
import inquirer from 'inquirer';
|
|
4
|
-
import fs from 'fs-extra';
|
|
5
|
-
import * as path from 'path';
|
|
6
|
-
import { TaskManager } from '../../core/task-manager.js';
|
|
7
|
-
import { SessionManager } from '../../core/session-manager.js';
|
|
8
|
-
import { ConversationAnalyzer } from '../../core/conversation-analyzer.js';
|
|
9
|
-
import { FileSystem } from '../../utils/file-system.js';
|
|
10
|
-
import { AgentErrorMessages } from '../../utils/agent-error-messages.js';
|
|
11
|
-
export default class Plan extends Command {
|
|
12
|
-
static description = 'Generate implementation task breakdown from PRD';
|
|
13
|
-
static examples = [
|
|
14
|
-
'<%= config.bin %> <%= command.id %>',
|
|
15
|
-
'<%= config.bin %> <%= command.id %> --project my-app',
|
|
16
|
-
'<%= config.bin %> <%= command.id %> --prd-path .clavix/outputs/my-project',
|
|
17
|
-
'<%= config.bin %> <%= command.id %> --session 1234-5678',
|
|
18
|
-
];
|
|
19
|
-
static flags = {
|
|
20
|
-
project: Flags.string({
|
|
21
|
-
char: 'p',
|
|
22
|
-
description: 'PRD project name (defaults to most recent)',
|
|
23
|
-
}),
|
|
24
|
-
'prd-path': Flags.string({
|
|
25
|
-
description: 'Direct path to PRD directory',
|
|
26
|
-
}),
|
|
27
|
-
session: Flags.string({
|
|
28
|
-
description: 'Session ID to plan from (generates mini-prd.md automatically)',
|
|
29
|
-
}),
|
|
30
|
-
'active-session': Flags.boolean({
|
|
31
|
-
description: 'Use the most recent active session as input',
|
|
32
|
-
default: false,
|
|
33
|
-
}),
|
|
34
|
-
source: Flags.string({
|
|
35
|
-
description: 'Preferred PRD source (auto|full|quick|mini|prompt)',
|
|
36
|
-
options: ['auto', 'full', 'quick', 'mini', 'prompt'],
|
|
37
|
-
default: 'auto',
|
|
38
|
-
}),
|
|
39
|
-
'max-tasks': Flags.integer({
|
|
40
|
-
description: 'Maximum tasks per phase',
|
|
41
|
-
default: 20,
|
|
42
|
-
}),
|
|
43
|
-
overwrite: Flags.boolean({
|
|
44
|
-
char: 'o',
|
|
45
|
-
description: 'Overwrite existing tasks.md file',
|
|
46
|
-
default: false,
|
|
47
|
-
}),
|
|
48
|
-
};
|
|
49
|
-
async run() {
|
|
50
|
-
const { flags } = await this.parse(Plan);
|
|
51
|
-
console.log(chalk.bold.cyan('\nTask Plan Generator\n'));
|
|
52
|
-
console.log(chalk.gray('Analyzing PRD and generating implementation tasks...\n'));
|
|
53
|
-
try {
|
|
54
|
-
this.validateSessionFlags(flags.session, flags['active-session']);
|
|
55
|
-
const manager = new TaskManager();
|
|
56
|
-
const sourcePreference = (flags.source ?? 'auto');
|
|
57
|
-
let projectName = null;
|
|
58
|
-
let prdPath = flags['prd-path'] ? path.resolve(flags['prd-path']) : null;
|
|
59
|
-
let generatedFromSession = false;
|
|
60
|
-
const generatedArtifacts = [];
|
|
61
|
-
if (flags.session || flags['active-session']) {
|
|
62
|
-
const sessionResult = await this.prepareArtifactsFromSession(flags.session, flags['active-session']);
|
|
63
|
-
prdPath = sessionResult.prdPath;
|
|
64
|
-
projectName = sessionResult.projectName;
|
|
65
|
-
generatedFromSession = true;
|
|
66
|
-
generatedArtifacts.push(...sessionResult.generatedArtifacts);
|
|
67
|
-
}
|
|
68
|
-
let selectedProject = null;
|
|
69
|
-
if (!prdPath) {
|
|
70
|
-
selectedProject = await this.resolveProjectDirectory(manager, flags.project);
|
|
71
|
-
if (!selectedProject) {
|
|
72
|
-
this.error(AgentErrorMessages.noPrdFound());
|
|
73
|
-
}
|
|
74
|
-
prdPath = selectedProject.path;
|
|
75
|
-
projectName = selectedProject.name;
|
|
76
|
-
}
|
|
77
|
-
if (!prdPath) {
|
|
78
|
-
throw new Error('Unable to resolve PRD directory.');
|
|
79
|
-
}
|
|
80
|
-
const resolvedProjectName = projectName ?? path.basename(prdPath);
|
|
81
|
-
// Check if tasks.md already exists
|
|
82
|
-
const tasksPath = path.join(prdPath, 'tasks.md');
|
|
83
|
-
if ((await fs.pathExists(tasksPath)) && !flags.overwrite) {
|
|
84
|
-
console.log(chalk.yellow('Warning: tasks.md already exists.'));
|
|
85
|
-
console.log(chalk.gray(`Location: ${tasksPath}`));
|
|
86
|
-
console.log(chalk.gray('Use --overwrite to regenerate tasks.md.\n'));
|
|
87
|
-
return;
|
|
88
|
-
}
|
|
89
|
-
console.log(chalk.dim('Looking for PRD artifacts...'));
|
|
90
|
-
const availableSources = await manager.detectAvailableSources(prdPath);
|
|
91
|
-
if (availableSources.length === 0) {
|
|
92
|
-
this.error(AgentErrorMessages.noPrdFound());
|
|
93
|
-
}
|
|
94
|
-
if (sourcePreference !== 'auto' && !availableSources.includes(sourcePreference)) {
|
|
95
|
-
this.error(`Preferred source "${sourcePreference}" not found in ${prdPath}\n\n` +
|
|
96
|
-
`Available sources: ${availableSources.join(', ') || 'none'}\n` +
|
|
97
|
-
'Hint: Override with --source flag');
|
|
98
|
-
}
|
|
99
|
-
if (availableSources.length > 1 && sourcePreference === 'auto') {
|
|
100
|
-
console.log(chalk.dim(`Found multiple sources (${availableSources.join(', ')}). Selecting best match...`));
|
|
101
|
-
}
|
|
102
|
-
// Generate tasks
|
|
103
|
-
console.log(chalk.dim('Analyzing PRD content...'));
|
|
104
|
-
const result = await manager.generateTasksFromPrd(prdPath, {
|
|
105
|
-
maxTasksPerPhase: flags['max-tasks'],
|
|
106
|
-
includeReferences: true,
|
|
107
|
-
clearMode: 'fast',
|
|
108
|
-
source: sourcePreference,
|
|
109
|
-
});
|
|
110
|
-
const chosenSourceFile = path.basename(result.sourcePath);
|
|
111
|
-
const usingOverride = sourcePreference !== 'auto';
|
|
112
|
-
if (usingOverride) {
|
|
113
|
-
console.log(chalk.dim(`Using source: ${chosenSourceFile}`));
|
|
114
|
-
}
|
|
115
|
-
else {
|
|
116
|
-
console.log(chalk.dim(`Using source: ${chosenSourceFile} (override with --source to pick a different artifact).`));
|
|
117
|
-
}
|
|
118
|
-
// Display results
|
|
119
|
-
console.log(chalk.bold.green('\nTask plan generated successfully!\n'));
|
|
120
|
-
if (generatedFromSession) {
|
|
121
|
-
console.log(chalk.bold('Generated artifacts:'));
|
|
122
|
-
generatedArtifacts.forEach((artifact) => {
|
|
123
|
-
console.log(chalk.gray(` • ${artifact}`));
|
|
124
|
-
});
|
|
125
|
-
console.log();
|
|
126
|
-
}
|
|
127
|
-
console.log(chalk.bold('Summary:'));
|
|
128
|
-
console.log(chalk.cyan(` Project: ${resolvedProjectName}`));
|
|
129
|
-
console.log(chalk.cyan(` Source: ${chosenSourceFile}`));
|
|
130
|
-
console.log(chalk.cyan(` Total Phases: ${result.phases.length}`));
|
|
131
|
-
console.log(chalk.cyan(` Total Tasks: ${result.totalTasks}`));
|
|
132
|
-
console.log();
|
|
133
|
-
console.log(chalk.bold('Task Breakdown:\n'));
|
|
134
|
-
for (const phase of result.phases) {
|
|
135
|
-
console.log(chalk.bold(` ${phase.name}`));
|
|
136
|
-
console.log(chalk.gray(` ${phase.tasks.length} tasks`));
|
|
137
|
-
const preview = phase.tasks.slice(0, 3);
|
|
138
|
-
preview.forEach((task) => {
|
|
139
|
-
console.log(chalk.dim(` • ${task.description}`));
|
|
140
|
-
});
|
|
141
|
-
if (phase.tasks.length > 3) {
|
|
142
|
-
console.log(chalk.dim(` ... and ${phase.tasks.length - 3} more`));
|
|
143
|
-
}
|
|
144
|
-
console.log();
|
|
145
|
-
}
|
|
146
|
-
console.log(chalk.bold('Output:'));
|
|
147
|
-
console.log(chalk.cyan(` ${result.outputPath}`));
|
|
148
|
-
console.log();
|
|
149
|
-
console.log(chalk.bold.green('Next Steps:\n'));
|
|
150
|
-
console.log(chalk.gray(' 1. Review the generated tasks in tasks.md'));
|
|
151
|
-
console.log(chalk.gray(' 2. Edit if needed (add/remove/modify tasks)'));
|
|
152
|
-
console.log(chalk.gray(' 3. Run'), chalk.cyan('clavix implement'), chalk.gray('to start implementation'));
|
|
153
|
-
console.log();
|
|
154
|
-
console.log(chalk.dim('Tip: Tasks are optimized with Clavix Intelligence for optimal AI execution\n'));
|
|
155
|
-
}
|
|
156
|
-
catch (error) {
|
|
157
|
-
const errorMessage = error instanceof Error ? error.message : 'An unexpected error occurred';
|
|
158
|
-
this.error(errorMessage);
|
|
159
|
-
}
|
|
160
|
-
}
|
|
161
|
-
validateSessionFlags(session, activeSession) {
|
|
162
|
-
if (session && activeSession) {
|
|
163
|
-
throw new Error('Use either --session or --active-session, not both.');
|
|
164
|
-
}
|
|
165
|
-
}
|
|
166
|
-
async prepareArtifactsFromSession(sessionId, useActive) {
|
|
167
|
-
const sessionManager = new SessionManager();
|
|
168
|
-
const analyzer = new ConversationAnalyzer();
|
|
169
|
-
let session = null;
|
|
170
|
-
if (sessionId) {
|
|
171
|
-
session = await sessionManager.getSession(sessionId);
|
|
172
|
-
if (!session) {
|
|
173
|
-
throw new Error(`Session not found: ${sessionId}`);
|
|
174
|
-
}
|
|
175
|
-
}
|
|
176
|
-
else if (useActive) {
|
|
177
|
-
session = await sessionManager.getActiveSession();
|
|
178
|
-
if (!session) {
|
|
179
|
-
throw new Error('No active session found.');
|
|
180
|
-
}
|
|
181
|
-
}
|
|
182
|
-
if (!session) {
|
|
183
|
-
throw new Error('Session resolution failed.');
|
|
184
|
-
}
|
|
185
|
-
if (session.messages.length === 0) {
|
|
186
|
-
throw new Error('Session has no messages to analyze.');
|
|
187
|
-
}
|
|
188
|
-
console.log(chalk.dim(`Generating mini-PRD from session ${session.id}...`));
|
|
189
|
-
const analysis = analyzer.analyze(session);
|
|
190
|
-
const projectDirName = this.sanitizeProjectName(session.projectName);
|
|
191
|
-
const outputsDir = path.join('.clavix', 'outputs', projectDirName);
|
|
192
|
-
await FileSystem.ensureDir(outputsDir);
|
|
193
|
-
const miniPrdPath = path.join(outputsDir, 'mini-prd.md');
|
|
194
|
-
const promptPath = path.join(outputsDir, 'optimized-prompt.md');
|
|
195
|
-
const miniPrdContent = analyzer.generateMiniPrd(session, analysis);
|
|
196
|
-
const promptContent = analyzer.generateOptimizedPrompt(session, analysis);
|
|
197
|
-
await FileSystem.writeFileAtomic(miniPrdPath, miniPrdContent);
|
|
198
|
-
await FileSystem.writeFileAtomic(promptPath, promptContent);
|
|
199
|
-
console.log(chalk.dim(`Saved mini-prd.md and optimized-prompt.md to ${outputsDir}.\n`));
|
|
200
|
-
return {
|
|
201
|
-
prdPath: outputsDir,
|
|
202
|
-
projectName: projectDirName,
|
|
203
|
-
generatedArtifacts: [miniPrdPath, promptPath],
|
|
204
|
-
};
|
|
205
|
-
}
|
|
206
|
-
async resolveProjectDirectory(manager, projectName) {
|
|
207
|
-
const outputsDir = path.join(process.cwd(), '.clavix', 'outputs');
|
|
208
|
-
if (!(await fs.pathExists(outputsDir))) {
|
|
209
|
-
return null;
|
|
210
|
-
}
|
|
211
|
-
const entries = await fs.readdir(outputsDir, { withFileTypes: true });
|
|
212
|
-
const projects = [];
|
|
213
|
-
for (const entry of entries) {
|
|
214
|
-
if (!entry.isDirectory()) {
|
|
215
|
-
continue;
|
|
216
|
-
}
|
|
217
|
-
if (entry.name === 'archive') {
|
|
218
|
-
continue;
|
|
219
|
-
}
|
|
220
|
-
const projectPath = path.join(outputsDir, entry.name);
|
|
221
|
-
const sources = await manager.detectAvailableSources(projectPath);
|
|
222
|
-
if (sources.length === 0) {
|
|
223
|
-
continue;
|
|
224
|
-
}
|
|
225
|
-
const hasTasks = await fs.pathExists(path.join(projectPath, 'tasks.md'));
|
|
226
|
-
const stats = await fs.stat(projectPath);
|
|
227
|
-
projects.push({
|
|
228
|
-
name: entry.name,
|
|
229
|
-
path: projectPath,
|
|
230
|
-
sources,
|
|
231
|
-
hasTasks,
|
|
232
|
-
mtime: stats.mtime,
|
|
233
|
-
});
|
|
234
|
-
}
|
|
235
|
-
if (projectName) {
|
|
236
|
-
const match = projects.find((project) => project.name === projectName);
|
|
237
|
-
if (!match) {
|
|
238
|
-
throw new Error(`PRD project not found: ${projectName}`);
|
|
239
|
-
}
|
|
240
|
-
console.log(chalk.dim(`Selected project: ${match.name}`));
|
|
241
|
-
return match;
|
|
242
|
-
}
|
|
243
|
-
if (projects.length === 0) {
|
|
244
|
-
return null;
|
|
245
|
-
}
|
|
246
|
-
if (projects.length === 1) {
|
|
247
|
-
const [project] = projects;
|
|
248
|
-
console.log(chalk.dim(`Auto-selected project: ${project.name}`));
|
|
249
|
-
return project;
|
|
250
|
-
}
|
|
251
|
-
if (this.isInteractive()) {
|
|
252
|
-
console.log(chalk.bold('Select a PRD project to generate a task plan:\n'));
|
|
253
|
-
const choices = projects.map((project) => {
|
|
254
|
-
const sourceLabel = project.sources.join('/') || 'prompt';
|
|
255
|
-
const taskLabel = project.hasTasks ? 'tasks present' : 'no tasks yet';
|
|
256
|
-
return {
|
|
257
|
-
name: `${project.name} — sources: ${sourceLabel}; ${taskLabel}`,
|
|
258
|
-
value: project.name,
|
|
259
|
-
};
|
|
260
|
-
});
|
|
261
|
-
const response = await inquirer.prompt([
|
|
262
|
-
{
|
|
263
|
-
type: 'list',
|
|
264
|
-
name: 'project',
|
|
265
|
-
message: 'Project:',
|
|
266
|
-
choices,
|
|
267
|
-
},
|
|
268
|
-
]);
|
|
269
|
-
const selected = projects.find((project) => project.name === response.project);
|
|
270
|
-
if (!selected) {
|
|
271
|
-
throw new Error('Project selection failed.');
|
|
272
|
-
}
|
|
273
|
-
return selected;
|
|
274
|
-
}
|
|
275
|
-
projects.sort((a, b) => b.mtime.getTime() - a.mtime.getTime());
|
|
276
|
-
const chosen = projects[0];
|
|
277
|
-
console.log(chalk.dim(`Multiple PRD projects found; selected most recent: ${chosen.name}. Use --project to choose explicitly.`));
|
|
278
|
-
return chosen;
|
|
279
|
-
}
|
|
280
|
-
sanitizeProjectName(name) {
|
|
281
|
-
const fallback = 'session-project';
|
|
282
|
-
if (!name) {
|
|
283
|
-
return fallback;
|
|
284
|
-
}
|
|
285
|
-
const sanitized = name
|
|
286
|
-
.toLowerCase()
|
|
287
|
-
.replace(/[^a-z0-9-]/g, '-')
|
|
288
|
-
.replace(/-+/g, '-')
|
|
289
|
-
.replace(/^-|-$/g, '')
|
|
290
|
-
.substring(0, 50);
|
|
291
|
-
return sanitized || fallback;
|
|
292
|
-
}
|
|
293
|
-
isInteractive() {
|
|
294
|
-
return Boolean(process.stdin.isTTY && process.stdout.isTTY);
|
|
295
|
-
}
|
|
296
|
-
}
|
|
297
|
-
//# sourceMappingURL=plan.js.map
|
|
@@ -1,24 +0,0 @@
|
|
|
1
|
-
import { Command } from '@oclif/core';
|
|
2
|
-
export default class Prd extends Command {
|
|
3
|
-
static description: string;
|
|
4
|
-
static examples: string[];
|
|
5
|
-
static flags: {
|
|
6
|
-
quick: import("@oclif/core/interfaces").BooleanFlag<boolean>;
|
|
7
|
-
project: import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
|
|
8
|
-
template: import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
|
|
9
|
-
};
|
|
10
|
-
run(): Promise<void>;
|
|
11
|
-
/**
|
|
12
|
-
* Derive a project name from the answers
|
|
13
|
-
*/
|
|
14
|
-
private deriveProjectName;
|
|
15
|
-
/**
|
|
16
|
-
* Auto-detect project tech stack from common config files
|
|
17
|
-
*/
|
|
18
|
-
private detectProjectTechStack;
|
|
19
|
-
/**
|
|
20
|
-
* Validate the generated quick-prd.md for AI consumption quality
|
|
21
|
-
*/
|
|
22
|
-
private validatePrdQuality;
|
|
23
|
-
}
|
|
24
|
-
//# sourceMappingURL=prd.d.ts.map
|