pi-crew 0.5.2 → 0.5.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/CHANGELOG.md +67 -0
- package/docs/bugs/cross-session-notification-leakage.md +82 -0
- package/docs/coding-agent-optimization.md +268 -0
- package/docs/deep-review-report.md +384 -0
- package/docs/distillation/cybersecurity-patterns.md +294 -0
- package/docs/migration-v0.4-v0.5.md +191 -0
- package/docs/optimization-plan.md +642 -0
- package/docs/pi-mono-opportunities.md +969 -0
- package/docs/pi-mono-review.md +291 -0
- package/docs/skills/REFERENCE.md +144 -0
- package/package.json +7 -6
- package/skills/artifact-analysis-loop/SKILL.md +302 -0
- package/skills/async-worker-recovery/SKILL.md +19 -1
- package/skills/child-pi-spawning/SKILL.md +19 -6
- package/skills/context-artifact-hygiene/SKILL.md +19 -2
- package/skills/delegation-patterns/SKILL.md +68 -3
- package/skills/detection-pipeline-design/SKILL.md +285 -0
- package/skills/event-log-tracing/SKILL.md +20 -6
- package/skills/git-master/SKILL.md +20 -6
- package/skills/hunting-investigation-loop/SKILL.md +401 -0
- package/skills/incident-playbook-construction/SKILL.md +383 -0
- package/skills/live-agent-lifecycle/SKILL.md +20 -6
- package/skills/mailbox-interactive/SKILL.md +19 -6
- package/skills/model-routing-context/SKILL.md +19 -1
- package/skills/multi-perspective-review/SKILL.md +19 -4
- package/skills/observability-reliability/SKILL.md +19 -2
- package/skills/orchestration/SKILL.md +20 -2
- package/skills/ownership-session-security/SKILL.md +20 -2
- package/skills/pi-extension-lifecycle/SKILL.md +20 -2
- package/skills/post-mortem/SKILL.md +7 -2
- package/skills/read-only-explorer/SKILL.md +20 -6
- package/skills/requirements-to-task-packet/SKILL.md +23 -3
- package/skills/resource-discovery-config/SKILL.md +20 -2
- package/skills/runtime-state-reader/SKILL.md +20 -2
- package/skills/safe-bash/SKILL.md +21 -6
- package/skills/scrutinize/SKILL.md +20 -2
- package/skills/secure-agent-orchestration-review/SKILL.md +29 -2
- package/skills/security-review/SKILL.md +560 -0
- package/skills/state-mutation-locking/SKILL.md +22 -2
- package/skills/systematic-debugging/SKILL.md +8 -6
- package/skills/threat-hypothesis-framework/SKILL.md +175 -0
- package/skills/ui-render-performance/SKILL.md +20 -2
- package/skills/verification-before-done/SKILL.md +17 -2
- package/skills/widget-rendering/SKILL.md +21 -6
- package/skills/workspace-isolation/SKILL.md +20 -6
- package/skills/worktree-isolation/SKILL.md +20 -6
- package/src/agents/agent-config.ts +40 -1
- package/src/config/config.ts +22 -5
- package/src/config/role-tools.ts +82 -0
- package/src/config/types.ts +4 -0
- package/src/extension/crew-cleanup.ts +114 -0
- package/src/extension/register.ts +15 -3
- package/src/extension/team-tool/run.ts +7 -7
- package/src/observability/event-bus.ts +60 -0
- package/src/runtime/background-runner.ts +8 -2
- package/src/runtime/child-pi.ts +122 -34
- package/src/runtime/crew-agent-runtime.ts +1 -0
- package/src/runtime/foreground-control.ts +87 -17
- package/src/runtime/pi-args.ts +11 -1
- package/src/runtime/pi-json-output.ts +31 -0
- package/src/runtime/progress-tracker.ts +124 -0
- package/src/runtime/skill-effectiveness.ts +473 -0
- package/src/runtime/skill-instructions.ts +37 -3
- package/src/runtime/task-runner.ts +91 -17
- package/src/runtime/team-runner.ts +11 -11
- package/src/runtime/tool-progress.ts +10 -3
- package/src/runtime/verification-gates.ts +367 -0
- package/src/schema/team-tool-schema.ts +7 -0
- package/src/state/decision-ledger.ts +92 -43
- package/src/state/event-log.ts +136 -10
- package/src/state/hook-instinct-bridge.ts +5 -5
- package/src/state/state-store.ts +3 -1
- package/src/state/types.ts +4 -0
- package/src/types/new-api-types.ts +34 -0
- package/src/ui/agent-management-overlay.ts +5 -1
- package/src/ui/crew-widget.ts +29 -15
- package/src/ui/powerbar-publisher.ts +100 -7
- package/src/ui/tool-render.ts +15 -15
- package/src/utils/session-utils.ts +52 -0
- package/src/worktree/worktree-manager.ts +32 -13
|
@@ -7,10 +7,11 @@ import type {
|
|
|
7
7
|
TeamRunManifest,
|
|
8
8
|
TeamTaskState,
|
|
9
9
|
UsageState,
|
|
10
|
+
VerificationEvidence,
|
|
10
11
|
} from "../state/types.ts";
|
|
11
12
|
import { logInternalError } from "../utils/internal-error.ts";
|
|
12
13
|
import { writeArtifact } from "../state/artifact-store.ts";
|
|
13
|
-
import { appendEvent, appendEventFireAndForget } from "../state/event-log.ts";
|
|
14
|
+
import { appendEvent, appendEventAsync, appendEventFireAndForget } from "../state/event-log.ts";
|
|
14
15
|
import { saveRunManifest } from "../state/state-store.ts";
|
|
15
16
|
import { createTaskClaim } from "../state/task-claims.ts";
|
|
16
17
|
import {
|
|
@@ -38,6 +39,7 @@ import { runChildPi, type ChildPiLifecycleEvent } from "./child-pi.ts";
|
|
|
38
39
|
import { buildTaskPacket } from "./task-packet.ts";
|
|
39
40
|
import { executeHook, appendHookEvent } from "../hooks/registry.ts";
|
|
40
41
|
import { createVerificationEvidence } from "./green-contract.ts";
|
|
42
|
+
import { executeVerificationCommands, computeGreenLevelFromResults } from "./verification-gates.ts";
|
|
41
43
|
import { createStartupEvidence } from "./worker-startup.ts";
|
|
42
44
|
import { permissionForRole } from "./role-permission.ts";
|
|
43
45
|
import { crewHooks } from "./crew-hooks.ts";
|
|
@@ -212,7 +214,7 @@ export async function runTeamTask(
|
|
|
212
214
|
"started",
|
|
213
215
|
));
|
|
214
216
|
upsertCrewAgent(manifest, recordFromTask(manifest, task, runtimeKind));
|
|
215
|
-
|
|
217
|
+
await appendEventAsync(manifest.eventsPath, {
|
|
216
218
|
type: "task.started",
|
|
217
219
|
runId: manifest.runId,
|
|
218
220
|
taskId: task.id,
|
|
@@ -244,6 +246,7 @@ export async function runTeamTask(
|
|
|
244
246
|
teamRole: { skills: input.teamRoleSkills },
|
|
245
247
|
step: input.step,
|
|
246
248
|
override: input.skillOverride,
|
|
249
|
+
runId: manifest.runId, // ECC INSTINCT: Enable skill confidence tracking
|
|
247
250
|
})
|
|
248
251
|
: undefined;
|
|
249
252
|
const skillBlock = input.skillBlock ?? renderedSkills?.block;
|
|
@@ -420,6 +423,11 @@ export async function runTeamTask(
|
|
|
420
423
|
graceTurns: input.runtimeConfig?.graceTurns,
|
|
421
424
|
inheritContext: input.runtimeConfig?.inheritContext,
|
|
422
425
|
parentContext: input.parentContext,
|
|
426
|
+
excludeContextBash: input.runtimeConfig?.excludeContextBash,
|
|
427
|
+
sessionId: manifest.sessionId,
|
|
428
|
+
role: task.role,
|
|
429
|
+
runId: manifest.runId,
|
|
430
|
+
agentId: task.id,
|
|
423
431
|
onSpawn: (pid) => {
|
|
424
432
|
try {
|
|
425
433
|
({ task, tasks } = checkpointTask(
|
|
@@ -444,7 +452,7 @@ export async function runTeamTask(
|
|
|
444
452
|
}
|
|
445
453
|
},
|
|
446
454
|
onLifecycleEvent: (event: ChildPiLifecycleEvent) => {
|
|
447
|
-
|
|
455
|
+
void appendEventAsync(manifest.eventsPath, {
|
|
448
456
|
type: `worker.${event.type}` as const,
|
|
449
457
|
runId: manifest.runId,
|
|
450
458
|
taskId: task.id,
|
|
@@ -590,7 +598,7 @@ export async function runTeamTask(
|
|
|
590
598
|
attemptStartedAt.toISOString(),
|
|
591
599
|
),
|
|
592
600
|
);
|
|
593
|
-
|
|
601
|
+
await appendEventAsync(manifest.eventsPath, {
|
|
594
602
|
type: "worker.cancelled",
|
|
595
603
|
runId: manifest.runId,
|
|
596
604
|
taskId: task.id,
|
|
@@ -863,7 +871,7 @@ export async function runTeamTask(
|
|
|
863
871
|
}
|
|
864
872
|
} else if (!error) {
|
|
865
873
|
noYield = true;
|
|
866
|
-
|
|
874
|
+
await appendEventAsync(manifest.eventsPath, {
|
|
867
875
|
type: "task.needs_attention",
|
|
868
876
|
runId: manifest.runId,
|
|
869
877
|
taskId: task.id,
|
|
@@ -896,6 +904,16 @@ export async function runTeamTask(
|
|
|
896
904
|
})
|
|
897
905
|
: undefined;
|
|
898
906
|
|
|
907
|
+
// Capture unified patches from edit tool results
|
|
908
|
+
const patchArtifact = parsedOutput?.patches?.length
|
|
909
|
+
? writeArtifact(manifest.artifactsRoot, {
|
|
910
|
+
kind: "patch",
|
|
911
|
+
relativePath: `patches/${task.id}.patch`,
|
|
912
|
+
content: parsedOutput.patches.join("\n---\n"),
|
|
913
|
+
producer: task.id,
|
|
914
|
+
})
|
|
915
|
+
: undefined;
|
|
916
|
+
|
|
899
917
|
const mutationGuardMode =
|
|
900
918
|
input.runtimeConfig?.completionMutationGuard ?? "warn";
|
|
901
919
|
const mutationGuard =
|
|
@@ -959,7 +977,7 @@ export async function runTeamTask(
|
|
|
959
977
|
if (outputText) {
|
|
960
978
|
outputValidation = validateWorkerOutput(task.role, outputText);
|
|
961
979
|
if (!outputValidation.valid) {
|
|
962
|
-
|
|
980
|
+
await appendEventAsync(manifest.eventsPath, {
|
|
963
981
|
type: "task.output_validation",
|
|
964
982
|
runId: manifest.runId,
|
|
965
983
|
taskId: task.id,
|
|
@@ -983,6 +1001,70 @@ export async function runTeamTask(
|
|
|
983
1001
|
}
|
|
984
1002
|
}
|
|
985
1003
|
|
|
1004
|
+
// --- ECC VERIFICATION_LOOP: Compute verification evidence before building task object ---
|
|
1005
|
+
// Compute verification evidence (may be async if verification commands need to run)
|
|
1006
|
+
const baseEvidence = createVerificationEvidence(
|
|
1007
|
+
taskPacket.verification,
|
|
1008
|
+
!error,
|
|
1009
|
+
error
|
|
1010
|
+
? `Task failed: ${error}`
|
|
1011
|
+
: runtimeKind === "scaffold"
|
|
1012
|
+
? "Safe scaffold mode; verification commands were not executed."
|
|
1013
|
+
: `${runtimeKind} worker finished without reporting a verification failure.`,
|
|
1014
|
+
);
|
|
1015
|
+
|
|
1016
|
+
// Only execute verification commands when:
|
|
1017
|
+
// 1. Task completed successfully (no error)
|
|
1018
|
+
// 2. Verification contract has commands
|
|
1019
|
+
// 3. Not in scaffold mode (scaffold mode intentionally skips execution)
|
|
1020
|
+
let verificationEvidence: VerificationEvidence = baseEvidence;
|
|
1021
|
+
if (!error && runtimeKind !== "scaffold" && taskPacket.verification?.commands?.length) {
|
|
1022
|
+
try {
|
|
1023
|
+
const commandResults = await executeVerificationCommands(
|
|
1024
|
+
taskPacket.verification,
|
|
1025
|
+
task.cwd,
|
|
1026
|
+
manifest.runId,
|
|
1027
|
+
task.id,
|
|
1028
|
+
manifest.artifactsRoot,
|
|
1029
|
+
input.signal,
|
|
1030
|
+
);
|
|
1031
|
+
|
|
1032
|
+
// Compute observed green level from results
|
|
1033
|
+
const observedGreenLevel = computeGreenLevelFromResults(
|
|
1034
|
+
commandResults,
|
|
1035
|
+
taskPacket.verification.requiredGreenLevel,
|
|
1036
|
+
);
|
|
1037
|
+
|
|
1038
|
+
// Determine satisfaction based on green level
|
|
1039
|
+
const requiredLevel = taskPacket.verification.requiredGreenLevel;
|
|
1040
|
+
const satisfied =
|
|
1041
|
+
observedGreenLevel === "none" ? false :
|
|
1042
|
+
observedGreenLevel === "targeted" ? requiredLevel === "targeted" :
|
|
1043
|
+
observedGreenLevel === "package" ? ["targeted", "package"].includes(requiredLevel) :
|
|
1044
|
+
observedGreenLevel === "workspace" ? ["targeted", "package", "workspace"].includes(requiredLevel) :
|
|
1045
|
+
observedGreenLevel === "merge_ready";
|
|
1046
|
+
|
|
1047
|
+
const allPassed = commandResults.every(r => r.status === "passed");
|
|
1048
|
+
const failedCount = commandResults.filter(r => r.status === "failed").length;
|
|
1049
|
+
|
|
1050
|
+
verificationEvidence = {
|
|
1051
|
+
requiredGreenLevel: taskPacket.verification.requiredGreenLevel,
|
|
1052
|
+
observedGreenLevel,
|
|
1053
|
+
satisfied: satisfied && allPassed,
|
|
1054
|
+
commands: commandResults,
|
|
1055
|
+
notes: allPassed
|
|
1056
|
+
? `${commandResults.length} verification commands passed`
|
|
1057
|
+
: `${failedCount}/${commandResults.length} verification commands failed`,
|
|
1058
|
+
};
|
|
1059
|
+
} catch (execError) {
|
|
1060
|
+
// On execution error, return base evidence with error note
|
|
1061
|
+
verificationEvidence = {
|
|
1062
|
+
...baseEvidence,
|
|
1063
|
+
notes: `Verification execution failed: ${execError instanceof Error ? execError.message : String(execError)}`,
|
|
1064
|
+
};
|
|
1065
|
+
}
|
|
1066
|
+
}
|
|
1067
|
+
|
|
986
1068
|
task = {
|
|
987
1069
|
...task,
|
|
988
1070
|
status: error ? "failed" : noYield ? "needs_attention" : "completed",
|
|
@@ -999,16 +1081,7 @@ export async function runTeamTask(
|
|
|
999
1081
|
}
|
|
1000
1082
|
: task.agentProgress,
|
|
1001
1083
|
error,
|
|
1002
|
-
verification:
|
|
1003
|
-
taskPacket.verification,
|
|
1004
|
-
!error,
|
|
1005
|
-
error
|
|
1006
|
-
? `Task failed: ${error}`
|
|
1007
|
-
: runtimeKind === "scaffold"
|
|
1008
|
-
? "Safe scaffold mode; verification commands were not executed."
|
|
1009
|
-
: `${runtimeKind} worker finished without reporting a verification failure.`,
|
|
1010
|
-
),
|
|
1011
|
-
promptArtifact,
|
|
1084
|
+
verification: verificationEvidence,
|
|
1012
1085
|
resultArtifact,
|
|
1013
1086
|
claim: undefined,
|
|
1014
1087
|
heartbeat: touchWorkerHeartbeat(
|
|
@@ -1105,6 +1178,7 @@ export async function runTeamTask(
|
|
|
1105
1178
|
...(transcriptArtifact ? [transcriptArtifact] : []),
|
|
1106
1179
|
...(diffArtifact ? [diffArtifact] : []),
|
|
1107
1180
|
...(diffStatArtifact ? [diffStatArtifact] : []),
|
|
1181
|
+
...(patchArtifact ? [patchArtifact] : []),
|
|
1108
1182
|
],
|
|
1109
1183
|
};
|
|
1110
1184
|
saveRunManifest(manifest);
|
|
@@ -1117,7 +1191,7 @@ export async function runTeamTask(
|
|
|
1117
1191
|
cwd: manifest.cwd,
|
|
1118
1192
|
});
|
|
1119
1193
|
appendHookEvent(manifest, hookReport);
|
|
1120
|
-
|
|
1194
|
+
await appendEventAsync(manifest.eventsPath, {
|
|
1121
1195
|
type: error ? "task.failed" : noYield ? "task.needs_attention" : "task.completed",
|
|
1122
1196
|
runId: manifest.runId,
|
|
1123
1197
|
taskId: task.id,
|
|
@@ -6,7 +6,7 @@ import type { CrewRuntimeKind } from "./crew-agent-runtime.ts";
|
|
|
6
6
|
import { resolveTaskRuntimeKind } from "./runtime-policy.ts";
|
|
7
7
|
import { writeArtifact } from "../state/artifact-store.ts";
|
|
8
8
|
import { executeHook, appendHookEvent } from "../hooks/registry.ts";
|
|
9
|
-
import { appendEvent, appendEventFireAndForget } from "../state/event-log.ts";
|
|
9
|
+
import { appendEvent, appendEventAsync, appendEventFireAndForget } from "../state/event-log.ts";
|
|
10
10
|
import type { TeamConfig } from "../teams/team-config.ts";
|
|
11
11
|
import type { ArtifactDescriptor, PolicyDecision, TeamRunManifest, TaskAttemptState, TeamTaskState } from "../state/types.ts";
|
|
12
12
|
import { loadRunManifestById, saveRunManifest, saveRunManifestAsync, saveRunTasksAsync, updateRunStatus } from "../state/state-store.ts";
|
|
@@ -395,7 +395,7 @@ async function executeTeamRunCore(
|
|
|
395
395
|
return base;
|
|
396
396
|
});
|
|
397
397
|
await saveRunTasksAsync(manifest, tasks);
|
|
398
|
-
for (const taskId of cancelledTaskIds)
|
|
398
|
+
for (const taskId of cancelledTaskIds) await appendEventAsync(manifest.eventsPath, { type: "task.cancelled", runId: manifest.runId, taskId, message, data: { reason: cancelReason.code } });
|
|
399
399
|
manifest = updateRunStatus(manifest, "cancelled", message, { data: { reason: cancelReason.code, cancelledTaskIds } });
|
|
400
400
|
return { manifest, tasks };
|
|
401
401
|
}
|
|
@@ -429,7 +429,7 @@ async function executeTeamRunCore(
|
|
|
429
429
|
};
|
|
430
430
|
const preconditions = validatePhasePreconditions(wfMachine, wfContext);
|
|
431
431
|
if (!preconditions.ready) {
|
|
432
|
-
|
|
432
|
+
await appendEventAsync(manifest.eventsPath, { type: "workflow.preconditions", runId: manifest.runId, message: `Workflow phase '${wfMachine.phases[wfMachine.currentPhaseIndex]?.name}' is missing inputs: ${preconditions.blocking.join(", ")}`, data: { phaseIndex: wfMachine.currentPhaseIndex, phaseName: wfMachine.phases[wfMachine.currentPhaseIndex]?.name, blocking: preconditions.blocking } });
|
|
433
433
|
} else {
|
|
434
434
|
// Advance the machine past completed phases.
|
|
435
435
|
while (wfMachine.currentPhaseIndex < wfMachine.phases.length && wfMachine.phases[wfMachine.currentPhaseIndex]?.status === "completed") {
|
|
@@ -441,7 +441,7 @@ async function executeTeamRunCore(
|
|
|
441
441
|
const readyRoles = effectiveReady.map((taskId) => tasks.find((task) => task.id === taskId)?.role).filter((role): role is string => Boolean(role));
|
|
442
442
|
const concurrency = resolveBatchConcurrency({ workflowName: workflow.name, workflowMaxConcurrency: workflow.maxConcurrency, teamMaxConcurrency: input.team.maxConcurrency, limitMaxConcurrentWorkers: input.limits?.maxConcurrentWorkers, allowUnboundedConcurrency: input.limits?.allowUnboundedConcurrency, readyCount: effectiveReady.length, workspaceMode: manifest.workspaceMode, readyRoles });
|
|
443
443
|
if (concurrency.reason.includes(";unbounded:")) {
|
|
444
|
-
|
|
444
|
+
await appendEventAsync(manifest.eventsPath, { type: "limits.unbounded", runId: manifest.runId, message: "Unbounded worker concurrency was explicitly enabled for this run.", data: { concurrencyReason: concurrency.reason, maxConcurrent: concurrency.maxConcurrent } });
|
|
445
445
|
}
|
|
446
446
|
const approvalPending = isPlanApprovalPending(manifest);
|
|
447
447
|
const readyIds = approvalPending ? effectiveReady : effectiveReady.slice(0, concurrency.selectedCount);
|
|
@@ -474,7 +474,7 @@ async function executeTeamRunCore(
|
|
|
474
474
|
}
|
|
475
475
|
const batchTasks = readyBatch.filter((task) => tasks.find((t) => t.id === task.id && t.status !== "skipped"));
|
|
476
476
|
if (batchTasks.length > 1) {
|
|
477
|
-
|
|
477
|
+
await appendEventAsync(manifest.eventsPath, { type: "task.parallel_start", runId: manifest.runId, message: `Launching ${batchTasks.length} tasks in PARALLEL (concurrency=${concurrency.selectedCount}): ${batchTasks.map((t) => `${t.role}(${t.id})`).join(", ")}`, data: { taskIds: batchTasks.map((t) => t.id), roles: batchTasks.map((t) => t.role), concurrency: concurrency.selectedCount } });
|
|
478
478
|
}
|
|
479
479
|
const results = await mapConcurrent(
|
|
480
480
|
batchTasks,
|
|
@@ -519,7 +519,7 @@ async function executeTeamRunCore(
|
|
|
519
519
|
attemptId: (attempt) => `${manifest.runId}:${task.id}:attempt-${attempt}`,
|
|
520
520
|
onAttemptFailed: (attempt, error, delayMs, info) => {
|
|
521
521
|
lastAttemptId = info.attemptId;
|
|
522
|
-
|
|
522
|
+
appendEventAsync(manifest.eventsPath, { type: "crew.task.retry_attempt", runId: manifest.runId, taskId: task.id, message: error.message, data: { attempt, attemptId: info.attemptId, delayMs }, metadata: { attemptId: info.attemptId } }).catch(() => {});
|
|
523
523
|
input.metricRegistry?.histogram("crew.task.retry_delay_ms", "Retry backoff delay, milliseconds").observe({ runId: manifest.runId, taskId: task.id }, delayMs);
|
|
524
524
|
},
|
|
525
525
|
onRetryGivenUp: (attempts, error, info) => {
|
|
@@ -536,7 +536,7 @@ async function executeTeamRunCore(
|
|
|
536
536
|
const freshManifest = fresh?.manifest ?? manifest;
|
|
537
537
|
const freshTasks = fresh?.tasks ?? tasks;
|
|
538
538
|
const cancelledTasks = freshTasks.map((item) => item.id === task.id && (item.status === "queued" || item.status === "running") ? { ...item, status: "cancelled" as const, finishedAt: new Date().toISOString(), error: `${reason.message} (${reason.code})` } : item);
|
|
539
|
-
|
|
539
|
+
appendEventAsync(freshManifest.eventsPath, { type: "task.cancelled", runId: freshManifest.runId, taskId: task.id, message: reason.message, data: { reason, phase: "retry" }, metadata: lastAttemptId ? { attemptId: lastAttemptId } : undefined }).catch(() => {});
|
|
540
540
|
return { manifest: updateRunStatus(freshManifest, "cancelled", reason.message), tasks: cancelledTasks };
|
|
541
541
|
}
|
|
542
542
|
if (lastFailed) return lastFailed;
|
|
@@ -586,10 +586,10 @@ async function executeTeamRunCore(
|
|
|
586
586
|
const transition = transitionPhase(wfMachine, pi, phaseStatus, wfContext);
|
|
587
587
|
wfMachine = transition.machine;
|
|
588
588
|
if (transition.guardResult && !transition.guardResult.allowed) {
|
|
589
|
-
|
|
589
|
+
await appendEventAsync(manifest.eventsPath, { type: "workflow.phase_guard_blocked", runId: manifest.runId, message: `Workflow phase '${phase.name}' guard blocked: ${transition.guardResult.reason ?? "unknown"}`, data: { phaseIndex: pi, phaseName: phase.name, reason: transition.guardResult.reason } });
|
|
590
590
|
break;
|
|
591
591
|
}
|
|
592
|
-
|
|
592
|
+
await appendEventAsync(manifest.eventsPath, { type: phaseStatus === "failed" ? "workflow.phase_failed" : "workflow.phase_completed", runId: manifest.runId, message: `Workflow phase '${phase.name}' ${phaseStatus}.`, data: { phaseIndex: pi, phaseStatus } });
|
|
593
593
|
}
|
|
594
594
|
wfMachine = { ...wfMachine, currentPhaseIndex: pi + 1 };
|
|
595
595
|
}
|
|
@@ -603,7 +603,7 @@ async function executeTeamRunCore(
|
|
|
603
603
|
await saveRunTasksAsync(manifest, tasks);
|
|
604
604
|
saveCrewAgents(manifest, recordsForMaterializedTasks(manifest, tasks, runtimeKind));
|
|
605
605
|
await saveRunManifestAsync(manifest);
|
|
606
|
-
|
|
606
|
+
await appendEventAsync(manifest.eventsPath, { type: "run.cancelled", runId: manifest.runId, message, data: { reason, phase: "task-batch", cancelledResultRunId: cancelledResult?.manifest.runId } });
|
|
607
607
|
return { manifest, tasks };
|
|
608
608
|
}
|
|
609
609
|
queueIndex = buildTaskGraphIndex(tasks);
|
|
@@ -651,7 +651,7 @@ async function executeTeamRunCore(
|
|
|
651
651
|
const effectivenessDecision = effectivenessPolicyDecision(effectiveness);
|
|
652
652
|
if (effectivenessDecision) {
|
|
653
653
|
manifest = { ...manifest, policyDecisions: [...(manifest.policyDecisions ?? []), effectivenessDecision], updatedAt: new Date().toISOString() };
|
|
654
|
-
|
|
654
|
+
await appendEventAsync(manifest.eventsPath, { type: "run.effectiveness", runId: manifest.runId, message: effectivenessDecision.message, data: { effectiveness, policyDecision: effectivenessDecision } });
|
|
655
655
|
}
|
|
656
656
|
const blockingDecision = manifest.policyDecisions?.find((item) => item.action === "block" || item.action === "escalate");
|
|
657
657
|
if (failed) {
|
|
@@ -150,12 +150,18 @@ export interface ToolProgressDisplay {
|
|
|
150
150
|
* Format tool progress for display
|
|
151
151
|
*/
|
|
152
152
|
export function formatToolProgress(progress: CrewAgentProgress, maxContextTokens = 128000): ToolProgressDisplay {
|
|
153
|
-
const recentTools
|
|
153
|
+
const recentTools: Array<{
|
|
154
|
+
tool: string;
|
|
155
|
+
args?: string;
|
|
156
|
+
startedAt?: string;
|
|
157
|
+
endedAt?: string;
|
|
158
|
+
status: "running" | "done" | "error";
|
|
159
|
+
}> = progress.recentTools.map((t) => ({
|
|
154
160
|
tool: t.tool,
|
|
155
161
|
args: t.args,
|
|
156
162
|
startedAt: t.startedAt,
|
|
157
163
|
endedAt: t.endedAt,
|
|
158
|
-
status: t.endedAt ? "done" : "running" as const,
|
|
164
|
+
status: t.endedAt ? ("done" as const) : ("running" as const),
|
|
159
165
|
}));
|
|
160
166
|
|
|
161
167
|
// If there's a currentTool but no endedAt, it's still running
|
|
@@ -167,7 +173,8 @@ export function formatToolProgress(progress: CrewAgentProgress, maxContextTokens
|
|
|
167
173
|
tool: progress.currentTool,
|
|
168
174
|
args: progress.currentToolArgs,
|
|
169
175
|
startedAt: progress.currentToolStartedAt,
|
|
170
|
-
|
|
176
|
+
endedAt: undefined as string | undefined,
|
|
177
|
+
status: "running" as const,
|
|
171
178
|
});
|
|
172
179
|
}
|
|
173
180
|
|