@blockspool/core 0.4.1 → 0.4.3
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/db/adapter.d.ts +191 -0
- package/dist/db/adapter.d.ts.map +1 -0
- package/dist/db/adapter.js +40 -0
- package/dist/db/adapter.js.map +1 -0
- package/dist/db/contract.d.ts +47 -0
- package/dist/db/contract.d.ts.map +1 -0
- package/dist/db/contract.js +258 -0
- package/dist/db/contract.js.map +1 -0
- package/dist/db/index.d.ts +6 -0
- package/dist/db/index.d.ts.map +1 -0
- package/dist/db/index.js +7 -0
- package/dist/db/index.js.map +1 -0
- package/dist/exec/index.d.ts +5 -0
- package/dist/exec/index.d.ts.map +1 -0
- package/dist/exec/index.js +5 -0
- package/dist/exec/index.js.map +1 -0
- package/dist/exec/types.d.ts +64 -0
- package/dist/exec/types.d.ts.map +1 -0
- package/dist/exec/types.js +8 -0
- package/dist/exec/types.js.map +1 -0
- package/dist/index.d.ts +23 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +27 -0
- package/dist/index.js.map +1 -0
- package/dist/repos/index.d.ts +15 -0
- package/dist/repos/index.d.ts.map +1 -0
- package/dist/repos/index.js +11 -0
- package/dist/repos/index.js.map +1 -0
- package/dist/repos/projects.d.ts +41 -0
- package/dist/repos/projects.d.ts.map +1 -0
- package/dist/repos/projects.js +74 -0
- package/dist/repos/projects.js.map +1 -0
- package/dist/repos/run_steps.d.ts +152 -0
- package/dist/repos/run_steps.d.ts.map +1 -0
- package/dist/repos/run_steps.js +321 -0
- package/dist/repos/run_steps.js.map +1 -0
- package/dist/repos/runs.d.ts +92 -0
- package/dist/repos/runs.d.ts.map +1 -0
- package/dist/repos/runs.js +177 -0
- package/dist/repos/runs.js.map +1 -0
- package/dist/repos/tickets.d.ts +71 -0
- package/dist/repos/tickets.d.ts.map +1 -0
- package/dist/repos/tickets.js +128 -0
- package/dist/repos/tickets.js.map +1 -0
- package/dist/scout/index.d.ts +15 -0
- package/dist/scout/index.d.ts.map +1 -0
- package/dist/scout/index.js +383 -0
- package/dist/scout/index.js.map +1 -0
- package/dist/scout/prompt.d.ts +32 -0
- package/dist/scout/prompt.d.ts.map +1 -0
- package/dist/scout/prompt.js +104 -0
- package/dist/scout/prompt.js.map +1 -0
- package/dist/scout/runner.d.ts +68 -0
- package/dist/scout/runner.d.ts.map +1 -0
- package/dist/scout/runner.js +270 -0
- package/dist/scout/runner.js.map +1 -0
- package/dist/scout/scanner.d.ts +35 -0
- package/dist/scout/scanner.d.ts.map +1 -0
- package/dist/scout/scanner.js +164 -0
- package/dist/scout/scanner.js.map +1 -0
- package/dist/scout/types.d.ts +179 -0
- package/dist/scout/types.d.ts.map +1 -0
- package/dist/scout/types.js +44 -0
- package/dist/scout/types.js.map +1 -0
- package/dist/services/index.d.ts +10 -0
- package/dist/services/index.d.ts.map +1 -0
- package/dist/services/index.js +9 -0
- package/dist/services/index.js.map +1 -0
- package/dist/services/qa.d.ts +76 -0
- package/dist/services/qa.d.ts.map +1 -0
- package/dist/services/qa.js +239 -0
- package/dist/services/qa.js.map +1 -0
- package/dist/services/scout.d.ts +120 -0
- package/dist/services/scout.d.ts.map +1 -0
- package/dist/services/scout.js +205 -0
- package/dist/services/scout.js.map +1 -0
- package/dist/utils/id.d.ts +12 -0
- package/dist/utils/id.d.ts.map +1 -0
- package/dist/utils/id.js +24 -0
- package/dist/utils/id.js.map +1 -0
- package/dist/utils/id.test.d.ts +5 -0
- package/dist/utils/id.test.d.ts.map +1 -0
- package/dist/utils/id.test.js +173 -0
- package/dist/utils/id.test.js.map +1 -0
- package/dist/utils/index.d.ts +6 -0
- package/dist/utils/index.d.ts.map +1 -0
- package/dist/utils/index.js +6 -0
- package/dist/utils/index.js.map +1 -0
- package/dist/utils/json.d.ts +9 -0
- package/dist/utils/json.d.ts.map +1 -0
- package/dist/utils/json.js +19 -0
- package/dist/utils/json.js.map +1 -0
- package/package.json +1 -1
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Ticket repository - Database operations for tickets
|
|
3
|
+
*/
|
|
4
|
+
import type { DatabaseAdapter } from '../db/adapter.js';
|
|
5
|
+
export type TicketStatus = 'backlog' | 'ready' | 'leased' | 'in_progress' | 'in_review' | 'done' | 'blocked' | 'aborted';
|
|
6
|
+
export type TicketCategory = 'refactor' | 'docs' | 'test' | 'perf' | 'security';
|
|
7
|
+
export interface Ticket {
|
|
8
|
+
id: string;
|
|
9
|
+
projectId: string;
|
|
10
|
+
title: string;
|
|
11
|
+
description: string | null;
|
|
12
|
+
status: TicketStatus;
|
|
13
|
+
priority: number;
|
|
14
|
+
shard: string | null;
|
|
15
|
+
category: TicketCategory | null;
|
|
16
|
+
allowedPaths: string[];
|
|
17
|
+
forbiddenPaths: string[];
|
|
18
|
+
verificationCommands: string[];
|
|
19
|
+
maxRetries: number;
|
|
20
|
+
retryCount: number;
|
|
21
|
+
createdAt: Date;
|
|
22
|
+
updatedAt: Date;
|
|
23
|
+
}
|
|
24
|
+
/**
|
|
25
|
+
* Get ticket by ID
|
|
26
|
+
*/
|
|
27
|
+
export declare function getById(db: DatabaseAdapter, id: string): Promise<Ticket | null>;
|
|
28
|
+
/**
|
|
29
|
+
* Create a new ticket
|
|
30
|
+
*/
|
|
31
|
+
export declare function create(db: DatabaseAdapter, opts: {
|
|
32
|
+
projectId: string;
|
|
33
|
+
title: string;
|
|
34
|
+
description?: string;
|
|
35
|
+
status?: TicketStatus;
|
|
36
|
+
priority?: number;
|
|
37
|
+
shard?: string;
|
|
38
|
+
category?: TicketCategory;
|
|
39
|
+
allowedPaths?: string[];
|
|
40
|
+
forbiddenPaths?: string[];
|
|
41
|
+
verificationCommands?: string[];
|
|
42
|
+
maxRetries?: number;
|
|
43
|
+
}): Promise<Ticket>;
|
|
44
|
+
/**
|
|
45
|
+
* Create multiple tickets in a transaction
|
|
46
|
+
*/
|
|
47
|
+
export declare function createMany(db: DatabaseAdapter, tickets: Array<Parameters<typeof create>[1]>): Promise<Ticket[]>;
|
|
48
|
+
/**
|
|
49
|
+
* Update ticket status
|
|
50
|
+
*/
|
|
51
|
+
export declare function updateStatus(db: DatabaseAdapter, id: string, status: TicketStatus): Promise<Ticket | null>;
|
|
52
|
+
/**
|
|
53
|
+
* List tickets for a project
|
|
54
|
+
*/
|
|
55
|
+
export declare function listByProject(db: DatabaseAdapter, projectId: string, opts?: {
|
|
56
|
+
status?: TicketStatus | TicketStatus[];
|
|
57
|
+
limit?: number;
|
|
58
|
+
}): Promise<Ticket[]>;
|
|
59
|
+
/**
|
|
60
|
+
* Get recently completed tickets (for dedup context)
|
|
61
|
+
*/
|
|
62
|
+
export declare function getRecentlyCompleted(db: DatabaseAdapter, projectId: string, limit?: number): Promise<Ticket[]>;
|
|
63
|
+
/**
|
|
64
|
+
* Count tickets by status
|
|
65
|
+
*/
|
|
66
|
+
export declare function countByStatus(db: DatabaseAdapter, projectId: string): Promise<Record<TicketStatus, number>>;
|
|
67
|
+
/**
|
|
68
|
+
* Find similar ticket by title (for dedup)
|
|
69
|
+
*/
|
|
70
|
+
export declare function findSimilarByTitle(db: DatabaseAdapter, projectId: string, title: string): Promise<Ticket | null>;
|
|
71
|
+
//# sourceMappingURL=tickets.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"tickets.d.ts","sourceRoot":"","sources":["../../src/repos/tickets.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,128 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Ticket repository - Database operations for tickets
|
|
3
|
+
*/
|
|
4
|
+
import { nanoid, parseJsonArray } from '../utils/index.js';
|
|
5
|
+
function rowToTicket(row) {
|
|
6
|
+
return {
|
|
7
|
+
id: row.id,
|
|
8
|
+
projectId: row.project_id,
|
|
9
|
+
title: row.title,
|
|
10
|
+
description: row.description,
|
|
11
|
+
status: row.status,
|
|
12
|
+
priority: row.priority,
|
|
13
|
+
shard: row.shard,
|
|
14
|
+
category: row.category,
|
|
15
|
+
allowedPaths: parseJsonArray(row.allowed_paths),
|
|
16
|
+
forbiddenPaths: parseJsonArray(row.forbidden_paths),
|
|
17
|
+
verificationCommands: parseJsonArray(row.verification_commands),
|
|
18
|
+
maxRetries: row.max_retries,
|
|
19
|
+
retryCount: row.retry_count,
|
|
20
|
+
createdAt: new Date(row.created_at),
|
|
21
|
+
updatedAt: new Date(row.updated_at),
|
|
22
|
+
};
|
|
23
|
+
}
|
|
24
|
+
/**
|
|
25
|
+
* Get ticket by ID
|
|
26
|
+
*/
|
|
27
|
+
export async function getById(db, id) {
|
|
28
|
+
const result = await db.query('SELECT * FROM tickets WHERE id = $1', [id]);
|
|
29
|
+
return result.rows[0] ? rowToTicket(result.rows[0]) : null;
|
|
30
|
+
}
|
|
31
|
+
/**
|
|
32
|
+
* Create a new ticket
|
|
33
|
+
*/
|
|
34
|
+
export async function create(db, opts) {
|
|
35
|
+
const id = `tkt_${nanoid(12)}`;
|
|
36
|
+
await db.query(`INSERT INTO tickets (
|
|
37
|
+
id, project_id, title, description, status, priority,
|
|
38
|
+
shard, category, allowed_paths, forbidden_paths,
|
|
39
|
+
verification_commands, max_retries
|
|
40
|
+
) VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, $12)`, [
|
|
41
|
+
id,
|
|
42
|
+
opts.projectId,
|
|
43
|
+
opts.title,
|
|
44
|
+
opts.description ?? null,
|
|
45
|
+
opts.status ?? 'ready',
|
|
46
|
+
opts.priority ?? 0,
|
|
47
|
+
opts.shard ?? null,
|
|
48
|
+
opts.category ?? null,
|
|
49
|
+
JSON.stringify(opts.allowedPaths ?? []),
|
|
50
|
+
JSON.stringify(opts.forbiddenPaths ?? []),
|
|
51
|
+
JSON.stringify(opts.verificationCommands ?? []),
|
|
52
|
+
opts.maxRetries ?? 3,
|
|
53
|
+
]);
|
|
54
|
+
const ticket = await getById(db, id);
|
|
55
|
+
if (!ticket) {
|
|
56
|
+
throw new Error('Failed to create ticket');
|
|
57
|
+
}
|
|
58
|
+
return ticket;
|
|
59
|
+
}
|
|
60
|
+
/**
|
|
61
|
+
* Create multiple tickets in a transaction
|
|
62
|
+
*/
|
|
63
|
+
export async function createMany(db, tickets) {
|
|
64
|
+
return db.withTransaction(async () => {
|
|
65
|
+
const created = [];
|
|
66
|
+
for (const opts of tickets) {
|
|
67
|
+
const ticket = await create(db, opts);
|
|
68
|
+
created.push(ticket);
|
|
69
|
+
}
|
|
70
|
+
return created;
|
|
71
|
+
});
|
|
72
|
+
}
|
|
73
|
+
/**
|
|
74
|
+
* Update ticket status
|
|
75
|
+
*/
|
|
76
|
+
export async function updateStatus(db, id, status) {
|
|
77
|
+
await db.query(`UPDATE tickets SET status = $1, updated_at = datetime('now') WHERE id = $2`, [status, id]);
|
|
78
|
+
return getById(db, id);
|
|
79
|
+
}
|
|
80
|
+
/**
|
|
81
|
+
* List tickets for a project
|
|
82
|
+
*/
|
|
83
|
+
export async function listByProject(db, projectId, opts) {
|
|
84
|
+
let sql = 'SELECT * FROM tickets WHERE project_id = $1';
|
|
85
|
+
const params = [projectId];
|
|
86
|
+
if (opts?.status) {
|
|
87
|
+
const statuses = Array.isArray(opts.status) ? opts.status : [opts.status];
|
|
88
|
+
const placeholders = statuses.map((_, i) => `$${i + 2}`).join(', ');
|
|
89
|
+
sql += ` AND status IN (${placeholders})`;
|
|
90
|
+
params.push(...statuses);
|
|
91
|
+
}
|
|
92
|
+
sql += ' ORDER BY priority DESC, created_at DESC';
|
|
93
|
+
if (opts?.limit !== undefined) {
|
|
94
|
+
const paramIndex = params.length + 1;
|
|
95
|
+
sql += ` LIMIT $${paramIndex}`;
|
|
96
|
+
params.push(opts.limit);
|
|
97
|
+
}
|
|
98
|
+
const result = await db.query(sql, params);
|
|
99
|
+
return result.rows.map(rowToTicket);
|
|
100
|
+
}
|
|
101
|
+
/**
|
|
102
|
+
* Get recently completed tickets (for dedup context)
|
|
103
|
+
*/
|
|
104
|
+
export async function getRecentlyCompleted(db, projectId, limit = 20) {
|
|
105
|
+
return listByProject(db, projectId, { status: 'done', limit });
|
|
106
|
+
}
|
|
107
|
+
/**
|
|
108
|
+
* Count tickets by status
|
|
109
|
+
*/
|
|
110
|
+
export async function countByStatus(db, projectId) {
|
|
111
|
+
const result = await db.query(`SELECT status, COUNT(*) as count FROM tickets
|
|
112
|
+
WHERE project_id = $1 GROUP BY status`, [projectId]);
|
|
113
|
+
const counts = {};
|
|
114
|
+
for (const row of result.rows) {
|
|
115
|
+
counts[row.status] = parseInt(row.count, 10);
|
|
116
|
+
}
|
|
117
|
+
return counts;
|
|
118
|
+
}
|
|
119
|
+
/**
|
|
120
|
+
* Find similar ticket by title (for dedup)
|
|
121
|
+
*/
|
|
122
|
+
export async function findSimilarByTitle(db, projectId, title) {
|
|
123
|
+
const result = await db.query(`SELECT * FROM tickets
|
|
124
|
+
WHERE project_id = $1 AND LOWER(title) = LOWER($2)
|
|
125
|
+
LIMIT 1`, [projectId, title]);
|
|
126
|
+
return result.rows[0] ? rowToTicket(result.rows[0]) : null;
|
|
127
|
+
}
|
|
128
|
+
//# sourceMappingURL=tickets.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"tickets.js","sourceRoot":"","sources":["../../src/repos/tickets.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Scout service - Analyzes codebases and generates improvement proposals
|
|
3
|
+
*
|
|
4
|
+
* This is the core scout implementation that works with any DatabaseAdapter.
|
|
5
|
+
*/
|
|
6
|
+
import type { ScoutOptions, ScoutResult } from './types.js';
|
|
7
|
+
export * from './types.js';
|
|
8
|
+
export { buildScoutPrompt, buildCategoryPrompt } from './prompt.js';
|
|
9
|
+
export { runClaude, parseClaudeOutput, ClaudeScoutBackend, CodexScoutBackend, type ScoutBackend } from './runner.js';
|
|
10
|
+
export { scanFiles, batchFiles, type ScannedFile } from './scanner.js';
|
|
11
|
+
/**
|
|
12
|
+
* Scout a codebase for improvement opportunities
|
|
13
|
+
*/
|
|
14
|
+
export declare function scout(options: ScoutOptions): Promise<ScoutResult>;
|
|
15
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/scout/index.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAMH,OAAO,KAAK,EACV,YAAY,EACZ,WAAW,EAIZ,MAAM,YAAY,CAAC;AAEpB,cAAc,YAAY,CAAC;AAC3B,OAAO,EAAE,gBAAgB,EAAE,mBAAmB,EAAE,MAAM,aAAa,CAAC;AACpE,OAAO,EAAE,SAAS,EAAE,iBAAiB,EAAE,kBAAkB,EAAE,iBAAiB,EAAE,KAAK,YAAY,EAAE,MAAM,aAAa,CAAC;AACrH,OAAO,EAAE,SAAS,EAAE,UAAU,EAAE,KAAK,WAAW,EAAE,MAAM,cAAc,CAAC;AA6PvE;;GAEG;AACH,wBAAsB,KAAK,CAAC,OAAO,EAAE,YAAY,GAAG,OAAO,CAAC,WAAW,CAAC,CAuLvE"}
|
|
@@ -0,0 +1,383 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Scout service - Analyzes codebases and generates improvement proposals
|
|
3
|
+
*
|
|
4
|
+
* This is the core scout implementation that works with any DatabaseAdapter.
|
|
5
|
+
*/
|
|
6
|
+
import { nanoid } from '../utils/id.js';
|
|
7
|
+
import { buildScoutPrompt } from './prompt.js';
|
|
8
|
+
import { parseClaudeOutput, ClaudeScoutBackend } from './runner.js';
|
|
9
|
+
import { scanFiles, batchFiles } from './scanner.js';
|
|
10
|
+
export * from './types.js';
|
|
11
|
+
export { buildScoutPrompt, buildCategoryPrompt } from './prompt.js';
|
|
12
|
+
export { runClaude, parseClaudeOutput, ClaudeScoutBackend, CodexScoutBackend } from './runner.js';
|
|
13
|
+
export { scanFiles, batchFiles } from './scanner.js';
|
|
14
|
+
/**
|
|
15
|
+
* Default verification commands by category
|
|
16
|
+
*/
|
|
17
|
+
const DEFAULT_VERIFICATION_COMMANDS = {
|
|
18
|
+
refactor: ['npm run build'],
|
|
19
|
+
docs: ['npm run build'],
|
|
20
|
+
test: ['npm run build', 'npm test'],
|
|
21
|
+
perf: ['npm run build'],
|
|
22
|
+
security: ['npm run build'],
|
|
23
|
+
};
|
|
24
|
+
/**
|
|
25
|
+
* Sanitize verification commands to prevent predictable failures
|
|
26
|
+
*/
|
|
27
|
+
function sanitizeVerificationCommands(commands, category) {
|
|
28
|
+
const sanitized = commands.filter(cmd => {
|
|
29
|
+
const lower = cmd.toLowerCase();
|
|
30
|
+
// Remove fragile commands
|
|
31
|
+
if (lower.includes('grep ') || lower.includes('wc '))
|
|
32
|
+
return false;
|
|
33
|
+
// Remove file-specific test commands (often fail)
|
|
34
|
+
if (lower.includes('npm test --') || lower.includes('npm test -- '))
|
|
35
|
+
return false;
|
|
36
|
+
// Remove npm test for non-test categories (wastes time)
|
|
37
|
+
if (category !== 'test' && lower.includes('npm test'))
|
|
38
|
+
return false;
|
|
39
|
+
return true;
|
|
40
|
+
});
|
|
41
|
+
// Ensure at least the default commands
|
|
42
|
+
if (sanitized.length === 0) {
|
|
43
|
+
return DEFAULT_VERIFICATION_COMMANDS[category];
|
|
44
|
+
}
|
|
45
|
+
return sanitized;
|
|
46
|
+
}
|
|
47
|
+
/**
|
|
48
|
+
* Expand allowed paths for test proposals to include test file locations
|
|
49
|
+
*
|
|
50
|
+
* When a proposal is about adding tests, we need to allow:
|
|
51
|
+
* 1. The original source file(s)
|
|
52
|
+
* 2. Corresponding test files (e.g., foo.ts -> foo.test.ts, foo.spec.ts)
|
|
53
|
+
* 3. Test directories (e.g., __tests__/, test/, tests/)
|
|
54
|
+
* 4. Config files (vitest.config.ts, jest.config.js, tsconfig.json)
|
|
55
|
+
*/
|
|
56
|
+
function expandPathsForTests(paths) {
|
|
57
|
+
const expanded = new Set(paths);
|
|
58
|
+
for (const filePath of paths) {
|
|
59
|
+
// Skip if already a test file
|
|
60
|
+
if (filePath.includes('.test.') || filePath.includes('.spec.') || filePath.includes('__tests__')) {
|
|
61
|
+
continue;
|
|
62
|
+
}
|
|
63
|
+
// Get directory and filename parts
|
|
64
|
+
const lastSlash = filePath.lastIndexOf('/');
|
|
65
|
+
const dir = lastSlash >= 0 ? filePath.slice(0, lastSlash) : '';
|
|
66
|
+
const filename = lastSlash >= 0 ? filePath.slice(lastSlash + 1) : filePath;
|
|
67
|
+
// Get extension and base name
|
|
68
|
+
const lastDot = filename.lastIndexOf('.');
|
|
69
|
+
const ext = lastDot >= 0 ? filename.slice(lastDot) : '';
|
|
70
|
+
const baseName = lastDot >= 0 ? filename.slice(0, lastDot) : filename;
|
|
71
|
+
// Add common test file patterns
|
|
72
|
+
// 1. Same directory: foo.test.ts, foo.spec.ts (with multiple extensions)
|
|
73
|
+
const testExts = [ext, '.ts', '.js', '.tsx', '.jsx'];
|
|
74
|
+
const uniqueExts = [...new Set(testExts)];
|
|
75
|
+
for (const testExt of uniqueExts) {
|
|
76
|
+
if (dir) {
|
|
77
|
+
expanded.add(`${dir}/${baseName}.test${testExt}`);
|
|
78
|
+
expanded.add(`${dir}/${baseName}.spec${testExt}`);
|
|
79
|
+
}
|
|
80
|
+
else {
|
|
81
|
+
expanded.add(`${baseName}.test${testExt}`);
|
|
82
|
+
expanded.add(`${baseName}.spec${testExt}`);
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
// 2. Adjacent __tests__ directory (comprehensive patterns)
|
|
86
|
+
if (dir) {
|
|
87
|
+
for (const testExt of uniqueExts) {
|
|
88
|
+
expanded.add(`${dir}/__tests__/${baseName}.test${testExt}`);
|
|
89
|
+
expanded.add(`${dir}/__tests__/${baseName}.spec${testExt}`);
|
|
90
|
+
expanded.add(`${dir}/__tests__/${baseName}${testExt}`);
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
// Root-level __tests__ directory
|
|
94
|
+
for (const testExt of uniqueExts) {
|
|
95
|
+
expanded.add(`__tests__/${baseName}.test${testExt}`);
|
|
96
|
+
expanded.add(`__tests__/${baseName}.spec${testExt}`);
|
|
97
|
+
expanded.add(`__tests__/${baseName}${testExt}`);
|
|
98
|
+
}
|
|
99
|
+
// 3. Project root test/ and tests/ directories
|
|
100
|
+
for (const testExt of uniqueExts) {
|
|
101
|
+
expanded.add(`test/${baseName}.test${testExt}`);
|
|
102
|
+
expanded.add(`test/${baseName}.spec${testExt}`);
|
|
103
|
+
expanded.add(`test/${baseName}${testExt}`);
|
|
104
|
+
expanded.add(`tests/${baseName}.test${testExt}`);
|
|
105
|
+
expanded.add(`tests/${baseName}.spec${testExt}`);
|
|
106
|
+
expanded.add(`tests/${baseName}${testExt}`);
|
|
107
|
+
}
|
|
108
|
+
// 4. For src/ files, also allow mirrored structure in test directories
|
|
109
|
+
if (dir.startsWith('src/')) {
|
|
110
|
+
const relPath = dir.slice(4); // Remove 'src/'
|
|
111
|
+
for (const testExt of uniqueExts) {
|
|
112
|
+
// test/path/to/foo.test.ts
|
|
113
|
+
expanded.add(`test/${relPath ? relPath + '/' : ''}${baseName}.test${testExt}`);
|
|
114
|
+
expanded.add(`test/${relPath ? relPath + '/' : ''}${baseName}.spec${testExt}`);
|
|
115
|
+
expanded.add(`test/${relPath ? relPath + '/' : ''}${baseName}${testExt}`);
|
|
116
|
+
// tests/path/to/foo.test.ts
|
|
117
|
+
expanded.add(`tests/${relPath ? relPath + '/' : ''}${baseName}.test${testExt}`);
|
|
118
|
+
expanded.add(`tests/${relPath ? relPath + '/' : ''}${baseName}.spec${testExt}`);
|
|
119
|
+
expanded.add(`tests/${relPath ? relPath + '/' : ''}${baseName}${testExt}`);
|
|
120
|
+
// src/test/path/to/foo.test.ts (for projects that use src/test)
|
|
121
|
+
expanded.add(`src/test/${relPath ? relPath + '/' : ''}${baseName}.test${testExt}`);
|
|
122
|
+
expanded.add(`src/test/${relPath ? relPath + '/' : ''}${baseName}.spec${testExt}`);
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
// 5. For packages/*/src/ files, allow test directories within the package
|
|
126
|
+
const packageMatch = dir.match(/^(packages\/[^/]+)\/(src\/)?(.*)$/);
|
|
127
|
+
if (packageMatch) {
|
|
128
|
+
const [, packageDir, , relPath] = packageMatch;
|
|
129
|
+
for (const testExt of uniqueExts) {
|
|
130
|
+
// packages/foo/test/bar.test.ts
|
|
131
|
+
expanded.add(`${packageDir}/test/${relPath ? relPath + '/' : ''}${baseName}.test${testExt}`);
|
|
132
|
+
expanded.add(`${packageDir}/test/${relPath ? relPath + '/' : ''}${baseName}.spec${testExt}`);
|
|
133
|
+
expanded.add(`${packageDir}/tests/${relPath ? relPath + '/' : ''}${baseName}.test${testExt}`);
|
|
134
|
+
expanded.add(`${packageDir}/tests/${relPath ? relPath + '/' : ''}${baseName}.spec${testExt}`);
|
|
135
|
+
// packages/foo/__tests__/bar.test.ts
|
|
136
|
+
expanded.add(`${packageDir}/__tests__/${relPath ? relPath + '/' : ''}${baseName}.test${testExt}`);
|
|
137
|
+
expanded.add(`${packageDir}/__tests__/${relPath ? relPath + '/' : ''}${baseName}.spec${testExt}`);
|
|
138
|
+
// packages/foo/src/__tests__/bar.test.ts
|
|
139
|
+
expanded.add(`${packageDir}/src/__tests__/${relPath ? relPath + '/' : ''}${baseName}.test${testExt}`);
|
|
140
|
+
expanded.add(`${packageDir}/src/__tests__/${relPath ? relPath + '/' : ''}${baseName}.spec${testExt}`);
|
|
141
|
+
}
|
|
142
|
+
}
|
|
143
|
+
}
|
|
144
|
+
return Array.from(expanded);
|
|
145
|
+
}
|
|
146
|
+
/**
|
|
147
|
+
* Validate and normalize a proposal
|
|
148
|
+
*/
|
|
149
|
+
function normalizeProposal(raw, category) {
|
|
150
|
+
try {
|
|
151
|
+
const proposal = raw;
|
|
152
|
+
// Validate required fields
|
|
153
|
+
if (!proposal.category || !proposal.title || !proposal.description) {
|
|
154
|
+
return null;
|
|
155
|
+
}
|
|
156
|
+
// Validate category
|
|
157
|
+
const validCategories = ['refactor', 'docs', 'test', 'perf', 'security'];
|
|
158
|
+
if (!validCategories.includes(proposal.category)) {
|
|
159
|
+
return null;
|
|
160
|
+
}
|
|
161
|
+
// Filter by category if specified
|
|
162
|
+
if (category && proposal.category !== category) {
|
|
163
|
+
return null;
|
|
164
|
+
}
|
|
165
|
+
// Ensure arrays
|
|
166
|
+
proposal.acceptance_criteria = Array.isArray(proposal.acceptance_criteria)
|
|
167
|
+
? proposal.acceptance_criteria
|
|
168
|
+
: [];
|
|
169
|
+
proposal.verification_commands = Array.isArray(proposal.verification_commands)
|
|
170
|
+
? proposal.verification_commands
|
|
171
|
+
: [];
|
|
172
|
+
proposal.allowed_paths = Array.isArray(proposal.allowed_paths)
|
|
173
|
+
? proposal.allowed_paths
|
|
174
|
+
: [];
|
|
175
|
+
proposal.files = Array.isArray(proposal.files)
|
|
176
|
+
? proposal.files
|
|
177
|
+
: [];
|
|
178
|
+
// Validate minimum requirements
|
|
179
|
+
if (proposal.acceptance_criteria.length === 0) {
|
|
180
|
+
proposal.acceptance_criteria = ['Implementation verified by tests'];
|
|
181
|
+
}
|
|
182
|
+
// Sanitize verification commands
|
|
183
|
+
proposal.verification_commands = sanitizeVerificationCommands(proposal.verification_commands, proposal.category);
|
|
184
|
+
// Ensure allowed_paths
|
|
185
|
+
if (proposal.allowed_paths.length === 0 && proposal.files.length > 0) {
|
|
186
|
+
proposal.allowed_paths = [...proposal.files];
|
|
187
|
+
}
|
|
188
|
+
// For test proposals, expand allowed_paths to include test file locations
|
|
189
|
+
// Combine files and allowed_paths since LLM may list source files in 'files' but test files in 'allowed_paths'
|
|
190
|
+
if (proposal.category === 'test') {
|
|
191
|
+
const allPaths = [...new Set([...proposal.allowed_paths, ...proposal.files])];
|
|
192
|
+
proposal.allowed_paths = expandPathsForTests(allPaths);
|
|
193
|
+
// Always allow config files for test tickets
|
|
194
|
+
const configFiles = [
|
|
195
|
+
'package.json',
|
|
196
|
+
'package-lock.json',
|
|
197
|
+
'tsconfig.json',
|
|
198
|
+
'vitest.config.ts',
|
|
199
|
+
'vitest.config.js',
|
|
200
|
+
'vitest.config.mts',
|
|
201
|
+
'vitest.config.mjs',
|
|
202
|
+
'jest.config.ts',
|
|
203
|
+
'jest.config.js',
|
|
204
|
+
'jest.config.mjs',
|
|
205
|
+
'jest.config.json',
|
|
206
|
+
];
|
|
207
|
+
for (const configFile of configFiles) {
|
|
208
|
+
if (!proposal.allowed_paths.includes(configFile)) {
|
|
209
|
+
proposal.allowed_paths.push(configFile);
|
|
210
|
+
}
|
|
211
|
+
}
|
|
212
|
+
}
|
|
213
|
+
// Generate ID
|
|
214
|
+
proposal.id = `scout-${Date.now()}-${nanoid(6)}`;
|
|
215
|
+
// Normalize confidence
|
|
216
|
+
proposal.confidence = Math.max(0, Math.min(100, proposal.confidence || 50));
|
|
217
|
+
// Normalize impact_score (optional, 1-10)
|
|
218
|
+
if (proposal.impact_score !== null && proposal.impact_score !== undefined) {
|
|
219
|
+
proposal.impact_score = Math.max(1, Math.min(10, proposal.impact_score));
|
|
220
|
+
}
|
|
221
|
+
// Validate complexity
|
|
222
|
+
const validComplexities = ['trivial', 'simple', 'moderate', 'complex'];
|
|
223
|
+
if (!validComplexities.includes(proposal.estimated_complexity)) {
|
|
224
|
+
proposal.estimated_complexity = 'simple';
|
|
225
|
+
}
|
|
226
|
+
return proposal;
|
|
227
|
+
}
|
|
228
|
+
catch {
|
|
229
|
+
return null;
|
|
230
|
+
}
|
|
231
|
+
}
|
|
232
|
+
/**
|
|
233
|
+
* Scout a codebase for improvement opportunities
|
|
234
|
+
*/
|
|
235
|
+
export async function scout(options) {
|
|
236
|
+
const { scope, types, excludeTypes, exclude = [], maxProposals = 10, minConfidence = 50, projectPath = process.cwd(), timeoutMs = 120000, signal, onProgress, recentlyCompletedTitles, model = 'opus', customPrompt, backend, protectedFiles, } = options;
|
|
237
|
+
const scoutBackend = backend ?? new ClaudeScoutBackend();
|
|
238
|
+
const startTime = Date.now();
|
|
239
|
+
const errors = [];
|
|
240
|
+
const proposals = [];
|
|
241
|
+
// Report progress
|
|
242
|
+
const report = (progress) => {
|
|
243
|
+
onProgress?.({
|
|
244
|
+
phase: 'discovering',
|
|
245
|
+
filesScanned: 0,
|
|
246
|
+
totalFiles: 0,
|
|
247
|
+
proposalsFound: 0,
|
|
248
|
+
currentBatch: 0,
|
|
249
|
+
totalBatches: 0,
|
|
250
|
+
...progress,
|
|
251
|
+
});
|
|
252
|
+
};
|
|
253
|
+
try {
|
|
254
|
+
// Phase 1: Discover files
|
|
255
|
+
report({ phase: 'discovering' });
|
|
256
|
+
const files = scanFiles({
|
|
257
|
+
cwd: projectPath,
|
|
258
|
+
include: [scope],
|
|
259
|
+
exclude,
|
|
260
|
+
maxFiles: 60, // Limit to avoid huge prompts
|
|
261
|
+
});
|
|
262
|
+
if (files.length === 0) {
|
|
263
|
+
return {
|
|
264
|
+
success: true,
|
|
265
|
+
proposals: [],
|
|
266
|
+
errors: ['No files found matching scope'],
|
|
267
|
+
scannedFiles: 0,
|
|
268
|
+
scanDurationMs: Date.now() - startTime,
|
|
269
|
+
};
|
|
270
|
+
}
|
|
271
|
+
report({
|
|
272
|
+
phase: 'analyzing',
|
|
273
|
+
totalFiles: files.length,
|
|
274
|
+
});
|
|
275
|
+
// Phase 2: Batch files and analyze
|
|
276
|
+
const batches = batchFiles(files, 3);
|
|
277
|
+
const maxBatches = Math.min(batches.length, 20); // Cap at 20 batches
|
|
278
|
+
for (let i = 0; i < maxBatches; i++) {
|
|
279
|
+
// Check for cancellation
|
|
280
|
+
if (signal?.aborted) {
|
|
281
|
+
errors.push('Scan aborted by user');
|
|
282
|
+
break;
|
|
283
|
+
}
|
|
284
|
+
// Check if we have enough proposals
|
|
285
|
+
if (proposals.length >= maxProposals) {
|
|
286
|
+
break;
|
|
287
|
+
}
|
|
288
|
+
const batch = batches[i];
|
|
289
|
+
report({
|
|
290
|
+
phase: 'analyzing',
|
|
291
|
+
filesScanned: i * 3,
|
|
292
|
+
totalFiles: files.length,
|
|
293
|
+
proposalsFound: proposals.length,
|
|
294
|
+
currentBatch: i + 1,
|
|
295
|
+
totalBatches: maxBatches,
|
|
296
|
+
currentFile: batch[0]?.path,
|
|
297
|
+
});
|
|
298
|
+
// Build prompt for this batch
|
|
299
|
+
const prompt = buildScoutPrompt({
|
|
300
|
+
files: batch.map(f => ({ path: f.path, content: f.content })),
|
|
301
|
+
scope,
|
|
302
|
+
types,
|
|
303
|
+
excludeTypes,
|
|
304
|
+
maxProposals: Math.min(5, maxProposals - proposals.length),
|
|
305
|
+
minConfidence,
|
|
306
|
+
recentlyCompletedTitles,
|
|
307
|
+
customPrompt,
|
|
308
|
+
protectedFiles,
|
|
309
|
+
});
|
|
310
|
+
// Run scout backend
|
|
311
|
+
const result = await scoutBackend.run({
|
|
312
|
+
prompt,
|
|
313
|
+
cwd: projectPath,
|
|
314
|
+
timeoutMs,
|
|
315
|
+
model,
|
|
316
|
+
signal,
|
|
317
|
+
});
|
|
318
|
+
if (!result.success) {
|
|
319
|
+
errors.push(`Batch ${i + 1} failed: ${result.error}`);
|
|
320
|
+
continue;
|
|
321
|
+
}
|
|
322
|
+
// Parse output
|
|
323
|
+
const parsed = parseClaudeOutput(result.output);
|
|
324
|
+
if (!parsed?.proposals) {
|
|
325
|
+
errors.push(`Batch ${i + 1}: Failed to parse output`);
|
|
326
|
+
continue;
|
|
327
|
+
}
|
|
328
|
+
// Normalize and filter proposals
|
|
329
|
+
for (const raw of parsed.proposals) {
|
|
330
|
+
const proposal = normalizeProposal(raw, types?.[0]);
|
|
331
|
+
if (!proposal)
|
|
332
|
+
continue;
|
|
333
|
+
// Apply category filters
|
|
334
|
+
if (types?.length && !types.includes(proposal.category))
|
|
335
|
+
continue;
|
|
336
|
+
if (excludeTypes?.length && excludeTypes.includes(proposal.category))
|
|
337
|
+
continue;
|
|
338
|
+
// Apply confidence filter
|
|
339
|
+
if (proposal.confidence < minConfidence)
|
|
340
|
+
continue;
|
|
341
|
+
// Check for duplicates (by title similarity)
|
|
342
|
+
const isDuplicate = proposals.some(p => p.title.toLowerCase() === proposal.title.toLowerCase());
|
|
343
|
+
if (isDuplicate)
|
|
344
|
+
continue;
|
|
345
|
+
proposals.push(proposal);
|
|
346
|
+
if (proposals.length >= maxProposals)
|
|
347
|
+
break;
|
|
348
|
+
}
|
|
349
|
+
}
|
|
350
|
+
// Sort proposals by impact * confidence (descending)
|
|
351
|
+
proposals.sort((a, b) => {
|
|
352
|
+
const scoreA = (a.impact_score ?? 5) * a.confidence;
|
|
353
|
+
const scoreB = (b.impact_score ?? 5) * b.confidence;
|
|
354
|
+
return scoreB - scoreA;
|
|
355
|
+
});
|
|
356
|
+
// Phase 3: Complete
|
|
357
|
+
report({
|
|
358
|
+
phase: 'complete',
|
|
359
|
+
filesScanned: files.length,
|
|
360
|
+
totalFiles: files.length,
|
|
361
|
+
proposalsFound: proposals.length,
|
|
362
|
+
currentBatch: maxBatches,
|
|
363
|
+
totalBatches: maxBatches,
|
|
364
|
+
});
|
|
365
|
+
return {
|
|
366
|
+
success: true,
|
|
367
|
+
proposals,
|
|
368
|
+
errors,
|
|
369
|
+
scannedFiles: files.length,
|
|
370
|
+
scanDurationMs: Date.now() - startTime,
|
|
371
|
+
};
|
|
372
|
+
}
|
|
373
|
+
catch (error) {
|
|
374
|
+
return {
|
|
375
|
+
success: false,
|
|
376
|
+
proposals,
|
|
377
|
+
errors: [...errors, error instanceof Error ? error.message : String(error)],
|
|
378
|
+
scannedFiles: 0,
|
|
379
|
+
scanDurationMs: Date.now() - startTime,
|
|
380
|
+
};
|
|
381
|
+
}
|
|
382
|
+
}
|
|
383
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/scout/index.ts"],"names":[],"mappings":"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"}
|