@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.
Files changed (134) hide show
  1. package/README.md +178 -0
  2. package/dist/advance-helpers.d.ts +27 -0
  3. package/dist/advance-helpers.d.ts.map +1 -0
  4. package/dist/advance-helpers.js +127 -0
  5. package/dist/advance-helpers.js.map +1 -0
  6. package/dist/advance-prompts.d.ts +48 -0
  7. package/dist/advance-prompts.d.ts.map +1 -0
  8. package/dist/advance-prompts.js +420 -0
  9. package/dist/advance-prompts.js.map +1 -0
  10. package/dist/advance.d.ts +30 -0
  11. package/dist/advance.d.ts.map +1 -0
  12. package/dist/advance.js +752 -0
  13. package/dist/advance.js.map +1 -0
  14. package/dist/codebase-index.d.ts +5 -0
  15. package/dist/codebase-index.d.ts.map +1 -0
  16. package/dist/codebase-index.js +5 -0
  17. package/dist/codebase-index.js.map +1 -0
  18. package/dist/dedup-memory.d.ts +30 -0
  19. package/dist/dedup-memory.d.ts.map +1 -0
  20. package/dist/dedup-memory.js +76 -0
  21. package/dist/dedup-memory.js.map +1 -0
  22. package/dist/direct-client.d.ts +57 -0
  23. package/dist/direct-client.d.ts.map +1 -0
  24. package/dist/direct-client.js +92 -0
  25. package/dist/direct-client.js.map +1 -0
  26. package/dist/event-handlers-qa.d.ts +5 -0
  27. package/dist/event-handlers-qa.d.ts.map +1 -0
  28. package/dist/event-handlers-qa.js +186 -0
  29. package/dist/event-handlers-qa.js.map +1 -0
  30. package/dist/event-handlers-scout.d.ts +5 -0
  31. package/dist/event-handlers-scout.d.ts.map +1 -0
  32. package/dist/event-handlers-scout.js +270 -0
  33. package/dist/event-handlers-scout.js.map +1 -0
  34. package/dist/event-handlers-ticket.d.ts +5 -0
  35. package/dist/event-handlers-ticket.d.ts.map +1 -0
  36. package/dist/event-handlers-ticket.js +232 -0
  37. package/dist/event-handlers-ticket.js.map +1 -0
  38. package/dist/event-helpers.d.ts +46 -0
  39. package/dist/event-helpers.d.ts.map +1 -0
  40. package/dist/event-helpers.js +125 -0
  41. package/dist/event-helpers.js.map +1 -0
  42. package/dist/event-processor.d.ts +15 -0
  43. package/dist/event-processor.d.ts.map +1 -0
  44. package/dist/event-processor.js +111 -0
  45. package/dist/event-processor.js.map +1 -0
  46. package/dist/formulas.d.ts +27 -0
  47. package/dist/formulas.d.ts.map +1 -0
  48. package/dist/formulas.js +109 -0
  49. package/dist/formulas.js.map +1 -0
  50. package/dist/guidelines.d.ts +16 -0
  51. package/dist/guidelines.d.ts.map +1 -0
  52. package/dist/guidelines.js +44 -0
  53. package/dist/guidelines.js.map +1 -0
  54. package/dist/index.d.ts +9 -0
  55. package/dist/index.d.ts.map +1 -0
  56. package/dist/index.js +42 -0
  57. package/dist/index.js.map +1 -0
  58. package/dist/learnings.d.ts +42 -0
  59. package/dist/learnings.d.ts.map +1 -0
  60. package/dist/learnings.js +117 -0
  61. package/dist/learnings.js.map +1 -0
  62. package/dist/project-metadata.d.ts +34 -0
  63. package/dist/project-metadata.d.ts.map +1 -0
  64. package/dist/project-metadata.js +617 -0
  65. package/dist/project-metadata.js.map +1 -0
  66. package/dist/proposals.d.ts +23 -0
  67. package/dist/proposals.d.ts.map +1 -0
  68. package/dist/proposals.js +201 -0
  69. package/dist/proposals.js.map +1 -0
  70. package/dist/qa-stats.d.ts +51 -0
  71. package/dist/qa-stats.d.ts.map +1 -0
  72. package/dist/qa-stats.js +121 -0
  73. package/dist/qa-stats.js.map +1 -0
  74. package/dist/run-manager.d.ts +97 -0
  75. package/dist/run-manager.d.ts.map +1 -0
  76. package/dist/run-manager.js +583 -0
  77. package/dist/run-manager.js.map +1 -0
  78. package/dist/run-state-bridge.d.ts +13 -0
  79. package/dist/run-state-bridge.d.ts.map +1 -0
  80. package/dist/run-state-bridge.js +101 -0
  81. package/dist/run-state-bridge.js.map +1 -0
  82. package/dist/scope-policy.d.ts +83 -0
  83. package/dist/scope-policy.d.ts.map +1 -0
  84. package/dist/scope-policy.js +278 -0
  85. package/dist/scope-policy.js.map +1 -0
  86. package/dist/server.d.ts +18 -0
  87. package/dist/server.d.ts.map +1 -0
  88. package/dist/server.js +35 -0
  89. package/dist/server.js.map +1 -0
  90. package/dist/spindle.d.ts +41 -0
  91. package/dist/spindle.d.ts.map +1 -0
  92. package/dist/spindle.js +230 -0
  93. package/dist/spindle.js.map +1 -0
  94. package/dist/state.d.ts +36 -0
  95. package/dist/state.d.ts.map +1 -0
  96. package/dist/state.js +50 -0
  97. package/dist/state.js.map +1 -0
  98. package/dist/ticket-worker.d.ts +37 -0
  99. package/dist/ticket-worker.d.ts.map +1 -0
  100. package/dist/ticket-worker.js +527 -0
  101. package/dist/ticket-worker.js.map +1 -0
  102. package/dist/tool-registry.d.ts +35 -0
  103. package/dist/tool-registry.d.ts.map +1 -0
  104. package/dist/tool-registry.js +129 -0
  105. package/dist/tool-registry.js.map +1 -0
  106. package/dist/tools/execute.d.ts +17 -0
  107. package/dist/tools/execute.d.ts.map +1 -0
  108. package/dist/tools/execute.js +418 -0
  109. package/dist/tools/execute.js.map +1 -0
  110. package/dist/tools/git.d.ts +7 -0
  111. package/dist/tools/git.d.ts.map +1 -0
  112. package/dist/tools/git.js +98 -0
  113. package/dist/tools/git.js.map +1 -0
  114. package/dist/tools/intelligence.d.ts +10 -0
  115. package/dist/tools/intelligence.d.ts.map +1 -0
  116. package/dist/tools/intelligence.js +432 -0
  117. package/dist/tools/intelligence.js.map +1 -0
  118. package/dist/tools/session.d.ts +7 -0
  119. package/dist/tools/session.d.ts.map +1 -0
  120. package/dist/tools/session.js +533 -0
  121. package/dist/tools/session.js.map +1 -0
  122. package/dist/tools/trajectory.d.ts +10 -0
  123. package/dist/tools/trajectory.d.ts.map +1 -0
  124. package/dist/tools/trajectory.js +374 -0
  125. package/dist/tools/trajectory.js.map +1 -0
  126. package/dist/trajectory-io.d.ts +21 -0
  127. package/dist/trajectory-io.d.ts.map +1 -0
  128. package/dist/trajectory-io.js +105 -0
  129. package/dist/trajectory-io.js.map +1 -0
  130. package/dist/types.d.ts +229 -0
  131. package/dist/types.d.ts.map +1 -0
  132. package/dist/types.js +13 -0
  133. package/dist/types.js.map +1 -0
  134. package/package.json +63 -0
