karajan-code 1.36.0 → 1.37.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.
@@ -48,14 +48,16 @@ function applyModelSelection(triageOutput, config, emitter, eventBase) {
48
48
 
49
49
  export async function runTriageStage({ config, logger, emitter, eventBase, session, coderRole, trackBudget }) {
50
50
  logger.setContext({ iteration: 0, stage: "triage" });
51
+
52
+ const triageProvider = config?.roles?.triage?.provider || coderRole.provider;
51
53
  emitProgress(
52
54
  emitter,
53
55
  makeEvent("triage:start", { ...eventBase, stage: "triage" }, {
54
- message: "Triage classifying task complexity"
56
+ message: "Triage classifying task complexity",
57
+ detail: { provider: triageProvider, executorType: "agent" }
55
58
  })
56
59
  );
57
60
 
58
- const triageProvider = config?.roles?.triage?.provider || coderRole.provider;
59
61
  const triageOnOutput = ({ stream, line }) => {
60
62
  emitProgress(emitter, makeEvent("agent:output", { ...eventBase, stage: "triage" }, {
61
63
  message: line,
@@ -132,7 +134,7 @@ export async function runTriageStage({ config, logger, emitter, eventBase, sessi
132
134
  makeEvent("triage:end", { ...eventBase, stage: "triage" }, {
133
135
  status: triageOutput.ok ? "ok" : "fail",
134
136
  message: triageOutput.ok ? "Triage completed" : `Triage failed: ${triageOutput.summary}`,
135
- detail: stageResult
137
+ detail: { ...stageResult, provider: triageProvider, executorType: "agent" }
136
138
  })
137
139
  );
138
140
 
@@ -141,14 +143,16 @@ export async function runTriageStage({ config, logger, emitter, eventBase, sessi
141
143
 
142
144
  export async function runResearcherStage({ config, logger, emitter, eventBase, session, coderRole, trackBudget }) {
143
145
  logger.setContext({ iteration: 0, stage: "researcher" });
146
+
147
+ const researcherProvider = config?.roles?.researcher?.provider || coderRole.provider;
144
148
  emitProgress(
145
149
  emitter,
146
150
  makeEvent("researcher:start", { ...eventBase, stage: "researcher" }, {
147
- message: "Researcher investigating codebase"
151
+ message: "Researcher investigating codebase",
152
+ detail: { researcher: researcherProvider, provider: researcherProvider, executorType: "agent" }
148
153
  })
149
154
  );
150
155
 
151
- const researcherProvider = config?.roles?.researcher?.provider || coderRole.provider;
152
156
  const researcherOnOutput = ({ stream, line }) => {
153
157
  emitProgress(emitter, makeEvent("agent:output", { ...eventBase, stage: "researcher" }, {
154
158
  message: line,
@@ -191,7 +195,8 @@ export async function runResearcherStage({ config, logger, emitter, eventBase, s
191
195
  emitter,
192
196
  makeEvent("researcher:end", { ...eventBase, stage: "researcher" }, {
193
197
  status: researchOutput.ok ? "ok" : "fail",
194
- message: researchOutput.ok ? "Research completed" : `Research failed: ${researchOutput.summary}`
198
+ message: researchOutput.ok ? "Research completed" : `Research failed: ${researchOutput.summary}`,
199
+ detail: { provider: researcherProvider, executorType: "agent" }
195
200
  })
196
201
  );
197
202
 
@@ -260,14 +265,14 @@ async function handleArchitectClarification({ architectOutput, askQuestion, conf
260
265
 
261
266
  export async function runArchitectStage({ config, logger, emitter, eventBase, session, coderRole, trackBudget, researchContext = null, discoverResult = null, triageLevel = null, askQuestion = null }) {
262
267
  logger.setContext({ iteration: 0, stage: "architect" });
268
+ const architectProvider = config?.roles?.architect?.provider || coderRole.provider;
263
269
  emitProgress(
264
270
  emitter,
265
271
  makeEvent("architect:start", { ...eventBase, stage: "architect" }, {
266
- message: "Architect designing solution architecture"
272
+ message: "Architect designing solution architecture",
273
+ detail: { architect: architectProvider, provider: architectProvider, executorType: "agent" }
267
274
  })
268
275
  );
269
-
270
- const architectProvider = config?.roles?.architect?.provider || coderRole.provider;
271
276
  const architectOnOutput = ({ stream, line }) => {
272
277
  emitProgress(emitter, makeEvent("agent:output", { ...eventBase, stage: "architect" }, {
273
278
  message: line,
@@ -330,7 +335,7 @@ export async function runArchitectStage({ config, logger, emitter, eventBase, se
330
335
  makeEvent("architect:end", { ...eventBase, stage: "architect" }, {
331
336
  status: architectOutput.ok ? "ok" : "fail",
332
337
  message: architectOutput.ok ? "Architecture completed" : `Architecture failed: ${architectOutput.summary}`,
333
- detail: stageResult
338
+ detail: { ...stageResult, provider: architectProvider, executorType: "agent" }
334
339
  })
335
340
  );
336
341
 
@@ -373,7 +378,7 @@ export async function runPlannerStage({ config, logger, emitter, eventBase, sess
373
378
  emitter,
374
379
  makeEvent("planner:start", { ...eventBase, stage: "planner" }, {
375
380
  message: `Planner (${plannerRole.provider}) running`,
376
- detail: { planner: plannerRole.provider }
381
+ detail: { planner: plannerRole.provider, provider: plannerRole.provider, executorType: "agent" }
377
382
  })
378
383
  );
379
384
 
@@ -416,7 +421,8 @@ export async function runPlannerStage({ config, logger, emitter, eventBase, sess
416
421
  emitter,
417
422
  makeEvent("planner:end", { ...eventBase, stage: "planner" }, {
418
423
  status: "fail",
419
- message: `Planner failed: ${details}`
424
+ message: `Planner failed: ${details}`,
425
+ detail: { provider: plannerRole.provider, executorType: "agent" }
420
426
  })
421
427
  );
422
428
  throw new Error(`Planner failed: ${details}`);
@@ -436,7 +442,8 @@ export async function runPlannerStage({ config, logger, emitter, eventBase, sess
436
442
  emitProgress(
437
443
  emitter,
438
444
  makeEvent("planner:end", { ...eventBase, stage: "planner" }, {
439
- message: "Planner completed"
445
+ message: "Planner completed",
446
+ detail: { provider: plannerRole.provider, executorType: "agent" }
440
447
  })
441
448
  );
442
449
 
@@ -445,14 +452,14 @@ export async function runPlannerStage({ config, logger, emitter, eventBase, sess
445
452
 
446
453
  export async function runDiscoverStage({ config, logger, emitter, eventBase, session, coderRole, trackBudget }) {
447
454
  logger.setContext({ iteration: 0, stage: "discover" });
455
+ const discoverProvider = config?.roles?.discover?.provider || coderRole.provider;
448
456
  emitProgress(
449
457
  emitter,
450
458
  makeEvent("discover:start", { ...eventBase, stage: "discover" }, {
451
- message: "Discover analyzing task for gaps"
459
+ message: "Discover analyzing task for gaps",
460
+ detail: { discover: discoverProvider, provider: discoverProvider, executorType: "agent" }
452
461
  })
453
462
  );
454
-
455
- const discoverProvider = config?.roles?.discover?.provider || coderRole.provider;
456
463
  const discoverOnOutput = ({ stream, line }) => {
457
464
  emitProgress(emitter, makeEvent("agent:output", { ...eventBase, stage: "discover" }, {
458
465
  message: line,
@@ -504,7 +511,7 @@ export async function runDiscoverStage({ config, logger, emitter, eventBase, ses
504
511
  makeEvent("discover:end", { ...eventBase, stage: "discover" }, {
505
512
  status: discoverOutput.ok ? "ok" : "fail",
506
513
  message: discoverOutput.ok ? "Discovery completed" : `Discovery failed: ${discoverOutput.summary}`,
507
- detail: stageResult
514
+ detail: { ...stageResult, provider: discoverProvider, executorType: "agent" }
508
515
  })
509
516
  );
510
517
 
@@ -518,10 +525,12 @@ export async function runDiscoverStage({ config, logger, emitter, eventBase, ses
518
525
  */
519
526
  export async function runHuReviewerStage({ config, logger, emitter, eventBase, session, coderRole, trackBudget, huFile, askQuestion }) {
520
527
  logger.setContext({ iteration: 0, stage: "hu-reviewer" });
528
+ const huReviewerProvider = config?.roles?.hu_reviewer?.provider || coderRole.provider;
521
529
  emitProgress(
522
530
  emitter,
523
531
  makeEvent("hu-reviewer:start", { ...eventBase, stage: "hu-reviewer" }, {
524
- message: "HU Reviewer certifying user stories"
532
+ message: "HU Reviewer certifying user stories",
533
+ detail: { provider: huReviewerProvider, executorType: "agent" }
525
534
  })
526
535
  );
527
536
 
@@ -569,7 +578,6 @@ export async function runHuReviewerStage({ config, logger, emitter, eventBase, s
569
578
  }
570
579
 
571
580
  // --- Evaluate loop (re-evaluate entire batch until all certified or needs_context with no askQuestion) ---
572
- const huReviewerProvider = config?.roles?.hu_reviewer?.provider || coderRole.provider;
573
581
  const huReviewerOnOutput = ({ stream, line }) => {
574
582
  emitProgress(emitter, makeEvent("agent:output", { ...eventBase, stage: "hu-reviewer" }, {
575
583
  message: line,
@@ -711,7 +719,7 @@ export async function runHuReviewerStage({ config, logger, emitter, eventBase, s
711
719
  makeEvent("hu-reviewer:end", { ...eventBase, stage: "hu-reviewer" }, {
712
720
  status: "ok",
713
721
  message: `HU Review complete: ${certifiedStories.length}/${batch.stories.length} certified`,
714
- detail: stageResult
722
+ detail: { ...stageResult, provider: huReviewerProvider, executorType: "agent" }
715
723
  })
716
724
  );
717
725
 
@@ -167,14 +167,14 @@ export async function runPreflightChecks({ config, logger, emitter, eventBase, r
167
167
  logger.info("Preflight: skipped (no sonar, no security)");
168
168
  emitProgress(emitter, makeEvent("preflight:end", { ...eventBase, stage: "preflight" }, {
169
169
  message: "Preflight skipped (no checks needed)",
170
- detail: result
170
+ detail: { ...result, executorType: "local" }
171
171
  }));
172
172
  return result;
173
173
  }
174
174
 
175
175
  emitProgress(emitter, makeEvent("preflight:start", { ...eventBase, stage: "preflight" }, {
176
176
  message: "Running preflight environment checks",
177
- detail: { sonarEnabled, securityEnabled }
177
+ detail: { sonarEnabled, securityEnabled, executorType: "local" }
178
178
  }));
179
179
 
180
180
  // --- 1. Docker (only if sonar enabled and not external) ---
@@ -286,7 +286,7 @@ export async function runPreflightChecks({ config, logger, emitter, eventBase, r
286
286
  : hasWarnings
287
287
  ? `Preflight completed with ${result.warnings.length} warning(s)`
288
288
  : "Preflight passed — all checks OK",
289
- detail: result
289
+ detail: { ...result, executorType: "local" }
290
290
  }));
291
291
 
292
292
  return result;
@@ -9,11 +9,12 @@ export async function invokeSolomon({ config, logger, emitter, eventBase, stage,
9
9
  return escalateToHuman({ askQuestion, session, emitter, eventBase, stage, conflict, iteration });
10
10
  }
11
11
 
12
+ const solomonProvider = config?.roles?.solomon?.provider || "gemini";
12
13
  emitProgress(
13
14
  emitter,
14
15
  makeEvent("solomon:start", { ...eventBase, stage: "solomon" }, {
15
16
  message: `Solomon arbitrating ${stage} conflict`,
16
- detail: { conflictStage: stage }
17
+ detail: { conflictStage: stage, provider: solomonProvider, executorType: "agent" }
17
18
  })
18
19
  );
19
20
 
@@ -41,7 +42,7 @@ export async function invokeSolomon({ config, logger, emitter, eventBase, stage,
41
42
  message: ruling.ok
42
43
  ? `Solomon ruling: ${ruling.result?.ruling || "unknown"}`
43
44
  : `Solomon failed: ${(solomonError || ruling.summary || "unknown error").slice(0, 200)}`,
44
- detail: ruling.result
45
+ detail: { ...ruling.result, provider: solomonProvider, executorType: "agent" }
45
46
  })
46
47
  );
47
48
 
@@ -177,7 +177,8 @@ function createBudgetManager({ config, emitter, eventBase }) {
177
177
  max_budget_usd: budgetLimit,
178
178
  warn_threshold_pct: warnThresholdPct,
179
179
  pct_used: Number(pctUsed.toFixed(2)),
180
- remaining_usd: budgetTracker.remaining(budgetLimit)
180
+ remaining_usd: budgetTracker.remaining(budgetLimit),
181
+ executorType: "system"
181
182
  }
182
183
  })
183
184
  );
@@ -379,7 +380,7 @@ async function handleCheckpoint({ checkpointDisabled, askQuestion, lastCheckpoin
379
380
  emitter,
380
381
  makeEvent("session:checkpoint", { ...eventBase, iteration: i, stage: "checkpoint" }, {
381
382
  message: `Checkpoint: progress detected, continuing (${elapsedStr} min elapsed)`,
382
- detail: { elapsed_minutes: Number(elapsedStr), iterations_done: i - 1, stages: stagesCompleted, auto_continued: true }
383
+ detail: { elapsed_minutes: Number(elapsedStr), iterations_done: i - 1, stages: stagesCompleted, auto_continued: true, executorType: "system" }
383
384
  })
384
385
  );
385
386
  return { action: "continue_loop", checkpointDisabled, lastCheckpointAt: Date.now(), lastCheckpointSnapshot: newSnapshot };
@@ -956,7 +957,7 @@ async function runGuardStages({ config, logger, emitter, eventBase, session, ite
956
957
  const warnings = outputResult.violations.filter(v => v.severity === "warning");
957
958
  emitProgress(emitter, makeEvent("guard:output", { ...eventBase, stage: "guard" }, {
958
959
  message: `Output guard: ${critical.length} critical, ${warnings.length} warnings`,
959
- detail: { violations: outputResult.violations }
960
+ detail: { violations: outputResult.violations, executorType: "local" }
960
961
  }));
961
962
  logger.info(`Output guard: ${outputResult.violations.length} violation(s) found`);
962
963
  for (const v of outputResult.violations) {
@@ -983,7 +984,7 @@ async function runGuardStages({ config, logger, emitter, eventBase, session, ite
983
984
  if (!perfResult.skipped && perfResult.violations.length > 0) {
984
985
  emitProgress(emitter, makeEvent("guard:perf", { ...eventBase, stage: "guard" }, {
985
986
  message: `Perf guard: ${perfResult.violations.length} issue(s)`,
986
- detail: { violations: perfResult.violations }
987
+ detail: { violations: perfResult.violations, executorType: "local" }
987
988
  }));
988
989
  logger.info(`Perf guard: ${perfResult.violations.length} issue(s) found`);
989
990
  for (const v of perfResult.violations) {
@@ -1165,7 +1166,7 @@ async function initFlowContext({ task, config, logger, emitter, askQuestion, pgT
1165
1166
  logger.info(`RTK detected (${rtkResult.version}) — instructing agents to prefix Bash commands with rtk`);
1166
1167
  emitProgress(emitter, makeEvent("rtk:detected", ctx.eventBase, {
1167
1168
  message: "RTK detected — agent commands will use token optimization",
1168
- detail: { version: rtkResult.version }
1169
+ detail: { version: rtkResult.version, executorType: "local" }
1169
1170
  }));
1170
1171
  }
1171
1172
 
@@ -47,6 +47,20 @@ const ICONS = {
47
47
  "budget:update": "\ud83d\udcb8",
48
48
  "iteration:end": "\u23f1\ufe0f",
49
49
  "session:end": "\ud83c\udfc1",
50
+ "discover:start": "\ud83d\udd0e",
51
+ "discover:end": "\ud83d\udd0e",
52
+ "architect:start": "\ud83c\udfdb\ufe0f",
53
+ "architect:end": "\ud83c\udfdb\ufe0f",
54
+ "hu-reviewer:start": "\ud83d\udcdd",
55
+ "hu-reviewer:end": "\ud83d\udcdd",
56
+ "impeccable:start": "\ud83c\udfa8",
57
+ "impeccable:end": "\ud83c\udfa8",
58
+ "audit:start": "\ud83d\udccb",
59
+ "audit:end": "\ud83d\udccb",
60
+ "sonarcloud:start": "\u2601\ufe0f",
61
+ "sonarcloud:end": "\u2601\ufe0f",
62
+ "preflight:start": "\ud83d\udee1\ufe0f",
63
+ "preflight:end": "\ud83d\udee1\ufe0f",
50
64
  question: "\u2753"
51
65
  };
52
66
 
@@ -95,24 +109,37 @@ export function printHeader({ task, config }) {
95
109
  console.log();
96
110
  }
97
111
 
112
+ /* ── Helper: executor/provider tag ───────────────────────────── */
113
+
114
+ function formatExecutor(detail) {
115
+ if (!detail) return '';
116
+ const provider = detail.provider || '';
117
+ const type = detail.executorType || '';
118
+ if (provider) return ` ${ANSI.dim}${provider}${ANSI.reset}`;
119
+ if (type === 'local') return ` ${ANSI.dim}local${ANSI.reset}`;
120
+ if (type === 'system') return ` ${ANSI.dim}system${ANSI.reset}`;
121
+ return '';
122
+ }
123
+
98
124
  /* ── Helper: role start/end one-liners ───────────────────────── */
99
125
 
100
126
  function roleStart(icon, label, provider) {
101
127
  console.log(` \u251c\u2500 ${icon} ${label} (${provider || "?"}) running...`);
102
128
  }
103
129
 
104
- function roleEnd(status, label, elapsed) {
105
- console.log(` \u251c\u2500 ${status} ${label} completed ${elapsed}`);
130
+ function roleEnd(status, label, elapsed, executor) {
131
+ console.log(` \u251c\u2500 ${status} ${label} completed${executor || ''} ${elapsed}`);
106
132
  }
107
133
 
108
134
  /* ── Helper: pass/fail stage result ─────────────────────────── */
109
135
 
110
136
  function passFailStage(detail, label, failDefault, elapsed) {
137
+ const executor = formatExecutor(detail);
111
138
  if (detail?.ok === false) {
112
139
  const summary = detail?.summary || failDefault;
113
- console.log(` \u251c\u2500 ${ANSI.red}\u274c ${label}: ${summary}${ANSI.reset} ${elapsed}`);
140
+ console.log(` \u251c\u2500 ${ANSI.red}\u274c ${label}: ${summary}${ANSI.reset}${executor} ${elapsed}`);
114
141
  } else {
115
- console.log(` \u251c\u2500 ${ANSI.green}\u2705 ${label}: passed${ANSI.reset} ${elapsed}`);
142
+ console.log(` \u251c\u2500 ${ANSI.green}\u2705 ${label}: passed${ANSI.reset}${executor} ${elapsed}`);
116
143
  }
117
144
  }
118
145
 
@@ -270,49 +297,52 @@ const EVENT_HANDLERS = {
270
297
  roleStart(icon, "Planner", event.detail?.planner);
271
298
  },
272
299
 
273
- "planner:end": (_event, _icon, elapsed, status) => {
274
- roleEnd(status, "Planner", elapsed);
300
+ "planner:end": (event, _icon, elapsed, status) => {
301
+ roleEnd(status, "Planner", elapsed, formatExecutor(event.detail));
275
302
  },
276
303
 
277
304
  "coder:start": (event, icon) => {
278
305
  roleStart(icon, "Coder", event.detail?.coder);
279
306
  },
280
307
 
281
- "coder:end": (_event, _icon, elapsed, status) => {
282
- roleEnd(status, "Coder", elapsed);
308
+ "coder:end": (event, _icon, elapsed, status) => {
309
+ roleEnd(status, "Coder", elapsed, formatExecutor(event.detail));
283
310
  },
284
311
 
285
312
  "refactorer:start": (event, icon) => {
286
313
  roleStart(icon, "Refactorer", event.detail?.refactorer);
287
314
  },
288
315
 
289
- "refactorer:end": (_event, _icon, elapsed, status) => {
290
- roleEnd(status, "Refactorer", elapsed);
316
+ "refactorer:end": (event, _icon, elapsed, status) => {
317
+ roleEnd(status, "Refactorer", elapsed, formatExecutor(event.detail));
291
318
  },
292
319
 
293
320
  "tdd:result": (event, icon) => {
294
321
  const tdd = event.detail || {};
295
322
  const label = tdd.ok ? `${ANSI.green}PASS${ANSI.reset}` : `${ANSI.red}FAIL${ANSI.reset}`;
296
323
  const files = tdd.sourceFiles === undefined ? "" : ` (${tdd.sourceFiles} src, ${tdd.testFiles} test)`;
297
- console.log(` \u251c\u2500 ${icon} TDD policy: ${label}${files}`);
324
+ const executor = formatExecutor(event.detail);
325
+ console.log(` \u251c\u2500 ${icon} TDD policy: ${label}${files}${executor}`);
298
326
  },
299
327
 
300
328
  "researcher:start": (event, icon) => {
301
329
  console.log(` \u251c\u2500 ${icon} Researcher (${event.detail?.researcher || "?"}) investigating...`);
302
330
  },
303
331
 
304
- "researcher:end": (_event, _icon, elapsed, status) => {
305
- roleEnd(status, "Researcher", elapsed);
332
+ "researcher:end": (event, _icon, elapsed, status) => {
333
+ roleEnd(status, "Researcher", elapsed, formatExecutor(event.detail));
306
334
  },
307
335
 
308
- "sonar:start": (_event, icon) => {
309
- console.log(` \u251c\u2500 ${icon} SonarQube scanning...`);
336
+ "sonar:start": (event, icon) => {
337
+ const executor = formatExecutor(event.detail);
338
+ console.log(` \u251c\u2500 ${icon} SonarQube scanning...${executor}`);
310
339
  },
311
340
 
312
341
  "sonar:end": (event, _icon, elapsed, status) => {
313
342
  const gate = event.detail?.gateStatus || "?";
314
343
  const gateColor = gate === "OK" ? ANSI.green : ANSI.red;
315
- console.log(` \u251c\u2500 ${status} Quality gate: ${gateColor}${gate}${ANSI.reset} ${elapsed}`);
344
+ const executor = formatExecutor(event.detail);
345
+ console.log(` \u251c\u2500 ${status} Quality gate: ${gateColor}${gate}${ANSI.reset}${executor} ${elapsed}`);
316
346
  },
317
347
 
318
348
  "reviewer:start": (event, icon) => {
@@ -321,11 +351,12 @@ const EVENT_HANDLERS = {
321
351
 
322
352
  "reviewer:end": (event, _icon, elapsed) => {
323
353
  const review = event.detail || {};
354
+ const executor = formatExecutor(event.detail);
324
355
  if (review.approved) {
325
- console.log(` \u251c\u2500 ${ANSI.green}\u2705 Review: APPROVED${ANSI.reset} ${elapsed}`);
356
+ console.log(` \u251c\u2500 ${ANSI.green}\u2705 Review: APPROVED${ANSI.reset}${executor} ${elapsed}`);
326
357
  } else {
327
358
  const count = review.blockingCount || 0;
328
- console.log(` \u251c\u2500 ${ANSI.red}\u274c Review: REJECTED (${count} blocking)${ANSI.reset}`);
359
+ console.log(` \u251c\u2500 ${ANSI.red}\u274c Review: REJECTED (${count} blocking)${ANSI.reset}${executor}`);
329
360
  if (review.issues) {
330
361
  for (const issue of review.issues) {
331
362
  console.log(` \u2502 ${ANSI.dim}${issue}${ANSI.reset}`);
@@ -334,16 +365,18 @@ const EVENT_HANDLERS = {
334
365
  }
335
366
  },
336
367
 
337
- "tester:start": (_event, icon) => {
338
- console.log(` \u251c\u2500 ${icon} Tester evaluating...`);
368
+ "tester:start": (event, icon) => {
369
+ const executor = formatExecutor(event.detail);
370
+ console.log(` \u251c\u2500 ${icon} Tester evaluating...${executor}`);
339
371
  },
340
372
 
341
373
  "tester:end": (event, _icon, elapsed) => {
342
374
  passFailStage(event.detail, "Tester", "issues found", elapsed);
343
375
  },
344
376
 
345
- "security:start": (_event, icon) => {
346
- console.log(` \u251c\u2500 ${icon} Security auditing...`);
377
+ "security:start": (event, icon) => {
378
+ const executor = formatExecutor(event.detail);
379
+ console.log(` \u251c\u2500 ${icon} Security auditing...${executor}`);
347
380
  },
348
381
 
349
382
  "security:end": (event, _icon, elapsed) => {
@@ -351,7 +384,8 @@ const EVENT_HANDLERS = {
351
384
  },
352
385
 
353
386
  "solomon:start": (event, icon) => {
354
- console.log(` \u251c\u2500 ${icon} Solomon arbitrating ${event.detail?.conflictStage || "?"} conflict...`);
387
+ const executor = formatExecutor(event.detail);
388
+ console.log(` \u251c\u2500 ${icon} Solomon arbitrating ${event.detail?.conflictStage || "?"} conflict...${executor}`);
355
389
  },
356
390
 
357
391
  "solomon:end": (event, _icon, elapsed) => {
@@ -422,6 +456,82 @@ const EVENT_HANDLERS = {
422
456
  console.log(`${ANSI.dim}Resume with: kj resume ${event.sessionId} --answer "<response>"${ANSI.reset}`);
423
457
  },
424
458
 
459
+ "preflight:start": (event) => {
460
+ const executor = formatExecutor(event.detail);
461
+ console.log(` \u251c\u2500 \ud83d\udee1\ufe0f Preflight checks running...${executor}`);
462
+ },
463
+
464
+ "preflight:end": (event, _icon, elapsed) => {
465
+ const executor = formatExecutor(event.detail);
466
+ const ok = event.status === "ok";
467
+ const statusIcon = ok ? `${ANSI.green}\u2705` : `${ANSI.red}\u274c`;
468
+ console.log(` \u251c\u2500 ${statusIcon} Preflight: ${event.message}${ANSI.reset}${executor} ${elapsed}`);
469
+ },
470
+
471
+ "discover:start": (event, icon) => {
472
+ const provider = event.detail?.provider || event.detail?.discover || "?";
473
+ console.log(` \u251c\u2500 ${icon || "\ud83d\udd0e"} Discover (${provider}) analyzing...`);
474
+ },
475
+
476
+ "discover:end": (event, _icon, elapsed, status) => {
477
+ roleEnd(status, "Discover", elapsed, formatExecutor(event.detail));
478
+ },
479
+
480
+ "architect:start": (event) => {
481
+ const provider = event.detail?.provider || event.detail?.architect || "?";
482
+ console.log(` \u251c\u2500 \ud83c\udfdb\ufe0f Architect (${provider}) designing...`);
483
+ },
484
+
485
+ "architect:end": (event, _icon, elapsed, status) => {
486
+ roleEnd(status, "Architect", elapsed, formatExecutor(event.detail));
487
+ },
488
+
489
+ "hu-reviewer:start": (event) => {
490
+ const executor = formatExecutor(event.detail);
491
+ console.log(` \u251c\u2500 \ud83d\udcdd HU Reviewer certifying...${executor}`);
492
+ },
493
+
494
+ "hu-reviewer:end": (event, _icon, elapsed, status) => {
495
+ roleEnd(status, "HU Reviewer", elapsed, formatExecutor(event.detail));
496
+ },
497
+
498
+ "impeccable:start": (event) => {
499
+ const executor = formatExecutor(event.detail);
500
+ console.log(` \u251c\u2500 \ud83c\udfa8 Impeccable auditing design...${executor}`);
501
+ },
502
+
503
+ "impeccable:end": (event, _icon, elapsed, status) => {
504
+ roleEnd(status, "Impeccable", elapsed, formatExecutor(event.detail));
505
+ },
506
+
507
+ "audit:start": (event) => {
508
+ const executor = formatExecutor(event.detail);
509
+ console.log(` \u251c\u2500 \ud83d\udccb Final audit running...${executor}`);
510
+ },
511
+
512
+ "audit:end": (event, _icon, elapsed, status) => {
513
+ roleEnd(status, "Audit", elapsed, formatExecutor(event.detail));
514
+ },
515
+
516
+ "sonarcloud:start": (event) => {
517
+ const executor = formatExecutor(event.detail);
518
+ console.log(` \u251c\u2500 \u2601\ufe0f SonarCloud scanning...${executor}`);
519
+ },
520
+
521
+ "sonarcloud:end": (event, _icon, elapsed, status) => {
522
+ roleEnd(status, "SonarCloud", elapsed, formatExecutor(event.detail));
523
+ },
524
+
525
+ "guard:output": (event) => {
526
+ const executor = formatExecutor(event.detail);
527
+ console.log(` \u251c\u2500 \ud83d\udee1\ufe0f ${event.message}${executor}`);
528
+ },
529
+
530
+ "guard:perf": (event) => {
531
+ const executor = formatExecutor(event.detail);
532
+ console.log(` \u251c\u2500 \u26a1 ${event.message}${executor}`);
533
+ },
534
+
425
535
  "pipeline:tracker": (event) => {
426
536
  const trackerStages = event.detail?.stages || [];
427
537
  console.log(` ${ANSI.dim}\u250c Pipeline${ANSI.reset}`);