@promptwheel/mcp 0.6.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 +178 -0
- package/dist/advance-helpers.d.ts +27 -0
- package/dist/advance-helpers.d.ts.map +1 -0
- package/dist/advance-helpers.js +127 -0
- package/dist/advance-helpers.js.map +1 -0
- package/dist/advance-prompts.d.ts +48 -0
- package/dist/advance-prompts.d.ts.map +1 -0
- package/dist/advance-prompts.js +420 -0
- package/dist/advance-prompts.js.map +1 -0
- package/dist/advance.d.ts +30 -0
- package/dist/advance.d.ts.map +1 -0
- package/dist/advance.js +752 -0
- package/dist/advance.js.map +1 -0
- package/dist/codebase-index.d.ts +5 -0
- package/dist/codebase-index.d.ts.map +1 -0
- package/dist/codebase-index.js +5 -0
- package/dist/codebase-index.js.map +1 -0
- package/dist/dedup-memory.d.ts +30 -0
- package/dist/dedup-memory.d.ts.map +1 -0
- package/dist/dedup-memory.js +76 -0
- package/dist/dedup-memory.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-handlers-qa.d.ts +5 -0
- package/dist/event-handlers-qa.d.ts.map +1 -0
- package/dist/event-handlers-qa.js +186 -0
- package/dist/event-handlers-qa.js.map +1 -0
- package/dist/event-handlers-scout.d.ts +5 -0
- package/dist/event-handlers-scout.d.ts.map +1 -0
- package/dist/event-handlers-scout.js +270 -0
- package/dist/event-handlers-scout.js.map +1 -0
- package/dist/event-handlers-ticket.d.ts +5 -0
- package/dist/event-handlers-ticket.d.ts.map +1 -0
- package/dist/event-handlers-ticket.js +232 -0
- package/dist/event-handlers-ticket.js.map +1 -0
- package/dist/event-helpers.d.ts +46 -0
- package/dist/event-helpers.d.ts.map +1 -0
- package/dist/event-helpers.js +125 -0
- package/dist/event-helpers.js.map +1 -0
- package/dist/event-processor.d.ts +15 -0
- package/dist/event-processor.d.ts.map +1 -0
- package/dist/event-processor.js +111 -0
- package/dist/event-processor.js.map +1 -0
- package/dist/formulas.d.ts +27 -0
- package/dist/formulas.d.ts.map +1 -0
- package/dist/formulas.js +109 -0
- package/dist/formulas.js.map +1 -0
- package/dist/guidelines.d.ts +16 -0
- package/dist/guidelines.d.ts.map +1 -0
- package/dist/guidelines.js +44 -0
- package/dist/guidelines.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/learnings.d.ts +42 -0
- package/dist/learnings.d.ts.map +1 -0
- package/dist/learnings.js +117 -0
- package/dist/learnings.js.map +1 -0
- package/dist/project-metadata.d.ts +34 -0
- package/dist/project-metadata.d.ts.map +1 -0
- package/dist/project-metadata.js +617 -0
- package/dist/project-metadata.js.map +1 -0
- package/dist/proposals.d.ts +23 -0
- package/dist/proposals.d.ts.map +1 -0
- package/dist/proposals.js +201 -0
- package/dist/proposals.js.map +1 -0
- package/dist/qa-stats.d.ts +51 -0
- package/dist/qa-stats.d.ts.map +1 -0
- package/dist/qa-stats.js +121 -0
- package/dist/qa-stats.js.map +1 -0
- package/dist/run-manager.d.ts +97 -0
- package/dist/run-manager.d.ts.map +1 -0
- package/dist/run-manager.js +583 -0
- package/dist/run-manager.js.map +1 -0
- package/dist/run-state-bridge.d.ts +13 -0
- package/dist/run-state-bridge.d.ts.map +1 -0
- package/dist/run-state-bridge.js +101 -0
- package/dist/run-state-bridge.js.map +1 -0
- package/dist/scope-policy.d.ts +83 -0
- package/dist/scope-policy.d.ts.map +1 -0
- package/dist/scope-policy.js +278 -0
- package/dist/scope-policy.js.map +1 -0
- package/dist/server.d.ts +18 -0
- package/dist/server.d.ts.map +1 -0
- package/dist/server.js +35 -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 +230 -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/ticket-worker.d.ts +37 -0
- package/dist/ticket-worker.d.ts.map +1 -0
- package/dist/ticket-worker.js +527 -0
- package/dist/ticket-worker.js.map +1 -0
- package/dist/tool-registry.d.ts +35 -0
- package/dist/tool-registry.d.ts.map +1 -0
- package/dist/tool-registry.js +129 -0
- package/dist/tool-registry.js.map +1 -0
- package/dist/tools/execute.d.ts +17 -0
- package/dist/tools/execute.d.ts.map +1 -0
- package/dist/tools/execute.js +418 -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 +98 -0
- package/dist/tools/git.js.map +1 -0
- package/dist/tools/intelligence.d.ts +10 -0
- package/dist/tools/intelligence.d.ts.map +1 -0
- package/dist/tools/intelligence.js +432 -0
- package/dist/tools/intelligence.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 +533 -0
- package/dist/tools/session.js.map +1 -0
- package/dist/tools/trajectory.d.ts +10 -0
- package/dist/tools/trajectory.d.ts.map +1 -0
- package/dist/tools/trajectory.js +374 -0
- package/dist/tools/trajectory.js.map +1 -0
- package/dist/trajectory-io.d.ts +21 -0
- package/dist/trajectory-io.d.ts.map +1 -0
- package/dist/trajectory-io.js +105 -0
- package/dist/trajectory-io.js.map +1 -0
- package/dist/types.d.ts +229 -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
|
@@ -0,0 +1,527 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Ticket Worker — self-contained mini state machine for one ticket in parallel mode.
|
|
3
|
+
*
|
|
4
|
+
* Each ticket worker follows: PLAN → EXECUTE → QA → PR → DONE
|
|
5
|
+
* State is stored in RunState.ticket_workers[ticketId].
|
|
6
|
+
*/
|
|
7
|
+
import { repos, EXECUTION_DEFAULTS } from '@promptwheel/core';
|
|
8
|
+
import { deriveScopePolicy, validatePlanScope, serializeScopePolicy } from './scope-policy.js';
|
|
9
|
+
import { getRegistry } from './tool-registry.js';
|
|
10
|
+
import { checkSpindle, recordDiff, recordCommandFailure, recordPlanHash } from './spindle.js';
|
|
11
|
+
import { loadGuidelines, formatGuidelinesForPrompt } from './guidelines.js';
|
|
12
|
+
import { computeRetryRisk, scoreStrategies, buildCriticBlock, } from '@promptwheel/core/critic/shared';
|
|
13
|
+
import * as fs from 'node:fs';
|
|
14
|
+
import * as path from 'node:path';
|
|
15
|
+
const MAX_PLAN_REJECTIONS = 3;
|
|
16
|
+
const MAX_QA_RETRIES = EXECUTION_DEFAULTS.MAX_QA_RETRIES;
|
|
17
|
+
/**
|
|
18
|
+
* Advance a single ticket worker through its lifecycle.
|
|
19
|
+
* Called by the promptwheel_advance_ticket MCP tool.
|
|
20
|
+
*/
|
|
21
|
+
export async function advanceTicketWorker(ctx, ticketId) {
|
|
22
|
+
const { run, db } = ctx;
|
|
23
|
+
const s = run.require();
|
|
24
|
+
run.ensureLearningsLoaded();
|
|
25
|
+
const worker = run.getTicketWorker(ticketId);
|
|
26
|
+
if (!worker) {
|
|
27
|
+
return {
|
|
28
|
+
action: 'FAILED',
|
|
29
|
+
phase: 'FAILED',
|
|
30
|
+
prompt: null,
|
|
31
|
+
constraints: null,
|
|
32
|
+
ticket_id: ticketId,
|
|
33
|
+
reason: `No worker state for ticket ${ticketId}`,
|
|
34
|
+
};
|
|
35
|
+
}
|
|
36
|
+
// Increment worker step count and mark as active
|
|
37
|
+
worker.step_count++;
|
|
38
|
+
run.updateTicketWorker(ticketId, { step_count: worker.step_count, last_active_at_step: s.step_count });
|
|
39
|
+
// Budget check per ticket
|
|
40
|
+
if (worker.step_count > s.ticket_step_budget) {
|
|
41
|
+
await repos.tickets.updateStatus(db, ticketId, 'blocked');
|
|
42
|
+
run.failTicketWorker(ticketId, 'Ticket step budget exhausted');
|
|
43
|
+
return {
|
|
44
|
+
action: 'FAILED',
|
|
45
|
+
phase: 'FAILED',
|
|
46
|
+
prompt: null,
|
|
47
|
+
constraints: null,
|
|
48
|
+
ticket_id: ticketId,
|
|
49
|
+
reason: `Ticket step budget exhausted (${worker.step_count}/${s.ticket_step_budget})`,
|
|
50
|
+
};
|
|
51
|
+
}
|
|
52
|
+
// Spindle check (EXECUTE/QA/CROSS_QA phases)
|
|
53
|
+
if (worker.phase === 'EXECUTE' || worker.phase === 'QA' || worker.phase === 'CROSS_QA') {
|
|
54
|
+
const spindleResult = checkSpindle(worker.spindle);
|
|
55
|
+
if (spindleResult.shouldAbort) {
|
|
56
|
+
await repos.tickets.updateStatus(db, ticketId, 'blocked');
|
|
57
|
+
run.failTicketWorker(ticketId, `Spindle abort: ${spindleResult.reason}`);
|
|
58
|
+
return {
|
|
59
|
+
action: 'FAILED',
|
|
60
|
+
phase: 'FAILED',
|
|
61
|
+
prompt: null,
|
|
62
|
+
constraints: null,
|
|
63
|
+
ticket_id: ticketId,
|
|
64
|
+
reason: `Spindle loop detected: ${spindleResult.reason}`,
|
|
65
|
+
};
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
// Terminal states
|
|
69
|
+
if (worker.phase === 'DONE' || worker.phase === 'FAILED') {
|
|
70
|
+
return {
|
|
71
|
+
action: worker.phase === 'DONE' ? 'DONE' : 'FAILED',
|
|
72
|
+
phase: worker.phase,
|
|
73
|
+
prompt: null,
|
|
74
|
+
constraints: null,
|
|
75
|
+
ticket_id: ticketId,
|
|
76
|
+
reason: worker.phase === 'DONE' ? 'Ticket completed' : 'Ticket failed',
|
|
77
|
+
};
|
|
78
|
+
}
|
|
79
|
+
const ticket = await repos.tickets.getById(db, ticketId);
|
|
80
|
+
if (!ticket) {
|
|
81
|
+
run.failTicketWorker(ticketId, 'Ticket not found');
|
|
82
|
+
return {
|
|
83
|
+
action: 'FAILED',
|
|
84
|
+
phase: 'FAILED',
|
|
85
|
+
prompt: null,
|
|
86
|
+
constraints: null,
|
|
87
|
+
ticket_id: ticketId,
|
|
88
|
+
reason: 'Ticket not found in database',
|
|
89
|
+
};
|
|
90
|
+
}
|
|
91
|
+
const worktreePath = `.promptwheel/worktrees/${ticketId}`;
|
|
92
|
+
const policy = deriveScopePolicy({
|
|
93
|
+
allowedPaths: ticket.allowedPaths ?? [],
|
|
94
|
+
category: ticket.category ?? 'refactor',
|
|
95
|
+
maxLinesPerTicket: s.max_lines_per_ticket,
|
|
96
|
+
worktreeRoot: s.direct ? undefined : worktreePath,
|
|
97
|
+
learnings: s.cached_learnings,
|
|
98
|
+
});
|
|
99
|
+
const constraints = {
|
|
100
|
+
allowed_paths: policy.allowed_paths,
|
|
101
|
+
denied_paths: policy.denied_paths,
|
|
102
|
+
denied_patterns: policy.denied_patterns.map(r => r.source),
|
|
103
|
+
max_files: policy.max_files,
|
|
104
|
+
max_lines: policy.max_lines,
|
|
105
|
+
required_commands: ticket.verificationCommands ?? [],
|
|
106
|
+
plan_required: policy.plan_required,
|
|
107
|
+
auto_approve_patterns: getRegistry(ctx.project.rootPath).getAutoApprovePatterns({
|
|
108
|
+
phase: worker.phase === 'QA' || worker.phase === 'CROSS_QA' ? 'QA' : worker.phase,
|
|
109
|
+
category: ticket.category ?? null,
|
|
110
|
+
}),
|
|
111
|
+
};
|
|
112
|
+
// Write per-ticket scope policy
|
|
113
|
+
writeScopePolicy(ctx.project.rootPath, ticketId, policy);
|
|
114
|
+
switch (worker.phase) {
|
|
115
|
+
case 'PLAN': {
|
|
116
|
+
if (!policy.plan_required) {
|
|
117
|
+
run.updateTicketWorker(ticketId, { plan_approved: true, phase: 'EXECUTE' });
|
|
118
|
+
return advanceTicketWorker(ctx, ticketId);
|
|
119
|
+
}
|
|
120
|
+
if (worker.plan_approved) {
|
|
121
|
+
run.updateTicketWorker(ticketId, { phase: 'EXECUTE' });
|
|
122
|
+
return advanceTicketWorker(ctx, ticketId);
|
|
123
|
+
}
|
|
124
|
+
if (worker.plan_rejections >= MAX_PLAN_REJECTIONS) {
|
|
125
|
+
await repos.tickets.updateStatus(db, ticketId, 'blocked');
|
|
126
|
+
run.failTicketWorker(ticketId, `Plan rejected ${MAX_PLAN_REJECTIONS} times`);
|
|
127
|
+
return {
|
|
128
|
+
action: 'FAILED',
|
|
129
|
+
phase: 'FAILED',
|
|
130
|
+
prompt: null,
|
|
131
|
+
constraints: null,
|
|
132
|
+
ticket_id: ticketId,
|
|
133
|
+
reason: `Commit plan rejected ${MAX_PLAN_REJECTIONS} times`,
|
|
134
|
+
};
|
|
135
|
+
}
|
|
136
|
+
const prompt = buildTicketPlanPrompt(ticket, worktreePath, worker.plan_rejections > 0);
|
|
137
|
+
return {
|
|
138
|
+
action: 'PROMPT',
|
|
139
|
+
phase: 'PLAN',
|
|
140
|
+
prompt,
|
|
141
|
+
constraints,
|
|
142
|
+
ticket_id: ticketId,
|
|
143
|
+
reason: worker.plan_rejections > 0
|
|
144
|
+
? `Re-planning (attempt ${worker.plan_rejections + 1}/${MAX_PLAN_REJECTIONS})`
|
|
145
|
+
: `Planning ticket: ${ticket.title}`,
|
|
146
|
+
};
|
|
147
|
+
}
|
|
148
|
+
case 'EXECUTE': {
|
|
149
|
+
const guidelines = loadGuidelines(ctx.project.rootPath);
|
|
150
|
+
const guidelinesBlock = guidelines ? formatGuidelinesForPrompt(guidelines) + '\n\n' : '';
|
|
151
|
+
// Build critic block for QA retries
|
|
152
|
+
let criticBlock = '';
|
|
153
|
+
if (worker.qa_retries > 0 && worker.last_qa_failure) {
|
|
154
|
+
const cachedLearnings = run.require().cached_learnings ?? [];
|
|
155
|
+
const failureContext = {
|
|
156
|
+
failed_commands: worker.last_qa_failure.failed_commands,
|
|
157
|
+
error_output: worker.last_qa_failure.error_output,
|
|
158
|
+
attempt: worker.qa_retries + 1,
|
|
159
|
+
max_attempts: MAX_QA_RETRIES,
|
|
160
|
+
};
|
|
161
|
+
const risk = computeRetryRisk(ticket.allowedPaths ?? [], ticket.verificationCommands ?? [], cachedLearnings, failureContext);
|
|
162
|
+
const strategies = scoreStrategies(ticket.allowedPaths ?? [], failureContext, cachedLearnings);
|
|
163
|
+
criticBlock = buildCriticBlock(failureContext, risk, strategies, cachedLearnings);
|
|
164
|
+
if (criticBlock)
|
|
165
|
+
criticBlock += '\n\n';
|
|
166
|
+
}
|
|
167
|
+
const prompt = guidelinesBlock + criticBlock + buildTicketExecutePrompt(ticket, worker.plan, worktreePath);
|
|
168
|
+
return {
|
|
169
|
+
action: 'PROMPT',
|
|
170
|
+
phase: 'EXECUTE',
|
|
171
|
+
prompt,
|
|
172
|
+
constraints,
|
|
173
|
+
ticket_id: ticketId,
|
|
174
|
+
reason: `Executing ticket: ${ticket.title}`,
|
|
175
|
+
};
|
|
176
|
+
}
|
|
177
|
+
case 'QA': {
|
|
178
|
+
if (worker.qa_retries >= MAX_QA_RETRIES) {
|
|
179
|
+
await repos.tickets.updateStatus(db, ticketId, 'blocked');
|
|
180
|
+
run.failTicketWorker(ticketId, `QA failed ${MAX_QA_RETRIES} times`);
|
|
181
|
+
return {
|
|
182
|
+
action: 'FAILED',
|
|
183
|
+
phase: 'FAILED',
|
|
184
|
+
prompt: null,
|
|
185
|
+
constraints: null,
|
|
186
|
+
ticket_id: ticketId,
|
|
187
|
+
reason: `QA failed ${MAX_QA_RETRIES} times`,
|
|
188
|
+
};
|
|
189
|
+
}
|
|
190
|
+
const prompt = buildTicketQaPrompt(ticket, worktreePath);
|
|
191
|
+
return {
|
|
192
|
+
action: 'PROMPT',
|
|
193
|
+
phase: 'QA',
|
|
194
|
+
prompt,
|
|
195
|
+
constraints,
|
|
196
|
+
ticket_id: ticketId,
|
|
197
|
+
reason: `Running QA for: ${ticket.title} (attempt ${worker.qa_retries + 1}/${MAX_QA_RETRIES})`,
|
|
198
|
+
};
|
|
199
|
+
}
|
|
200
|
+
case 'CROSS_QA': {
|
|
201
|
+
if (worker.qa_retries >= MAX_QA_RETRIES) {
|
|
202
|
+
await repos.tickets.updateStatus(db, ticketId, 'blocked');
|
|
203
|
+
run.failTicketWorker(ticketId, `Cross-verify QA failed ${MAX_QA_RETRIES} times`);
|
|
204
|
+
return {
|
|
205
|
+
action: 'FAILED',
|
|
206
|
+
phase: 'FAILED',
|
|
207
|
+
prompt: null,
|
|
208
|
+
constraints: null,
|
|
209
|
+
ticket_id: ticketId,
|
|
210
|
+
reason: `Cross-verify QA failed ${MAX_QA_RETRIES} times`,
|
|
211
|
+
};
|
|
212
|
+
}
|
|
213
|
+
const prompt = buildCrossQaPrompt(ticket, worktreePath);
|
|
214
|
+
return {
|
|
215
|
+
action: 'PROMPT',
|
|
216
|
+
phase: 'CROSS_QA',
|
|
217
|
+
prompt,
|
|
218
|
+
constraints,
|
|
219
|
+
ticket_id: ticketId,
|
|
220
|
+
reason: `Cross-verifying: ${ticket.title} (attempt ${worker.qa_retries + 1}/${MAX_QA_RETRIES})`,
|
|
221
|
+
};
|
|
222
|
+
}
|
|
223
|
+
case 'PR': {
|
|
224
|
+
const prompt = buildTicketPrPrompt(ticket, s.draft, worktreePath);
|
|
225
|
+
return {
|
|
226
|
+
action: 'PROMPT',
|
|
227
|
+
phase: 'PR',
|
|
228
|
+
prompt,
|
|
229
|
+
constraints: null,
|
|
230
|
+
ticket_id: ticketId,
|
|
231
|
+
reason: `Creating PR for: ${ticket.title}`,
|
|
232
|
+
};
|
|
233
|
+
}
|
|
234
|
+
default:
|
|
235
|
+
return {
|
|
236
|
+
action: 'FAILED',
|
|
237
|
+
phase: 'FAILED',
|
|
238
|
+
prompt: null,
|
|
239
|
+
constraints: null,
|
|
240
|
+
ticket_id: ticketId,
|
|
241
|
+
reason: `Unknown worker phase: ${worker.phase}`,
|
|
242
|
+
};
|
|
243
|
+
}
|
|
244
|
+
}
|
|
245
|
+
/**
|
|
246
|
+
* Ingest an event for a specific ticket worker.
|
|
247
|
+
* Mirrors event-processor.ts logic but scoped to one ticket.
|
|
248
|
+
*/
|
|
249
|
+
export async function ingestTicketEvent(ctx, ticketId, type, payload) {
|
|
250
|
+
const { run, db } = ctx;
|
|
251
|
+
const worker = run.getTicketWorker(ticketId);
|
|
252
|
+
if (!worker) {
|
|
253
|
+
return { processed: false, message: `No worker for ticket ${ticketId}` };
|
|
254
|
+
}
|
|
255
|
+
run.appendEvent(type, { ...payload, ticket_id: ticketId, parallel: true });
|
|
256
|
+
switch (type) {
|
|
257
|
+
case 'PLAN_SUBMITTED': {
|
|
258
|
+
if (worker.phase !== 'PLAN') {
|
|
259
|
+
return { processed: true, message: 'Plan submitted outside PLAN phase' };
|
|
260
|
+
}
|
|
261
|
+
const raw = payload;
|
|
262
|
+
const rawFiles = Array.isArray(raw.files_to_touch) ? raw.files_to_touch
|
|
263
|
+
: Array.isArray(raw.files) ? raw.files
|
|
264
|
+
: Array.isArray(raw.touched_files) ? raw.touched_files : [];
|
|
265
|
+
const files_to_touch = rawFiles.map((f) => {
|
|
266
|
+
if (typeof f === 'string')
|
|
267
|
+
return { path: f, action: 'modify', reason: '' };
|
|
268
|
+
if (f && typeof f === 'object' && 'path' in f)
|
|
269
|
+
return f;
|
|
270
|
+
return { path: String(f), action: 'modify', reason: '' };
|
|
271
|
+
});
|
|
272
|
+
const plan = {
|
|
273
|
+
ticket_id: ticketId,
|
|
274
|
+
files_to_touch,
|
|
275
|
+
expected_tests: Array.isArray(raw.expected_tests) ? raw.expected_tests.map(String) : [],
|
|
276
|
+
risk_level: (raw.risk_level === 'low' || raw.risk_level === 'medium' || raw.risk_level === 'high')
|
|
277
|
+
? raw.risk_level : 'low',
|
|
278
|
+
estimated_lines: typeof raw.estimated_lines === 'number' ? raw.estimated_lines : 50,
|
|
279
|
+
};
|
|
280
|
+
const ticket = await repos.tickets.getById(db, ticketId);
|
|
281
|
+
const worktreeRoot = run.require().direct ? undefined : `.promptwheel/worktrees/${ticketId}`;
|
|
282
|
+
const policy = deriveScopePolicy({
|
|
283
|
+
allowedPaths: ticket?.allowedPaths ?? [],
|
|
284
|
+
category: ticket?.category ?? 'refactor',
|
|
285
|
+
maxLinesPerTicket: run.require().max_lines_per_ticket,
|
|
286
|
+
worktreeRoot,
|
|
287
|
+
learnings: run.require().cached_learnings,
|
|
288
|
+
});
|
|
289
|
+
const scopeResult = validatePlanScope(plan.files_to_touch, plan.estimated_lines, plan.risk_level, policy);
|
|
290
|
+
if (!scopeResult.valid) {
|
|
291
|
+
worker.plan_rejections++;
|
|
292
|
+
run.updateTicketWorker(ticketId, { plan_rejections: worker.plan_rejections });
|
|
293
|
+
return { processed: true, message: `Plan rejected: ${scopeResult.reason}` };
|
|
294
|
+
}
|
|
295
|
+
if (plan.risk_level === 'high') {
|
|
296
|
+
await repos.tickets.updateStatus(db, ticketId, 'blocked');
|
|
297
|
+
run.failTicketWorker(ticketId, 'High-risk plan requires human approval');
|
|
298
|
+
return { processed: true, message: 'High-risk plan requires human approval' };
|
|
299
|
+
}
|
|
300
|
+
recordPlanHash(worker.spindle, plan);
|
|
301
|
+
run.updateTicketWorker(ticketId, {
|
|
302
|
+
plan,
|
|
303
|
+
plan_approved: true,
|
|
304
|
+
phase: 'EXECUTE',
|
|
305
|
+
});
|
|
306
|
+
return { processed: true, message: 'Plan approved, moving to EXECUTE' };
|
|
307
|
+
}
|
|
308
|
+
case 'TICKET_RESULT': {
|
|
309
|
+
// Accept TICKET_RESULT in any phase — inline prompts (Task subagents) don't
|
|
310
|
+
// call back at each step, so worker.phase may still be 'PLAN'.
|
|
311
|
+
const status = payload['status'];
|
|
312
|
+
if (status === 'done' || status === 'success') {
|
|
313
|
+
// For inline prompts, 'success' means the subagent completed everything
|
|
314
|
+
// including QA, commit, push. If PR_CREATED follows, that's the final step.
|
|
315
|
+
// If not, treat this as ticket complete (e.g., direct commit without PR).
|
|
316
|
+
if (payload['pr_url']) {
|
|
317
|
+
// PR was created — mark complete
|
|
318
|
+
if (run.require().create_prs) {
|
|
319
|
+
run.require().prs_created++;
|
|
320
|
+
}
|
|
321
|
+
run.completeTicketWorker(ticketId);
|
|
322
|
+
return { processed: true, message: 'Ticket complete with PR' };
|
|
323
|
+
}
|
|
324
|
+
// No PR URL — move to QA if in traditional flow, or complete if inline
|
|
325
|
+
if (worker.phase === 'EXECUTE') {
|
|
326
|
+
const diff = (payload['diff'] ?? null);
|
|
327
|
+
const changedFiles = (payload['changed_files'] ?? []);
|
|
328
|
+
recordDiff(worker.spindle, diff ?? (changedFiles.length > 0 ? changedFiles.join('\n') : null));
|
|
329
|
+
const nextPhase = run.require().cross_verify ? 'CROSS_QA' : 'QA';
|
|
330
|
+
run.updateTicketWorker(ticketId, { phase: nextPhase, spindle: worker.spindle });
|
|
331
|
+
return { processed: true, message: run.require().cross_verify ? 'Moving to CROSS_QA (independent verification)' : 'Moving to QA' };
|
|
332
|
+
}
|
|
333
|
+
// Inline prompt completed without PR — mark complete
|
|
334
|
+
run.completeTicketWorker(ticketId);
|
|
335
|
+
return { processed: true, message: 'Ticket complete (no PR)' };
|
|
336
|
+
}
|
|
337
|
+
if (status === 'failed') {
|
|
338
|
+
await repos.tickets.updateStatus(db, ticketId, 'blocked');
|
|
339
|
+
run.failTicketWorker(ticketId, payload['reason'] ?? 'Execution failed');
|
|
340
|
+
return { processed: true, message: 'Ticket failed' };
|
|
341
|
+
}
|
|
342
|
+
return { processed: true, message: `Ticket result: ${status}` };
|
|
343
|
+
}
|
|
344
|
+
case 'QA_COMMAND_RESULT': {
|
|
345
|
+
const success = payload['success'];
|
|
346
|
+
if (!success) {
|
|
347
|
+
recordCommandFailure(worker.spindle, payload['command'], (payload['output'] ?? ''));
|
|
348
|
+
run.updateTicketWorker(ticketId, { spindle: worker.spindle });
|
|
349
|
+
}
|
|
350
|
+
return { processed: true, message: `QA command ${success ? 'passed' : 'failed'}` };
|
|
351
|
+
}
|
|
352
|
+
case 'QA_PASSED': {
|
|
353
|
+
if (worker.phase !== 'QA' && worker.phase !== 'CROSS_QA') {
|
|
354
|
+
return { processed: true, message: 'QA passed outside QA/CROSS_QA phase' };
|
|
355
|
+
}
|
|
356
|
+
await repos.tickets.updateStatus(db, ticketId, 'done');
|
|
357
|
+
// Skip PR phase when not creating PRs
|
|
358
|
+
if (!run.require().create_prs) {
|
|
359
|
+
run.completeTicketWorker(ticketId);
|
|
360
|
+
return { processed: true, message: 'QA passed, PRs disabled — ticket complete' };
|
|
361
|
+
}
|
|
362
|
+
run.updateTicketWorker(ticketId, { phase: 'PR' });
|
|
363
|
+
return { processed: true, message: 'QA passed, moving to PR' };
|
|
364
|
+
}
|
|
365
|
+
case 'QA_FAILED': {
|
|
366
|
+
if (worker.phase !== 'QA' && worker.phase !== 'CROSS_QA') {
|
|
367
|
+
return { processed: true, message: 'QA failed outside QA/CROSS_QA phase' };
|
|
368
|
+
}
|
|
369
|
+
recordDiff(worker.spindle, null);
|
|
370
|
+
worker.qa_retries++;
|
|
371
|
+
// Store failure context for critic block injection on retry
|
|
372
|
+
{
|
|
373
|
+
const failedCmds = (payload['failed_commands'] ?? payload['command'] ?? '');
|
|
374
|
+
const errorOutput = (payload['error'] ?? payload['output'] ?? '');
|
|
375
|
+
worker.last_qa_failure = {
|
|
376
|
+
failed_commands: Array.isArray(failedCmds) ? failedCmds : failedCmds ? [failedCmds] : [],
|
|
377
|
+
error_output: errorOutput.slice(0, 500),
|
|
378
|
+
};
|
|
379
|
+
}
|
|
380
|
+
if (worker.qa_retries >= MAX_QA_RETRIES) {
|
|
381
|
+
await repos.tickets.updateStatus(db, ticketId, 'blocked');
|
|
382
|
+
run.failTicketWorker(ticketId, `QA failed ${worker.qa_retries} times`);
|
|
383
|
+
return { processed: true, message: `QA failed ${worker.qa_retries} times, giving up` };
|
|
384
|
+
}
|
|
385
|
+
// On CROSS_QA failure, send back to EXECUTE (implementer re-tries), not CROSS_QA
|
|
386
|
+
run.updateTicketWorker(ticketId, { phase: 'EXECUTE', qa_retries: worker.qa_retries, spindle: worker.spindle });
|
|
387
|
+
return { processed: true, message: `QA failed (attempt ${worker.qa_retries}/${MAX_QA_RETRIES}), retrying from EXECUTE` };
|
|
388
|
+
}
|
|
389
|
+
case 'PR_CREATED': {
|
|
390
|
+
// Accept PR_CREATED in any phase — inline prompts (Task subagents) don't
|
|
391
|
+
// call back at each step, so worker.phase may still be 'PLAN'.
|
|
392
|
+
// The session-level phase is PARALLEL_EXECUTE which is what matters.
|
|
393
|
+
if (run.require().create_prs) {
|
|
394
|
+
run.require().prs_created++;
|
|
395
|
+
}
|
|
396
|
+
run.completeTicketWorker(ticketId);
|
|
397
|
+
return { processed: true, message: 'PR created, ticket complete' };
|
|
398
|
+
}
|
|
399
|
+
default:
|
|
400
|
+
return { processed: true, message: `Event ${type} recorded for ticket ${ticketId}` };
|
|
401
|
+
}
|
|
402
|
+
}
|
|
403
|
+
// ---------------------------------------------------------------------------
|
|
404
|
+
// Per-ticket scope policy writer
|
|
405
|
+
// ---------------------------------------------------------------------------
|
|
406
|
+
function writeScopePolicy(projectRoot, ticketId, policy) {
|
|
407
|
+
const dir = path.join(projectRoot, '.promptwheel', 'scope-policies');
|
|
408
|
+
fs.mkdirSync(dir, { recursive: true });
|
|
409
|
+
const policyPath = path.join(dir, `${ticketId}.json`);
|
|
410
|
+
fs.writeFileSync(policyPath, JSON.stringify(serializeScopePolicy(policy), null, 2), 'utf8');
|
|
411
|
+
}
|
|
412
|
+
// ---------------------------------------------------------------------------
|
|
413
|
+
// Prompt builders (ticket-scoped, with worktree instructions)
|
|
414
|
+
// ---------------------------------------------------------------------------
|
|
415
|
+
function buildTicketPlanPrompt(ticket, worktreePath, isRetry) {
|
|
416
|
+
const parts = [
|
|
417
|
+
'# Commit Plan Required',
|
|
418
|
+
'',
|
|
419
|
+
`**Ticket:** ${ticket.title}`,
|
|
420
|
+
'',
|
|
421
|
+
ticket.description ?? '',
|
|
422
|
+
'',
|
|
423
|
+
`**Working directory:** \`${worktreePath}\``,
|
|
424
|
+
'Ensure you are working in the git worktree above. If it does not exist, create it:',
|
|
425
|
+
'```bash',
|
|
426
|
+
`git worktree add ${worktreePath} -b promptwheel/${ticket.title.toLowerCase().replace(/[^a-z0-9]+/g, '-').slice(0, 50)}`,
|
|
427
|
+
'```',
|
|
428
|
+
'',
|
|
429
|
+
];
|
|
430
|
+
if (isRetry) {
|
|
431
|
+
parts.unshift('Your previous commit plan was rejected. Please revise.\n');
|
|
432
|
+
}
|
|
433
|
+
parts.push('Output a `<commit-plan>` XML block with:', '```json', '{', ` "ticket_id": "${ticket.id}",`, ' "files_to_touch": [{"path": "...", "action": "create|modify|delete", "reason": "..."}],', ' "expected_tests": ["npm test -- --grep ..."],', ' "estimated_lines": <number>,', ' "risk_level": "low|medium|high"', '}', '```', '', `**Allowed paths:** ${ticket.allowedPaths.length > 0 ? ticket.allowedPaths.join(', ') : 'any'}`, `**Verification commands:** ${ticket.verificationCommands.join(', ') || 'none specified'}`, '', 'Then call `promptwheel_ticket_event` with the ticket_id, type `PLAN_SUBMITTED`, and the plan as payload.');
|
|
434
|
+
return parts.join('\n');
|
|
435
|
+
}
|
|
436
|
+
function buildTicketExecutePrompt(ticket, plan, worktreePath) {
|
|
437
|
+
const parts = [
|
|
438
|
+
`# Execute: ${ticket.title}`,
|
|
439
|
+
'',
|
|
440
|
+
ticket.description ?? '',
|
|
441
|
+
'',
|
|
442
|
+
`**Working directory:** \`${worktreePath}\``,
|
|
443
|
+
'All file modifications MUST be made inside this worktree directory.',
|
|
444
|
+
'',
|
|
445
|
+
];
|
|
446
|
+
if (plan) {
|
|
447
|
+
parts.push('## Approved Commit Plan');
|
|
448
|
+
parts.push('```json');
|
|
449
|
+
parts.push(JSON.stringify(plan, null, 2));
|
|
450
|
+
parts.push('```');
|
|
451
|
+
parts.push('');
|
|
452
|
+
parts.push('Follow the plan above. Only touch the files listed.');
|
|
453
|
+
parts.push('');
|
|
454
|
+
}
|
|
455
|
+
parts.push('## Constraints', `- Only modify files in: ${ticket.allowedPaths.length > 0 ? ticket.allowedPaths.join(', ') : 'any'}`, '- Make minimal, focused changes', '', '## When done', 'Output a `<ticket-result>` block with status, changed_files, summary, lines_added, lines_removed.', `Then call \`promptwheel_ticket_event\` with ticket_id="${ticket.id}", type \`TICKET_RESULT\`, and the result as payload.`);
|
|
456
|
+
return parts.join('\n');
|
|
457
|
+
}
|
|
458
|
+
function buildTicketQaPrompt(ticket, worktreePath) {
|
|
459
|
+
return [
|
|
460
|
+
`# QA: ${ticket.title}`,
|
|
461
|
+
'',
|
|
462
|
+
`**Working directory:** \`${worktreePath}\``,
|
|
463
|
+
'Run all commands from within the worktree.',
|
|
464
|
+
'',
|
|
465
|
+
'Run the following verification commands and report results:',
|
|
466
|
+
'',
|
|
467
|
+
...ticket.verificationCommands.map(c => `\`\`\`bash\ncd ${worktreePath} && ${c}\n\`\`\``),
|
|
468
|
+
'',
|
|
469
|
+
'For each command, call `promptwheel_ticket_event` with type `QA_COMMAND_RESULT` and:',
|
|
470
|
+
'`{ "command": "...", "success": true/false, "output": "stdout+stderr" }`',
|
|
471
|
+
'',
|
|
472
|
+
'After all commands, call `promptwheel_ticket_event` with type `QA_PASSED` if all pass, or `QA_FAILED` with failure details.',
|
|
473
|
+
].join('\n');
|
|
474
|
+
}
|
|
475
|
+
function buildCrossQaPrompt(ticket, worktreePath) {
|
|
476
|
+
return [
|
|
477
|
+
`# Independent Cross-Verification: ${ticket.title}`,
|
|
478
|
+
'',
|
|
479
|
+
'## IMPORTANT — You are an INDEPENDENT VERIFIER',
|
|
480
|
+
'',
|
|
481
|
+
'You are verifying work done by a DIFFERENT agent. Do NOT trust any claims of success.',
|
|
482
|
+
'You must run ALL verification commands yourself and report results honestly.',
|
|
483
|
+
'If something is broken, report it — even if the implementing agent claimed it works.',
|
|
484
|
+
'',
|
|
485
|
+
`**Working directory:** \`${worktreePath}\``,
|
|
486
|
+
'Run all commands from within the worktree.',
|
|
487
|
+
'',
|
|
488
|
+
'## Verification Commands',
|
|
489
|
+
'',
|
|
490
|
+
...ticket.verificationCommands.map(c => `\`\`\`bash\ncd ${worktreePath} && ${c}\n\`\`\``),
|
|
491
|
+
'',
|
|
492
|
+
'## Steps',
|
|
493
|
+
'',
|
|
494
|
+
'1. Read the changed files to understand what was modified',
|
|
495
|
+
'2. Run ALL verification commands listed above',
|
|
496
|
+
'3. Check for any obvious issues the implementer may have missed',
|
|
497
|
+
'4. Report results honestly',
|
|
498
|
+
'',
|
|
499
|
+
'For each command, call `promptwheel_ticket_event` with type `QA_COMMAND_RESULT` and:',
|
|
500
|
+
'`{ "command": "...", "success": true/false, "output": "stdout+stderr" }`',
|
|
501
|
+
'',
|
|
502
|
+
'After all commands, call `promptwheel_ticket_event` with type `QA_PASSED` if all pass, or `QA_FAILED` with failure details.',
|
|
503
|
+
].join('\n');
|
|
504
|
+
}
|
|
505
|
+
function buildTicketPrPrompt(ticket, draftPr, worktreePath) {
|
|
506
|
+
return [
|
|
507
|
+
'# Create PR',
|
|
508
|
+
'',
|
|
509
|
+
`**Working directory:** \`${worktreePath}\``,
|
|
510
|
+
'',
|
|
511
|
+
`Create a ${draftPr ? 'draft ' : ''}pull request for the changes.`,
|
|
512
|
+
'',
|
|
513
|
+
`**Title:** ${ticket.title}`,
|
|
514
|
+
ticket.description ? `**Description:** ${ticket.description.slice(0, 200)}` : '',
|
|
515
|
+
'',
|
|
516
|
+
'## Steps',
|
|
517
|
+
'',
|
|
518
|
+
`1. \`cd ${worktreePath}\``,
|
|
519
|
+
'2. Stage changes: `git add <files>`',
|
|
520
|
+
'3. Create commit: `git commit -m "..."`',
|
|
521
|
+
'4. Push to remote: `git push -u origin <branch>`',
|
|
522
|
+
`5. Create ${draftPr ? 'draft ' : ''}PR: \`gh pr create${draftPr ? ' --draft' : ''}\``,
|
|
523
|
+
'',
|
|
524
|
+
'Call `promptwheel_ticket_event` with type `PR_CREATED` and `{ "url": "<pr-url>", "branch": "<branch-name>" }` as payload.',
|
|
525
|
+
].join('\n');
|
|
526
|
+
}
|
|
527
|
+
//# sourceMappingURL=ticket-worker.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ticket-worker.js","sourceRoot":"","sources":["../src/ticket-worker.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Tool Registry — queryable registry of tool specs for phase/category/trust filtering.
|
|
3
|
+
*
|
|
4
|
+
* Replaces hardcoded auto-approve arrays and CATEGORY_TOOL_POLICIES
|
|
5
|
+
* with a single registry that loads built-in specs + custom user tools.
|
|
6
|
+
*
|
|
7
|
+
* Custom tools are loaded from `.promptwheel/tools/*.json`.
|
|
8
|
+
*/
|
|
9
|
+
import { type ToolSpec, type ToolPhase, type TrustLevel } from '@promptwheel/core/tools/shared';
|
|
10
|
+
export type { ToolSpec, ToolPhase, TrustLevel } from '@promptwheel/core/tools/shared';
|
|
11
|
+
export interface ToolContext {
|
|
12
|
+
phase: ToolPhase;
|
|
13
|
+
category: string | null;
|
|
14
|
+
trustLevel?: TrustLevel;
|
|
15
|
+
}
|
|
16
|
+
/**
|
|
17
|
+
* Get a cached ToolRegistry instance for the given project path.
|
|
18
|
+
* Creates a new one if the project path changed.
|
|
19
|
+
*/
|
|
20
|
+
export declare function getRegistry(projectPath?: string): ToolRegistry;
|
|
21
|
+
export declare class ToolRegistry {
|
|
22
|
+
private specs;
|
|
23
|
+
constructor(projectPath?: string);
|
|
24
|
+
/** Get all tool specs matching the given context. */
|
|
25
|
+
getToolsForContext(ctx: ToolContext): ToolSpec[];
|
|
26
|
+
/** Get auto-approve patterns for the given context. */
|
|
27
|
+
getAutoApprovePatterns(ctx: ToolContext): string[];
|
|
28
|
+
/** Get constraint note for the given context (if any). */
|
|
29
|
+
getConstraintNote(ctx: ToolContext): string | undefined;
|
|
30
|
+
/** Serialize tools for a subagent prompt (markdown block). */
|
|
31
|
+
serializeForSubagent(ctx: ToolContext): string;
|
|
32
|
+
/** Get all specs (for testing). */
|
|
33
|
+
getAllSpecs(): ToolSpec[];
|
|
34
|
+
}
|
|
35
|
+
//# sourceMappingURL=tool-registry.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"tool-registry.d.ts","sourceRoot":"","sources":["../src/tool-registry.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAIH,OAAO,EAKL,KAAK,QAAQ,EACb,KAAK,SAAS,EACd,KAAK,UAAU,EAChB,MAAM,gCAAgC,CAAC;AAGxC,YAAY,EAAE,QAAQ,EAAE,SAAS,EAAE,UAAU,EAAE,MAAM,gCAAgC,CAAC;AAEtF,MAAM,WAAW,WAAW;IAC1B,KAAK,EAAE,SAAS,CAAC;IACjB,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAC;IACxB,UAAU,CAAC,EAAE,UAAU,CAAC;CACzB;AASD;;;GAGG;AACH,wBAAgB,WAAW,CAAC,WAAW,CAAC,EAAE,MAAM,GAAG,YAAY,CAO9D;AAMD,qBAAa,YAAY;IACvB,OAAO,CAAC,KAAK,CAAa;gBAEd,WAAW,CAAC,EAAE,MAAM;IA6BhC,qDAAqD;IACrD,kBAAkB,CAAC,GAAG,EAAE,WAAW,GAAG,QAAQ,EAAE;IAIhD,uDAAuD;IACvD,sBAAsB,CAAC,GAAG,EAAE,WAAW,GAAG,MAAM,EAAE;IAKlD,0DAA0D;IAC1D,iBAAiB,CAAC,GAAG,EAAE,WAAW,GAAG,MAAM,GAAG,SAAS;IAKvD,8DAA8D;IAC9D,oBAAoB,CAAC,GAAG,EAAE,WAAW,GAAG,MAAM;IAc9C,mCAAmC;IACnC,WAAW,IAAI,QAAQ,EAAE;CAG1B"}
|