@@ -0,0 +1,270 @@
1
+ import { loadSectorsState, atomicWriteJsonSync } from './event-helpers.js';
2
+ import { repos, SCOUT_DEFAULTS } from '@promptwheel/core';
3
+ import { filterAndCreateTickets, parseReviewedProposals } from './proposals.js';
4
+ import { addLearning, extractTags } from './learnings.js';
5
+ import { recordScanResult as recordScanResultCore, } from '@promptwheel/core/sectors/shared';
6
+ const MAX_SCOUT_RETRIES = SCOUT_DEFAULTS.MAX_SCOUT_RETRIES;
7
+ export async function handleScoutOutput(ctx, payload) {
8
+ const s = ctx.run.require();
9
+ if (s.phase !== 'SCOUT') {
10
+ return { processed: true, phase_changed: false, message: 'Scout output outside SCOUT phase, ignored' };
11
+ }
12
+ // Track explored directories for rotation across cycles
13
+ const exploredDirs = (payload['explored_dirs'] ?? []);
14
+ if (exploredDirs.length > 0) {
15
+ for (const dir of exploredDirs) {
16
+ if (!s.scouted_dirs.includes(dir)) {
17
+ s.scouted_dirs.push(dir);
18
+ }
19
+ }
20
+ }
21
+ // Update coverage from codebase index + scouted dirs (production modules only)
22
+ if (s.codebase_index) {
23
+ const scoutedSet = new Set(s.scouted_dirs.map(d => d.replace(/\/$/, '')));
24
+ let scannedSectors = 0;
25
+ let scannedFiles = 0;
26
+ let totalFiles = 0;
27
+ let totalSectors = 0;
28
+ for (const mod of s.codebase_index.modules) {
29
+ if (mod.production === false)
30
+ continue;
31
+ const fc = mod.production_file_count ?? mod.file_count ?? 0;
32
+ totalFiles += fc;
33
+ totalSectors++;
34
+ if (scoutedSet.has(mod.path) || scoutedSet.has(mod.path + '/')) {
35
+ scannedSectors++;
36
+ scannedFiles += fc;
37
+ }
38
+ }
39
+ s.sectors_scanned = scannedSectors;
40
+ s.sectors_total = totalSectors;
41
+ s.files_scanned = scannedFiles;
42
+ s.files_total = totalFiles;
43
+ }
44
+ // Handle sector reclassification if present — use recordScanResult with 0 proposals
45
+ const sectorReclass = payload['sector_reclassification'];
46
+ if (sectorReclass && (sectorReclass.confidence === 'medium' || sectorReclass.confidence === 'high') && exploredDirs.length > 0) {
47
+ try {
48
+ const loaded = loadSectorsState(ctx.run.rootPath);
49
+ if (loaded) {
50
+ const targetPath = exploredDirs[0].replace(/\/$/, '');
51
+ const target = loaded.state.sectors.find(sec => sec.path === targetPath);
52
+ if (target) {
53
+ // Apply reclassification directly (recordScanResult would also bump scan counters)
54
+ if (sectorReclass.production !== undefined) {
55
+ target.production = sectorReclass.production;
56
+ }
57
+ target.classificationConfidence = sectorReclass.confidence;
58
+ atomicWriteJsonSync(loaded.filePath, loaded.state);
59
+ }
60
+ }
61
+ }
62
+ catch (err) {
63
+ console.warn(`[promptwheel] sector reclassification: ${err instanceof Error ? err.message : String(err)}`);
64
+ }
65
+ }
66
+ // Fallback: if pending_proposals exist and the LLM sent review results
67
+ // through SCOUT_OUTPUT instead of PROPOSALS_REVIEWED, redirect to the
68
+ // PROPOSALS_REVIEWED handler.
69
+ if (s.pending_proposals !== null) {
70
+ // Path 1: structured reviewed_proposals array in payload
71
+ const reviewedArray = payload['reviewed_proposals'];
72
+ if (Array.isArray(reviewedArray) && reviewedArray.length > 0) {
73
+ return handleProposalsReviewed(ctx, payload);
74
+ }
75
+ // Path 2: XML <reviewed-proposals> block in payload text
76
+ const payloadText = payload['text'];
77
+ if (typeof payloadText === 'string' && payloadText.includes('<reviewed-proposals>')) {
78
+ const parsed = parseReviewedProposals(payloadText);
79
+ if (parsed && parsed.length > 0) {
80
+ return handleProposalsReviewed(ctx, { reviewed_proposals: parsed });
81
+ }
82
+ }
83
+ }
84
+ // Extract proposals from payload
85
+ const rawProposals = (payload['proposals'] ?? []);
86
+ // Build exploration log entry (before empty-check so retries also get logged)
87
+ const explorationSummary = (payload['exploration_summary'] ?? '');
88
+ const logEntry = explorationSummary
89
+ ? `Attempt ${s.scout_retries + 1}: Explored ${exploredDirs.join(', ') || '(unknown)'}. Found ${rawProposals.length} proposals. ${explorationSummary}`
90
+ : `Attempt ${s.scout_retries + 1}: Explored ${exploredDirs.join(', ') || '(unknown)'}. Found ${rawProposals.length} proposals.`;
91
+ s.scout_exploration_log.push(logEntry);
92
+ if (rawProposals.length === 0) {
93
+ if (s.scout_retries < MAX_SCOUT_RETRIES) {
94
+ s.scout_retries++;
95
+ // Stay in SCOUT phase — advance() will return an escalated prompt
96
+ return {
97
+ processed: true,
98
+ phase_changed: false,
99
+ message: `No proposals found (attempt ${s.scout_retries}/${MAX_SCOUT_RETRIES + 1}). Retrying with deeper analysis.`,
100
+ };
101
+ }
102
+ // Exhausted retries — genuinely no work
103
+ ctx.run.setPhase('DONE');
104
+ return {
105
+ processed: true,
106
+ phase_changed: true,
107
+ new_phase: 'DONE',
108
+ message: 'No proposals in scout output after all retries, transitioning to DONE',
109
+ };
110
+ }
111
+ // Update sector scan stats if a sector was selected for this cycle
112
+ if (s.selected_sector_path) {
113
+ try {
114
+ const loaded = loadSectorsState(ctx.run.rootPath);
115
+ if (loaded) {
116
+ recordScanResultCore(loaded.state, s.selected_sector_path, s.scout_cycles, rawProposals.length);
117
+ atomicWriteJsonSync(loaded.filePath, loaded.state);
118
+ }
119
+ }
120
+ catch (err) {
121
+ console.warn(`[promptwheel] record sector scan stats: ${err instanceof Error ? err.message : String(err)}`);
122
+ }
123
+ s.current_sector_path = s.selected_sector_path;
124
+ s.selected_sector_path = undefined;
125
+ }
126
+ // skip_review: create tickets directly without adversarial review pass
127
+ if (s.skip_review) {
128
+ ctx.run.saveArtifact(`${s.step_count}-scout-proposals.json`, JSON.stringify({ raw: rawProposals, skip_review: true }, null, 2));
129
+ const result = await filterAndCreateTickets(ctx.run, ctx.db, rawProposals);
130
+ if (result.created_ticket_ids.length > 0) {
131
+ s.scout_retries = 0;
132
+ ctx.run.setPhase('NEXT_TICKET');
133
+ return {
134
+ processed: true,
135
+ phase_changed: true,
136
+ new_phase: 'NEXT_TICKET',
137
+ message: `Created ${result.created_ticket_ids.length} tickets (review skipped, ${result.rejected.length} rejected)`,
138
+ };
139
+ }
140
+ // All proposals rejected
141
+ if (s.scout_retries < MAX_SCOUT_RETRIES) {
142
+ s.scout_retries++;
143
+ return {
144
+ processed: true,
145
+ phase_changed: false,
146
+ message: `All proposals rejected (review skipped, attempt ${s.scout_retries}/${MAX_SCOUT_RETRIES + 1}). Retrying.`,
147
+ };
148
+ }
149
+ ctx.run.setPhase('DONE');
150
+ return {
151
+ processed: true,
152
+ phase_changed: true,
153
+ new_phase: 'DONE',
154
+ message: `All proposals rejected (review skipped) after all retries`,
155
+ };
156
+ }
157
+ // Store proposals as pending for adversarial review (instead of creating tickets immediately)
158
+ s.pending_proposals = rawProposals;
159
+ // Save proposals artifact
160
+ ctx.run.saveArtifact(`${s.step_count}-scout-proposals.json`, JSON.stringify({ raw: rawProposals, pending_review: true }, null, 2));
161
+ return {
162
+ processed: true,
163
+ phase_changed: false,
164
+ message: `${rawProposals.length} proposals pending adversarial review`,
165
+ };
166
+ }
167
+ export async function handleProposalsReviewed(ctx, payload) {
168
+ const s = ctx.run.require();
169
+ if (s.phase !== 'SCOUT') {
170
+ return { processed: true, phase_changed: false, message: 'PROPOSALS_REVIEWED outside SCOUT phase, ignored' };
171
+ }
172
+ const pendingProposals = s.pending_proposals;
173
+ if (!pendingProposals || pendingProposals.length === 0) {
174
+ return { processed: true, phase_changed: false, message: 'No pending proposals to review' };
175
+ }
176
+ // Apply revised scores from review
177
+ const reviewedItems = (payload['reviewed_proposals'] ?? []);
178
+ // Merge reviewed scores back into pending proposals
179
+ for (const reviewed of reviewedItems) {
180
+ if (!reviewed.title)
181
+ continue;
182
+ const match = pendingProposals.find(p => p.title === reviewed.title);
183
+ if (match) {
184
+ // Record learning if confidence lowered >20 pts
185
+ if (s.learnings_enabled && typeof reviewed.confidence === 'number' && typeof match.confidence === 'number') {
186
+ const drop = match.confidence - reviewed.confidence;
187
+ if (drop > 20) {
188
+ addLearning(ctx.run.rootPath, {
189
+ text: `Proposal "${reviewed.title}" had inflated confidence (${match.confidence}→${reviewed.confidence})`,
190
+ category: 'warning',
191
+ source: { type: 'review_downgrade', detail: reviewed.review_note },
192
+ tags: extractTags(match.files ?? match.allowed_paths ?? [], []),
193
+ structured: {
194
+ root_cause: reviewed.review_note ?? `Confidence inflated by ${drop} points`,
195
+ applies_to: match.allowed_paths?.[0],
196
+ },
197
+ });
198
+ }
199
+ }
200
+ if (typeof reviewed.confidence === 'number')
201
+ match.confidence = reviewed.confidence;
202
+ if (typeof reviewed.impact_score === 'number')
203
+ match.impact_score = reviewed.impact_score;
204
+ }
205
+ }
206
+ // Clear pending
207
+ s.pending_proposals = null;
208
+ // Now filter and create tickets with revised scores
209
+ const result = await filterAndCreateTickets(ctx.run, ctx.db, pendingProposals);
210
+ // Update exploration log with rejection info
211
+ const lastIdx = s.scout_exploration_log.length - 1;
212
+ if (lastIdx >= 0) {
213
+ s.scout_exploration_log[lastIdx] += ` ${result.accepted.length} accepted, ${result.rejected.length} rejected (${result.rejected.map(r => r.reason).slice(0, 3).join('; ')}).`;
214
+ }
215
+ // Save reviewed artifact
216
+ ctx.run.saveArtifact(`${s.step_count}-scout-proposals-reviewed.json`, JSON.stringify({ reviewed: reviewedItems, result }, null, 2));
217
+ if (result.created_ticket_ids.length > 0) {
218
+ s.scout_retries = 0;
219
+ ctx.run.setPhase('NEXT_TICKET');
220
+ return {
221
+ processed: true,
222
+ phase_changed: true,
223
+ new_phase: 'NEXT_TICKET',
224
+ message: `Created ${result.created_ticket_ids.length} tickets after review (${result.rejected.length} rejected)`,
225
+ };
226
+ }
227
+ // All proposals rejected after review
228
+ if (s.scout_retries < MAX_SCOUT_RETRIES) {
229
+ s.scout_retries++;
230
+ return {
231
+ processed: true,
232
+ phase_changed: false,
233
+ message: `All proposals rejected after review (attempt ${s.scout_retries}/${MAX_SCOUT_RETRIES + 1}). Retrying.`,
234
+ };
235
+ }
236
+ ctx.run.setPhase('DONE');
237
+ return {
238
+ processed: true,
239
+ phase_changed: true,
240
+ new_phase: 'DONE',
241
+ message: `All proposals rejected after review and all retries: ${result.rejected.map(r => r.reason).join('; ')}`,
242
+ };
243
+ }
244
+ export async function handleProposalsFiltered(ctx, payload) {
245
+ const s = ctx.run.require();
246
+ // Emitted after proposal filtering.
247
+ // Check if we have ready tickets now.
248
+ const readyCount = await repos.tickets.countByStatus(ctx.db, s.project_id);
249
+ const ready = readyCount['ready'] ?? 0;
250
+ if (ready > 0 && s.phase === 'SCOUT') {
251
+ ctx.run.setPhase('NEXT_TICKET');
252
+ return {
253
+ processed: true,
254
+ phase_changed: true,
255
+ new_phase: 'NEXT_TICKET',
256
+ message: `${ready} tickets ready, transitioning to NEXT_TICKET`,
257
+ };
258
+ }
259
+ if (ready === 0 && s.phase === 'SCOUT') {
260
+ ctx.run.setPhase('DONE');
261
+ return {
262
+ processed: true,
263
+ phase_changed: true,
264
+ new_phase: 'DONE',
265
+ message: 'No proposals accepted, transitioning to DONE',
266
+ };
267
+ }
268
+ return { processed: true, phase_changed: false, message: 'Proposals filtered' };
269
+ }
270
+ //# sourceMappingURL=event-handlers-scout.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"event-handlers-scout.js","sourceRoot":"","sources":["../src/event-handlers-scout.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,5 @@
1
+ import type { EventContext, ProcessResult } from './event-helpers.js';
2
+ export declare function handlePlanSubmitted(ctx: EventContext, payload: Record<string, unknown>): Promise<ProcessResult>;
3
+ export declare function handleTicketResult(ctx: EventContext, payload: Record<string, unknown>): Promise<ProcessResult>;
4
+ export declare function handlePrCreated(ctx: EventContext, payload: Record<string, unknown>): Promise<ProcessResult>;
5
+ //# sourceMappingURL=event-handlers-ticket.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"event-handlers-ticket.d.ts","sourceRoot":"","sources":["../src/event-handlers-ticket.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,YAAY,EAAE,aAAa,EAAE,MAAM,oBAAoB,CAAC;AAQtE,wBAAsB,mBAAmB,CAAC,GAAG,EAAE,YAAY,EAAE,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,OAAO,CAAC,aAAa,CAAC,CAkGrH;AAED,wBAAsB,kBAAkB,CAAC,GAAG,EAAE,YAAY,EAAE,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,OAAO,CAAC,aAAa,CAAC,CA+HpH;AAED,wBAAsB,eAAe,CAAC,GAAG,EAAE,YAAY,EAAE,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,OAAO,CAAC,aAAa,CAAC,CA+BjH"}
@@ -0,0 +1,232 @@
1
+ import { repos } from '@promptwheel/core';
2
+ import { recordSectorOutcome, recordTicketDedup } from './event-helpers.js';
3
+ import { deriveScopePolicy, validatePlanScope } from './scope-policy.js';
4
+ import { recordDiff, recordPlanHash } from './spindle.js';
5
+ import { addLearning, extractTags } from './learnings.js';
6
+ import { isStreamJsonOutput, analyzeTrace } from '@promptwheel/core/trace/shared';
7
+ export async function handlePlanSubmitted(ctx, payload) {
8
+ const s = ctx.run.require();
9
+ if (s.phase !== 'PLAN') {
10
+ return { processed: true, phase_changed: false, message: 'Plan submitted outside PLAN phase, ignored' };
11
+ }
12
+ const raw = payload;
13
+ // Coerce files_to_touch — accept files/touched_files as fallback names
14
+ const rawFiles = Array.isArray(raw.files_to_touch) ? raw.files_to_touch
15
+ : Array.isArray(raw.files) ? raw.files
16
+ : Array.isArray(raw.touched_files) ? raw.touched_files : [];
17
+ const files_to_touch = rawFiles.map((f) => {
18
+ if (typeof f === 'string')
19
+ return { path: f, action: 'modify', reason: '' };
20
+ if (f && typeof f === 'object' && 'path' in f)
21
+ return f;
22
+ return { path: String(f), action: 'modify', reason: '' };
23
+ });
24
+ const plan = {
25
+ ticket_id: String(raw.ticket_id ?? s.current_ticket_id ?? ''),
26
+ files_to_touch,
27
+ expected_tests: Array.isArray(raw.expected_tests) ? raw.expected_tests.map(String) : [],
28
+ risk_level: (raw.risk_level === 'low' || raw.risk_level === 'medium' || raw.risk_level === 'high')
29
+ ? raw.risk_level : 'low',
30
+ estimated_lines: typeof raw.estimated_lines === 'number' ? raw.estimated_lines : 50,
31
+ };
32
+ // Derive scope policy for the current ticket
33
+ const ticket = s.current_ticket_id
34
+ ? await repos.tickets.getById(ctx.db, s.current_ticket_id)
35
+ : null;
36
+ const policy = deriveScopePolicy({
37
+ allowedPaths: ticket?.allowedPaths ?? [],
38
+ category: ticket?.category ?? 'refactor',
39
+ maxLinesPerTicket: s.max_lines_per_ticket,
40
+ learnings: s.cached_learnings,
41
+ });
42
+ // Validate plan against scope policy
43
+ const scopeResult = validatePlanScope(plan.files_to_touch, plan.estimated_lines, plan.risk_level, policy);
44
+ if (!scopeResult.valid) {
45
+ s.plan_rejections++;
46
+ s.last_plan_rejection_reason = scopeResult.reason ?? null;
47
+ ctx.run.appendEvent('PLAN_REJECTED', { reason: scopeResult.reason, attempt: s.plan_rejections });
48
+ // Record learning on plan rejection
49
+ if (s.learnings_enabled) {
50
+ const structured = {
51
+ root_cause: scopeResult.reason ?? 'scope violation',
52
+ pattern_type: 'convention',
53
+ applies_to: ticket?.allowedPaths?.[0],
54
+ };
55
+ addLearning(ctx.run.rootPath, {
56
+ text: `Plan rejected: ${scopeResult.reason}`.slice(0, 200),
57
+ category: 'gotcha',
58
+ source: { type: 'plan_rejection', detail: scopeResult.reason ?? undefined },
59
+ tags: extractTags(plan.files_to_touch.map(f => f.path), []),
60
+ structured,
61
+ });
62
+ }
63
+ return {
64
+ processed: true,
65
+ phase_changed: false,
66
+ message: `Plan rejected: ${scopeResult.reason} (attempt ${s.plan_rejections}/${3})`,
67
+ };
68
+ }
69
+ // Plan passed validation
70
+ s.current_ticket_plan = plan;
71
+ recordPlanHash(s.spindle, plan);
72
+ // High-risk plans → BLOCKED_NEEDS_HUMAN
73
+ if (plan.risk_level === 'high') {
74
+ ctx.run.appendEvent('PLAN_REJECTED', { reason: 'High-risk plan requires human approval', risk_level: 'high' });
75
+ ctx.run.setPhase('BLOCKED_NEEDS_HUMAN');
76
+ return {
77
+ processed: true,
78
+ phase_changed: true,
79
+ new_phase: 'BLOCKED_NEEDS_HUMAN',
80
+ message: 'High-risk plan requires human approval',
81
+ };
82
+ }
83
+ // Low/medium risk — auto-approve
84
+ s.plan_approved = true;
85
+ ctx.run.appendEvent('PLAN_APPROVED', { risk_level: plan.risk_level, auto: true });
86
+ ctx.run.setPhase('EXECUTE');
87
+ return {
88
+ processed: true,
89
+ phase_changed: true,
90
+ new_phase: 'EXECUTE',
91
+ message: `${plan.risk_level}-risk plan auto-approved, moving to EXECUTE`,
92
+ };
93
+ }
94
+ export async function handleTicketResult(ctx, payload) {
95
+ const s = ctx.run.require();
96
+ if (s.phase !== 'EXECUTE') {
97
+ return { processed: true, phase_changed: false, message: 'Ticket result outside EXECUTE phase' };
98
+ }
99
+ const status = payload['status'];
100
+ // Accept both 'done' and 'success' as completion status
101
+ if (status === 'done' || status === 'success') {
102
+ // Validate changed_files against plan (if plan exists)
103
+ const changedFiles = (payload['changed_files'] ?? []);
104
+ const linesAdded = (payload['lines_added'] ?? 0);
105
+ const linesRemoved = (payload['lines_removed'] ?? 0);
106
+ const totalLines = linesAdded + linesRemoved;
107
+ // Save ticket result artifact
108
+ ctx.run.saveArtifact(`${s.step_count}-ticket-result.json`, JSON.stringify({
109
+ status,
110
+ changed_files: changedFiles,
111
+ lines_added: linesAdded,
112
+ lines_removed: linesRemoved,
113
+ summary: payload['summary'],
114
+ }, null, 2));
115
+ // Validate changed files against approved plan
116
+ if (s.current_ticket_plan) {
117
+ const plannedPaths = new Set(s.current_ticket_plan.files_to_touch.map(f => f.path));
118
+ const surpriseFiles = changedFiles.filter(f => !plannedPaths.has(f));
119
+ if (surpriseFiles.length > 0) {
120
+ ctx.run.appendEvent('SCOPE_BLOCKED', {
121
+ ticket_id: s.current_ticket_id,
122
+ surprise_files: surpriseFiles,
123
+ planned_files: [...plannedPaths],
124
+ });
125
+ return {
126
+ processed: true,
127
+ phase_changed: false,
128
+ message: `Changed files not in plan: ${surpriseFiles.join(', ')}. Revert those changes and re-submit.`,
129
+ };
130
+ }
131
+ // Validate lines against budget
132
+ if (totalLines > s.max_lines_per_ticket) {
133
+ return {
134
+ processed: true,
135
+ phase_changed: false,
136
+ message: `Lines changed (${totalLines}) exceeds budget (${s.max_lines_per_ticket}). Reduce changes.`,
137
+ };
138
+ }
139
+ }
140
+ // Track lines
141
+ s.total_lines_changed += totalLines;
142
+ // Update spindle state with diff info
143
+ const diff = (payload['diff'] ?? null);
144
+ recordDiff(s.spindle, diff ?? (changedFiles.length > 0 ? changedFiles.join('\n') : null));
145
+ // Opportunistic trace analysis: if stdout is in payload, check for stream-json
146
+ const stdout = payload['stdout'];
147
+ if (stdout && isStreamJsonOutput(stdout.split('\n')[0] ?? '')) {
148
+ try {
149
+ const traceAnalysis = analyzeTrace(stdout);
150
+ ctx.run.appendEvent('TRACE_ANALYSIS', {
151
+ ticket_id: s.current_ticket_id,
152
+ is_stream_json: traceAnalysis.is_stream_json,
153
+ compaction_count: traceAnalysis.compactions.length,
154
+ total_tokens: traceAnalysis.total_input_tokens + traceAnalysis.total_output_tokens,
155
+ tool_count: traceAnalysis.tool_profiles.length,
156
+ });
157
+ }
158
+ catch (err) {
159
+ console.warn(`[promptwheel] trace analysis: ${err instanceof Error ? err.message : String(err)}`);
160
+ }
161
+ }
162
+ // Move to QA
163
+ ctx.run.setPhase('QA');
164
+ return {
165
+ processed: true,
166
+ phase_changed: true,
167
+ new_phase: 'QA',
168
+ message: `Ticket result accepted (${changedFiles.length} files, ${totalLines} lines), moving to QA`,
169
+ };
170
+ }
171
+ if (status === 'failed') {
172
+ // Fetch ticket once for both learning and dedup
173
+ const ticket = s.current_ticket_id ? await repos.tickets.getById(ctx.db, s.current_ticket_id) : null;
174
+ // Record learning on ticket failure
175
+ if (s.learnings_enabled) {
176
+ const reason = payload['reason'] ?? 'Execution failed';
177
+ const structured = {
178
+ root_cause: reason.slice(0, 200),
179
+ fragile_paths: ticket?.allowedPaths?.filter(p => !p.includes('*')),
180
+ };
181
+ addLearning(ctx.run.rootPath, {
182
+ text: `Ticket failed on ${ticket?.title ?? 'unknown'} — ${reason}`.slice(0, 200),
183
+ category: 'warning',
184
+ source: { type: 'ticket_failure', detail: reason },
185
+ tags: extractTags(ticket?.allowedPaths ?? [], ticket?.verificationCommands ?? []),
186
+ structured,
187
+ });
188
+ }
189
+ // Record failed ticket in dedup memory + sector failure
190
+ await recordTicketDedup(ctx.db, ctx.run.rootPath, s.current_ticket_id, false, 'agent_error', ticket);
191
+ recordSectorOutcome(ctx.run.rootPath, s.current_sector_path, 'failure');
192
+ // Fail the ticket, move to next
193
+ if (s.current_ticket_id) {
194
+ await repos.tickets.updateStatus(ctx.db, s.current_ticket_id, 'blocked');
195
+ ctx.run.failTicket(payload['reason'] ?? 'Execution failed');
196
+ }
197
+ ctx.run.setPhase('NEXT_TICKET');
198
+ return {
199
+ processed: true,
200
+ phase_changed: true,
201
+ new_phase: 'NEXT_TICKET',
202
+ message: 'Ticket failed, moving to NEXT_TICKET',
203
+ };
204
+ }
205
+ return { processed: true, phase_changed: false, message: `Ticket result: ${status}` };
206
+ }
207
+ export async function handlePrCreated(ctx, payload) {
208
+ const s = ctx.run.require();
209
+ if (s.phase !== 'PR') {
210
+ return { processed: true, phase_changed: false, message: 'PR created outside PR phase' };
211
+ }
212
+ // Record completed ticket in dedup memory + sector success (before completeTicket clears current_ticket_id)
213
+ await recordTicketDedup(ctx.db, ctx.run.rootPath, s.current_ticket_id, true);
214
+ recordSectorOutcome(ctx.run.rootPath, s.current_sector_path, 'success');
215
+ // Save PR artifact
216
+ ctx.run.saveArtifact(`${s.step_count}-pr-created.json`, JSON.stringify({
217
+ ticket_id: s.current_ticket_id,
218
+ pr_number: s.prs_created + 1,
219
+ ...payload,
220
+ }, null, 2));
221
+ s.prs_created++;
222
+ ctx.run.completeTicket();
223
+ ctx.run.appendEvent('PR_CREATED', payload);
224
+ ctx.run.setPhase('NEXT_TICKET');
225
+ return {
226
+ processed: true,
227
+ phase_changed: true,
228
+ new_phase: 'NEXT_TICKET',
229
+ message: `PR created (${s.prs_created}/${s.max_prs}), moving to NEXT_TICKET`,
230
+ };
231
+ }
232
+ //# sourceMappingURL=event-handlers-ticket.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"event-handlers-ticket.js","sourceRoot":"","sources":["../src/event-handlers-ticket.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,46 @@
1
+ import type { DatabaseAdapter } from '@promptwheel/core';
2
+ import type { Project } from '@promptwheel/core';
3
+ import { RunManager } from './run-manager.js';
4
+ import type { SectorState } from '@promptwheel/core/sectors/shared';
5
+ export interface EventContext {
6
+ run: RunManager;
7
+ db: DatabaseAdapter;
8
+ project?: Project;
9
+ }
10
+ export interface ProcessResult {
11
+ processed: boolean;
12
+ phase_changed: boolean;
13
+ new_phase?: string;
14
+ message: string;
15
+ }
16
+ /** Atomic write: write to .tmp then rename, preventing corruption on crash */
17
+ export declare function atomicWriteJsonSync(filePath: string, data: unknown): void;
18
+ /** Load sectors.json, return null if missing/invalid. */
19
+ export declare function loadSectorsState(rootPath: string): {
20
+ state: SectorState;
21
+ filePath: string;
22
+ } | null;
23
+ export declare function recordSectorOutcome(rootPath: string, sectorPath: string | undefined, outcome: 'success' | 'failure'): void;
24
+ export declare function recordTicketDedup(db: DatabaseAdapter, rootPath: string, ticketId: string | null, completed: boolean, reason?: string,
25
+ /** Pass a pre-fetched ticket to avoid a redundant DB lookup */
26
+ prefetchedTicket?: {
27
+ title: string;
28
+ } | null): Promise<void>;
29
+ /**
30
+ * Extract a normalized error signature from raw error output.
31
+ * Captures the first recognizable error pattern (TypeError, SyntaxError, assertion, etc.)
32
+ * and truncates to 120 chars for storage.
33
+ */
34
+ export declare function extractErrorSignature(errorOutput: string): string | undefined;
35
+ export type QaErrorClass = 'environment' | 'timeout' | 'code' | 'unknown';
36
+ /**
37
+ * Classify a QA error to determine retry strategy.
38
+ * - environment: permission denied, missing tools, env vars — don't retry (will never pass)
39
+ * - timeout: command timed out — retry once (transient)
40
+ * - code: test failures, type errors, syntax errors — full retries (agent can fix)
41
+ * - unknown: can't classify — full retries (default)
42
+ */
43
+ export declare function classifyQaError(errorOutput: string): QaErrorClass;
44
+ /** Max retries per error class */
45
+ export declare function maxRetriesForClass(errorClass: QaErrorClass): number;
46
+ //# sourceMappingURL=event-helpers.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"event-helpers.d.ts","sourceRoot":"","sources":["../src/event-helpers.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,mBAAmB,CAAC;AACzD,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,mBAAmB,CAAC;AAEjD,OAAO,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAC;AAK9C,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,kCAAkC,CAAC;AAMpE,MAAM,WAAW,YAAY;IAC3B,GAAG,EAAE,UAAU,CAAC;IAChB,EAAE,EAAE,eAAe,CAAC;IACpB,OAAO,CAAC,EAAE,OAAO,CAAC;CACnB;AAMD,MAAM,WAAW,aAAa;IAC5B,SAAS,EAAE,OAAO,CAAC;IACnB,aAAa,EAAE,OAAO,CAAC;IACvB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,OAAO,EAAE,MAAM,CAAC;CACjB;AAMD,8EAA8E;AAC9E,wBAAgB,mBAAmB,CAAC,QAAQ,EAAE,MAAM,EAAE,IAAI,EAAE,OAAO,GAAG,IAAI,CAIzE;AAED,yDAAyD;AACzD,wBAAgB,gBAAgB,CAAC,QAAQ,EAAE,MAAM,GAAG;IAAE,KAAK,EAAE,WAAW,CAAC;IAAC,QAAQ,EAAE,MAAM,CAAA;CAAE,GAAG,IAAI,CAWlG;AAED,wBAAgB,mBAAmB,CACjC,QAAQ,EAAE,MAAM,EAChB,UAAU,EAAE,MAAM,GAAG,SAAS,EAC9B,OAAO,EAAE,SAAS,GAAG,SAAS,GAC7B,IAAI,CAUN;AAED,wBAAsB,iBAAiB,CACrC,EAAE,EAAE,eAAe,EACnB,QAAQ,EAAE,MAAM,EAChB,QAAQ,EAAE,MAAM,GAAG,IAAI,EACvB,SAAS,EAAE,OAAO,EAClB,MAAM,CAAC,EAAE,MAAM;AACf,+DAA+D;AAC/D,gBAAgB,CAAC,EAAE;IAAE,KAAK,EAAE,MAAM,CAAA;CAAE,GAAG,IAAI,GAC1C,OAAO,CAAC,IAAI,CAAC,CAUf;AAED;;;;GAIG;AACH,wBAAgB,qBAAqB,CAAC,WAAW,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,CAgB7E;AAMD,MAAM,MAAM,YAAY,GAAG,aAAa,GAAG,SAAS,GAAG,MAAM,GAAG,SAAS,CAAC;AAE1E;;;;;;GAMG;AACH,wBAAgB,eAAe,CAAC,WAAW,EAAE,MAAM,GAAG,YAAY,CAejE;AAED,kCAAkC;AAClC,wBAAgB,kBAAkB,CAAC,UAAU,EAAE,YAAY,GAAG,MAAM,CAOnE"}