@blockspool/mcp 0.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/README.md +174 -0
- package/dist/advance.d.ts +30 -0
- package/dist/advance.d.ts.map +1 -0
- package/dist/advance.js +514 -0
- package/dist/advance.js.map +1 -0
- package/dist/direct-client.d.ts +57 -0
- package/dist/direct-client.d.ts.map +1 -0
- package/dist/direct-client.js +92 -0
- package/dist/direct-client.js.map +1 -0
- package/dist/event-processor.d.ts +17 -0
- package/dist/event-processor.d.ts.map +1 -0
- package/dist/event-processor.js +360 -0
- package/dist/event-processor.js.map +1 -0
- package/dist/formulas.d.ts +37 -0
- package/dist/formulas.d.ts.map +1 -0
- package/dist/formulas.js +245 -0
- package/dist/formulas.js.map +1 -0
- package/dist/index.d.ts +9 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +42 -0
- package/dist/index.js.map +1 -0
- package/dist/proposals.d.ts +51 -0
- package/dist/proposals.d.ts.map +1 -0
- package/dist/proposals.js +207 -0
- package/dist/proposals.js.map +1 -0
- package/dist/run-manager.d.ts +69 -0
- package/dist/run-manager.d.ts.map +1 -0
- package/dist/run-manager.js +315 -0
- package/dist/run-manager.js.map +1 -0
- package/dist/scope-policy.d.ts +34 -0
- package/dist/scope-policy.d.ts.map +1 -0
- package/dist/scope-policy.js +145 -0
- package/dist/scope-policy.js.map +1 -0
- package/dist/server.d.ts +16 -0
- package/dist/server.d.ts.map +1 -0
- package/dist/server.js +31 -0
- package/dist/server.js.map +1 -0
- package/dist/spindle.d.ts +41 -0
- package/dist/spindle.d.ts.map +1 -0
- package/dist/spindle.js +279 -0
- package/dist/spindle.js.map +1 -0
- package/dist/state.d.ts +36 -0
- package/dist/state.d.ts.map +1 -0
- package/dist/state.js +50 -0
- package/dist/state.js.map +1 -0
- package/dist/tools/execute.d.ts +7 -0
- package/dist/tools/execute.d.ts.map +1 -0
- package/dist/tools/execute.js +238 -0
- package/dist/tools/execute.js.map +1 -0
- package/dist/tools/git.d.ts +7 -0
- package/dist/tools/git.d.ts.map +1 -0
- package/dist/tools/git.js +67 -0
- package/dist/tools/git.js.map +1 -0
- package/dist/tools/scout.d.ts +7 -0
- package/dist/tools/scout.d.ts.map +1 -0
- package/dist/tools/scout.js +199 -0
- package/dist/tools/scout.js.map +1 -0
- package/dist/tools/session.d.ts +7 -0
- package/dist/tools/session.d.ts.map +1 -0
- package/dist/tools/session.js +296 -0
- package/dist/tools/session.js.map +1 -0
- package/dist/types.d.ts +116 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +13 -0
- package/dist/types.js.map +1 -0
- package/package.json +63 -0
package/dist/formulas.js
ADDED
|
@@ -0,0 +1,245 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Formulas — typed, versioned, testable sweep recipes.
|
|
3
|
+
*
|
|
4
|
+
* A formula configures what a scout session looks for and how strictly
|
|
5
|
+
* it gates execution. Built-in formulas mirror the CLI's set; users can
|
|
6
|
+
* add custom formulas in `.blockspool/formulas/` as simple YAML files.
|
|
7
|
+
*/
|
|
8
|
+
import * as fs from 'node:fs';
|
|
9
|
+
import * as path from 'node:path';
|
|
10
|
+
// ---------------------------------------------------------------------------
|
|
11
|
+
// Built-in Formulas
|
|
12
|
+
// ---------------------------------------------------------------------------
|
|
13
|
+
export const BUILTIN_FORMULAS = [
|
|
14
|
+
{
|
|
15
|
+
name: 'security-audit',
|
|
16
|
+
version: 1,
|
|
17
|
+
description: 'Find and fix security vulnerabilities',
|
|
18
|
+
categories: ['security'],
|
|
19
|
+
min_confidence: 80,
|
|
20
|
+
risk_tolerance: 'low',
|
|
21
|
+
prompt: [
|
|
22
|
+
'Look for OWASP Top 10 vulnerabilities, insecure defaults,',
|
|
23
|
+
'missing input validation, credential exposure, and injection risks.',
|
|
24
|
+
'Focus on real vulnerabilities, not style issues.',
|
|
25
|
+
].join(' '),
|
|
26
|
+
max_prs: 10,
|
|
27
|
+
tags: ['security'],
|
|
28
|
+
},
|
|
29
|
+
{
|
|
30
|
+
name: 'test-coverage',
|
|
31
|
+
version: 1,
|
|
32
|
+
description: 'Add missing unit tests for untested code',
|
|
33
|
+
categories: ['test'],
|
|
34
|
+
min_confidence: 70,
|
|
35
|
+
risk_tolerance: 'medium',
|
|
36
|
+
prompt: [
|
|
37
|
+
'Find functions and modules with no test coverage.',
|
|
38
|
+
'Write focused unit tests with edge cases.',
|
|
39
|
+
'Prioritize business logic over utility functions.',
|
|
40
|
+
].join(' '),
|
|
41
|
+
max_prs: 15,
|
|
42
|
+
tags: ['quality'],
|
|
43
|
+
},
|
|
44
|
+
{
|
|
45
|
+
name: 'type-safety',
|
|
46
|
+
version: 1,
|
|
47
|
+
description: 'Strengthen TypeScript types and remove any/unknown',
|
|
48
|
+
categories: ['types'],
|
|
49
|
+
min_confidence: 75,
|
|
50
|
+
risk_tolerance: 'medium',
|
|
51
|
+
prompt: [
|
|
52
|
+
'Find uses of any, unknown, or weak typing.',
|
|
53
|
+
'Add proper type annotations, interfaces, and type guards.',
|
|
54
|
+
'Do not change runtime behavior.',
|
|
55
|
+
].join(' '),
|
|
56
|
+
max_prs: 10,
|
|
57
|
+
tags: ['quality'],
|
|
58
|
+
},
|
|
59
|
+
{
|
|
60
|
+
name: 'cleanup',
|
|
61
|
+
version: 1,
|
|
62
|
+
description: 'Remove dead code, unused imports, and stale comments',
|
|
63
|
+
categories: ['refactor'],
|
|
64
|
+
min_confidence: 85,
|
|
65
|
+
risk_tolerance: 'low',
|
|
66
|
+
prompt: [
|
|
67
|
+
'Find dead code, unused imports, unreachable branches,',
|
|
68
|
+
'commented-out code, and stale TODO comments.',
|
|
69
|
+
'Only remove things that are clearly unused.',
|
|
70
|
+
].join(' '),
|
|
71
|
+
max_prs: 10,
|
|
72
|
+
tags: ['cleanup'],
|
|
73
|
+
},
|
|
74
|
+
{
|
|
75
|
+
name: 'deep',
|
|
76
|
+
version: 1,
|
|
77
|
+
description: 'Find high-impact structural and architectural improvements',
|
|
78
|
+
categories: ['refactor', 'perf', 'security'],
|
|
79
|
+
min_confidence: 60,
|
|
80
|
+
risk_tolerance: 'high',
|
|
81
|
+
model: 'opus',
|
|
82
|
+
max_prs: 5,
|
|
83
|
+
prompt: [
|
|
84
|
+
'Principal engineer architecture review. Ignore trivial issues.',
|
|
85
|
+
'Focus on: leaky abstractions, silent error swallowing, coupling/circular deps,',
|
|
86
|
+
'mixed concerns (business logic + I/O), algorithmic perf issues,',
|
|
87
|
+
'missing security boundaries, brittle integration points.',
|
|
88
|
+
'Prefer moderate/complex complexity. Set impact_score 1-10.',
|
|
89
|
+
].join(' '),
|
|
90
|
+
tags: ['architecture', 'deep'],
|
|
91
|
+
},
|
|
92
|
+
{
|
|
93
|
+
name: 'docs',
|
|
94
|
+
version: 1,
|
|
95
|
+
description: 'Add or improve documentation for public APIs',
|
|
96
|
+
categories: ['docs'],
|
|
97
|
+
min_confidence: 70,
|
|
98
|
+
risk_tolerance: 'medium',
|
|
99
|
+
prompt: [
|
|
100
|
+
'Find exported functions, classes, and types missing JSDoc.',
|
|
101
|
+
'Add clear, concise documentation that explains the purpose,',
|
|
102
|
+
'parameters, and return values. Do not over-document obvious code.',
|
|
103
|
+
].join(' '),
|
|
104
|
+
max_prs: 10,
|
|
105
|
+
tags: ['docs'],
|
|
106
|
+
},
|
|
107
|
+
];
|
|
108
|
+
// ---------------------------------------------------------------------------
|
|
109
|
+
// Loader
|
|
110
|
+
// ---------------------------------------------------------------------------
|
|
111
|
+
/**
|
|
112
|
+
* Load a formula by name.
|
|
113
|
+
* Search order: user formulas in `.blockspool/formulas/`, then built-ins.
|
|
114
|
+
*/
|
|
115
|
+
export function loadFormula(name, projectPath) {
|
|
116
|
+
const userFormula = loadUserFormula(name, projectPath);
|
|
117
|
+
if (userFormula)
|
|
118
|
+
return userFormula;
|
|
119
|
+
return BUILTIN_FORMULAS.find(f => f.name === name) ?? null;
|
|
120
|
+
}
|
|
121
|
+
/**
|
|
122
|
+
* List all available formulas (user + built-in, user overrides built-in).
|
|
123
|
+
*/
|
|
124
|
+
export function listFormulas(projectPath) {
|
|
125
|
+
const userFormulas = loadAllUserFormulas(projectPath);
|
|
126
|
+
const userNames = new Set(userFormulas.map(f => f.name));
|
|
127
|
+
const builtins = BUILTIN_FORMULAS.filter(f => !userNames.has(f.name));
|
|
128
|
+
return [...userFormulas, ...builtins];
|
|
129
|
+
}
|
|
130
|
+
/**
|
|
131
|
+
* Apply a formula's settings to a SessionConfig.
|
|
132
|
+
* Formula values are defaults — explicit config values take precedence.
|
|
133
|
+
*/
|
|
134
|
+
export function applyFormula(formula, config) {
|
|
135
|
+
return {
|
|
136
|
+
...config,
|
|
137
|
+
scope: config.scope ?? formula.scope,
|
|
138
|
+
categories: config.categories ?? formula.categories,
|
|
139
|
+
min_confidence: config.min_confidence ?? formula.min_confidence,
|
|
140
|
+
max_prs: config.max_prs ?? formula.max_prs,
|
|
141
|
+
// formula name stays as-is for prompt injection
|
|
142
|
+
formula: config.formula,
|
|
143
|
+
};
|
|
144
|
+
}
|
|
145
|
+
// ---------------------------------------------------------------------------
|
|
146
|
+
// User formulas (YAML)
|
|
147
|
+
// ---------------------------------------------------------------------------
|
|
148
|
+
function getFormulasDir(projectPath) {
|
|
149
|
+
const base = projectPath ?? process.cwd();
|
|
150
|
+
return path.join(base, '.blockspool', 'formulas');
|
|
151
|
+
}
|
|
152
|
+
function loadUserFormula(name, projectPath) {
|
|
153
|
+
const dir = getFormulasDir(projectPath);
|
|
154
|
+
for (const ext of ['.yaml', '.yml']) {
|
|
155
|
+
const filePath = path.join(dir, `${name}${ext}`);
|
|
156
|
+
if (fs.existsSync(filePath)) {
|
|
157
|
+
return parseFormulaFile(filePath, name);
|
|
158
|
+
}
|
|
159
|
+
}
|
|
160
|
+
return null;
|
|
161
|
+
}
|
|
162
|
+
function loadAllUserFormulas(projectPath) {
|
|
163
|
+
const dir = getFormulasDir(projectPath);
|
|
164
|
+
if (!fs.existsSync(dir))
|
|
165
|
+
return [];
|
|
166
|
+
const files = fs.readdirSync(dir).filter(f => f.endsWith('.yaml') || f.endsWith('.yml'));
|
|
167
|
+
const formulas = [];
|
|
168
|
+
for (const file of files) {
|
|
169
|
+
const name = path.basename(file, path.extname(file));
|
|
170
|
+
const formula = parseFormulaFile(path.join(dir, file), name);
|
|
171
|
+
if (formula)
|
|
172
|
+
formulas.push(formula);
|
|
173
|
+
}
|
|
174
|
+
return formulas;
|
|
175
|
+
}
|
|
176
|
+
function parseFormulaFile(filePath, name) {
|
|
177
|
+
try {
|
|
178
|
+
const content = fs.readFileSync(filePath, 'utf-8');
|
|
179
|
+
const parsed = parseSimpleYaml(content);
|
|
180
|
+
return {
|
|
181
|
+
name,
|
|
182
|
+
version: parsed.version ? parseInt(parsed.version, 10) : 1,
|
|
183
|
+
description: parsed.description || `Formula: ${name}`,
|
|
184
|
+
scope: parsed.scope,
|
|
185
|
+
categories: parsed.categories ? parseStringList(parsed.categories) : undefined,
|
|
186
|
+
min_confidence: parsed.min_confidence ? parseInt(parsed.min_confidence, 10) : undefined,
|
|
187
|
+
prompt: parsed.prompt,
|
|
188
|
+
max_prs: parsed.max_prs ? parseInt(parsed.max_prs, 10) : undefined,
|
|
189
|
+
model: parsed.model,
|
|
190
|
+
risk_tolerance: parsed.risk_tolerance,
|
|
191
|
+
tags: parsed.tags ? parseStringList(parsed.tags) : undefined,
|
|
192
|
+
};
|
|
193
|
+
}
|
|
194
|
+
catch {
|
|
195
|
+
return null;
|
|
196
|
+
}
|
|
197
|
+
}
|
|
198
|
+
// ---------------------------------------------------------------------------
|
|
199
|
+
// Simple YAML parser (avoids external dependency)
|
|
200
|
+
// ---------------------------------------------------------------------------
|
|
201
|
+
function parseSimpleYaml(content) {
|
|
202
|
+
const result = {};
|
|
203
|
+
const lines = content.split('\n');
|
|
204
|
+
let currentKey = null;
|
|
205
|
+
let multilineValue = [];
|
|
206
|
+
let multilineIndent = 0;
|
|
207
|
+
for (const line of lines) {
|
|
208
|
+
if (!currentKey && (line.trim().startsWith('#') || line.trim() === ''))
|
|
209
|
+
continue;
|
|
210
|
+
if (currentKey) {
|
|
211
|
+
const indent = line.length - line.trimStart().length;
|
|
212
|
+
if (indent > multilineIndent && line.trim() !== '') {
|
|
213
|
+
multilineValue.push(line.trim());
|
|
214
|
+
continue;
|
|
215
|
+
}
|
|
216
|
+
else {
|
|
217
|
+
result[currentKey] = multilineValue.join(' ');
|
|
218
|
+
currentKey = null;
|
|
219
|
+
multilineValue = [];
|
|
220
|
+
}
|
|
221
|
+
}
|
|
222
|
+
const match = line.match(/^(\w[\w_-]*)\s*:\s*(.*)/);
|
|
223
|
+
if (match) {
|
|
224
|
+
const [, key, value] = match;
|
|
225
|
+
const trimmedValue = value.trim();
|
|
226
|
+
if (trimmedValue === '|' || trimmedValue === '>') {
|
|
227
|
+
currentKey = key;
|
|
228
|
+
multilineIndent = line.length - line.trimStart().length;
|
|
229
|
+
multilineValue = [];
|
|
230
|
+
}
|
|
231
|
+
else {
|
|
232
|
+
result[key] = trimmedValue;
|
|
233
|
+
}
|
|
234
|
+
}
|
|
235
|
+
}
|
|
236
|
+
if (currentKey) {
|
|
237
|
+
result[currentKey] = multilineValue.join(' ');
|
|
238
|
+
}
|
|
239
|
+
return result;
|
|
240
|
+
}
|
|
241
|
+
function parseStringList(value) {
|
|
242
|
+
const stripped = value.replace(/^\[/, '').replace(/\]$/, '');
|
|
243
|
+
return stripped.split(',').map(s => s.trim()).filter(s => s.length > 0);
|
|
244
|
+
}
|
|
245
|
+
//# sourceMappingURL=formulas.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"formulas.js","sourceRoot":"","sources":["../src/formulas.ts"],"names":[],"mappings":"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"}
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";AACA;;;;;GAKG"}
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
/**
|
|
3
|
+
* @blockspool/mcp — MCP server entry point
|
|
4
|
+
*
|
|
5
|
+
* Runs as a stdio MCP server for Claude Code.
|
|
6
|
+
* Usage: npx @blockspool/mcp
|
|
7
|
+
*/
|
|
8
|
+
import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js';
|
|
9
|
+
import { createSQLiteAdapter } from '@blockspool/sqlite';
|
|
10
|
+
import { createServer } from './server.js';
|
|
11
|
+
import * as path from 'node:path';
|
|
12
|
+
import * as fs from 'node:fs';
|
|
13
|
+
async function main() {
|
|
14
|
+
const projectPath = process.env.BLOCKSPOOL_PROJECT_PATH ?? process.cwd();
|
|
15
|
+
// Determine DB path
|
|
16
|
+
const bsDir = path.join(projectPath, '.blockspool');
|
|
17
|
+
if (!fs.existsSync(bsDir)) {
|
|
18
|
+
fs.mkdirSync(bsDir, { recursive: true });
|
|
19
|
+
}
|
|
20
|
+
const dbPath = path.join(bsDir, 'state.sqlite');
|
|
21
|
+
const db = await createSQLiteAdapter({ url: dbPath });
|
|
22
|
+
const { server } = await createServer({
|
|
23
|
+
db,
|
|
24
|
+
projectPath,
|
|
25
|
+
});
|
|
26
|
+
const transport = new StdioServerTransport();
|
|
27
|
+
await server.connect(transport);
|
|
28
|
+
// Graceful shutdown
|
|
29
|
+
process.on('SIGINT', async () => {
|
|
30
|
+
await db.close();
|
|
31
|
+
process.exit(0);
|
|
32
|
+
});
|
|
33
|
+
process.on('SIGTERM', async () => {
|
|
34
|
+
await db.close();
|
|
35
|
+
process.exit(0);
|
|
36
|
+
});
|
|
37
|
+
}
|
|
38
|
+
main().catch((err) => {
|
|
39
|
+
console.error('BlockSpool MCP server failed to start:', err);
|
|
40
|
+
process.exit(1);
|
|
41
|
+
});
|
|
42
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";AACA;;;;;GAKG;AAEH,OAAO,EAAE,oBAAoB,EAAE,MAAM,2CAA2C,CAAC;AACjF,OAAO,EAAE,mBAAmB,EAAE,MAAM,oBAAoB,CAAC;AACzD,OAAO,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAC3C,OAAO,KAAK,IAAI,MAAM,WAAW,CAAC;AAClC,OAAO,KAAK,EAAE,MAAM,SAAS,CAAC;AAE9B,KAAK,UAAU,IAAI;IACjB,MAAM,WAAW,GAAG,OAAO,CAAC,GAAG,CAAC,uBAAuB,IAAI,OAAO,CAAC,GAAG,EAAE,CAAC;IAEzE,oBAAoB;IACpB,MAAM,KAAK,GAAG,IAAI,CAAC,IAAI,CAAC,WAAW,EAAE,aAAa,CAAC,CAAC;IACpD,IAAI,CAAC,EAAE,CAAC,UAAU,CAAC,KAAK,CAAC,EAAE,CAAC;QAC1B,EAAE,CAAC,SAAS,CAAC,KAAK,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;IAC3C,CAAC;IACD,MAAM,MAAM,GAAG,IAAI,CAAC,IAAI,CAAC,KAAK,EAAE,cAAc,CAAC,CAAC;IAEhD,MAAM,EAAE,GAAG,MAAM,mBAAmB,CAAC,EAAE,GAAG,EAAE,MAAM,EAAE,CAAC,CAAC;IAEtD,MAAM,EAAE,MAAM,EAAE,GAAG,MAAM,YAAY,CAAC;QACpC,EAAE;QACF,WAAW;KACZ,CAAC,CAAC;IAEH,MAAM,SAAS,GAAG,IAAI,oBAAoB,EAAE,CAAC;IAC7C,MAAM,MAAM,CAAC,OAAO,CAAC,SAAS,CAAC,CAAC;IAEhC,oBAAoB;IACpB,OAAO,CAAC,EAAE,CAAC,QAAQ,EAAE,KAAK,IAAI,EAAE;QAC9B,MAAM,EAAE,CAAC,KAAK,EAAE,CAAC;QACjB,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC,CAAC,CAAC;IACH,OAAO,CAAC,EAAE,CAAC,SAAS,EAAE,KAAK,IAAI,EAAE;QAC/B,MAAM,EAAE,CAAC,KAAK,EAAE,CAAC;QACjB,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC,CAAC,CAAC;AACL,CAAC;AAED,IAAI,EAAE,CAAC,KAAK,CAAC,CAAC,GAAG,EAAE,EAAE;IACnB,OAAO,CAAC,KAAK,CAAC,wCAAwC,EAAE,GAAG,CAAC,CAAC;IAC7D,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;AAClB,CAAC,CAAC,CAAC"}
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Proposal filtering, dedup, scoring, and ticket creation.
|
|
3
|
+
*
|
|
4
|
+
* Used by the event processor when SCOUT_OUTPUT is ingested,
|
|
5
|
+
* and by the blockspool_submit_proposals tool.
|
|
6
|
+
*/
|
|
7
|
+
import type { DatabaseAdapter } from '@blockspool/core';
|
|
8
|
+
import { RunManager } from './run-manager.js';
|
|
9
|
+
export interface RawProposal {
|
|
10
|
+
category?: string;
|
|
11
|
+
title?: string;
|
|
12
|
+
description?: string;
|
|
13
|
+
acceptance_criteria?: string[];
|
|
14
|
+
verification_commands?: string[];
|
|
15
|
+
allowed_paths?: string[];
|
|
16
|
+
files?: string[];
|
|
17
|
+
confidence?: number;
|
|
18
|
+
impact_score?: number;
|
|
19
|
+
rationale?: string;
|
|
20
|
+
estimated_complexity?: string;
|
|
21
|
+
risk?: string;
|
|
22
|
+
touched_files_estimate?: number;
|
|
23
|
+
rollback_note?: string;
|
|
24
|
+
}
|
|
25
|
+
export interface ValidatedProposal {
|
|
26
|
+
category: string;
|
|
27
|
+
title: string;
|
|
28
|
+
description: string;
|
|
29
|
+
acceptance_criteria: string[];
|
|
30
|
+
verification_commands: string[];
|
|
31
|
+
allowed_paths: string[];
|
|
32
|
+
files: string[];
|
|
33
|
+
confidence: number;
|
|
34
|
+
impact_score: number;
|
|
35
|
+
rationale: string;
|
|
36
|
+
estimated_complexity: string;
|
|
37
|
+
risk: string;
|
|
38
|
+
touched_files_estimate: number;
|
|
39
|
+
rollback_note: string;
|
|
40
|
+
}
|
|
41
|
+
export interface FilterResult {
|
|
42
|
+
accepted: ValidatedProposal[];
|
|
43
|
+
rejected: Array<{
|
|
44
|
+
proposal: RawProposal;
|
|
45
|
+
reason: string;
|
|
46
|
+
}>;
|
|
47
|
+
created_ticket_ids: string[];
|
|
48
|
+
}
|
|
49
|
+
export declare function filterAndCreateTickets(run: RunManager, db: DatabaseAdapter, rawProposals: RawProposal[]): Promise<FilterResult>;
|
|
50
|
+
export declare function titleSimilarity(a: string, b: string): number;
|
|
51
|
+
//# sourceMappingURL=proposals.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"proposals.d.ts","sourceRoot":"","sources":["../src/proposals.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,KAAK,EAAE,eAAe,EAAkB,MAAM,kBAAkB,CAAC;AAExE,OAAO,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAC;AAM9C,MAAM,WAAW,WAAW;IAC1B,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,mBAAmB,CAAC,EAAE,MAAM,EAAE,CAAC;IAC/B,qBAAqB,CAAC,EAAE,MAAM,EAAE,CAAC;IACjC,aAAa,CAAC,EAAE,MAAM,EAAE,CAAC;IACzB,KAAK,CAAC,EAAE,MAAM,EAAE,CAAC;IACjB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,oBAAoB,CAAC,EAAE,MAAM,CAAC;IAC9B,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,sBAAsB,CAAC,EAAE,MAAM,CAAC;IAChC,aAAa,CAAC,EAAE,MAAM,CAAC;CACxB;AAED,MAAM,WAAW,iBAAiB;IAChC,QAAQ,EAAE,MAAM,CAAC;IACjB,KAAK,EAAE,MAAM,CAAC;IACd,WAAW,EAAE,MAAM,CAAC;IACpB,mBAAmB,EAAE,MAAM,EAAE,CAAC;IAC9B,qBAAqB,EAAE,MAAM,EAAE,CAAC;IAChC,aAAa,EAAE,MAAM,EAAE,CAAC;IACxB,KAAK,EAAE,MAAM,EAAE,CAAC;IAChB,UAAU,EAAE,MAAM,CAAC;IACnB,YAAY,EAAE,MAAM,CAAC;IACrB,SAAS,EAAE,MAAM,CAAC;IAClB,oBAAoB,EAAE,MAAM,CAAC;IAC7B,IAAI,EAAE,MAAM,CAAC;IACb,sBAAsB,EAAE,MAAM,CAAC;IAC/B,aAAa,EAAE,MAAM,CAAC;CACvB;AAED,MAAM,WAAW,YAAY;IAC3B,QAAQ,EAAE,iBAAiB,EAAE,CAAC;IAC9B,QAAQ,EAAE,KAAK,CAAC;QAAE,QAAQ,EAAE,WAAW,CAAC;QAAC,MAAM,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;IAC3D,kBAAkB,EAAE,MAAM,EAAE,CAAC;CAC9B;AAYD,wBAAsB,sBAAsB,CAC1C,GAAG,EAAE,UAAU,EACf,EAAE,EAAE,eAAe,EACnB,YAAY,EAAE,WAAW,EAAE,GAC1B,OAAO,CAAC,YAAY,CAAC,CAuGvB;AA8CD,wBAAgB,eAAe,CAAC,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,MAAM,GAAG,MAAM,CAc5D"}
|
|
@@ -0,0 +1,207 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Proposal filtering, dedup, scoring, and ticket creation.
|
|
3
|
+
*
|
|
4
|
+
* Used by the event processor when SCOUT_OUTPUT is ingested,
|
|
5
|
+
* and by the blockspool_submit_proposals tool.
|
|
6
|
+
*/
|
|
7
|
+
import { repos } from '@blockspool/core';
|
|
8
|
+
const REQUIRED_FIELDS = [
|
|
9
|
+
'category', 'title', 'description', 'allowed_paths',
|
|
10
|
+
'files', 'confidence', 'verification_commands',
|
|
11
|
+
'risk', 'touched_files_estimate', 'rollback_note',
|
|
12
|
+
];
|
|
13
|
+
// ---------------------------------------------------------------------------
|
|
14
|
+
// Main entry: filter + create tickets
|
|
15
|
+
// ---------------------------------------------------------------------------
|
|
16
|
+
export async function filterAndCreateTickets(run, db, rawProposals) {
|
|
17
|
+
const s = run.require();
|
|
18
|
+
const rejected = [];
|
|
19
|
+
// Step 1: Schema validation
|
|
20
|
+
const valid = [];
|
|
21
|
+
for (const raw of rawProposals) {
|
|
22
|
+
const missing = validateSchema(raw);
|
|
23
|
+
if (missing) {
|
|
24
|
+
rejected.push({ proposal: raw, reason: `Missing fields: ${missing}` });
|
|
25
|
+
continue;
|
|
26
|
+
}
|
|
27
|
+
valid.push(normalizeProposal(raw));
|
|
28
|
+
}
|
|
29
|
+
// Step 2: Confidence filter
|
|
30
|
+
const afterConfidence = valid.filter(p => {
|
|
31
|
+
if (p.confidence < s.min_confidence) {
|
|
32
|
+
rejected.push({ proposal: p, reason: `Confidence ${p.confidence} below min ${s.min_confidence}` });
|
|
33
|
+
return false;
|
|
34
|
+
}
|
|
35
|
+
return true;
|
|
36
|
+
});
|
|
37
|
+
// Step 3: Category trust ladder
|
|
38
|
+
const allowedCategories = new Set(s.categories);
|
|
39
|
+
const afterCategory = afterConfidence.filter(p => {
|
|
40
|
+
if (!allowedCategories.has(p.category)) {
|
|
41
|
+
rejected.push({ proposal: p, reason: `Category '${p.category}' not in trust ladder` });
|
|
42
|
+
return false;
|
|
43
|
+
}
|
|
44
|
+
return true;
|
|
45
|
+
});
|
|
46
|
+
// Step 4: Dedup against existing tickets (title similarity)
|
|
47
|
+
const existingTickets = await repos.tickets.listByProject(db, s.project_id);
|
|
48
|
+
const existingTitles = existingTickets.map(t => t.title);
|
|
49
|
+
const afterDedup = afterCategory.filter(p => {
|
|
50
|
+
const isDupe = existingTitles.some(t => titleSimilarity(t, p.title) >= 0.6);
|
|
51
|
+
if (isDupe) {
|
|
52
|
+
rejected.push({ proposal: p, reason: 'Duplicate of existing ticket (title similarity >= 0.6)' });
|
|
53
|
+
return false;
|
|
54
|
+
}
|
|
55
|
+
return true;
|
|
56
|
+
});
|
|
57
|
+
// Also dedup within the batch
|
|
58
|
+
const uniqueByTitle = [];
|
|
59
|
+
for (const p of afterDedup) {
|
|
60
|
+
const isDupeInBatch = uniqueByTitle.some(q => titleSimilarity(q.title, p.title) >= 0.6);
|
|
61
|
+
if (isDupeInBatch) {
|
|
62
|
+
rejected.push({ proposal: p, reason: 'Duplicate within batch (title similarity >= 0.6)' });
|
|
63
|
+
continue;
|
|
64
|
+
}
|
|
65
|
+
uniqueByTitle.push(p);
|
|
66
|
+
}
|
|
67
|
+
// Step 5: Score and cap
|
|
68
|
+
const scored = uniqueByTitle
|
|
69
|
+
.map(p => ({
|
|
70
|
+
proposal: p,
|
|
71
|
+
score: (p.impact_score ?? 5) * p.confidence,
|
|
72
|
+
}))
|
|
73
|
+
.sort((a, b) => b.score - a.score)
|
|
74
|
+
.slice(0, s.max_proposals_per_scout);
|
|
75
|
+
const accepted = scored.map(s => s.proposal);
|
|
76
|
+
// Step 6: Create tickets
|
|
77
|
+
const ticketInputs = accepted.map(p => ({
|
|
78
|
+
projectId: s.project_id,
|
|
79
|
+
title: p.title,
|
|
80
|
+
description: formatDescription(p),
|
|
81
|
+
status: 'ready',
|
|
82
|
+
priority: Math.round((p.impact_score ?? 5) * p.confidence / 10),
|
|
83
|
+
category: p.category,
|
|
84
|
+
allowedPaths: p.allowed_paths,
|
|
85
|
+
verificationCommands: p.verification_commands,
|
|
86
|
+
}));
|
|
87
|
+
let createdIds = [];
|
|
88
|
+
if (ticketInputs.length > 0) {
|
|
89
|
+
const created = await repos.tickets.createMany(db, ticketInputs);
|
|
90
|
+
createdIds = created.map(t => t.id);
|
|
91
|
+
run.appendEvent('TICKETS_CREATED', {
|
|
92
|
+
count: created.length,
|
|
93
|
+
ids: createdIds,
|
|
94
|
+
titles: accepted.map(p => p.title),
|
|
95
|
+
});
|
|
96
|
+
}
|
|
97
|
+
run.appendEvent('PROPOSALS_FILTERED', {
|
|
98
|
+
submitted: rawProposals.length,
|
|
99
|
+
valid: valid.length,
|
|
100
|
+
after_confidence: afterConfidence.length,
|
|
101
|
+
after_category: afterCategory.length,
|
|
102
|
+
after_dedup: uniqueByTitle.length,
|
|
103
|
+
accepted: accepted.length,
|
|
104
|
+
rejected_count: rejected.length,
|
|
105
|
+
});
|
|
106
|
+
return { accepted, rejected, created_ticket_ids: createdIds };
|
|
107
|
+
}
|
|
108
|
+
// ---------------------------------------------------------------------------
|
|
109
|
+
// Schema validation
|
|
110
|
+
// ---------------------------------------------------------------------------
|
|
111
|
+
function validateSchema(raw) {
|
|
112
|
+
const missing = [];
|
|
113
|
+
if (!raw.category || typeof raw.category !== 'string')
|
|
114
|
+
missing.push('category');
|
|
115
|
+
if (!raw.title || typeof raw.title !== 'string')
|
|
116
|
+
missing.push('title');
|
|
117
|
+
if (!raw.description || typeof raw.description !== 'string')
|
|
118
|
+
missing.push('description');
|
|
119
|
+
if (!Array.isArray(raw.allowed_paths))
|
|
120
|
+
missing.push('allowed_paths');
|
|
121
|
+
if (!Array.isArray(raw.files))
|
|
122
|
+
missing.push('files');
|
|
123
|
+
if (typeof raw.confidence !== 'number')
|
|
124
|
+
missing.push('confidence');
|
|
125
|
+
if (!Array.isArray(raw.verification_commands))
|
|
126
|
+
missing.push('verification_commands');
|
|
127
|
+
if (!raw.risk || typeof raw.risk !== 'string')
|
|
128
|
+
missing.push('risk');
|
|
129
|
+
if (typeof raw.touched_files_estimate !== 'number')
|
|
130
|
+
missing.push('touched_files_estimate');
|
|
131
|
+
if (!raw.rollback_note || typeof raw.rollback_note !== 'string')
|
|
132
|
+
missing.push('rollback_note');
|
|
133
|
+
return missing.length > 0 ? missing.join(', ') : null;
|
|
134
|
+
}
|
|
135
|
+
function normalizeProposal(raw) {
|
|
136
|
+
return {
|
|
137
|
+
category: raw.category,
|
|
138
|
+
title: raw.title,
|
|
139
|
+
description: raw.description,
|
|
140
|
+
acceptance_criteria: raw.acceptance_criteria ?? [],
|
|
141
|
+
verification_commands: raw.verification_commands ?? [],
|
|
142
|
+
allowed_paths: raw.allowed_paths ?? [],
|
|
143
|
+
files: raw.files ?? [],
|
|
144
|
+
confidence: raw.confidence,
|
|
145
|
+
impact_score: raw.impact_score ?? 5,
|
|
146
|
+
rationale: raw.rationale ?? '',
|
|
147
|
+
estimated_complexity: raw.estimated_complexity ?? 'moderate',
|
|
148
|
+
risk: raw.risk,
|
|
149
|
+
touched_files_estimate: raw.touched_files_estimate,
|
|
150
|
+
rollback_note: raw.rollback_note,
|
|
151
|
+
};
|
|
152
|
+
}
|
|
153
|
+
// ---------------------------------------------------------------------------
|
|
154
|
+
// Title similarity (Jaccard on bigrams, case-insensitive)
|
|
155
|
+
// ---------------------------------------------------------------------------
|
|
156
|
+
export function titleSimilarity(a, b) {
|
|
157
|
+
const bigramsA = bigrams(a.toLowerCase());
|
|
158
|
+
const bigramsB = bigrams(b.toLowerCase());
|
|
159
|
+
if (bigramsA.size === 0 && bigramsB.size === 0)
|
|
160
|
+
return 1;
|
|
161
|
+
if (bigramsA.size === 0 || bigramsB.size === 0)
|
|
162
|
+
return 0;
|
|
163
|
+
let intersection = 0;
|
|
164
|
+
for (const bg of bigramsA) {
|
|
165
|
+
if (bigramsB.has(bg))
|
|
166
|
+
intersection++;
|
|
167
|
+
}
|
|
168
|
+
const union = bigramsA.size + bigramsB.size - intersection;
|
|
169
|
+
return union === 0 ? 0 : intersection / union;
|
|
170
|
+
}
|
|
171
|
+
function bigrams(s) {
|
|
172
|
+
const result = new Set();
|
|
173
|
+
const cleaned = s.replace(/[^a-z0-9 ]/g, '').trim();
|
|
174
|
+
for (let i = 0; i < cleaned.length - 1; i++) {
|
|
175
|
+
result.add(cleaned.slice(i, i + 2));
|
|
176
|
+
}
|
|
177
|
+
return result;
|
|
178
|
+
}
|
|
179
|
+
// ---------------------------------------------------------------------------
|
|
180
|
+
// Description formatter
|
|
181
|
+
// ---------------------------------------------------------------------------
|
|
182
|
+
function formatDescription(p) {
|
|
183
|
+
const parts = [
|
|
184
|
+
p.description,
|
|
185
|
+
'',
|
|
186
|
+
'## Acceptance Criteria',
|
|
187
|
+
...p.acceptance_criteria.map(c => `- ${c}`),
|
|
188
|
+
'',
|
|
189
|
+
'## Details',
|
|
190
|
+
`**Risk:** ${p.risk}`,
|
|
191
|
+
`**Complexity:** ${p.estimated_complexity}`,
|
|
192
|
+
`**Confidence:** ${p.confidence}%`,
|
|
193
|
+
`**Impact:** ${p.impact_score}/10`,
|
|
194
|
+
`**Estimated files:** ${p.touched_files_estimate}`,
|
|
195
|
+
'',
|
|
196
|
+
'## Rollback',
|
|
197
|
+
p.rollback_note,
|
|
198
|
+
];
|
|
199
|
+
if (p.rationale) {
|
|
200
|
+
parts.push('', '## Rationale', p.rationale);
|
|
201
|
+
}
|
|
202
|
+
if (p.files.length > 0) {
|
|
203
|
+
parts.push('', '## Files', ...p.files.map(f => `- \`${f}\``));
|
|
204
|
+
}
|
|
205
|
+
return parts.join('\n');
|
|
206
|
+
}
|
|
207
|
+
//# sourceMappingURL=proposals.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"proposals.js","sourceRoot":"","sources":["../src/proposals.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Run Manager — creates and manages run folders on disk.
|
|
3
|
+
*
|
|
4
|
+
* Each run lives at `.blockspool/runs/<run_id>/` and contains:
|
|
5
|
+
* - state.json — current RunState (overwritten on every change)
|
|
6
|
+
* - events.ndjson — append-only event log
|
|
7
|
+
* - diffs/ — patch files per step
|
|
8
|
+
* - artifacts/ — QA logs, scout proposals, etc.
|
|
9
|
+
*/
|
|
10
|
+
import type { RunState, EventType, Phase, SessionConfig } from './types.js';
|
|
11
|
+
export declare class RunManager {
|
|
12
|
+
private readonly projectPath;
|
|
13
|
+
private state;
|
|
14
|
+
private runDir;
|
|
15
|
+
private eventsPath;
|
|
16
|
+
constructor(projectPath: string);
|
|
17
|
+
/** The base .blockspool directory */
|
|
18
|
+
private get bsDir();
|
|
19
|
+
/** Create a new run, write initial state.json and SESSION_START event */
|
|
20
|
+
create(projectId: string, config: SessionConfig): RunState;
|
|
21
|
+
/** Get current state or throw */
|
|
22
|
+
require(): RunState;
|
|
23
|
+
/** Get current state (may be null) */
|
|
24
|
+
get current(): RunState | null;
|
|
25
|
+
/** Get run directory path */
|
|
26
|
+
get dir(): string | null;
|
|
27
|
+
/** Transition to a new phase */
|
|
28
|
+
setPhase(phase: Phase): void;
|
|
29
|
+
/** Increment step counter (called on each advance) */
|
|
30
|
+
incrementStep(): void;
|
|
31
|
+
/** Assign a ticket as current work */
|
|
32
|
+
assignTicket(ticketId: string): void;
|
|
33
|
+
/** Mark current ticket completed */
|
|
34
|
+
completeTicket(): void;
|
|
35
|
+
/** Mark current ticket failed */
|
|
36
|
+
failTicket(reason: string): void;
|
|
37
|
+
/** Add a hint */
|
|
38
|
+
addHint(hint: string): void;
|
|
39
|
+
/** Consume and return all pending hints */
|
|
40
|
+
consumeHints(): string[];
|
|
41
|
+
/** End the run */
|
|
42
|
+
end(): RunState;
|
|
43
|
+
/** Append an event to events.ndjson */
|
|
44
|
+
appendEvent(type: EventType, payload: Record<string, unknown>): void;
|
|
45
|
+
/** Save an artifact file */
|
|
46
|
+
saveArtifact(filename: string, content: string): void;
|
|
47
|
+
/** Save a diff/patch file */
|
|
48
|
+
saveDiff(step: number, ticketId: string, patch: string): void;
|
|
49
|
+
/** Check if any budget is exhausted */
|
|
50
|
+
isBudgetExhausted(): {
|
|
51
|
+
exhausted: boolean;
|
|
52
|
+
which?: string;
|
|
53
|
+
};
|
|
54
|
+
/** Check if approaching budget limits (80%) */
|
|
55
|
+
getBudgetWarnings(): string[];
|
|
56
|
+
/** Build the digest for advance responses */
|
|
57
|
+
buildDigest(): {
|
|
58
|
+
step: number;
|
|
59
|
+
phase: string;
|
|
60
|
+
tickets_completed: number;
|
|
61
|
+
tickets_failed: number;
|
|
62
|
+
budget_remaining: number;
|
|
63
|
+
ticket_budget_remaining: number;
|
|
64
|
+
spindle_risk: 'none' | 'low' | 'medium' | 'high';
|
|
65
|
+
time_remaining_ms: number | null;
|
|
66
|
+
};
|
|
67
|
+
private persistState;
|
|
68
|
+
}
|
|
69
|
+
//# sourceMappingURL=run-manager.d.ts.map
|