clavix 7.2.2 → 7.3.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/dist/clean/cleaner.d.ts +56 -0
- package/dist/clean/cleaner.js +266 -0
- package/dist/clean/discovery.d.ts +68 -0
- package/dist/clean/discovery.js +351 -0
- package/dist/clean/guards.d.ts +56 -0
- package/dist/clean/guards.js +182 -0
- package/dist/clean/prompts.d.ts +67 -0
- package/dist/clean/prompts.js +203 -0
- package/dist/clean/scanner.d.ts +54 -0
- package/dist/clean/scanner.js +174 -0
- package/dist/clean/types.d.ts +28 -0
- package/dist/clean/types.js +15 -0
- package/dist/cli/commands/clean.d.ts +13 -0
- package/dist/cli/commands/clean.js +118 -0
- package/dist/templates/skills/improve.md +52 -20
- package/dist/templates/slash-commands/_canonical/archive.md +1 -1
- package/dist/templates/slash-commands/_canonical/implement.md +1 -1
- package/dist/templates/slash-commands/_canonical/improve.md +1 -1
- package/dist/templates/slash-commands/_canonical/plan.md +1 -1
- package/dist/templates/slash-commands/_canonical/prd.md +1 -1
- package/dist/templates/slash-commands/_canonical/refine.md +1 -1
- package/dist/templates/slash-commands/_canonical/review.md +1 -1
- package/dist/templates/slash-commands/_canonical/start.md +1 -1
- package/dist/templates/slash-commands/_canonical/summarize.md +1 -1
- package/dist/templates/slash-commands/_canonical/verify.md +1 -1
- package/dist/utils/schemas.d.ts +32 -32
- package/package.json +1 -1
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Cleaner module for executing deletions with safety guards
|
|
3
|
+
*/
|
|
4
|
+
import type { BatchInfo, CleanResult } from './types.js';
|
|
5
|
+
/**
|
|
6
|
+
* Cleaner class for executing deletions safely
|
|
7
|
+
*/
|
|
8
|
+
export declare class Cleaner {
|
|
9
|
+
/**
|
|
10
|
+
* Clean a batch of targets
|
|
11
|
+
* @param batch - The batch information with targets to delete
|
|
12
|
+
* @param dryRun - If true, only simulate deletions
|
|
13
|
+
* @returns CleanResult with statistics
|
|
14
|
+
*/
|
|
15
|
+
static cleanBatch(batch: BatchInfo, dryRun?: boolean): Promise<CleanResult>;
|
|
16
|
+
/**
|
|
17
|
+
* Clean all global Clavix artifacts
|
|
18
|
+
* @param dryRun - If true, only simulate deletions
|
|
19
|
+
* @returns CleanResult with statistics
|
|
20
|
+
*/
|
|
21
|
+
static cleanGlobal(dryRun?: boolean): Promise<CleanResult>;
|
|
22
|
+
/**
|
|
23
|
+
* Clean global integrations from config
|
|
24
|
+
*/
|
|
25
|
+
private static cleanGlobalIntegrations;
|
|
26
|
+
/**
|
|
27
|
+
* Clean files matching a specific integration pattern
|
|
28
|
+
*/
|
|
29
|
+
private static cleanPattern;
|
|
30
|
+
/**
|
|
31
|
+
* Clean files matching a glob pattern
|
|
32
|
+
* @param pattern - Glob pattern with ~ support
|
|
33
|
+
* @param result - Result object to update
|
|
34
|
+
* @param dryRun - If true, only simulate deletions
|
|
35
|
+
*/
|
|
36
|
+
private static cleanGlob;
|
|
37
|
+
/**
|
|
38
|
+
* Clean a specific directory
|
|
39
|
+
* @param dirPath - Directory path with ~ support
|
|
40
|
+
* @param result - Result object to update
|
|
41
|
+
* @param dryRun - If true, only simulate deletions
|
|
42
|
+
*/
|
|
43
|
+
private static cleanDirectory;
|
|
44
|
+
/**
|
|
45
|
+
* Clean orphaned backup files created by DocInjector
|
|
46
|
+
* @param dryRun - If true, only simulate deletions
|
|
47
|
+
*/
|
|
48
|
+
private static cleanBackups;
|
|
49
|
+
/**
|
|
50
|
+
* Recursively find and remove backup files
|
|
51
|
+
* @param dirPath - Directory to search
|
|
52
|
+
* @param dryRun - If true, only simulate deletions
|
|
53
|
+
*/
|
|
54
|
+
private static findAndRemoveBackups;
|
|
55
|
+
}
|
|
56
|
+
//# sourceMappingURL=cleaner.d.ts.map
|
|
@@ -0,0 +1,266 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Cleaner module for executing deletions with safety guards
|
|
3
|
+
*/
|
|
4
|
+
import path from 'node:path';
|
|
5
|
+
import os from 'node:os';
|
|
6
|
+
import { DocInjector } from '../core/doc-injector.js';
|
|
7
|
+
import { FileSystem } from '../utils/file-system.js';
|
|
8
|
+
import { CLAVIX_BLOCK_START, CLAVIX_BLOCK_END } from '../constants.js';
|
|
9
|
+
import { Discovery } from './discovery.js';
|
|
10
|
+
/**
|
|
11
|
+
* Cleaner class for executing deletions safely
|
|
12
|
+
*/
|
|
13
|
+
export class Cleaner {
|
|
14
|
+
/**
|
|
15
|
+
* Clean a batch of targets
|
|
16
|
+
* @param batch - The batch information with targets to delete
|
|
17
|
+
* @param dryRun - If true, only simulate deletions
|
|
18
|
+
* @returns CleanResult with statistics
|
|
19
|
+
*/
|
|
20
|
+
static async cleanBatch(batch, dryRun = false) {
|
|
21
|
+
const result = { deleted: 0, skipped: 0, errors: [] };
|
|
22
|
+
for (const target of batch.targets) {
|
|
23
|
+
try {
|
|
24
|
+
const fullPath = path.resolve(batch.location, target.path);
|
|
25
|
+
if (dryRun) {
|
|
26
|
+
result.skipped++;
|
|
27
|
+
continue;
|
|
28
|
+
}
|
|
29
|
+
if (target.type === 'directory') {
|
|
30
|
+
// Remove directory recursively
|
|
31
|
+
await FileSystem.remove(fullPath);
|
|
32
|
+
result.deleted++;
|
|
33
|
+
}
|
|
34
|
+
else if (target.type === 'file') {
|
|
35
|
+
// Remove file
|
|
36
|
+
await FileSystem.remove(fullPath);
|
|
37
|
+
result.deleted++;
|
|
38
|
+
}
|
|
39
|
+
else if (target.type === 'block') {
|
|
40
|
+
// Remove managed block from file
|
|
41
|
+
await DocInjector.removeBlock(fullPath, CLAVIX_BLOCK_START, CLAVIX_BLOCK_END);
|
|
42
|
+
result.deleted++;
|
|
43
|
+
// Also try to remove any backup files
|
|
44
|
+
const backupPath = `${fullPath}.backup`;
|
|
45
|
+
if (await FileSystem.exists(backupPath)) {
|
|
46
|
+
await FileSystem.remove(backupPath);
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
catch (error) {
|
|
51
|
+
const errorMsg = error instanceof Error ? error.message : String(error);
|
|
52
|
+
result.errors.push(`${target.path}: ${errorMsg}`);
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
return result;
|
|
56
|
+
}
|
|
57
|
+
/**
|
|
58
|
+
* Clean all global Clavix artifacts
|
|
59
|
+
* @param dryRun - If true, only simulate deletions
|
|
60
|
+
* @returns CleanResult with statistics
|
|
61
|
+
*/
|
|
62
|
+
static async cleanGlobal(dryRun = false) {
|
|
63
|
+
const result = { deleted: 0, skipped: 0, errors: [] };
|
|
64
|
+
// 1. Clean agent skills
|
|
65
|
+
await this.cleanGlob('~/.config/agents/skills/clavix-*', result, dryRun);
|
|
66
|
+
// 2. Clean global integrations from config
|
|
67
|
+
await this.cleanGlobalIntegrations(result, dryRun);
|
|
68
|
+
// 3. Remove orphaned backup files
|
|
69
|
+
await this.cleanBackups(dryRun);
|
|
70
|
+
return result;
|
|
71
|
+
}
|
|
72
|
+
/**
|
|
73
|
+
* Clean global integrations from config
|
|
74
|
+
*/
|
|
75
|
+
static async cleanGlobalIntegrations(result, dryRun) {
|
|
76
|
+
// Load integration configs
|
|
77
|
+
const fs = await import('node:fs/promises');
|
|
78
|
+
const configPath = path.join(process.cwd(), 'src/config/integrations.json');
|
|
79
|
+
let integrations = [];
|
|
80
|
+
try {
|
|
81
|
+
const config = JSON.parse(await fs.readFile(configPath, 'utf-8'));
|
|
82
|
+
integrations = config.integrations || [];
|
|
83
|
+
}
|
|
84
|
+
catch {
|
|
85
|
+
return;
|
|
86
|
+
}
|
|
87
|
+
for (const integration of integrations) {
|
|
88
|
+
// Only process global integrations
|
|
89
|
+
if (!integration.global)
|
|
90
|
+
continue;
|
|
91
|
+
const targetPath = integration.directory.startsWith('~')
|
|
92
|
+
? integration.directory.replace('~', os.homedir())
|
|
93
|
+
: path.join(os.homedir(), integration.directory);
|
|
94
|
+
// Find and clean files matching pattern
|
|
95
|
+
await this.cleanPattern(targetPath, integration, result, dryRun);
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
/**
|
|
99
|
+
* Clean files matching a specific integration pattern
|
|
100
|
+
*/
|
|
101
|
+
static async cleanPattern(dirPath, integration, result, dryRun) {
|
|
102
|
+
const fs = await import('node:fs/promises');
|
|
103
|
+
try {
|
|
104
|
+
const dir = await fs.opendir(dirPath);
|
|
105
|
+
for await (const entry of dir) {
|
|
106
|
+
if (!entry.isFile())
|
|
107
|
+
continue;
|
|
108
|
+
if (Discovery.fileMatchesIntegration(entry.name, integration)) {
|
|
109
|
+
const fullPath = path.join(dirPath, entry.name);
|
|
110
|
+
if (dryRun) {
|
|
111
|
+
result.skipped++;
|
|
112
|
+
}
|
|
113
|
+
else {
|
|
114
|
+
await FileSystem.remove(fullPath);
|
|
115
|
+
result.deleted++;
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
catch {
|
|
121
|
+
// Directory doesn't exist
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
/**
|
|
125
|
+
* Clean files matching a glob pattern
|
|
126
|
+
* @param pattern - Glob pattern with ~ support
|
|
127
|
+
* @param result - Result object to update
|
|
128
|
+
* @param dryRun - If true, only simulate deletions
|
|
129
|
+
*/
|
|
130
|
+
static async cleanGlob(pattern, result, dryRun) {
|
|
131
|
+
const fs = await import('node:fs/promises');
|
|
132
|
+
const expandedPattern = pattern.startsWith('~') ? pattern.replace('~', os.homedir()) : pattern;
|
|
133
|
+
// For simple patterns, just check single file/directory
|
|
134
|
+
try {
|
|
135
|
+
const stats = await fs.stat(expandedPattern);
|
|
136
|
+
if (stats.isDirectory()) {
|
|
137
|
+
const files = await fs.readdir(expandedPattern);
|
|
138
|
+
for (const file of files) {
|
|
139
|
+
const fullPath = path.join(expandedPattern, file);
|
|
140
|
+
if (dryRun) {
|
|
141
|
+
result.skipped++;
|
|
142
|
+
}
|
|
143
|
+
else {
|
|
144
|
+
await FileSystem.remove(fullPath);
|
|
145
|
+
result.deleted++;
|
|
146
|
+
}
|
|
147
|
+
}
|
|
148
|
+
// Also remove the directory if it's empty
|
|
149
|
+
const remainingFiles = await fs.readdir(expandedPattern);
|
|
150
|
+
if (remainingFiles.length === 0 && !dryRun) {
|
|
151
|
+
await fs.rm(expandedPattern, { recursive: true, force: true });
|
|
152
|
+
}
|
|
153
|
+
}
|
|
154
|
+
else {
|
|
155
|
+
if (dryRun) {
|
|
156
|
+
result.skipped++;
|
|
157
|
+
}
|
|
158
|
+
else {
|
|
159
|
+
await FileSystem.remove(expandedPattern);
|
|
160
|
+
result.deleted++;
|
|
161
|
+
}
|
|
162
|
+
}
|
|
163
|
+
}
|
|
164
|
+
catch {
|
|
165
|
+
// Pattern doesn't exist, skip
|
|
166
|
+
}
|
|
167
|
+
// Also handle glob patterns (simplified - check for clavix-* matches)
|
|
168
|
+
if (pattern.includes('*')) {
|
|
169
|
+
const dirPattern = path.dirname(expandedPattern);
|
|
170
|
+
const filePattern = path.basename(expandedPattern.replace('*', ''));
|
|
171
|
+
try {
|
|
172
|
+
const files = await fs.readdir(dirPattern);
|
|
173
|
+
for (const file of files) {
|
|
174
|
+
if (file.startsWith(filePattern) && file !== filePattern) {
|
|
175
|
+
const fullPath = path.join(dirPattern, file);
|
|
176
|
+
if (dryRun) {
|
|
177
|
+
result.skipped++;
|
|
178
|
+
}
|
|
179
|
+
else {
|
|
180
|
+
await FileSystem.remove(fullPath);
|
|
181
|
+
result.deleted++;
|
|
182
|
+
}
|
|
183
|
+
}
|
|
184
|
+
}
|
|
185
|
+
}
|
|
186
|
+
catch {
|
|
187
|
+
// Directory doesn't exist
|
|
188
|
+
}
|
|
189
|
+
}
|
|
190
|
+
}
|
|
191
|
+
/**
|
|
192
|
+
* Clean a specific directory
|
|
193
|
+
* @param dirPath - Directory path with ~ support
|
|
194
|
+
* @param result - Result object to update
|
|
195
|
+
* @param dryRun - If true, only simulate deletions
|
|
196
|
+
*/
|
|
197
|
+
static async cleanDirectory(dirPath, result, dryRun) {
|
|
198
|
+
const fs = await import('node:fs/promises');
|
|
199
|
+
const expandedPath = dirPath.startsWith('~') ? dirPath.replace('~', os.homedir()) : dirPath;
|
|
200
|
+
try {
|
|
201
|
+
if (await FileSystem.exists(expandedPath)) {
|
|
202
|
+
// Count items first
|
|
203
|
+
const files = await fs.readdir(expandedPath);
|
|
204
|
+
const itemCount = files.length;
|
|
205
|
+
if (dryRun) {
|
|
206
|
+
result.skipped += itemCount;
|
|
207
|
+
return;
|
|
208
|
+
}
|
|
209
|
+
// Remove recursively
|
|
210
|
+
await FileSystem.remove(expandedPath);
|
|
211
|
+
result.deleted += itemCount;
|
|
212
|
+
}
|
|
213
|
+
}
|
|
214
|
+
catch (error) {
|
|
215
|
+
const errorMsg = error instanceof Error ? error.message : String(error);
|
|
216
|
+
result.errors.push(`${dirPath}: ${errorMsg}`);
|
|
217
|
+
}
|
|
218
|
+
}
|
|
219
|
+
/**
|
|
220
|
+
* Clean orphaned backup files created by DocInjector
|
|
221
|
+
* @param dryRun - If true, only simulate deletions
|
|
222
|
+
*/
|
|
223
|
+
static async cleanBackups(dryRun = false) {
|
|
224
|
+
const cleaned = 0;
|
|
225
|
+
// Check common project locations for backup files
|
|
226
|
+
const backupLocations = ['~/Documents', '~/Projects', '~/dev', '~/workspace'];
|
|
227
|
+
for (const location of backupLocations) {
|
|
228
|
+
const expandedDir = location.startsWith('~') ? location.replace('~', os.homedir()) : location;
|
|
229
|
+
try {
|
|
230
|
+
await this.findAndRemoveBackups(expandedDir, dryRun);
|
|
231
|
+
}
|
|
232
|
+
catch {
|
|
233
|
+
// Skip locations we can't access
|
|
234
|
+
}
|
|
235
|
+
}
|
|
236
|
+
return cleaned;
|
|
237
|
+
}
|
|
238
|
+
/**
|
|
239
|
+
* Recursively find and remove backup files
|
|
240
|
+
* @param dirPath - Directory to search
|
|
241
|
+
* @param dryRun - If true, only simulate deletions
|
|
242
|
+
*/
|
|
243
|
+
static async findAndRemoveBackups(dirPath, dryRun = false) {
|
|
244
|
+
const fs = await import('node:fs/promises');
|
|
245
|
+
try {
|
|
246
|
+
const entries = await fs.readdir(dirPath, { withFileTypes: true });
|
|
247
|
+
for (const entry of entries) {
|
|
248
|
+
const fullPath = path.join(dirPath, entry.name);
|
|
249
|
+
if (entry.isDirectory()) {
|
|
250
|
+
// Recurse into subdirectories
|
|
251
|
+
await this.findAndRemoveBackups(fullPath, dryRun);
|
|
252
|
+
}
|
|
253
|
+
else if (entry.name.endsWith('.backup')) {
|
|
254
|
+
// Remove backup file
|
|
255
|
+
if (!dryRun) {
|
|
256
|
+
await FileSystem.remove(fullPath);
|
|
257
|
+
}
|
|
258
|
+
}
|
|
259
|
+
}
|
|
260
|
+
}
|
|
261
|
+
catch {
|
|
262
|
+
// Skip directories we can't read
|
|
263
|
+
}
|
|
264
|
+
}
|
|
265
|
+
}
|
|
266
|
+
//# sourceMappingURL=cleaner.js.map
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Discovery module for finding Clavix artifacts
|
|
3
|
+
*/
|
|
4
|
+
import type { CleanTarget } from './types.js';
|
|
5
|
+
/**
|
|
6
|
+
* Discovery class for finding Clavix artifacts in a project
|
|
7
|
+
*/
|
|
8
|
+
export declare class Discovery {
|
|
9
|
+
/**
|
|
10
|
+
* Find all Clavix artifacts in a specific location
|
|
11
|
+
* @param rootPath - The root path to search
|
|
12
|
+
* @returns Array of CleanTarget objects
|
|
13
|
+
*/
|
|
14
|
+
static findArtifacts(rootPath: string): Promise<CleanTarget[]>;
|
|
15
|
+
/**
|
|
16
|
+
* Load integration configs from integrations.json
|
|
17
|
+
*/
|
|
18
|
+
private static loadIntegrations;
|
|
19
|
+
/**
|
|
20
|
+
* Find integration generated files dynamically
|
|
21
|
+
*/
|
|
22
|
+
private static findIntegrationArtifacts;
|
|
23
|
+
/**
|
|
24
|
+
* Find files matching integration pattern
|
|
25
|
+
*/
|
|
26
|
+
private static findMatchingFiles;
|
|
27
|
+
/**
|
|
28
|
+
* Check if filename matches integration's pattern
|
|
29
|
+
*/
|
|
30
|
+
static fileMatchesIntegration(filename: string, integration: any): boolean;
|
|
31
|
+
/**
|
|
32
|
+
* Find Clavix skill directories (.skills/clavix-*)
|
|
33
|
+
*/
|
|
34
|
+
private static findClavixSkillDirectories;
|
|
35
|
+
/**
|
|
36
|
+
* Find files starting with a specific prefix in a directory
|
|
37
|
+
* @param dirPath - The directory to search
|
|
38
|
+
* @param prefix - The file prefix to match
|
|
39
|
+
* @returns Array of matching file paths
|
|
40
|
+
*/
|
|
41
|
+
private static findFilesStartingWith;
|
|
42
|
+
/**
|
|
43
|
+
* Get the size of a file in bytes
|
|
44
|
+
* @param filePath - The file path
|
|
45
|
+
* @returns File size in bytes
|
|
46
|
+
*/
|
|
47
|
+
private static getFileSize;
|
|
48
|
+
/**
|
|
49
|
+
* Get the total size of a directory in bytes
|
|
50
|
+
* @param dirPath - The directory path
|
|
51
|
+
* @returns Total size in bytes
|
|
52
|
+
*/
|
|
53
|
+
private static getDirectorySize;
|
|
54
|
+
/**
|
|
55
|
+
* Get a description for a file based on its name and location
|
|
56
|
+
* @param filePath - The file path
|
|
57
|
+
* @returns A human-readable description
|
|
58
|
+
*/
|
|
59
|
+
private static getFileDescription;
|
|
60
|
+
/**
|
|
61
|
+
* Check if a directory is effectively empty (only contains .clavix)
|
|
62
|
+
* Used to determine if we should also remove empty parent directories
|
|
63
|
+
* @param dirPath - The directory to check
|
|
64
|
+
* @returns true if the directory is considered empty for cleanup purposes
|
|
65
|
+
*/
|
|
66
|
+
static isEmptyClavixParent(dirPath: string): Promise<boolean>;
|
|
67
|
+
}
|
|
68
|
+
//# sourceMappingURL=discovery.d.ts.map
|