clavix 4.11.2 → 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 +72 -60
- package/dist/cli/commands/update.js +9 -10
- package/dist/templates/agents/agents.md +14 -8
- package/dist/templates/agents/copilot-instructions.md +1 -1
- package/dist/templates/instructions/core/verification.md +2 -2
- 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 +14 -53
- package/dist/templates/slash-commands/_canonical/start.md +1 -1
- package/dist/templates/slash-commands/_canonical/summarize.md +8 -8
- 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/agent-protocols/state-assertion.md +1 -1
- package/dist/templates/slash-commands/_components/references/intent-types.md +1 -1
- package/dist/templates/slash-commands/_components/sections/file-saving-protocol.md +20 -27
- package/dist/templates/slash-commands/_components/sections/pattern-visibility.md +29 -46
- package/dist/templates/slash-commands/_components/troubleshooting/file-not-saved.md +4 -5
- package/dist/types/config.d.ts +57 -0
- package/dist/utils/legacy-command-cleanup.js +31 -4
- package/package.json +5 -4
- 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 -339
- 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 -51
- package/dist/core/intelligence/quality-assessor.js +0 -505
- 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 -84
- package/dist/core/intelligence/universal-optimizer.js +0 -371
- 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,173 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* PrdGenerator - Generates Product Requirements Documents from collected answers
|
|
3
|
-
*
|
|
4
|
-
* This class handles:
|
|
5
|
-
* - Template loading and rendering with Handlebars
|
|
6
|
-
* - Project name extraction
|
|
7
|
-
* - File generation (full PRD and quick PRD)
|
|
8
|
-
* - Output organization and timestamps
|
|
9
|
-
*/
|
|
10
|
-
import fs from 'fs-extra';
|
|
11
|
-
import * as path from 'path';
|
|
12
|
-
import { fileURLToPath } from 'url';
|
|
13
|
-
import { dirname } from 'path';
|
|
14
|
-
import Handlebars from 'handlebars';
|
|
15
|
-
import { FileSystem } from '../utils/file-system.js';
|
|
16
|
-
const __filename = fileURLToPath(import.meta.url);
|
|
17
|
-
const __dirname = dirname(__filename);
|
|
18
|
-
/**
|
|
19
|
-
* PrdGenerator class
|
|
20
|
-
*
|
|
21
|
-
* Generates comprehensive and quick-reference PRD documents
|
|
22
|
-
* from collected question answers
|
|
23
|
-
*/
|
|
24
|
-
export class PrdGenerator {
|
|
25
|
-
templatesDir;
|
|
26
|
-
defaultOutputDir = '.clavix/outputs';
|
|
27
|
-
constructor() {
|
|
28
|
-
// Templates are in src/templates (or dist/templates when built)
|
|
29
|
-
this.templatesDir = path.join(__dirname, '../templates');
|
|
30
|
-
}
|
|
31
|
-
/**
|
|
32
|
-
* Generate PRD documents from answers
|
|
33
|
-
*
|
|
34
|
-
* @param answers - Collected answers from QuestionEngine
|
|
35
|
-
* @param options - Generation options
|
|
36
|
-
* @returns Path to the output directory
|
|
37
|
-
*/
|
|
38
|
-
async generate(answers, options = {}) {
|
|
39
|
-
const projectName = options.projectName || this.extractProjectName(answers);
|
|
40
|
-
const outputDir = options.outputDir || this.defaultOutputDir;
|
|
41
|
-
const timestamp = options.timestamp || new Date();
|
|
42
|
-
// Create output directory
|
|
43
|
-
const projectDir = path.join(outputDir, this.sanitizeProjectName(projectName));
|
|
44
|
-
await FileSystem.ensureDir(projectDir);
|
|
45
|
-
// Prepare template data
|
|
46
|
-
const metadata = {
|
|
47
|
-
generatedAt: timestamp.toISOString(),
|
|
48
|
-
generatedBy: 'Clavix PRD Generator',
|
|
49
|
-
projectName,
|
|
50
|
-
version: '1.0.0',
|
|
51
|
-
};
|
|
52
|
-
const templateData = {
|
|
53
|
-
...this.prepareAnswersForTemplate(answers),
|
|
54
|
-
metadata,
|
|
55
|
-
timestamp: this.formatTimestamp(timestamp),
|
|
56
|
-
};
|
|
57
|
-
// Generate full PRD
|
|
58
|
-
const fullPrdPath = path.join(projectDir, 'full-prd.md');
|
|
59
|
-
await this.generateFullPrd(templateData, fullPrdPath);
|
|
60
|
-
// Generate quick PRD
|
|
61
|
-
const quickPrdPath = path.join(projectDir, 'quick-prd.md');
|
|
62
|
-
await this.generateQuickPrd(templateData, quickPrdPath);
|
|
63
|
-
return projectDir;
|
|
64
|
-
}
|
|
65
|
-
/**
|
|
66
|
-
* Extract project name from answers
|
|
67
|
-
*
|
|
68
|
-
* Tries to infer a project name from the problem statement or user responses
|
|
69
|
-
*/
|
|
70
|
-
extractProjectName(answers) {
|
|
71
|
-
// Try to find a project name in the answers
|
|
72
|
-
// Look in common question answers like "problem", "name", "title"
|
|
73
|
-
const possibleNameFields = ['projectName', 'name', 'title', 'q1', 'problem'];
|
|
74
|
-
for (const field of possibleNameFields) {
|
|
75
|
-
if (answers[field] && typeof answers[field] === 'string') {
|
|
76
|
-
const extracted = this.extractNameFromText(answers[field]);
|
|
77
|
-
if (extracted) {
|
|
78
|
-
return extracted;
|
|
79
|
-
}
|
|
80
|
-
}
|
|
81
|
-
}
|
|
82
|
-
// Default to timestamp-based name
|
|
83
|
-
return `project-${Date.now()}`;
|
|
84
|
-
}
|
|
85
|
-
/**
|
|
86
|
-
* Extract a concise name from text (e.g., from problem statement)
|
|
87
|
-
*/
|
|
88
|
-
extractNameFromText(text) {
|
|
89
|
-
// Take first few words, clean up, and create a name
|
|
90
|
-
const words = text
|
|
91
|
-
.split(/\s+/)
|
|
92
|
-
.slice(0, 4)
|
|
93
|
-
.map((w) => w.toLowerCase())
|
|
94
|
-
.filter((w) => w.length > 2);
|
|
95
|
-
if (words.length === 0) {
|
|
96
|
-
return null;
|
|
97
|
-
}
|
|
98
|
-
return words.join('-').replace(/[^a-z0-9-]/g, '');
|
|
99
|
-
}
|
|
100
|
-
/**
|
|
101
|
-
* Sanitize project name for use as directory name
|
|
102
|
-
*/
|
|
103
|
-
sanitizeProjectName(name) {
|
|
104
|
-
return name
|
|
105
|
-
.toLowerCase()
|
|
106
|
-
.replace(/[^a-z0-9-]/g, '-')
|
|
107
|
-
.replace(/-+/g, '-')
|
|
108
|
-
.replace(/^-|-$/g, '')
|
|
109
|
-
.substring(0, 50);
|
|
110
|
-
}
|
|
111
|
-
/**
|
|
112
|
-
* Prepare answers for template rendering
|
|
113
|
-
*/
|
|
114
|
-
prepareAnswersForTemplate(answers) {
|
|
115
|
-
const prepared = {};
|
|
116
|
-
// Map question IDs to friendly names (updated for CLEAR-optimized 5-question flow)
|
|
117
|
-
const questionMap = {
|
|
118
|
-
q1: 'problem', // What are we building and why?
|
|
119
|
-
q2: 'features', // Core features
|
|
120
|
-
q3: 'technical', // Tech stack (optional, smart-detected)
|
|
121
|
-
q4: 'outOfScope', // Out of scope
|
|
122
|
-
q5: 'additional', // Additional context (optional)
|
|
123
|
-
};
|
|
124
|
-
for (const [questionId, value] of Object.entries(answers)) {
|
|
125
|
-
const friendlyName = questionMap[questionId] || questionId;
|
|
126
|
-
prepared[friendlyName] = value;
|
|
127
|
-
}
|
|
128
|
-
return prepared;
|
|
129
|
-
}
|
|
130
|
-
/**
|
|
131
|
-
* Generate full PRD document
|
|
132
|
-
*/
|
|
133
|
-
async generateFullPrd(data, outputPath) {
|
|
134
|
-
const templatePath = path.join(this.templatesDir, 'full-prd-template.hbs');
|
|
135
|
-
// Check if custom template exists
|
|
136
|
-
const customTemplatePath = '.clavix/templates/full-prd-template.hbs';
|
|
137
|
-
const templateToUse = await fs.pathExists(customTemplatePath)
|
|
138
|
-
? customTemplatePath
|
|
139
|
-
: templatePath;
|
|
140
|
-
const template = await fs.readFile(templateToUse, 'utf-8');
|
|
141
|
-
const compiled = Handlebars.compile(template);
|
|
142
|
-
const rendered = compiled(data);
|
|
143
|
-
await FileSystem.writeFileAtomic(outputPath, rendered);
|
|
144
|
-
}
|
|
145
|
-
/**
|
|
146
|
-
* Generate quick PRD document
|
|
147
|
-
*/
|
|
148
|
-
async generateQuickPrd(data, outputPath) {
|
|
149
|
-
const templatePath = path.join(this.templatesDir, 'quick-prd-template.hbs');
|
|
150
|
-
// Check if custom template exists
|
|
151
|
-
const customTemplatePath = '.clavix/templates/quick-prd-template.hbs';
|
|
152
|
-
const templateToUse = await fs.pathExists(customTemplatePath)
|
|
153
|
-
? customTemplatePath
|
|
154
|
-
: templatePath;
|
|
155
|
-
const template = await fs.readFile(templateToUse, 'utf-8');
|
|
156
|
-
const compiled = Handlebars.compile(template);
|
|
157
|
-
const rendered = compiled(data);
|
|
158
|
-
await FileSystem.writeFileAtomic(outputPath, rendered);
|
|
159
|
-
}
|
|
160
|
-
/**
|
|
161
|
-
* Format timestamp for display
|
|
162
|
-
*/
|
|
163
|
-
formatTimestamp(date) {
|
|
164
|
-
return date.toLocaleString('en-US', {
|
|
165
|
-
year: 'numeric',
|
|
166
|
-
month: 'long',
|
|
167
|
-
day: 'numeric',
|
|
168
|
-
hour: '2-digit',
|
|
169
|
-
minute: '2-digit',
|
|
170
|
-
});
|
|
171
|
-
}
|
|
172
|
-
}
|
|
173
|
-
//# sourceMappingURL=prd-generator.js.map
|
|
@@ -1,110 +0,0 @@
|
|
|
1
|
-
import { DepthLevel } from './intelligence/types.js';
|
|
2
|
-
/**
|
|
3
|
-
* v4.11: Unified prompt metadata
|
|
4
|
-
* Replaces separate fast/deep storage with single directory and depthUsed field
|
|
5
|
-
*/
|
|
6
|
-
export interface PromptMetadata {
|
|
7
|
-
id: string;
|
|
8
|
-
filename: string;
|
|
9
|
-
depthUsed: DepthLevel;
|
|
10
|
-
timestamp: string;
|
|
11
|
-
createdAt: Date;
|
|
12
|
-
path: string;
|
|
13
|
-
originalPrompt: string;
|
|
14
|
-
executed: boolean;
|
|
15
|
-
executedAt: string | null;
|
|
16
|
-
ageInDays?: number;
|
|
17
|
-
linkedProject?: string;
|
|
18
|
-
verificationRequired: boolean;
|
|
19
|
-
verified: boolean;
|
|
20
|
-
verifiedAt: string | null;
|
|
21
|
-
}
|
|
22
|
-
export interface PromptsIndex {
|
|
23
|
-
version: string;
|
|
24
|
-
prompts: PromptMetadata[];
|
|
25
|
-
}
|
|
26
|
-
export interface PromptData {
|
|
27
|
-
metadata: PromptMetadata;
|
|
28
|
-
content: string;
|
|
29
|
-
}
|
|
30
|
-
export interface PromptFilters {
|
|
31
|
-
depthUsed?: DepthLevel;
|
|
32
|
-
executed?: boolean;
|
|
33
|
-
stale?: boolean;
|
|
34
|
-
old?: boolean;
|
|
35
|
-
}
|
|
36
|
-
export interface StorageStats {
|
|
37
|
-
totalPrompts: number;
|
|
38
|
-
standardPrompts: number;
|
|
39
|
-
comprehensivePrompts: number;
|
|
40
|
-
executedPrompts: number;
|
|
41
|
-
pendingPrompts: number;
|
|
42
|
-
stalePrompts: number;
|
|
43
|
-
oldPrompts: number;
|
|
44
|
-
oldestPromptAge: number;
|
|
45
|
-
}
|
|
46
|
-
export declare class PromptManager {
|
|
47
|
-
private readonly promptsDir;
|
|
48
|
-
constructor(baseDir?: string);
|
|
49
|
-
/**
|
|
50
|
-
* v4.11: Get unified index file path
|
|
51
|
-
*/
|
|
52
|
-
private getIndexPath;
|
|
53
|
-
/**
|
|
54
|
-
* v4.11: Ensure prompts directory exists (single directory)
|
|
55
|
-
*/
|
|
56
|
-
ensurePromptsDir(): Promise<void>;
|
|
57
|
-
/**
|
|
58
|
-
* v4.11: Generate unique prompt ID with depth and timestamp
|
|
59
|
-
*/
|
|
60
|
-
generatePromptId(depthLevel: DepthLevel, _originalPrompt: string): string;
|
|
61
|
-
/**
|
|
62
|
-
* v4.11: Save optimized prompt to file system
|
|
63
|
-
*/
|
|
64
|
-
savePrompt(content: string, depthUsed: DepthLevel, originalPrompt: string, linkedProject?: string): Promise<PromptMetadata>;
|
|
65
|
-
/**
|
|
66
|
-
* v4.11: Load prompt by ID
|
|
67
|
-
*/
|
|
68
|
-
loadPrompt(id: string): Promise<PromptData | null>;
|
|
69
|
-
/**
|
|
70
|
-
* v4.11: List prompts with optional filtering
|
|
71
|
-
*/
|
|
72
|
-
listPrompts(filters?: PromptFilters): Promise<PromptMetadata[]>;
|
|
73
|
-
/**
|
|
74
|
-
* v4.11: Mark prompt as executed
|
|
75
|
-
*/
|
|
76
|
-
markExecuted(id: string): Promise<void>;
|
|
77
|
-
/**
|
|
78
|
-
* v4.11: Mark prompt as verified (v4.8)
|
|
79
|
-
*/
|
|
80
|
-
markVerified(id: string): Promise<void>;
|
|
81
|
-
/**
|
|
82
|
-
* v4.11: Delete prompts by filter
|
|
83
|
-
*/
|
|
84
|
-
deletePrompts(filters: PromptFilters): Promise<number>;
|
|
85
|
-
/**
|
|
86
|
-
* Get age of prompt in days
|
|
87
|
-
*/
|
|
88
|
-
getPromptAge(prompt: PromptMetadata): number;
|
|
89
|
-
/**
|
|
90
|
-
* Get stale prompts (>30 days old)
|
|
91
|
-
*/
|
|
92
|
-
getStalePrompts(_daysOld?: number): Promise<PromptMetadata[]>;
|
|
93
|
-
/**
|
|
94
|
-
* v4.11: Get storage statistics
|
|
95
|
-
*/
|
|
96
|
-
getStorageStats(): Promise<StorageStats>;
|
|
97
|
-
/**
|
|
98
|
-
* v4.11: Load unified index from file
|
|
99
|
-
*/
|
|
100
|
-
private loadIndex;
|
|
101
|
-
/**
|
|
102
|
-
* v4.11: Save unified index to file
|
|
103
|
-
*/
|
|
104
|
-
private saveIndex;
|
|
105
|
-
/**
|
|
106
|
-
* v4.11: Add prompt to unified index
|
|
107
|
-
*/
|
|
108
|
-
private addToIndex;
|
|
109
|
-
}
|
|
110
|
-
//# sourceMappingURL=prompt-manager.d.ts.map
|
|
@@ -1,274 +0,0 @@
|
|
|
1
|
-
import fs from 'fs-extra';
|
|
2
|
-
import * as path from 'path';
|
|
3
|
-
import { v4 as uuidv4 } from 'uuid';
|
|
4
|
-
export class PromptManager {
|
|
5
|
-
promptsDir;
|
|
6
|
-
constructor(baseDir) {
|
|
7
|
-
// v4.11: Single prompts directory (no fast/deep subdirs)
|
|
8
|
-
if (baseDir) {
|
|
9
|
-
this.promptsDir = baseDir.endsWith('prompts') ? baseDir : path.join(baseDir, 'prompts');
|
|
10
|
-
}
|
|
11
|
-
else {
|
|
12
|
-
this.promptsDir = path.join(process.cwd(), '.clavix', 'outputs', 'prompts');
|
|
13
|
-
}
|
|
14
|
-
}
|
|
15
|
-
/**
|
|
16
|
-
* v4.11: Get unified index file path
|
|
17
|
-
*/
|
|
18
|
-
getIndexPath() {
|
|
19
|
-
return path.join(this.promptsDir, '.index.json');
|
|
20
|
-
}
|
|
21
|
-
/**
|
|
22
|
-
* v4.11: Ensure prompts directory exists (single directory)
|
|
23
|
-
*/
|
|
24
|
-
async ensurePromptsDir() {
|
|
25
|
-
await fs.ensureDir(this.promptsDir);
|
|
26
|
-
}
|
|
27
|
-
/**
|
|
28
|
-
* v4.11: Generate unique prompt ID with depth and timestamp
|
|
29
|
-
*/
|
|
30
|
-
generatePromptId(depthLevel, _originalPrompt) {
|
|
31
|
-
const timestamp = new Date().toISOString().replace(/[:.]/g, '-').split('T');
|
|
32
|
-
const date = timestamp[0].replace(/-/g, '');
|
|
33
|
-
const time = timestamp[1].split('-').slice(0, 3).join('');
|
|
34
|
-
// Use UUID for uniqueness (mockable for tests - first 13 chars for readability)
|
|
35
|
-
const hash = uuidv4().substring(0, 13);
|
|
36
|
-
// v4.11: Use depth level abbreviation in ID
|
|
37
|
-
const depthAbbrev = depthLevel === 'comprehensive' ? 'comp' : 'std';
|
|
38
|
-
return `${depthAbbrev}-${date}-${time}-${hash}`;
|
|
39
|
-
}
|
|
40
|
-
/**
|
|
41
|
-
* v4.11: Save optimized prompt to file system
|
|
42
|
-
*/
|
|
43
|
-
async savePrompt(content, depthUsed, originalPrompt, linkedProject) {
|
|
44
|
-
await this.ensurePromptsDir();
|
|
45
|
-
const id = this.generatePromptId(depthUsed, originalPrompt);
|
|
46
|
-
const filename = `${id}.md`;
|
|
47
|
-
// v4.11: Single directory, no subdirs
|
|
48
|
-
const filePath = path.join(this.promptsDir, filename);
|
|
49
|
-
const now = new Date();
|
|
50
|
-
const metadata = {
|
|
51
|
-
id,
|
|
52
|
-
filename,
|
|
53
|
-
depthUsed, // v4.11: Replaces 'source'
|
|
54
|
-
timestamp: now.toISOString(),
|
|
55
|
-
createdAt: now,
|
|
56
|
-
path: filePath,
|
|
57
|
-
originalPrompt,
|
|
58
|
-
executed: false,
|
|
59
|
-
executedAt: null,
|
|
60
|
-
linkedProject,
|
|
61
|
-
// Verification tracking (v4.8)
|
|
62
|
-
verificationRequired: true,
|
|
63
|
-
verified: false,
|
|
64
|
-
verifiedAt: null,
|
|
65
|
-
};
|
|
66
|
-
// Create file with frontmatter
|
|
67
|
-
const frontmatter = [
|
|
68
|
-
'---',
|
|
69
|
-
`id: ${id}`,
|
|
70
|
-
`depthUsed: ${depthUsed}`,
|
|
71
|
-
`timestamp: ${metadata.timestamp}`,
|
|
72
|
-
`executed: ${metadata.executed}`,
|
|
73
|
-
`originalPrompt: ${originalPrompt}`,
|
|
74
|
-
linkedProject ? `linkedProject: ${linkedProject}` : '',
|
|
75
|
-
`verificationRequired: ${metadata.verificationRequired}`,
|
|
76
|
-
`verified: ${metadata.verified}`,
|
|
77
|
-
'---',
|
|
78
|
-
'',
|
|
79
|
-
]
|
|
80
|
-
.filter(Boolean)
|
|
81
|
-
.join('\n');
|
|
82
|
-
const fileContent = frontmatter + content;
|
|
83
|
-
await fs.writeFile(filePath, fileContent, 'utf-8');
|
|
84
|
-
// Update index
|
|
85
|
-
await this.addToIndex(metadata);
|
|
86
|
-
return metadata;
|
|
87
|
-
}
|
|
88
|
-
/**
|
|
89
|
-
* v4.11: Load prompt by ID
|
|
90
|
-
*/
|
|
91
|
-
async loadPrompt(id) {
|
|
92
|
-
const index = await this.loadIndex();
|
|
93
|
-
const metadata = index.prompts.find((p) => p.id === id);
|
|
94
|
-
if (!metadata) {
|
|
95
|
-
return null;
|
|
96
|
-
}
|
|
97
|
-
// v4.11: Single directory - no subdirs
|
|
98
|
-
const filePath = path.join(this.promptsDir, metadata.filename);
|
|
99
|
-
if (!(await fs.pathExists(filePath))) {
|
|
100
|
-
return null;
|
|
101
|
-
}
|
|
102
|
-
const content = await fs.readFile(filePath, 'utf-8');
|
|
103
|
-
// Strip frontmatter for clean content
|
|
104
|
-
const contentWithoutFrontmatter = content.replace(/^---\n[\s\S]*?\n---\n*/, '');
|
|
105
|
-
return {
|
|
106
|
-
metadata,
|
|
107
|
-
content: contentWithoutFrontmatter,
|
|
108
|
-
};
|
|
109
|
-
}
|
|
110
|
-
/**
|
|
111
|
-
* v4.11: List prompts with optional filtering
|
|
112
|
-
*/
|
|
113
|
-
async listPrompts(filters) {
|
|
114
|
-
const index = await this.loadIndex();
|
|
115
|
-
let prompts = index.prompts;
|
|
116
|
-
// Apply filters
|
|
117
|
-
if (filters) {
|
|
118
|
-
// v4.11: Filter by depth level
|
|
119
|
-
if (filters.depthUsed) {
|
|
120
|
-
prompts = prompts.filter((p) => p.depthUsed === filters.depthUsed);
|
|
121
|
-
}
|
|
122
|
-
if (filters.executed !== undefined) {
|
|
123
|
-
prompts = prompts.filter((p) => p.executed === filters.executed);
|
|
124
|
-
}
|
|
125
|
-
if (filters.stale) {
|
|
126
|
-
prompts = prompts.filter((p) => this.getPromptAge(p) > 30);
|
|
127
|
-
}
|
|
128
|
-
if (filters.old) {
|
|
129
|
-
prompts = prompts.filter((p) => this.getPromptAge(p) > 7);
|
|
130
|
-
}
|
|
131
|
-
}
|
|
132
|
-
// Add age calculation
|
|
133
|
-
prompts = prompts.map((p) => ({
|
|
134
|
-
...p,
|
|
135
|
-
createdAt: new Date(p.timestamp),
|
|
136
|
-
ageInDays: this.getPromptAge(p),
|
|
137
|
-
}));
|
|
138
|
-
// Sort by timestamp (newest first)
|
|
139
|
-
prompts.sort((a, b) => {
|
|
140
|
-
return new Date(b.timestamp).getTime() - new Date(a.timestamp).getTime();
|
|
141
|
-
});
|
|
142
|
-
return prompts;
|
|
143
|
-
}
|
|
144
|
-
/**
|
|
145
|
-
* v4.11: Mark prompt as executed
|
|
146
|
-
*/
|
|
147
|
-
async markExecuted(id) {
|
|
148
|
-
const index = await this.loadIndex();
|
|
149
|
-
const indexPrompt = index.prompts.find((p) => p.id === id);
|
|
150
|
-
if (!indexPrompt) {
|
|
151
|
-
throw new Error(`Prompt not found: ${id}`);
|
|
152
|
-
}
|
|
153
|
-
indexPrompt.executed = true;
|
|
154
|
-
indexPrompt.executedAt = new Date().toISOString();
|
|
155
|
-
await this.saveIndex(index);
|
|
156
|
-
}
|
|
157
|
-
/**
|
|
158
|
-
* v4.11: Mark prompt as verified (v4.8)
|
|
159
|
-
*/
|
|
160
|
-
async markVerified(id) {
|
|
161
|
-
const index = await this.loadIndex();
|
|
162
|
-
const indexPrompt = index.prompts.find((p) => p.id === id);
|
|
163
|
-
if (!indexPrompt) {
|
|
164
|
-
throw new Error(`Prompt not found: ${id}`);
|
|
165
|
-
}
|
|
166
|
-
indexPrompt.verified = true;
|
|
167
|
-
indexPrompt.verifiedAt = new Date().toISOString();
|
|
168
|
-
await this.saveIndex(index);
|
|
169
|
-
}
|
|
170
|
-
/**
|
|
171
|
-
* v4.11: Delete prompts by filter
|
|
172
|
-
*/
|
|
173
|
-
async deletePrompts(filters) {
|
|
174
|
-
const toDelete = await this.listPrompts(filters);
|
|
175
|
-
let deleteCount = 0;
|
|
176
|
-
const deletedIds = new Set();
|
|
177
|
-
for (const prompt of toDelete) {
|
|
178
|
-
// v4.11: Single directory - no subdirs
|
|
179
|
-
const filePath = path.join(this.promptsDir, prompt.filename);
|
|
180
|
-
if (await fs.pathExists(filePath)) {
|
|
181
|
-
await fs.remove(filePath);
|
|
182
|
-
deleteCount++;
|
|
183
|
-
deletedIds.add(prompt.id);
|
|
184
|
-
}
|
|
185
|
-
}
|
|
186
|
-
// Update unified index
|
|
187
|
-
if (deletedIds.size > 0) {
|
|
188
|
-
const index = await this.loadIndex();
|
|
189
|
-
index.prompts = index.prompts.filter((p) => !deletedIds.has(p.id));
|
|
190
|
-
await this.saveIndex(index);
|
|
191
|
-
}
|
|
192
|
-
return deleteCount;
|
|
193
|
-
}
|
|
194
|
-
/**
|
|
195
|
-
* Get age of prompt in days
|
|
196
|
-
*/
|
|
197
|
-
getPromptAge(prompt) {
|
|
198
|
-
const created = new Date(prompt.timestamp);
|
|
199
|
-
const now = new Date();
|
|
200
|
-
const diffMs = now.getTime() - created.getTime();
|
|
201
|
-
return Math.floor(diffMs / (1000 * 60 * 60 * 24));
|
|
202
|
-
}
|
|
203
|
-
/**
|
|
204
|
-
* Get stale prompts (>30 days old)
|
|
205
|
-
*/
|
|
206
|
-
async getStalePrompts(_daysOld = 30) {
|
|
207
|
-
return this.listPrompts({ stale: true });
|
|
208
|
-
}
|
|
209
|
-
/**
|
|
210
|
-
* v4.11: Get storage statistics
|
|
211
|
-
*/
|
|
212
|
-
async getStorageStats() {
|
|
213
|
-
const allPrompts = await this.listPrompts();
|
|
214
|
-
const stats = {
|
|
215
|
-
totalPrompts: allPrompts.length,
|
|
216
|
-
standardPrompts: allPrompts.filter((p) => p.depthUsed === 'standard').length,
|
|
217
|
-
comprehensivePrompts: allPrompts.filter((p) => p.depthUsed === 'comprehensive').length,
|
|
218
|
-
executedPrompts: allPrompts.filter((p) => p.executed).length,
|
|
219
|
-
pendingPrompts: allPrompts.filter((p) => !p.executed).length,
|
|
220
|
-
stalePrompts: allPrompts.filter((p) => (p.ageInDays || 0) > 30).length,
|
|
221
|
-
oldPrompts: allPrompts.filter((p) => (p.ageInDays || 0) > 7).length,
|
|
222
|
-
oldestPromptAge: allPrompts.length > 0 ? Math.max(...allPrompts.map((p) => p.ageInDays || 0)) : 0,
|
|
223
|
-
};
|
|
224
|
-
return stats;
|
|
225
|
-
}
|
|
226
|
-
/**
|
|
227
|
-
* v4.11: Load unified index from file
|
|
228
|
-
*/
|
|
229
|
-
async loadIndex() {
|
|
230
|
-
const indexPath = this.getIndexPath();
|
|
231
|
-
if (!(await fs.pathExists(indexPath))) {
|
|
232
|
-
return {
|
|
233
|
-
version: '2.0', // v4.11: New version for unified index
|
|
234
|
-
prompts: [],
|
|
235
|
-
};
|
|
236
|
-
}
|
|
237
|
-
try {
|
|
238
|
-
const content = await fs.readFile(indexPath, 'utf-8');
|
|
239
|
-
const parsed = JSON.parse(content);
|
|
240
|
-
// Ensure prompts array exists
|
|
241
|
-
return {
|
|
242
|
-
version: parsed.version || '2.0',
|
|
243
|
-
prompts: Array.isArray(parsed.prompts) ? parsed.prompts : [],
|
|
244
|
-
};
|
|
245
|
-
}
|
|
246
|
-
catch {
|
|
247
|
-
// Corrupt index, return empty
|
|
248
|
-
return {
|
|
249
|
-
version: '2.0',
|
|
250
|
-
prompts: [],
|
|
251
|
-
};
|
|
252
|
-
}
|
|
253
|
-
}
|
|
254
|
-
/**
|
|
255
|
-
* v4.11: Save unified index to file
|
|
256
|
-
*/
|
|
257
|
-
async saveIndex(index) {
|
|
258
|
-
const indexPath = this.getIndexPath();
|
|
259
|
-
await fs.ensureDir(path.dirname(indexPath));
|
|
260
|
-
await fs.writeFile(indexPath, JSON.stringify(index, null, 2), 'utf-8');
|
|
261
|
-
}
|
|
262
|
-
/**
|
|
263
|
-
* v4.11: Add prompt to unified index
|
|
264
|
-
*/
|
|
265
|
-
async addToIndex(metadata) {
|
|
266
|
-
const index = await this.loadIndex();
|
|
267
|
-
// Remove any existing entry with same ID (shouldn't happen, but be safe)
|
|
268
|
-
index.prompts = index.prompts.filter((p) => p.id !== metadata.id);
|
|
269
|
-
// Add new entry
|
|
270
|
-
index.prompts.push(metadata);
|
|
271
|
-
await this.saveIndex(index);
|
|
272
|
-
}
|
|
273
|
-
}
|
|
274
|
-
//# sourceMappingURL=prompt-manager.js.map
|