@rallycry/conveyor-agent 7.2.4 → 7.2.5

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/cli.js CHANGED
@@ -5,7 +5,7 @@ import {
5
5
  loadConveyorConfig,
6
6
  runSetupCommand,
7
7
  runStartCommand
8
- } from "./chunk-AS3FYEBJ.js";
8
+ } from "./chunk-JFWVIDQ2.js";
9
9
  import "./chunk-C5YAMQJ2.js";
10
10
  import {
11
11
  createServiceLogger
package/dist/index.js CHANGED
@@ -24,7 +24,7 @@ import {
24
24
  runStartCommand,
25
25
  stageAndCommit,
26
26
  updateRemoteToken
27
- } from "./chunk-AS3FYEBJ.js";
27
+ } from "./chunk-JFWVIDQ2.js";
28
28
  import "./chunk-C5YAMQJ2.js";
29
29
  import "./chunk-RRXX6DTB.js";
30
30
 
@@ -9,6 +9,167 @@ import {
9
9
 
10
10
  // src/runner/task-audit-handler.ts
11
11
  import { z } from "zod";
12
+
13
+ // src/runner/task-audit-parsing.ts
14
+ function formatMacroEvaluation(macro) {
15
+ if (!macro) return null;
16
+ const lines = [];
17
+ if (macro.instructionsQuality) lines.push(`- Instructions Quality: ${macro.instructionsQuality}`);
18
+ if (macro.modelSuitability) lines.push(`- Model Suitability: ${macro.modelSuitability}`);
19
+ if (macro.contextAndPlanning) lines.push(`- Context & Planning: ${macro.contextAndPlanning}`);
20
+ if (macro.overallResult) lines.push(`- Overall Result: ${macro.overallResult}`);
21
+ return lines.length > 0 ? lines.join("\n") : null;
22
+ }
23
+ function formatHumanEvaluations(evals) {
24
+ if (evals.length === 0) return null;
25
+ const total = evals.reduce((sum, e) => sum + e.rating, 0);
26
+ const avg = total / evals.length;
27
+ const label = avg > 0.3 ? "Helpful" : avg < -0.3 ? "Unhelpful" : "Neutral";
28
+ const lines = [
29
+ `- Overall: ${label} (avg ${avg.toFixed(2)}, ${evals.length} message${evals.length === 1 ? "" : "s"})`
30
+ ];
31
+ for (const e of evals) {
32
+ const ratingLabel = e.rating > 0 ? "helpful" : e.rating < 0 ? "unhelpful" : "neutral";
33
+ lines.push(` - Message ${e.messageIndex}: ${ratingLabel} \u2014 ${e.reasoning}`);
34
+ }
35
+ return lines.join("\n");
36
+ }
37
+ function toAuditResult(parsed) {
38
+ if (!parsed || !Array.isArray(parsed.turnGrades)) return null;
39
+ const macro = parsed.macroEvaluation;
40
+ const rawHumanEvals = Array.isArray(parsed.humanEvaluations) ? parsed.humanEvaluations : [];
41
+ const baseSummary = parsed.summary ?? "";
42
+ const macroText = formatMacroEvaluation(macro);
43
+ const humanEvalText = formatHumanEvaluations(rawHumanEvals);
44
+ let summary = baseSummary;
45
+ if (macroText) summary += `
46
+
47
+ ---
48
+
49
+ Macro Evaluation:
50
+ ${macroText}`;
51
+ if (humanEvalText) summary += `
52
+
53
+ ---
54
+
55
+ Human Contributions:
56
+ ${humanEvalText}`;
57
+ return {
58
+ turnGrades: parsed.turnGrades,
59
+ summary,
60
+ planningAccuracy: parsed.planningAccuracy ?? null,
61
+ buildingAccuracy: parsed.buildingAccuracy ?? null,
62
+ humanAccuracy: parsed.humanAccuracy ?? null,
63
+ humanEvaluations: rawHumanEvals,
64
+ macroEvaluation: macro ? {
65
+ instructionsQuality: macro.instructionsQuality ?? void 0,
66
+ modelSuitability: macro.modelSuitability ?? void 0,
67
+ contextAndPlanning: macro.contextAndPlanning ?? void 0,
68
+ overallResult: macro.overallResult ?? void 0
69
+ } : null
70
+ };
71
+ }
72
+ function extractJsonFromResponse(text) {
73
+ const codeBlockMatch = text.match(/```(?:json)?\s*\n?([\s\S]*?)```/);
74
+ const jsonStr = codeBlockMatch ? codeBlockMatch[1].trim() : text;
75
+ try {
76
+ const result = toAuditResult(JSON.parse(jsonStr));
77
+ if (result) return result;
78
+ } catch {
79
+ }
80
+ const objectMatch = text.match(/\{[\s\S]*"turnGrades"[\s\S]*\}/);
81
+ if (objectMatch) {
82
+ try {
83
+ const result = toAuditResult(JSON.parse(objectMatch[0]));
84
+ if (result) return result;
85
+ } catch {
86
+ }
87
+ }
88
+ throw new Error("Could not parse task audit grades from Claude response");
89
+ }
90
+ function computeGradeCounts(turnGrades) {
91
+ const counts = {
92
+ planningCorrect: 0,
93
+ planningNeutral: 0,
94
+ planningBlunder: 0,
95
+ buildingCorrect: 0,
96
+ buildingNeutral: 0,
97
+ buildingBlunder: 0,
98
+ humanCorrect: 0,
99
+ humanNeutral: 0,
100
+ humanBlunder: 0
101
+ };
102
+ for (const tg of turnGrades) {
103
+ const key = `${tg.phase}${tg.grade.charAt(0).toUpperCase()}${tg.grade.slice(1)}`;
104
+ if (key in counts) {
105
+ counts[key]++;
106
+ }
107
+ }
108
+ return counts;
109
+ }
110
+ function addCosts(base, addition) {
111
+ if (base === null) return addition;
112
+ if (addition === null) return base;
113
+ return base + addition;
114
+ }
115
+ function buildErrorResult(projectId, requestId, taskId, error) {
116
+ return {
117
+ projectId,
118
+ requestId,
119
+ taskId,
120
+ summary: "",
121
+ turnGrades: [],
122
+ planningAccuracy: null,
123
+ buildingAccuracy: null,
124
+ humanAccuracy: null,
125
+ planningCorrect: 0,
126
+ planningNeutral: 0,
127
+ planningBlunder: 0,
128
+ buildingCorrect: 0,
129
+ buildingNeutral: 0,
130
+ buildingBlunder: 0,
131
+ humanCorrect: 0,
132
+ humanNeutral: 0,
133
+ humanBlunder: 0,
134
+ suggestionIds: [],
135
+ auditCostUsd: null,
136
+ model: null,
137
+ error
138
+ };
139
+ }
140
+ function buildSuggestionPrompt(parsed, task) {
141
+ const parts = [`# Suggestion Generation for: ${task.taskTitle}
142
+ `];
143
+ parts.push(`## Audit Summary
144
+ ${parsed.summary}
145
+ `);
146
+ if (parsed.macroEvaluation) {
147
+ parts.push("## Macro Evaluation");
148
+ if (parsed.macroEvaluation.instructionsQuality)
149
+ parts.push(`- Instructions Quality: ${parsed.macroEvaluation.instructionsQuality}`);
150
+ if (parsed.macroEvaluation.modelSuitability)
151
+ parts.push(`- Model Suitability: ${parsed.macroEvaluation.modelSuitability}`);
152
+ if (parsed.macroEvaluation.contextAndPlanning)
153
+ parts.push(`- Context & Planning: ${parsed.macroEvaluation.contextAndPlanning}`);
154
+ if (parsed.macroEvaluation.overallResult)
155
+ parts.push(`- Overall Result: ${parsed.macroEvaluation.overallResult}`);
156
+ parts.push("");
157
+ }
158
+ const blunders = parsed.turnGrades.filter((tg) => tg.grade === "blunder");
159
+ if (blunders.length > 0) {
160
+ parts.push("## Notable Blunders");
161
+ for (const b of blunders.slice(0, 10)) {
162
+ parts.push(`- Turn ${b.turnIndex} (${b.phase}): ${b.reasoning}`);
163
+ }
164
+ parts.push("");
165
+ }
166
+ parts.push(
167
+ "Based on the findings above, call create_suggestion for each actionable cross-cutting improvement."
168
+ );
169
+ return parts.join("\n");
170
+ }
171
+
172
+ // src/runner/task-audit-handler.ts
12
173
  var logger = createServiceLogger("TaskAudit");
13
174
  var FALLBACK_MODEL = "claude-sonnet-4-6";
14
175
  var TASK_AUDIT_SYSTEM_PROMPT = `You are a chess-style analysis engine for AI agent task execution. You grade each turn of an agent's work trace like a chess engine grades moves: Correct, Neutral, or Blunder.
@@ -100,18 +261,7 @@ After grading individual turns, perform a high-level assessment of the overall t
100
261
  - **Context & Planning**: Was the plan/context sufficient for the agent to succeed? Were there information gaps that caused wasted effort?
101
262
  - **Overall Result**: Did the final result meet the task requirements? Was the outcome proportional to the effort spent?
102
263
 
103
- Include a "macroEvaluation" object in your JSON output.
104
-
105
- ## Suggestion Creation (MANDATORY)
106
-
107
- After outputting the JSON block above, you MUST call the \`create_suggestion\` tool for each actionable cross-cutting improvement. Do NOT stop after the JSON block \u2014 you must continue and call the tool. Focus on:
108
- - Recurring patterns of wasted effort
109
- - Missing documentation or context that caused confusion
110
- - Process improvements that would prevent common blunders
111
- - Tool or workflow optimizations
112
- - Actionable macro findings that would improve future task execution
113
-
114
- You MUST call create_suggestion at least once. If the execution was flawless, suggest what made it work well so the pattern can be replicated.`;
264
+ Include a "macroEvaluation" object in your JSON output.`;
115
265
  function buildSessionInfoSection(info) {
116
266
  const lines = ["## Session Info"];
117
267
  if (info.model) lines.push(`- Model: ${info.model}`);
@@ -162,11 +312,19 @@ ${task.agentInstructions}
162
312
  parts.push("");
163
313
  }
164
314
  parts.push(buildTraceSection(task.agentTrace));
165
- parts.push(
166
- "Grade each turn above, then output the structured JSON result, then call create_suggestion for each cross-cutting improvement. You must call create_suggestion at least once."
167
- );
315
+ parts.push("Grade each turn above, then output the structured JSON result.");
168
316
  return parts.join("\n");
169
317
  }
318
+ var SUGGESTION_SYSTEM_PROMPT = `You are a suggestion generator for an AI task audit system. Based on the audit findings below, create actionable project-level suggestions using the create_suggestion tool.
319
+
320
+ Focus on:
321
+ - Recurring patterns of wasted effort that could be prevented
322
+ - Missing documentation or context that caused agent confusion
323
+ - Process improvements that would prevent common blunders
324
+ - Tool or workflow optimizations
325
+ - Actionable macro findings that would improve future task execution
326
+
327
+ You MUST call create_suggestion at least once. If the execution was flawless, suggest what made it work well so the pattern can be replicated.`;
170
328
  function buildProjectSuggestionTool(connection, projectId) {
171
329
  return defineTool(
172
330
  "create_suggestion",
@@ -200,173 +358,79 @@ function buildProjectSuggestionTool(connection, projectId) {
200
358
  }
201
359
  async function fetchModel(connection) {
202
360
  try {
203
- const ctx = await connection.call("getProjectAgentContext", {
204
- projectId: connection.projectId
361
+ const ctx = await connection.call("getProjectAgentContextByRole", {
362
+ projectId: connection.projectId,
363
+ role: "reviewer"
205
364
  });
206
365
  return ctx.model || FALLBACK_MODEL;
207
366
  } catch {
208
367
  return FALLBACK_MODEL;
209
368
  }
210
369
  }
211
- function formatMacroEvaluation(macro) {
212
- if (!macro) return null;
213
- const lines = [];
214
- if (macro.instructionsQuality) lines.push(`- Instructions Quality: ${macro.instructionsQuality}`);
215
- if (macro.modelSuitability) lines.push(`- Model Suitability: ${macro.modelSuitability}`);
216
- if (macro.contextAndPlanning) lines.push(`- Context & Planning: ${macro.contextAndPlanning}`);
217
- if (macro.overallResult) lines.push(`- Overall Result: ${macro.overallResult}`);
218
- return lines.length > 0 ? lines.join("\n") : null;
219
- }
220
- function formatHumanEvaluations(evals) {
221
- if (evals.length === 0) return null;
222
- const total = evals.reduce((sum, e) => sum + e.rating, 0);
223
- const avg = total / evals.length;
224
- const label = avg > 0.3 ? "Helpful" : avg < -0.3 ? "Unhelpful" : "Neutral";
225
- const lines = [
226
- `- Overall: ${label} (avg ${avg.toFixed(2)}, ${evals.length} message${evals.length === 1 ? "" : "s"})`
227
- ];
228
- for (const e of evals) {
229
- const ratingLabel = e.rating > 0 ? "helpful" : e.rating < 0 ? "unhelpful" : "neutral";
230
- lines.push(` - Message ${e.messageIndex}: ${ratingLabel} \u2014 ${e.reasoning}`);
231
- }
232
- return lines.join("\n");
233
- }
234
- function toAuditResult(parsed) {
235
- if (!parsed || !Array.isArray(parsed.turnGrades)) return null;
236
- const macro = parsed.macroEvaluation;
237
- const rawHumanEvals = Array.isArray(parsed.humanEvaluations) ? parsed.humanEvaluations : [];
238
- const baseSummary = parsed.summary ?? "";
239
- const macroText = formatMacroEvaluation(macro);
240
- const humanEvalText = formatHumanEvaluations(rawHumanEvals);
241
- let summary = baseSummary;
242
- if (macroText) summary += `
243
-
244
- ---
245
-
246
- Macro Evaluation:
247
- ${macroText}`;
248
- if (humanEvalText) summary += `
249
-
250
- ---
251
-
252
- Human Contributions:
253
- ${humanEvalText}`;
254
- return {
255
- turnGrades: parsed.turnGrades,
256
- summary,
257
- planningAccuracy: parsed.planningAccuracy ?? null,
258
- buildingAccuracy: parsed.buildingAccuracy ?? null,
259
- humanAccuracy: parsed.humanAccuracy ?? null,
260
- humanEvaluations: rawHumanEvals,
261
- macroEvaluation: macro ? {
262
- instructionsQuality: macro.instructionsQuality ?? void 0,
263
- modelSuitability: macro.modelSuitability ?? void 0,
264
- contextAndPlanning: macro.contextAndPlanning ?? void 0,
265
- overallResult: macro.overallResult ?? void 0
266
- } : null
267
- };
268
- }
269
- function extractJsonFromResponse(text) {
270
- const codeBlockMatch = text.match(/```(?:json)?\s*\n?([\s\S]*?)```/);
271
- const jsonStr = codeBlockMatch ? codeBlockMatch[1].trim() : text;
272
- try {
273
- const result = toAuditResult(JSON.parse(jsonStr));
274
- if (result) return result;
275
- } catch {
276
- }
277
- const objectMatch = text.match(/\{[\s\S]*"turnGrades"[\s\S]*\}/);
278
- if (objectMatch) {
279
- try {
280
- const result = toAuditResult(JSON.parse(objectMatch[0]));
281
- if (result) return result;
282
- } catch {
283
- }
284
- }
285
- throw new Error("Could not parse task audit grades from Claude response");
370
+ function reportProgress(connection, requestId, taskId, tool, input) {
371
+ void connection.call("reportTaskAuditProgress", {
372
+ projectId: connection.projectId,
373
+ requestId,
374
+ taskId,
375
+ activity: { tool, input, timestamp: (/* @__PURE__ */ new Date()).toISOString() }
376
+ }).catch(() => {
377
+ });
286
378
  }
287
- function computeGradeCounts(turnGrades) {
288
- const counts = {
289
- planningCorrect: 0,
290
- planningNeutral: 0,
291
- planningBlunder: 0,
292
- buildingCorrect: 0,
293
- buildingNeutral: 0,
294
- buildingBlunder: 0,
295
- humanCorrect: 0,
296
- humanNeutral: 0,
297
- humanBlunder: 0
298
- };
299
- for (const tg of turnGrades) {
300
- const key = `${tg.phase}${tg.grade.charAt(0).toUpperCase()}${tg.grade.slice(1)}`;
301
- if (key in counts) {
302
- counts[key]++;
379
+ function processAssistantBlocks(blocks, responseParts, ctx, reportedFirstText) {
380
+ for (const block of blocks) {
381
+ if (block.type === "text" && block.text) {
382
+ responseParts.push(block.text);
383
+ if (reportedFirstText.value) continue;
384
+ reportedFirstText.value = true;
385
+ reportProgress(
386
+ ctx.connection,
387
+ ctx.requestId,
388
+ ctx.taskId,
389
+ "thinking",
390
+ block.text.slice(0, 200)
391
+ );
392
+ } else if (block.type === "tool_use" && block.name) {
393
+ const inputStr = typeof block.input === "string" ? block.input : JSON.stringify(block.input);
394
+ reportProgress(ctx.connection, ctx.requestId, ctx.taskId, block.name, inputStr.slice(0, 500));
303
395
  }
304
396
  }
305
- return counts;
306
397
  }
307
398
  async function collectResponseFromEvents(events, connection, requestId, taskId) {
308
399
  const responseParts = [];
309
400
  let costUsd = null;
310
401
  let model = null;
402
+ const reportedFirstText = { value: false };
403
+ const ctx = { connection, requestId, taskId };
311
404
  for await (const event of events) {
312
405
  if (event.type === "system") {
313
406
  const sysEvent = event;
314
407
  if (sysEvent.subtype === "init" && sysEvent.model) {
315
408
  model = sysEvent.model;
409
+ reportProgress(
410
+ connection,
411
+ requestId,
412
+ taskId,
413
+ "system",
414
+ `Initialized model: ${sysEvent.model}`
415
+ );
316
416
  }
317
417
  }
318
418
  if (event.type === "assistant") {
319
419
  const { message } = event;
320
- for (const block of message.content) {
321
- if (block.type === "text" && block.text) {
322
- responseParts.push(block.text);
323
- } else if (block.type === "tool_use" && block.name) {
324
- const inputStr = typeof block.input === "string" ? block.input : JSON.stringify(block.input);
325
- await connection.call("reportTaskAuditProgress", {
326
- projectId: connection.projectId,
327
- requestId,
328
- taskId,
329
- activity: `${block.name}: ${inputStr.slice(0, 500)}`
330
- }).catch(() => {
331
- });
332
- }
333
- }
420
+ processAssistantBlocks(message.content, responseParts, ctx, reportedFirstText);
334
421
  }
335
422
  if (event.type === "result") {
336
423
  const resultEvent = event;
337
424
  if (resultEvent.subtype === "success" && resultEvent.total_cost_usd !== void 0) {
338
425
  costUsd = resultEvent.total_cost_usd;
339
426
  }
427
+ const status = resultEvent.subtype === "success" ? "success" : `error: ${resultEvent.subtype}`;
428
+ reportProgress(connection, requestId, taskId, "complete", status);
340
429
  break;
341
430
  }
342
431
  }
343
432
  return { text: responseParts.join("\n\n").trim(), costUsd, model };
344
433
  }
345
- function buildErrorResult(projectId, requestId, taskId, error) {
346
- return {
347
- projectId,
348
- requestId,
349
- taskId,
350
- summary: "",
351
- turnGrades: [],
352
- planningAccuracy: null,
353
- buildingAccuracy: null,
354
- humanAccuracy: null,
355
- planningCorrect: 0,
356
- planningNeutral: 0,
357
- planningBlunder: 0,
358
- buildingCorrect: 0,
359
- buildingNeutral: 0,
360
- buildingBlunder: 0,
361
- humanCorrect: 0,
362
- humanNeutral: 0,
363
- humanBlunder: 0,
364
- suggestionIds: [],
365
- auditCostUsd: null,
366
- model: null,
367
- error
368
- };
369
- }
370
434
  function buildTrackedSuggestionTool(connection, projectId, suggestionIds) {
371
435
  const suggestionTool = buildProjectSuggestionTool(connection, projectId);
372
436
  return defineTool(
@@ -382,23 +446,46 @@ function buildTrackedSuggestionTool(connection, projectId, suggestionIds) {
382
446
  }
383
447
  );
384
448
  }
385
- async function auditSingleTask(taskPayload, request, connection, projectDir, model) {
386
- const { requestId, projectId } = request;
387
- await connection.call("reportTaskAuditProgress", {
388
- projectId: connection.projectId,
449
+ async function runSuggestionPhase(parsed, taskPayload, connection, requestId, projectId, projectDir, model, suggestionIds) {
450
+ reportProgress(
451
+ connection,
389
452
  requestId,
390
- taskId: taskPayload.taskId,
391
- activity: "Starting task audit..."
392
- }).catch(() => {
393
- });
394
- const suggestionIds = [];
453
+ taskPayload.taskId,
454
+ "status",
455
+ "Creating suggestions from findings..."
456
+ );
395
457
  const wrappedSuggestionTool = buildTrackedSuggestionTool(connection, projectId, suggestionIds);
396
458
  const harness = createHarness();
397
- const mcpServer = harness.createMcpServer({
398
- name: "conveyor",
399
- tools: [wrappedSuggestionTool]
400
- });
459
+ const mcpServer = harness.createMcpServer({ name: "conveyor", tools: [wrappedSuggestionTool] });
401
460
  const events = harness.executeQuery({
461
+ prompt: buildSuggestionPrompt(parsed, taskPayload),
462
+ options: {
463
+ model,
464
+ systemPrompt: SUGGESTION_SYSTEM_PROMPT,
465
+ cwd: projectDir,
466
+ permissionMode: "bypassPermissions",
467
+ allowDangerouslySkipPermissions: true,
468
+ tools: { type: "preset", preset: "claude_code" },
469
+ mcpServers: { conveyor: mcpServer },
470
+ maxTurns: 4,
471
+ maxBudgetUsd: 0.5,
472
+ disallowedTools: ["Edit", "Write", "Bash", "NotebookEdit", "MultiEdit"]
473
+ }
474
+ });
475
+ const response = await collectResponseFromEvents(
476
+ events,
477
+ connection,
478
+ requestId,
479
+ taskPayload.taskId
480
+ );
481
+ return response.costUsd;
482
+ }
483
+ async function auditSingleTask(taskPayload, request, connection, projectDir, model) {
484
+ const { requestId, projectId } = request;
485
+ const suggestionIds = [];
486
+ reportProgress(connection, requestId, taskPayload.taskId, "status", "Generating audit grades...");
487
+ const analysisHarness = createHarness();
488
+ const analysisEvents = analysisHarness.executeQuery({
402
489
  prompt: buildTaskAuditPrompt(taskPayload),
403
490
  options: {
404
491
  model,
@@ -407,21 +494,41 @@ async function auditSingleTask(taskPayload, request, connection, projectDir, mod
407
494
  permissionMode: "bypassPermissions",
408
495
  allowDangerouslySkipPermissions: true,
409
496
  tools: { type: "preset", preset: "claude_code" },
410
- mcpServers: { conveyor: mcpServer },
497
+ mcpServers: {},
411
498
  maxTurns: 16,
412
499
  maxBudgetUsd: 3,
413
500
  disallowedTools: ["Edit", "Write", "Bash", "NotebookEdit", "MultiEdit"]
414
501
  }
415
502
  });
416
- const response = await collectResponseFromEvents(
417
- events,
503
+ const analysisResponse = await collectResponseFromEvents(
504
+ analysisEvents,
418
505
  connection,
419
506
  requestId,
420
507
  taskPayload.taskId
421
508
  );
422
- if (!response.text) throw new Error("No response from Claude");
423
- const parsed = extractJsonFromResponse(response.text);
509
+ if (!analysisResponse.text) throw new Error("No response from Claude");
510
+ const parsed = extractJsonFromResponse(analysisResponse.text);
424
511
  const counts = computeGradeCounts(parsed.turnGrades);
512
+ let totalCostUsd = analysisResponse.costUsd;
513
+ try {
514
+ const suggestionCost = await runSuggestionPhase(
515
+ parsed,
516
+ taskPayload,
517
+ connection,
518
+ requestId,
519
+ projectId,
520
+ projectDir,
521
+ model,
522
+ suggestionIds
523
+ );
524
+ totalCostUsd = addCosts(totalCostUsd, suggestionCost);
525
+ } catch (err) {
526
+ logger.warn("Suggestion phase failed, proceeding without suggestions", {
527
+ requestId,
528
+ taskId: taskPayload.taskId,
529
+ error: err instanceof Error ? err.message : String(err)
530
+ });
531
+ }
425
532
  logger.info("Task audit complete", {
426
533
  requestId,
427
534
  taskId: taskPayload.taskId,
@@ -440,8 +547,8 @@ async function auditSingleTask(taskPayload, request, connection, projectDir, mod
440
547
  humanEvaluations: parsed.humanEvaluations,
441
548
  ...counts,
442
549
  suggestionIds,
443
- auditCostUsd: response.costUsd,
444
- model: response.model
550
+ auditCostUsd: totalCostUsd,
551
+ model: analysisResponse.model
445
552
  });
446
553
  }
447
554
  async function handleTaskAudit(request, connection, projectDir) {
@@ -474,4 +581,4 @@ async function handleTaskAudit(request, connection, projectDir) {
474
581
  export {
475
582
  handleTaskAudit
476
583
  };
477
- //# sourceMappingURL=task-audit-handler-LH35J3TX.js.map
584
+ //# sourceMappingURL=task-audit-handler-7Q7EJENK.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/runner/task-audit-handler.ts","../src/runner/task-audit-parsing.ts"],"sourcesContent":["import { z } from \"zod\";\nimport { createHarness, defineTool } from \"../harness/index.js\";\nimport type { ProjectConnection } from \"../connection/project-connection.js\";\nimport type { TaskAuditRunnerRequest, TaskAuditPayload } from \"@project/shared\";\nimport { textResult } from \"../tools/helpers.js\";\nimport { createServiceLogger } from \"../utils/logger.js\";\nimport {\n type AuditJsonResult,\n extractJsonFromResponse,\n computeGradeCounts,\n addCosts,\n buildErrorResult,\n buildSuggestionPrompt,\n} from \"./task-audit-parsing.js\";\n\nconst logger = createServiceLogger(\"TaskAudit\");\n\nconst FALLBACK_MODEL = \"claude-sonnet-4-6\";\n\n// ── System prompt ────────────────────────────────────────────────────────\n\nconst TASK_AUDIT_SYSTEM_PROMPT = `You are a chess-style analysis engine for AI agent task execution. You grade each turn of an agent's work trace like a chess engine grades moves: Correct, Neutral, or Blunder.\n\nYou receive the agent's full execution trace (tool calls, reasoning, errors) along with the task plan, description, and human messages. Your job is to objectively assess the quality of the agent's work.\n\n## Grading Scale\n\n- **Correct** (♟): Sound moves toward completion — necessary file reads, proper tool use, following plan steps, logical reasoning, adapting to feedback\n- **Neutral** (·): No significant positive or negative effect — exploratory reads, clarifying questions, minor tangents that don't waste resources\n- **Blunder** (??): Wasted effort or wrong direction — incorrect edits, reading irrelevant files repeatedly, ignoring the plan, repeated failures without adapting\n\n## Phase Identification\n\nClassify each turn into a phase based on the trace context:\n- **planning**: Events before the first file modification (Edit/Write tool use) — reading files, analyzing requirements, reasoning about approach\n- **building**: File modification events and related reasoning — writing code, running tests, fixing errors\n- **human**: Turns that are direct responses to user/human chat messages\n\n## Specific Blunder Examples\n- Reading the same file 5+ times without making meaningful changes\n- Making edits that are immediately reverted or overwritten\n- Ignoring explicit plan steps or user corrections\n- Repeated failed tool calls (isError: true) without changing approach\n- Using wrong APIs despite project patterns visible in the trace\n- Spending many turns on tangential work not in the plan\n\n## Specific Correct Examples\n- Reading context files before implementation\n- Following plan steps in logical sequence\n- Proper error handling and recovery after tool failures\n- Adapting approach based on user feedback\n- Efficient tool usage with clear purpose\n\n## Output Format\n\nAfter analyzing all turns, output a JSON block:\n\n\\`\\`\\`json\n{\n \"turnGrades\": [\n {\n \"turnIndex\": 0,\n \"phase\": \"planning\",\n \"grade\": \"correct\",\n \"reasoning\": \"Read relevant config files to understand project structure before making changes\",\n \"eventType\": \"tool_use\",\n \"eventSummary\": \"Read package.json and tsconfig.json\"\n }\n ],\n \"summary\": \"Brief 2-3 sentence assessment of overall execution quality\",\n \"planningAccuracy\": 0.85,\n \"buildingAccuracy\": 0.72,\n \"humanAccuracy\": 1.0,\n \"humanEvaluations\": [\n {\n \"messageIndex\": 0,\n \"rating\": 1,\n \"reasoning\": \"Provided clear context about the bug with reproduction steps\"\n }\n ],\n \"macroEvaluation\": {\n \"instructionsQuality\": \"Brief assessment\",\n \"modelSuitability\": \"Brief assessment\",\n \"contextAndPlanning\": \"Brief assessment\",\n \"overallResult\": \"Brief assessment\"\n }\n}\n\\`\\`\\`\n\n**Accuracy Calculation**: For each phase, accuracy = correct / (correct + blunder). Neutral turns are excluded from the ratio. Return null if a phase has no correct or blunder turns.\n\n## Human Contribution Evaluation\n\nFor each human message in the trace, evaluate whether the human's contribution was helpful, neutral, or unhelpful to the agent's success:\n\n- **Helpful (+1)**: Provided useful context, clear corrections, actionable feedback, or unblocked the agent\n- **Neutral (0)**: Acknowledgements, status checks, or messages with no material impact on execution\n- **Unhelpful (-1)**: Contradictory instructions, incorrect guidance, unnecessary interruptions, or vague requests that caused wasted effort\n\nInclude a \\`humanEvaluations\\` array in your JSON output. Each entry has: \\`messageIndex\\` (0-based index into the Human Messages list), \\`rating\\` (+1, 0, or -1), and \\`reasoning\\` (brief explanation). If there are no human messages, return an empty array.\n\n## Macro Evaluation\n\nAfter grading individual turns, perform a high-level assessment of the overall task execution:\n\n- **Instructions Quality**: Were the agent instructions appropriate for this task type? Too vague, too prescriptive, or missing critical guidance?\n- **Model Suitability**: Was the model choice appropriate for the complexity of this task?\n- **Context & Planning**: Was the plan/context sufficient for the agent to succeed? Were there information gaps that caused wasted effort?\n- **Overall Result**: Did the final result meet the task requirements? Was the outcome proportional to the effort spent?\n\nInclude a \"macroEvaluation\" object in your JSON output.`;\n\n// ── Prompt section builders ─────────────────────────────────────────────\n\nfunction buildSessionInfoSection(info: NonNullable<TaskAuditPayload[\"sessionInfo\"]>): string {\n const lines: string[] = [\"## Session Info\"];\n if (info.model) lines.push(`- Model: ${info.model}`);\n if (info.totalCostUsd !== null) lines.push(`- Total Cost: $${info.totalCostUsd.toFixed(4)}`);\n if (info.planningTurns !== null) lines.push(`- Planning Turns: ${info.planningTurns}`);\n if (info.buildingTurns !== null) lines.push(`- Building Turns: ${info.buildingTurns}`);\n if (info.locDiff !== null) lines.push(`- Lines Changed: ${info.locDiff}`);\n lines.push(\"\");\n return lines.join(\"\\n\");\n}\n\nfunction buildTraceSection(trace: TaskAuditPayload[\"agentTrace\"]): string {\n const lines: string[] = [\"## Agent Trace\\n\"];\n if (trace.length === 0) {\n lines.push(\"No agent trace data available.\\n\");\n } else {\n for (let i = 0; i < trace.length; i++) {\n const event = trace[i];\n const dataStr = JSON.stringify(event.data);\n const truncated = dataStr.length > 2000 ? dataStr.slice(0, 2000) + \"...\" : dataStr;\n lines.push(`### Turn ${i} [${event.type}] @ ${event.timestamp}`);\n lines.push(truncated);\n lines.push(\"\");\n }\n }\n return lines.join(\"\\n\");\n}\n\n// ── Prompt builder ──────────────────────────────────────────────────────\n\nfunction buildTaskAuditPrompt(task: TaskAuditPayload): string {\n const parts: string[] = [`# Task Audit: ${task.taskTitle}\\n`];\n\n if (task.taskDescription) parts.push(`## Description\\n${task.taskDescription}\\n`);\n if (task.taskPlan) parts.push(`## Plan\\n${task.taskPlan}\\n`);\n\n parts.push(`## Task Status: ${task.taskStatus}`);\n if (task.storyPointValue !== null) parts.push(`## Story Points: ${task.storyPointValue}`);\n parts.push(\"\");\n\n if (task.sessionInfo) parts.push(buildSessionInfoSection(task.sessionInfo));\n if (task.agentInstructions) parts.push(`## Agent Instructions\\n${task.agentInstructions}\\n`);\n\n if (task.humanMessages.length > 0) {\n parts.push(\"## Human Messages\\n\");\n for (const msg of task.humanMessages) {\n parts.push(`[${msg.createdAt}] **${msg.role}**: ${msg.content}`);\n }\n parts.push(\"\");\n }\n\n parts.push(buildTraceSection(task.agentTrace));\n parts.push(\"Grade each turn above, then output the structured JSON result.\");\n\n return parts.join(\"\\n\");\n}\n\n// ── Suggestion phase prompt ──────────────────────────────────────────────\n\nconst SUGGESTION_SYSTEM_PROMPT = `You are a suggestion generator for an AI task audit system. Based on the audit findings below, create actionable project-level suggestions using the create_suggestion tool.\n\nFocus on:\n- Recurring patterns of wasted effort that could be prevented\n- Missing documentation or context that caused agent confusion\n- Process improvements that would prevent common blunders\n- Tool or workflow optimizations\n- Actionable macro findings that would improve future task execution\n\nYou MUST call create_suggestion at least once. If the execution was flawless, suggest what made it work well so the pattern can be replicated.`;\n\n// ── Suggestion MCP tool ─────────────────────────────────────────────────\n\nfunction buildProjectSuggestionTool(connection: ProjectConnection, projectId: string) {\n return defineTool(\n \"create_suggestion\",\n \"Suggest a cross-cutting improvement for the project based on patterns found during audit. If a similar suggestion exists, your vote is added instead of creating a duplicate.\",\n {\n title: z.string().describe(\"Short title for the suggestion\"),\n description: z.string().optional().describe(\"Details about the suggestion\"),\n tag_names: z.array(z.string()).optional().describe(\"Tag names to categorize the suggestion\"),\n },\n async ({ title, description, tag_names }) => {\n try {\n const result = await connection.call(\"createProjectSuggestion\", {\n projectId,\n title,\n description,\n tagNames: tag_names,\n });\n if (result.merged) {\n return textResult(\n `Merged into existing suggestion (ID: ${result.mergedIntoId ?? result.id}).`,\n );\n }\n return textResult(`Suggestion created (ID: ${result.id}).`);\n } catch (error) {\n return textResult(\n `Failed to create suggestion: ${error instanceof Error ? error.message : \"Unknown error\"}`,\n );\n }\n },\n );\n}\n\n// ── Fetch model ─────────────────────────────────────────────────────────\n\nasync function fetchModel(connection: ProjectConnection): Promise<string> {\n try {\n const ctx = await connection.call(\"getProjectAgentContextByRole\", {\n projectId: connection.projectId,\n role: \"reviewer\",\n });\n return ctx.model || FALLBACK_MODEL;\n } catch {\n return FALLBACK_MODEL;\n }\n}\n\n// ── Event stream processing ─────────────────────────────────────────────\n\nfunction reportProgress(\n connection: ProjectConnection,\n requestId: string,\n taskId: string,\n tool: string,\n input?: string,\n): void {\n void connection\n .call(\"reportTaskAuditProgress\", {\n projectId: connection.projectId,\n requestId,\n taskId,\n activity: { tool, input, timestamp: new Date().toISOString() },\n })\n .catch(() => {});\n}\n\ninterface ProgressContext {\n connection: ProjectConnection;\n requestId: string;\n taskId: string;\n}\n\nfunction processAssistantBlocks(\n blocks: Array<{ type: string; text?: string; name?: string; input?: unknown }>,\n responseParts: string[],\n ctx: ProgressContext,\n reportedFirstText: { value: boolean },\n): void {\n for (const block of blocks) {\n if (block.type === \"text\" && block.text) {\n responseParts.push(block.text);\n if (reportedFirstText.value) continue;\n reportedFirstText.value = true;\n reportProgress(\n ctx.connection,\n ctx.requestId,\n ctx.taskId,\n \"thinking\",\n block.text.slice(0, 200),\n );\n } else if (block.type === \"tool_use\" && block.name) {\n const inputStr = typeof block.input === \"string\" ? block.input : JSON.stringify(block.input);\n reportProgress(ctx.connection, ctx.requestId, ctx.taskId, block.name, inputStr.slice(0, 500));\n }\n }\n}\n\nasync function collectResponseFromEvents(\n events: AsyncIterable<{ type: string }>,\n connection: ProjectConnection,\n requestId: string,\n taskId: string,\n): Promise<{ text: string; costUsd: number | null; model: string | null }> {\n const responseParts: string[] = [];\n let costUsd: number | null = null;\n let model: string | null = null;\n const reportedFirstText = { value: false };\n const ctx: ProgressContext = { connection, requestId, taskId };\n\n for await (const event of events) {\n if (event.type === \"system\") {\n const sysEvent = event as { type: string; subtype?: string; model?: string };\n if (sysEvent.subtype === \"init\" && sysEvent.model) {\n model = sysEvent.model;\n reportProgress(\n connection,\n requestId,\n taskId,\n \"system\",\n `Initialized model: ${sysEvent.model}`,\n );\n }\n }\n\n if (event.type === \"assistant\") {\n const { message } = event as {\n type: string;\n message: {\n content: Array<{ type: string; text?: string; name?: string; input?: unknown }>;\n };\n };\n processAssistantBlocks(message.content, responseParts, ctx, reportedFirstText);\n }\n\n if (event.type === \"result\") {\n const resultEvent = event as { type: string; subtype?: string; total_cost_usd?: number };\n if (resultEvent.subtype === \"success\" && resultEvent.total_cost_usd !== undefined) {\n costUsd = resultEvent.total_cost_usd;\n }\n const status =\n resultEvent.subtype === \"success\" ? \"success\" : `error: ${resultEvent.subtype}`;\n reportProgress(connection, requestId, taskId, \"complete\", status);\n break;\n }\n }\n\n return { text: responseParts.join(\"\\n\\n\").trim(), costUsd, model };\n}\n\n// ── Suggestion tool with ID capture ───────────────────────────────────\n\nfunction buildTrackedSuggestionTool(\n connection: ProjectConnection,\n projectId: string,\n suggestionIds: string[],\n) {\n const suggestionTool = buildProjectSuggestionTool(connection, projectId);\n return defineTool(\n suggestionTool.name,\n suggestionTool.description,\n suggestionTool.schema as z.ZodRawShape,\n async (input: Record<string, unknown>) => {\n const result = await suggestionTool.handler(input);\n const text = result.content?.[0]?.text ?? \"\";\n const idMatch = text.match(/ID: ([a-z0-9]+)/i);\n if (idMatch) suggestionIds.push(idMatch[1]);\n return result;\n },\n );\n}\n\n// ── Suggestion phase ───────────────────────────────────────────────────\n\nasync function runSuggestionPhase(\n parsed: AuditJsonResult,\n taskPayload: TaskAuditPayload,\n connection: ProjectConnection,\n requestId: string,\n projectId: string,\n projectDir: string,\n model: string,\n suggestionIds: string[],\n): Promise<number | null> {\n reportProgress(\n connection,\n requestId,\n taskPayload.taskId,\n \"status\",\n \"Creating suggestions from findings...\",\n );\n\n const wrappedSuggestionTool = buildTrackedSuggestionTool(connection, projectId, suggestionIds);\n const harness = createHarness();\n const mcpServer = harness.createMcpServer({ name: \"conveyor\", tools: [wrappedSuggestionTool] });\n\n const events = harness.executeQuery({\n prompt: buildSuggestionPrompt(parsed, taskPayload),\n options: {\n model,\n systemPrompt: SUGGESTION_SYSTEM_PROMPT,\n cwd: projectDir,\n permissionMode: \"bypassPermissions\",\n allowDangerouslySkipPermissions: true,\n tools: { type: \"preset\" as const, preset: \"claude_code\" as const },\n mcpServers: { conveyor: mcpServer },\n maxTurns: 4,\n maxBudgetUsd: 0.5,\n disallowedTools: [\"Edit\", \"Write\", \"Bash\", \"NotebookEdit\", \"MultiEdit\"],\n },\n });\n\n const response = await collectResponseFromEvents(\n events,\n connection,\n requestId,\n taskPayload.taskId,\n );\n return response.costUsd;\n}\n\n// ── Per-task audit execution ────────────────────────────────────────────\n\nasync function auditSingleTask(\n taskPayload: TaskAuditPayload,\n request: TaskAuditRunnerRequest,\n connection: ProjectConnection,\n projectDir: string,\n model: string,\n): Promise<void> {\n const { requestId, projectId } = request;\n const suggestionIds: string[] = [];\n\n // Phase 1: Analysis (no MCP tools — pure grading)\n reportProgress(connection, requestId, taskPayload.taskId, \"status\", \"Generating audit grades...\");\n\n const analysisHarness = createHarness();\n const analysisEvents = analysisHarness.executeQuery({\n prompt: buildTaskAuditPrompt(taskPayload),\n options: {\n model,\n systemPrompt: TASK_AUDIT_SYSTEM_PROMPT,\n cwd: projectDir,\n permissionMode: \"bypassPermissions\",\n allowDangerouslySkipPermissions: true,\n tools: { type: \"preset\" as const, preset: \"claude_code\" as const },\n mcpServers: {},\n maxTurns: 16,\n maxBudgetUsd: 3,\n disallowedTools: [\"Edit\", \"Write\", \"Bash\", \"NotebookEdit\", \"MultiEdit\"],\n },\n });\n\n const analysisResponse = await collectResponseFromEvents(\n analysisEvents,\n connection,\n requestId,\n taskPayload.taskId,\n );\n if (!analysisResponse.text) throw new Error(\"No response from Claude\");\n\n const parsed = extractJsonFromResponse(analysisResponse.text);\n const counts = computeGradeCounts(parsed.turnGrades);\n\n // Phase 2: Suggestions (dedicated MCP query)\n let totalCostUsd = analysisResponse.costUsd;\n try {\n const suggestionCost = await runSuggestionPhase(\n parsed,\n taskPayload,\n connection,\n requestId,\n projectId,\n projectDir,\n model,\n suggestionIds,\n );\n totalCostUsd = addCosts(totalCostUsd, suggestionCost);\n } catch (err) {\n logger.warn(\"Suggestion phase failed, proceeding without suggestions\", {\n requestId,\n taskId: taskPayload.taskId,\n error: err instanceof Error ? err.message : String(err),\n });\n }\n\n logger.info(\"Task audit complete\", {\n requestId,\n taskId: taskPayload.taskId,\n grades: parsed.turnGrades.length,\n suggestions: suggestionIds.length,\n });\n\n await connection.call(\"reportTaskAuditResult\", {\n projectId: connection.projectId,\n requestId,\n taskId: taskPayload.taskId,\n summary: parsed.summary,\n turnGrades: parsed.turnGrades,\n planningAccuracy: parsed.planningAccuracy,\n buildingAccuracy: parsed.buildingAccuracy,\n humanAccuracy: parsed.humanAccuracy,\n humanEvaluations: parsed.humanEvaluations,\n ...counts,\n suggestionIds,\n auditCostUsd: totalCostUsd,\n model: analysisResponse.model,\n });\n}\n\n// ── Main handler ────────────────────────────────────────────────────────\n\nexport async function handleTaskAudit(\n request: TaskAuditRunnerRequest,\n connection: ProjectConnection,\n projectDir: string,\n): Promise<void> {\n const { requestId } = request;\n\n logger.info(\"Starting task audit\", { requestId, taskCount: request.tasks.length });\n\n const model = await fetchModel(connection);\n\n for (const taskPayload of request.tasks) {\n try {\n await auditSingleTask(taskPayload, request, connection, projectDir, model);\n } catch (err) {\n const msg = err instanceof Error ? err.message : String(err);\n logger.error(\"Task audit failed for task\", {\n requestId,\n taskId: taskPayload.taskId,\n error: msg,\n });\n await connection\n .call(\n \"reportTaskAuditResult\",\n buildErrorResult(connection.projectId, requestId, taskPayload.taskId, msg),\n )\n .catch(() => {});\n }\n }\n\n // Signal batch completion to API/UI\n await connection\n .call(\"reportTaskAuditBatchComplete\", {\n projectId: connection.projectId,\n requestId,\n })\n .catch(() => {});\n}\n","import type {\n TaskAuditTurnGrade,\n TaskAuditHumanEvaluation,\n TaskAuditPayload,\n} from \"@project/shared\";\n\n// ── Types ──────────────────────────────────────────────────────────────\n\nexport interface AuditJsonResult {\n turnGrades: TaskAuditTurnGrade[];\n summary: string;\n planningAccuracy: number | null;\n buildingAccuracy: number | null;\n humanAccuracy: number | null;\n humanEvaluations: TaskAuditHumanEvaluation[];\n macroEvaluation?: {\n instructionsQuality?: string;\n modelSuitability?: string;\n contextAndPlanning?: string;\n overallResult?: string;\n } | null;\n}\n\n// ── Formatting helpers ─────────────────────────────────────────────────\n\nfunction formatMacroEvaluation(macro: Record<string, unknown> | null | undefined): string | null {\n if (!macro) return null;\n const lines: string[] = [];\n if (macro.instructionsQuality) lines.push(`- Instructions Quality: ${macro.instructionsQuality}`);\n if (macro.modelSuitability) lines.push(`- Model Suitability: ${macro.modelSuitability}`);\n if (macro.contextAndPlanning) lines.push(`- Context & Planning: ${macro.contextAndPlanning}`);\n if (macro.overallResult) lines.push(`- Overall Result: ${macro.overallResult}`);\n return lines.length > 0 ? lines.join(\"\\n\") : null;\n}\n\nfunction formatHumanEvaluations(evals: TaskAuditHumanEvaluation[]): string | null {\n if (evals.length === 0) return null;\n const total = evals.reduce((sum, e) => sum + e.rating, 0);\n const avg = total / evals.length;\n const label = avg > 0.3 ? \"Helpful\" : avg < -0.3 ? \"Unhelpful\" : \"Neutral\";\n const lines = [\n `- Overall: ${label} (avg ${avg.toFixed(2)}, ${evals.length} message${evals.length === 1 ? \"\" : \"s\"})`,\n ];\n for (const e of evals) {\n const ratingLabel = e.rating > 0 ? \"helpful\" : e.rating < 0 ? \"unhelpful\" : \"neutral\";\n lines.push(` - Message ${e.messageIndex}: ${ratingLabel} — ${e.reasoning}`);\n }\n return lines.join(\"\\n\");\n}\n\n// ── JSON parsing ───────────────────────────────────────────────────────\n\nfunction toAuditResult(parsed: Record<string, unknown>): AuditJsonResult | null {\n if (!parsed || !Array.isArray(parsed.turnGrades)) return null;\n\n const macro = parsed.macroEvaluation as Record<string, unknown> | null | undefined;\n const rawHumanEvals = Array.isArray(parsed.humanEvaluations)\n ? (parsed.humanEvaluations as TaskAuditHumanEvaluation[])\n : [];\n const baseSummary = (parsed.summary as string) ?? \"\";\n\n const macroText = formatMacroEvaluation(macro);\n const humanEvalText = formatHumanEvaluations(rawHumanEvals);\n\n let summary = baseSummary;\n if (macroText) summary += `\\n\\n---\\n\\nMacro Evaluation:\\n${macroText}`;\n if (humanEvalText) summary += `\\n\\n---\\n\\nHuman Contributions:\\n${humanEvalText}`;\n\n return {\n turnGrades: parsed.turnGrades as TaskAuditTurnGrade[],\n summary,\n planningAccuracy: (parsed.planningAccuracy as number) ?? null,\n buildingAccuracy: (parsed.buildingAccuracy as number) ?? null,\n humanAccuracy: (parsed.humanAccuracy as number) ?? null,\n humanEvaluations: rawHumanEvals,\n macroEvaluation: macro\n ? {\n instructionsQuality: (macro.instructionsQuality as string) ?? undefined,\n modelSuitability: (macro.modelSuitability as string) ?? undefined,\n contextAndPlanning: (macro.contextAndPlanning as string) ?? undefined,\n overallResult: (macro.overallResult as string) ?? undefined,\n }\n : null,\n };\n}\n\nexport function extractJsonFromResponse(text: string): AuditJsonResult {\n const codeBlockMatch = text.match(/```(?:json)?\\s*\\n?([\\s\\S]*?)```/);\n const jsonStr = codeBlockMatch ? codeBlockMatch[1].trim() : text;\n\n try {\n const result = toAuditResult(JSON.parse(jsonStr));\n if (result) return result;\n } catch {\n // Try fallback: find a JSON object in raw text\n }\n\n const objectMatch = text.match(/\\{[\\s\\S]*\"turnGrades\"[\\s\\S]*\\}/);\n if (objectMatch) {\n try {\n const result = toAuditResult(JSON.parse(objectMatch[0]));\n if (result) return result;\n } catch {\n // Fall through\n }\n }\n\n throw new Error(\"Could not parse task audit grades from Claude response\");\n}\n\n// ── Grade counting ─────────────────────────────────────────────────────\n\nexport function computeGradeCounts(turnGrades: TaskAuditTurnGrade[]) {\n const counts = {\n planningCorrect: 0,\n planningNeutral: 0,\n planningBlunder: 0,\n buildingCorrect: 0,\n buildingNeutral: 0,\n buildingBlunder: 0,\n humanCorrect: 0,\n humanNeutral: 0,\n humanBlunder: 0,\n };\n\n for (const tg of turnGrades) {\n const key =\n `${tg.phase}${tg.grade.charAt(0).toUpperCase()}${tg.grade.slice(1)}` as keyof typeof counts;\n if (key in counts) {\n counts[key]++;\n }\n }\n\n return counts;\n}\n\n// ── Cost helpers ──────────────────────────────────────────────────────\n\nexport function addCosts(base: number | null, addition: number | null): number | null {\n if (base === null) return addition;\n if (addition === null) return base;\n return base + addition;\n}\n\n// ── Error result builder ──────────────────────────────────────────────\n\nexport function buildErrorResult(\n projectId: string,\n requestId: string,\n taskId: string,\n error: string,\n) {\n return {\n projectId,\n requestId,\n taskId,\n summary: \"\",\n turnGrades: [] as TaskAuditTurnGrade[],\n planningAccuracy: null,\n buildingAccuracy: null,\n humanAccuracy: null,\n planningCorrect: 0,\n planningNeutral: 0,\n planningBlunder: 0,\n buildingCorrect: 0,\n buildingNeutral: 0,\n buildingBlunder: 0,\n humanCorrect: 0,\n humanNeutral: 0,\n humanBlunder: 0,\n suggestionIds: [] as string[],\n auditCostUsd: null,\n model: null,\n error,\n };\n}\n\n// ── Suggestion prompt builder ─────────────────────────────────────────\n\nexport function buildSuggestionPrompt(parsed: AuditJsonResult, task: TaskAuditPayload): string {\n const parts: string[] = [`# Suggestion Generation for: ${task.taskTitle}\\n`];\n\n parts.push(`## Audit Summary\\n${parsed.summary}\\n`);\n\n if (parsed.macroEvaluation) {\n parts.push(\"## Macro Evaluation\");\n if (parsed.macroEvaluation.instructionsQuality)\n parts.push(`- Instructions Quality: ${parsed.macroEvaluation.instructionsQuality}`);\n if (parsed.macroEvaluation.modelSuitability)\n parts.push(`- Model Suitability: ${parsed.macroEvaluation.modelSuitability}`);\n if (parsed.macroEvaluation.contextAndPlanning)\n parts.push(`- Context & Planning: ${parsed.macroEvaluation.contextAndPlanning}`);\n if (parsed.macroEvaluation.overallResult)\n parts.push(`- Overall Result: ${parsed.macroEvaluation.overallResult}`);\n parts.push(\"\");\n }\n\n const blunders = parsed.turnGrades.filter((tg) => tg.grade === \"blunder\");\n if (blunders.length > 0) {\n parts.push(\"## Notable Blunders\");\n for (const b of blunders.slice(0, 10)) {\n parts.push(`- Turn ${b.turnIndex} (${b.phase}): ${b.reasoning}`);\n }\n parts.push(\"\");\n }\n\n parts.push(\n \"Based on the findings above, call create_suggestion for each actionable cross-cutting improvement.\",\n );\n\n return parts.join(\"\\n\");\n}\n"],"mappings":"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","names":[]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@rallycry/conveyor-agent",
3
- "version": "7.2.4",
3
+ "version": "7.2.5",
4
4
  "description": "Conveyor Agent Runner v7.0 - Agent-as-User architecture with BaseService patterns. Works locally too.",
5
5
  "keywords": [
6
6
  "agent",