pi-crew 0.9.55 → 0.9.57
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/AGENTS.md +1 -1
- package/CHANGELOG.md +58 -0
- package/README.md +53 -5
- package/dist/index.mjs +5666 -4370
- package/docs/README.md +54 -0
- package/package.json +12 -13
- package/skills/real-test-pi-crew/SKILL.md +93 -3
- package/src/agents/discover-agents.ts +68 -10
- package/src/benchmark/feedback-loop.ts +1 -1
- package/src/config/config.ts +2 -1
- package/src/config/types.ts +12 -0
- package/src/extension/action-suggestions.ts +16 -63
- package/src/extension/async-notifier.ts +3 -3
- package/src/extension/command-completions.ts +2 -2
- package/src/extension/crew-cleanup.ts +3 -3
- package/src/extension/crew-vibes/footer.ts +4 -2
- package/src/extension/cross-extension-rpc.ts +10 -5
- package/src/extension/knowledge-injection.ts +57 -10
- package/src/extension/register.ts +2 -2
- package/src/extension/registration/artifact-cleanup.ts +41 -3
- package/src/extension/registration/commands.ts +4 -4
- package/src/extension/registration/context-builder.ts +10 -10
- package/src/extension/registration/crash-recovery-cache.ts +3 -3
- package/src/extension/registration/foreground-run-controller.ts +1 -1
- package/src/extension/registration/lazy-configurers.ts +2 -2
- package/src/extension/registration/lifecycle-handlers.ts +12 -12
- package/src/extension/registration/lifecycle.ts +2 -2
- package/src/extension/registration/observability.ts +2 -2
- package/src/extension/registration/registration-types.ts +3 -3
- package/src/extension/registration/runtime-cleanup.ts +1 -1
- package/src/extension/registration/subagent-helpers.ts +2 -2
- package/src/extension/registration/subagent-manager-setup.ts +2 -2
- package/src/extension/registration/subagent-tools.ts +21 -16
- package/src/extension/registration/team-tool.ts +109 -17
- package/src/extension/registration/viewers.ts +3 -4
- package/src/extension/registration/wire-cross-extension.ts +7 -7
- package/src/extension/rpc-hmac.ts +3 -2
- package/src/extension/run-bundle-schema.ts +13 -4
- package/src/extension/run-export.ts +2 -2
- package/src/extension/run-index.ts +2 -3
- package/src/extension/run-maintenance.ts +57 -1
- package/src/extension/team-manager-command.ts +3 -1
- package/src/extension/team-tool/anchor.ts +8 -2
- package/src/extension/team-tool/api.ts +117 -39
- package/src/extension/team-tool/cancel.ts +23 -8
- package/src/extension/team-tool/chain-executor.ts +1 -1
- package/src/extension/team-tool/dispatch/automate.ts +17 -2
- package/src/extension/team-tool/dispatch/control.ts +17 -2
- package/src/extension/team-tool/dispatch/manage.ts +34 -2
- package/src/extension/team-tool/dispatch/run.ts +17 -2
- package/src/extension/team-tool/dispatch/status.ts +37 -5
- package/src/extension/team-tool/doctor.ts +2 -2
- package/src/extension/team-tool/explain.ts +1 -1
- package/src/extension/team-tool/goal-wrap.ts +5 -5
- package/src/extension/team-tool/goal.ts +30 -9
- package/src/extension/team-tool/handle-schedule.ts +37 -19
- package/src/extension/team-tool/inspect.ts +21 -5
- package/src/extension/team-tool/lifecycle-actions.ts +53 -10
- package/src/extension/team-tool/parallel-dispatch.ts +14 -5
- package/src/extension/team-tool/param-error.ts +138 -0
- package/src/extension/team-tool/respond.ts +20 -6
- package/src/extension/team-tool/run.ts +27 -17
- package/src/extension/team-tool/status.ts +17 -6
- package/src/extension/team-tool.ts +26 -19
- package/src/hooks/registry.ts +1 -1
- package/src/i18n.ts +22 -0
- package/src/observability/event-bus.ts +1 -1
- package/src/prompt/prompt-runtime.ts +2 -2
- package/src/runtime/README.md +35 -0
- package/src/runtime/agent-control.ts +1 -1
- package/src/runtime/anchor-manager.ts +0 -2
- package/src/runtime/async-runner.ts +1 -1
- package/src/runtime/attention-events.ts +3 -2
- package/src/runtime/auto-summarize.ts +0 -2
- package/src/runtime/background-runner.ts +103 -30
- package/src/runtime/{crew-broker-child.ts → broker/crew-broker-child.ts} +2 -2
- package/src/runtime/{crew-broker-client.ts → broker/crew-broker-client.ts} +4 -7
- package/src/runtime/{crew-broker.ts → broker/crew-broker.ts} +13 -21
- package/src/runtime/chain-runner.ts +50 -5
- package/src/runtime/{child-pi-constants.ts → child-pi/child-pi-constants.ts} +1 -1
- package/src/runtime/{child-pi-kill.ts → child-pi/child-pi-kill.ts} +3 -3
- package/src/runtime/{child-pi-spawn.ts → child-pi/child-pi-spawn.ts} +28 -12
- package/src/runtime/{child-pi-steering.ts → child-pi/child-pi-steering.ts} +1 -1
- package/src/runtime/{child-pi-streams.ts → child-pi/child-pi-streams.ts} +23 -4
- package/src/runtime/{child-pi-transcript.ts → child-pi/child-pi-transcript.ts} +6 -6
- package/src/runtime/{child-pi.ts → child-pi/child-pi.ts} +47 -78
- package/src/runtime/compaction/compact-stages/bounded-tail.ts +84 -0
- package/src/runtime/{compact-stages → compaction/compact-stages}/index.ts +2 -2
- package/src/runtime/{compaction-summary.ts → compaction/compaction-summary.ts} +3 -3
- package/src/runtime/{tool-output-pruner.ts → compaction/tool-output-pruner.ts} +1 -1
- package/src/runtime/crew-agent-records.ts +48 -2
- package/src/runtime/custom-tools/irc-tool.ts +2 -2
- package/src/runtime/delivery-coordinator.ts +0 -3
- package/src/runtime/diagnostic-export.ts +5 -4
- package/src/runtime/foreground-control.ts +1 -1
- package/src/runtime/foreground-watchdog.ts +1 -1
- package/src/runtime/{adaptive-plan.ts → goal-workflow/adaptive-plan.ts} +8 -8
- package/src/runtime/{dynamic-workflow-context.ts → goal-workflow/dynamic-workflow-context.ts} +16 -16
- package/src/runtime/{dynamic-workflow-runner.ts → goal-workflow/dynamic-workflow-runner.ts} +10 -10
- package/src/runtime/{goal-achievement.ts → goal-workflow/goal-achievement.ts} +3 -3
- package/src/runtime/{goal-evaluator.ts → goal-workflow/goal-evaluator.ts} +8 -8
- package/src/runtime/{goal-loop-runner.ts → goal-workflow/goal-loop-runner.ts} +27 -25
- package/src/runtime/{goal-state-store.ts → goal-workflow/goal-state-store.ts} +8 -8
- package/src/runtime/{plan-templates.ts → goal-workflow/plan-templates.ts} +1 -1
- package/src/runtime/group-join.ts +3 -3
- package/src/runtime/handoff-manager.ts +0 -2
- package/src/runtime/{heartbeat-watcher.ts → heartbeat/heartbeat-watcher.ts} +7 -7
- package/src/runtime/iteration-hooks.ts +1 -1
- package/src/runtime/{live-agent-control.ts → live-session/live-agent-control.ts} +2 -2
- package/src/runtime/{live-agent-manager.ts → live-session/live-agent-manager.ts} +4 -4
- package/src/runtime/{live-session-runtime.ts → live-session/live-session-runtime.ts} +39 -41
- package/src/runtime/manifest-cache.ts +6 -2
- package/src/runtime/{model-fallback.ts → model/model-fallback.ts} +1 -1
- package/src/runtime/{pi-args.ts → model/pi-args.ts} +20 -5
- package/src/runtime/model/provider-extensions.ts +116 -0
- package/src/runtime/{runtime-policy.ts → model/runtime-policy.ts} +2 -2
- package/src/runtime/{runtime-resolver.ts → model/runtime-resolver.ts} +3 -3
- package/src/runtime/{runtime-warmup.ts → model/runtime-warmup.ts} +8 -8
- package/src/runtime/orphan-worker-registry.ts +1 -1
- package/src/runtime/{progress-tracker.ts → output/progress-tracker.ts} +1 -1
- package/src/runtime/{result-extractor.ts → output/result-extractor.ts} +4 -4
- package/src/runtime/{sidechain-output.ts → output/sidechain-output.ts} +2 -2
- package/src/runtime/{stream-preview.ts → output/stream-preview.ts} +1 -1
- package/src/runtime/{streaming-output.ts → output/streaming-output.ts} +2 -2
- package/src/runtime/{tool-progress.ts → output/tool-progress.ts} +1 -1
- package/src/runtime/parent-guard.ts +30 -10
- package/src/runtime/pipeline-runner.ts +2 -2
- package/src/runtime/policy-engine.ts +2 -2
- package/src/runtime/{cancellation.ts → process/cancellation.ts} +1 -1
- package/src/runtime/{post-exit-stdio-guard.ts → process/post-exit-stdio-guard.ts} +1 -1
- package/src/runtime/{process-lifecycle.ts → process/process-lifecycle.ts} +3 -3
- package/src/runtime/{checkpoint.ts → recovery/checkpoint.ts} +4 -4
- package/src/runtime/{crash-recovery.ts → recovery/crash-recovery.ts} +93 -21
- package/src/runtime/{overflow-recovery.ts → recovery/overflow-recovery.ts} +1 -1
- package/src/runtime/{recovery-recipes.ts → recovery/recovery-recipes.ts} +1 -1
- package/src/runtime/{retry-executor.ts → recovery/retry-executor.ts} +2 -2
- package/src/runtime/{retry-runner.ts → recovery/retry-runner.ts} +2 -8
- package/src/runtime/run-tracker.ts +1 -1
- package/src/runtime/run-worker.ts +3 -3
- package/src/runtime/{coalesce-tasks.ts → scheduling/coalesce-tasks.ts} +3 -3
- package/src/runtime/{concurrency.ts → scheduling/concurrency.ts} +9 -3
- package/src/runtime/{parallel-research.ts → scheduling/parallel-research.ts} +4 -2
- package/src/runtime/{run-coalesced-task-group.ts → scheduling/run-coalesced-task-group.ts} +95 -36
- package/src/runtime/{semaphore.ts → scheduling/semaphore.ts} +4 -1
- package/src/runtime/{task-graph-scheduler.ts → scheduling/task-graph-scheduler.ts} +1 -1
- package/src/runtime/session-resources.ts +1 -1
- package/src/runtime/settings-store.ts +1 -1
- package/src/runtime/single-agent-compose.ts +1 -0
- package/src/runtime/stale-reconciler.ts +1 -1
- package/src/runtime/subagent-manager.ts +1 -1
- package/src/runtime/supervisor-contact.ts +28 -13
- package/src/runtime/task-output-context.ts +7 -5
- package/src/runtime/task-runner/child-executor.ts +67 -31
- package/src/runtime/task-runner/live-executor.ts +8 -8
- package/src/runtime/task-runner/post-execution.ts +12 -12
- package/src/runtime/task-runner/pre-execution.ts +6 -6
- package/src/runtime/task-runner/progress.ts +1 -1
- package/src/runtime/task-runner/run-projection.ts +1 -1
- package/src/runtime/task-runner/scaffold-executor.ts +1 -1
- package/src/runtime/task-runner/state-helpers.ts +2 -2
- package/src/runtime/task-runner.ts +4 -4
- package/src/runtime/team-runner.ts +441 -175
- package/src/runtime/{completion-guard.ts → verification/completion-guard.ts} +1 -1
- package/src/runtime/{green-contract.ts → verification/green-contract.ts} +1 -1
- package/src/runtime/{post-checks.ts → verification/post-checks.ts} +4 -4
- package/src/runtime/{verification-gates.ts → verification/verification-gates.ts} +5 -5
- package/src/runtime/{verification-integrity.ts → verification/verification-integrity.ts} +1 -1
- package/src/schema/config-schema.ts +1 -0
- package/src/schema/team-tool-schema.ts +149 -185
- package/src/state/README.md +44 -0
- package/src/state/atomic-write.ts +24 -3
- package/src/state/{locks.ts → coordination/locks.ts} +118 -38
- package/src/state/{mailbox.ts → coordination/mailbox.ts} +14 -8
- package/src/state/{schedule.ts → coordination/schedule.ts} +3 -3
- package/src/state/{task-claims.ts → coordination/task-claims.ts} +1 -1
- package/src/state/decision-ledger.ts +1 -1
- package/src/state/{event-log-rotation.ts → event-log/event-log-rotation.ts} +189 -31
- package/src/state/{event-log.ts → event-log/event-log.ts} +77 -39
- package/src/state/{jsonl-writer.ts → event-log/jsonl-writer.ts} +14 -6
- package/src/state/hook-instinct-bridge.ts +2 -2
- package/src/state/{active-run-registry.ts → stores/active-run-registry.ts} +7 -7
- package/src/state/{artifact-store.ts → stores/artifact-store.ts} +62 -4
- package/src/state/{blob-store.ts → stores/blob-store.ts} +3 -3
- package/src/state/{health-store.ts → stores/health-store.ts} +3 -3
- package/src/state/{instinct-store.ts → stores/instinct-store.ts} +3 -3
- package/src/state/{observation-store.ts → stores/observation-store.ts} +2 -2
- package/src/state/{run-cache.ts → stores/run-cache.ts} +4 -4
- package/src/state/{run-graph.ts → stores/run-graph.ts} +4 -4
- package/src/state/{run-metrics.ts → stores/run-metrics.ts} +3 -3
- package/src/state/{state-store.ts → stores/state-store.ts} +254 -21
- package/src/state/types.ts +27 -3
- package/src/ui/component.ts +55 -0
- package/src/ui/crew-select-list.ts +3 -1
- package/src/ui/dashboard-panes/agents-pane.ts +1 -1
- package/src/ui/dwf-phase-display.ts +1 -1
- package/src/ui/heartbeat-aggregator.ts +1 -1
- package/src/ui/keybinding-map.ts +179 -6
- package/src/ui/layout-primitives.ts +9 -5
- package/src/ui/live-conversation-overlay.ts +1 -1
- package/src/ui/live-run-sidebar.ts +1 -1
- package/src/ui/overlay-stack.ts +148 -0
- package/src/ui/overlays/agent-picker-overlay.ts +1 -1
- package/src/ui/overlays/mailbox-compose-overlay.ts +1 -1
- package/src/ui/overlays/mailbox-detail-overlay.ts +2 -2
- package/src/ui/powerbar-publisher.ts +1 -1
- package/src/ui/render-scheduler.ts +1 -1
- package/src/ui/run-action-dispatcher.ts +3 -3
- package/src/ui/run-dashboard.ts +5 -33
- package/src/ui/run-event-bus.ts +3 -3
- package/src/ui/run-snapshot-cache.ts +37 -18
- package/src/ui/settings-overlay.ts +13 -21
- package/src/ui/snapshot-types.ts +1 -1
- package/src/ui/status-colors.ts +0 -2
- package/src/ui/terminal-status.ts +1 -1
- package/src/ui/theme-adapter.ts +33 -13
- package/src/ui/tool-renderers/index.ts +8 -0
- package/src/ui/transcript-viewer.ts +37 -13
- package/src/ui/widget/index.ts +32 -9
- package/src/ui/widget/widget-formatters.ts +62 -4
- package/src/ui/widget/widget-model.ts +2 -2
- package/src/ui/widget/widget-renderer.ts +1 -1
- package/src/utils/conflict-detect.ts +58 -5
- package/src/utils/ndjson.ts +2 -2
- package/src/utils/redaction.ts +39 -0
- package/src/utils/socket-path.ts +1 -1
- package/src/workflows/workflow-config.ts +1 -1
- package/src/worktree/cleanup.ts +1 -1
- package/src/worktree/worktree-manager.ts +111 -47
- package/workflows/chain.workflow.md +2 -2
- package/dist/build-meta.json +0 -16807
- package/index.bundle.ts +0 -25
- package/scripts/bench-check.mjs +0 -96
- package/scripts/bench-cold-start.mjs +0 -216
- package/scripts/build-bundle.mjs +0 -92
- package/scripts/check-all-skills.ts +0 -294
- package/scripts/check-bundle-size.mjs +0 -38
- package/scripts/check-bundle-staleness.mjs +0 -97
- package/scripts/check-conflict-markers.mjs +0 -91
- package/scripts/check-lazy-imports.mjs +0 -28
- package/scripts/dev-runner.mjs +0 -106
- package/scripts/profile-startup.mjs +0 -125
- package/scripts/release-smoke.mjs +0 -74
- package/scripts/run-bench.mjs +0 -47
- package/scripts/run-real-chain.ts +0 -41
- package/scripts/test-issue-29-crash.ts +0 -111
- package/scripts/test-issue-29-e2e.ts +0 -183
- package/scripts/test-issue-29-real-runtime.ts +0 -330
- package/scripts/test-issue-29-real-tasks.ts +0 -387
- package/scripts/test-issue-29-team-tool.ts +0 -105
- package/scripts/test-runner.mjs +0 -84
- package/scripts/verify-flicker-fix.ts +0 -109
- package/scripts/verify-skill.ts +0 -550
- package/scripts/watch-bundle.mjs +0 -259
- package/scripts/watchdog-harness.ts +0 -119
- package/src/adapters/claude-adapter.ts +0 -23
- package/src/adapters/codex-adapter.ts +0 -21
- package/src/adapters/cursor-adapter.ts +0 -17
- package/src/adapters/export-util.ts +0 -143
- package/src/adapters/index.ts +0 -15
- package/src/adapters/registry.ts +0 -18
- package/src/adapters/types.ts +0 -23
- package/src/runtime/code-summary.ts +0 -292
- package/src/runtime/cross-extension-rpc.ts +0 -143
- package/src/runtime/hidden-handoff.ts +0 -407
- package/src/runtime/prose-compressor.ts +0 -162
- package/src/subagents/async-entry.ts +0 -1
- package/src/subagents/index.ts +0 -3
- package/src/subagents/live/control.ts +0 -1
- package/src/subagents/live/manager.ts +0 -1
- package/src/subagents/live/realtime.ts +0 -1
- package/src/subagents/live/session-runtime.ts +0 -1
- package/src/subagents/manager.ts +0 -1
- package/src/subagents/spawn.ts +0 -1
- package/test-integration-check.ts +0 -118
- /package/src/runtime/{broker-issuer.ts → broker/broker-issuer.ts} +0 -0
- /package/src/runtime/{crew-broker-tokens.ts → broker/crew-broker-tokens.ts} +0 -0
- /package/src/runtime/{child-pi-pool.ts → child-pi/child-pi-pool.ts} +0 -0
- /package/src/runtime/{compact-pipeline.ts → compaction/compact-pipeline.ts} +0 -0
- /package/src/runtime/{compact-stages → compaction/compact-stages}/ansi-strip-stage.ts +0 -0
- /package/src/runtime/{compact-stages → compaction/compact-stages}/blank-collapse-stage.ts +0 -0
- /package/src/runtime/{compact-stages → compaction/compact-stages}/deduplicate-stage.ts +0 -0
- /package/src/runtime/{compact-stages → compaction/compact-stages}/head-snap-stage.ts +0 -0
- /package/src/runtime/{compact-stages → compaction/compact-stages}/tail-capture-stage.ts +0 -0
- /package/src/runtime/{compact-stages → compaction/compact-stages}/truncation-stage.ts +0 -0
- /package/src/runtime/{important-line-classifier.ts → compaction/important-line-classifier.ts} +0 -0
- /package/src/runtime/{heartbeat-gradient.ts → heartbeat/heartbeat-gradient.ts} +0 -0
- /package/src/runtime/{worker-heartbeat.ts → heartbeat/worker-heartbeat.ts} +0 -0
- /package/src/runtime/{worker-startup.ts → heartbeat/worker-startup.ts} +0 -0
- /package/src/runtime/{intercom-bridge.ts → live-session/intercom-bridge.ts} +0 -0
- /package/src/runtime/{live-control-realtime.ts → live-session/live-control-realtime.ts} +0 -0
- /package/src/runtime/{live-extension-bridge.ts → live-session/live-extension-bridge.ts} +0 -0
- /package/src/runtime/{live-irc.ts → live-session/live-irc.ts} +0 -0
- /package/src/runtime/{live-session-health.ts → live-session/live-session-health.ts} +0 -0
- /package/src/runtime/{model-resolver.ts → model/model-resolver.ts} +0 -0
- /package/src/runtime/{model-scope.ts → model/model-scope.ts} +0 -0
- /package/src/runtime/{output-validator.ts → output/output-validator.ts} +0 -0
- /package/src/runtime/{pi-json-output.ts → output/pi-json-output.ts} +0 -0
- /package/src/runtime/{progress-event-coalescer.ts → output/progress-event-coalescer.ts} +0 -0
- /package/src/runtime/{cancellation-token.ts → process/cancellation-token.ts} +0 -0
- /package/src/runtime/{zombie-scanner.ts → process/zombie-scanner.ts} +0 -0
- /package/src/runtime/{crash-classification.ts → recovery/crash-classification.ts} +0 -0
- /package/src/runtime/{batch-barrier.ts → scheduling/batch-barrier.ts} +0 -0
- /package/src/runtime/{global-worker-cap.ts → scheduling/global-worker-cap.ts} +0 -0
- /package/src/runtime/{parallel-utils.ts → scheduling/parallel-utils.ts} +0 -0
- /package/src/runtime/{scheduler.ts → scheduling/scheduler.ts} +0 -0
- /package/src/runtime/{task-graph.ts → scheduling/task-graph.ts} +0 -0
- /package/src/runtime/{verification-worktree.ts → verification/verification-worktree.ts} +0 -0
- /package/src/state/{event-reconstructor.ts → event-log/event-reconstructor.ts} +0 -0
- /package/src/state/{worker-atomic-writer.ts → event-log/worker-atomic-writer.ts} +0 -0
|
@@ -1,18 +1,20 @@
|
|
|
1
|
-
import type { AgentConfig } from "
|
|
2
|
-
import {
|
|
3
|
-
import { appendEventAsync } from "
|
|
4
|
-
import {
|
|
5
|
-
import
|
|
6
|
-
import type {
|
|
7
|
-
import {
|
|
8
|
-
import {
|
|
9
|
-
import {
|
|
10
|
-
import type {
|
|
11
|
-
import {
|
|
12
|
-
import {
|
|
13
|
-
import {
|
|
14
|
-
import {
|
|
15
|
-
import {
|
|
1
|
+
import type { AgentConfig } from "../../agents/agent-config.ts";
|
|
2
|
+
import type { CrewReliabilityConfig, CrewRuntimeConfig } from "../../config/types.ts";
|
|
3
|
+
import { appendEventAsync } from "../../state/event-log/event-log.ts";
|
|
4
|
+
import { writeArtifact } from "../../state/stores/artifact-store.ts";
|
|
5
|
+
import { saveRunTasksAsync, updateRunStatus } from "../../state/stores/state-store.ts";
|
|
6
|
+
import type { TeamRunManifest, TeamTaskState } from "../../state/types.ts";
|
|
7
|
+
import type { WorkflowStep } from "../../workflows/workflow-config.ts";
|
|
8
|
+
import { createWorkerHeartbeat, touchWorkerHeartbeat } from "../heartbeat/worker-heartbeat.ts";
|
|
9
|
+
import type { CrewRuntimeMode } from "../model/runtime-resolver.ts";
|
|
10
|
+
import type { RetryPolicy } from "../recovery/retry-executor.ts";
|
|
11
|
+
import { DEFAULT_RETRY_POLICY, executeWithRetry } from "../recovery/retry-executor.ts";
|
|
12
|
+
import { permissionForRole } from "../role-permission.ts";
|
|
13
|
+
import { runWorker } from "../run-worker.ts";
|
|
14
|
+
import { sanitizeTaskText } from "../task-packet.ts";
|
|
15
|
+
import { splitCoalescedOutput } from "../task-runner/output-splitter.ts";
|
|
16
|
+
import { mergeArtifacts } from "../team-runner-artifacts.ts";
|
|
17
|
+
import { buildWorkspaceTree } from "../workspace-tree.ts";
|
|
16
18
|
|
|
17
19
|
export interface CoalescedTaskGroupInput {
|
|
18
20
|
manifest: TeamRunManifest;
|
|
@@ -27,6 +29,10 @@ export interface CoalescedTaskGroupInput {
|
|
|
27
29
|
onJsonEvent?: (taskId: string, runId: string, event: unknown) => void;
|
|
28
30
|
teamRole?: unknown;
|
|
29
31
|
perTaskRuntime?: CrewRuntimeMode;
|
|
32
|
+
/** RT-5: runtime config for maxTurns, graceTurns, taskTimeoutMs (mirror singleton). */
|
|
33
|
+
runtimeConfig?: CrewRuntimeConfig;
|
|
34
|
+
/** RT-5: reliability config for autoRetry + retryPolicy (mirror singleton). */
|
|
35
|
+
reliability?: CrewReliabilityConfig;
|
|
30
36
|
}
|
|
31
37
|
|
|
32
38
|
export interface CoalescedTaskGroupResult {
|
|
@@ -80,6 +86,9 @@ export async function runCoalescedTaskGroup(input: CoalescedTaskGroupInput): Pro
|
|
|
80
86
|
|
|
81
87
|
let rawOutput = "";
|
|
82
88
|
let success = false;
|
|
89
|
+
// RT-5 #1: track cancellation separately from failure so the status
|
|
90
|
+
// mapping can branch cancel → "cancelled" (not "failed").
|
|
91
|
+
let cancelled = false;
|
|
83
92
|
// FIND-06: serialize heartbeat saves and retain the active save so terminal
|
|
84
93
|
// results can drain it before their final write.
|
|
85
94
|
let heartbeatTimer: ReturnType<typeof setInterval> | null = null;
|
|
@@ -110,7 +119,7 @@ export async function runCoalescedTaskGroup(input: CoalescedTaskGroupInput): Pro
|
|
|
110
119
|
if (!taskIds.includes(t.id)) return t;
|
|
111
120
|
// FIND-06 belt-and-suspenders: never replace terminal state or its
|
|
112
121
|
// resultArtifact with a heartbeat-only snapshot.
|
|
113
|
-
if (t.status === "completed" || t.status === "failed") return t;
|
|
122
|
+
if (t.status === "completed" || t.status === "failed" || t.status === "cancelled") return t;
|
|
114
123
|
return {
|
|
115
124
|
...t,
|
|
116
125
|
heartbeat: touchWorkerHeartbeat(t.heartbeat ?? createWorkerHeartbeat(t.id), { alive: true }),
|
|
@@ -135,26 +144,76 @@ export async function runCoalescedTaskGroup(input: CoalescedTaskGroupInput): Pro
|
|
|
135
144
|
}
|
|
136
145
|
})();
|
|
137
146
|
}, 15_000);
|
|
147
|
+
// RT-5 #3/#4/#5: compute maxTurns, wall-clock timeout, and retry policy
|
|
148
|
+
// from config instead of hardcoding — mirrors the singleton path
|
|
149
|
+
// (team-runner.ts:1548-1578 + child-executor.ts:395-430).
|
|
150
|
+
const taskTimeoutMs = input.runtimeConfig?.taskTimeoutMs ?? 0;
|
|
151
|
+
const useRetry = input.reliability?.autoRetry !== false;
|
|
152
|
+
const policy: RetryPolicy = {
|
|
153
|
+
...DEFAULT_RETRY_POLICY,
|
|
154
|
+
...(input.reliability?.retryPolicy ?? {}),
|
|
155
|
+
};
|
|
156
|
+
// RT-5 #3: pass maxTurns from config instead of hardcoded 5.
|
|
157
|
+
// RT-5 #4: arm a per-attempt wall-clock timeout mirroring the singleton's
|
|
158
|
+
// AbortController+setTimeout pattern (child-executor.ts:395-430). The
|
|
159
|
+
// timeoutController is linked to the run-level signal so an external
|
|
160
|
+
// abort also aborts the worker. Its signal is passed to runWorker; the
|
|
161
|
+
// existing SIGTERM→SIGKILL escalation in child-pi.ts handles cleanup.
|
|
162
|
+
const runOnce = async () => {
|
|
163
|
+
const timeoutController = new AbortController();
|
|
164
|
+
let externalAbortListener: (() => void) | undefined;
|
|
165
|
+
if (signal) {
|
|
166
|
+
if (signal.aborted) {
|
|
167
|
+
timeoutController.abort(signal.reason);
|
|
168
|
+
} else {
|
|
169
|
+
externalAbortListener = () => timeoutController.abort(signal!.reason);
|
|
170
|
+
signal.addEventListener("abort", externalAbortListener, { once: true });
|
|
171
|
+
}
|
|
172
|
+
}
|
|
173
|
+
let timeoutHandle: ReturnType<typeof setTimeout> | undefined;
|
|
174
|
+
if (taskTimeoutMs > 0 && !timeoutController.signal.aborted) {
|
|
175
|
+
timeoutHandle = setTimeout(() => {
|
|
176
|
+
if (!timeoutController.signal.aborted) {
|
|
177
|
+
timeoutController.abort(new Error(`Task exceeded wall-clock timeout of ${taskTimeoutMs}ms`));
|
|
178
|
+
}
|
|
179
|
+
}, taskTimeoutMs);
|
|
180
|
+
timeoutHandle.unref?.();
|
|
181
|
+
}
|
|
182
|
+
try {
|
|
183
|
+
return await runWorker({
|
|
184
|
+
cwd: firstTask.cwd,
|
|
185
|
+
task: combinedPrompt,
|
|
186
|
+
agent,
|
|
187
|
+
signal: timeoutController.signal,
|
|
188
|
+
excludeContextBash: true,
|
|
189
|
+
maxTurns: input.runtimeConfig?.maxTurns,
|
|
190
|
+
graceTurns: input.runtimeConfig?.graceTurns,
|
|
191
|
+
onJsonEvent: (e) => input.onJsonEvent?.(firstTask.id, manifest.runId, e),
|
|
192
|
+
});
|
|
193
|
+
} finally {
|
|
194
|
+
if (timeoutHandle) clearTimeout(timeoutHandle);
|
|
195
|
+
if (externalAbortListener && signal) {
|
|
196
|
+
signal.removeEventListener("abort", externalAbortListener);
|
|
197
|
+
}
|
|
198
|
+
}
|
|
199
|
+
};
|
|
138
200
|
try {
|
|
139
|
-
const result = await executeWithRetry(
|
|
140
|
-
async () => {
|
|
141
|
-
return await runWorker({
|
|
142
|
-
cwd: firstTask.cwd,
|
|
143
|
-
task: combinedPrompt,
|
|
144
|
-
agent,
|
|
145
|
-
signal,
|
|
146
|
-
excludeContextBash: true,
|
|
147
|
-
maxTurns: 5,
|
|
148
|
-
onJsonEvent: (e) => input.onJsonEvent?.(firstTask.id, manifest.runId, e),
|
|
149
|
-
});
|
|
150
|
-
},
|
|
151
|
-
DEFAULT_RETRY_POLICY,
|
|
152
|
-
{ signal },
|
|
153
|
-
);
|
|
201
|
+
const result = useRetry ? await executeWithRetry(runOnce, policy, { signal }) : await runOnce();
|
|
154
202
|
rawOutput = result.rawFinalText ?? result.stdout ?? "";
|
|
155
|
-
|
|
203
|
+
// RT-5 #1/#2: distinguish cancel from failure. Cancel = run-level
|
|
204
|
+
// signal aborted OR the child reports cooperative cancellation.
|
|
205
|
+
// success requires exitCode===0 AND no error AND not cancelled
|
|
206
|
+
// (previously success = exitCode===0 only, which misreported
|
|
207
|
+
// depth-guard exitCode:1 and ignored the error field).
|
|
208
|
+
cancelled = signal?.aborted === true || result.exitStatus?.cancelled === true;
|
|
209
|
+
success = !cancelled && result.exitCode === 0 && !result.error;
|
|
156
210
|
} catch (err) {
|
|
157
|
-
|
|
211
|
+
// RT-5 #1: detect cancel in the throw path (e.g. executeWithRetry's
|
|
212
|
+
// throwIfCancelled when the run-level signal is already aborted).
|
|
213
|
+
cancelled = signal?.aborted === true;
|
|
214
|
+
rawOutput = cancelled
|
|
215
|
+
? `Worker dispatch cancelled: ${err instanceof Error ? err.message : String(err)}`
|
|
216
|
+
: `Worker dispatch failed: ${err instanceof Error ? err.message : String(err)}`;
|
|
158
217
|
success = false;
|
|
159
218
|
} finally {
|
|
160
219
|
if (heartbeatTimer !== null) clearInterval(heartbeatTimer);
|
|
@@ -186,7 +245,7 @@ export async function runCoalescedTaskGroup(input: CoalescedTaskGroupInput): Pro
|
|
|
186
245
|
newArtifacts.push(resultArtifact);
|
|
187
246
|
return {
|
|
188
247
|
...t,
|
|
189
|
-
status: ok ? ("completed" as const) : ("failed" as const),
|
|
248
|
+
status: ok ? ("completed" as const) : cancelled ? ("cancelled" as const) : ("failed" as const),
|
|
190
249
|
finishedAt,
|
|
191
250
|
result: {
|
|
192
251
|
text,
|
|
@@ -232,8 +291,8 @@ export async function runCoalescedTaskGroup(input: CoalescedTaskGroupInput): Pro
|
|
|
232
291
|
await appendEventAsync(updatedManifest.eventsPath, {
|
|
233
292
|
type: "task.coalesced_dispatch_end",
|
|
234
293
|
runId: manifest.runId,
|
|
235
|
-
message: `Coalesced dispatch ${success ? "completed" : "failed"} (${taskIds.length} tasks, ${split[0]?.strategy ?? "broadcast"} split)`,
|
|
236
|
-
data: { groupId, taskIds, success, strategy: split[0]?.strategy },
|
|
294
|
+
message: `Coalesced dispatch ${success ? "completed" : cancelled ? "cancelled" : "failed"} (${taskIds.length} tasks, ${split[0]?.strategy ?? "broadcast"} split)`,
|
|
295
|
+
data: { groupId, taskIds, success, cancelled, strategy: split[0]?.strategy },
|
|
237
296
|
});
|
|
238
297
|
|
|
239
298
|
return { manifest: updatedManifest, tasks: updatedTasks, taskIds, rawOutput, success };
|
|
@@ -33,7 +33,10 @@ export class Semaphore {
|
|
|
33
33
|
// implementation let #queue grow without bound, risking memory
|
|
34
34
|
// exhaustion under sustained high concurrency with slow releases.
|
|
35
35
|
if (this.#queue.length >= Semaphore.MAX_QUEUE) {
|
|
36
|
-
|
|
36
|
+
// P1-7: reject (don't throw) so callers can backpressure instead of crashing.
|
|
37
|
+
return Promise.reject(
|
|
38
|
+
new Error(`Semaphore queue full: ${this.#queue.length} waiters (max ${Semaphore.MAX_QUEUE}); cannot acquire slot`),
|
|
39
|
+
);
|
|
37
40
|
}
|
|
38
41
|
const { promise, resolve } = (() => {
|
|
39
42
|
let res: () => void;
|
|
@@ -12,7 +12,7 @@ export function tryRegisterSessionCleanup(pi: ExtensionAPI, cleanup: () => void)
|
|
|
12
12
|
const registerFn = api.registerSessionResourceCleanup;
|
|
13
13
|
if (typeof registerFn === "function") {
|
|
14
14
|
try {
|
|
15
|
-
const unregister = (registerFn as (fn: () => void) => (() => void) |
|
|
15
|
+
const unregister = (registerFn as (fn: () => void) => (() => void) | undefined)(cleanup);
|
|
16
16
|
if (typeof unregister === "function") return unregister;
|
|
17
17
|
// API returned void — cleanup is registered but cannot be unregistered
|
|
18
18
|
return undefined;
|
|
@@ -2,7 +2,7 @@ import * as fs from "node:fs";
|
|
|
2
2
|
import { homedir } from "node:os";
|
|
3
3
|
import * as path from "node:path";
|
|
4
4
|
import { atomicWriteJson } from "../state/atomic-write.ts";
|
|
5
|
-
import { withFileLockSync } from "../state/locks.ts";
|
|
5
|
+
import { withFileLockSync } from "../state/coordination/locks.ts";
|
|
6
6
|
import { logInternalError } from "../utils/internal-error.ts";
|
|
7
7
|
import type { JoinMode } from "./group-join.ts";
|
|
8
8
|
|
|
@@ -72,6 +72,7 @@ export function composeSingleAgentPrompt(workflow: WorkflowConfig, goal: string)
|
|
|
72
72
|
if (step.output) {
|
|
73
73
|
lines.push(`Output: write your result to \`${step.output}\``);
|
|
74
74
|
}
|
|
75
|
+
// biome-ignore lint/complexity/useOptionalChain: reads is `string[] | false | undefined` — optional chain doesn't narrow out `false` (no .length on boolean)
|
|
75
76
|
if (step.reads && step.reads.length) {
|
|
76
77
|
lines.push(`Read first: ${step.reads.join(", ")}`);
|
|
77
78
|
}
|
|
@@ -3,7 +3,7 @@ import * as os from "node:os";
|
|
|
3
3
|
import * as path from "node:path";
|
|
4
4
|
import { errors } from "../errors.ts";
|
|
5
5
|
import { atomicWriteFile, atomicWriteJson } from "../state/atomic-write.ts";
|
|
6
|
-
import { saveRunManifest } from "../state/state-store.ts";
|
|
6
|
+
import { saveRunManifest } from "../state/stores/state-store.ts";
|
|
7
7
|
import type { TeamRunManifest, TeamTaskState } from "../state/types.ts";
|
|
8
8
|
import { recordFromTask, upsertCrewAgent } from "./crew-agent-records.ts";
|
|
9
9
|
import { checkProcessLiveness } from "./process-status.ts";
|
|
@@ -2,7 +2,7 @@ import * as fs from "node:fs";
|
|
|
2
2
|
import * as path from "node:path";
|
|
3
3
|
import { DEFAULT_PATHS, DEFAULT_SUBAGENT } from "../config/defaults.ts";
|
|
4
4
|
import type { PiTeamsToolResult } from "../extension/tool-result.ts";
|
|
5
|
-
import { loadRunManifestById } from "../state/state-store.ts";
|
|
5
|
+
import { loadRunManifestById } from "../state/stores/state-store.ts";
|
|
6
6
|
import { logInternalError } from "../utils/internal-error.ts";
|
|
7
7
|
import { projectCrewRoot } from "../utils/paths.ts";
|
|
8
8
|
import { redactSecrets } from "../utils/redaction.ts";
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { appendEvent } from "../state/event-log.ts";
|
|
1
|
+
import { appendEvent } from "../state/event-log/event-log.ts";
|
|
2
2
|
import type { TeamRunManifest } from "../state/types.ts";
|
|
3
3
|
import { logInternalError } from "../utils/internal-error.ts";
|
|
4
4
|
|
|
@@ -37,22 +37,21 @@ export function recordSupervisorContact(manifest: TeamRunManifest, payload: Omit
|
|
|
37
37
|
* Parse a supervisor contact request from child Pi stdout.
|
|
38
38
|
* Detects structured JSON lines with type "supervisor_contact".
|
|
39
39
|
*/
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
if (!
|
|
49
|
-
const record =
|
|
40
|
+
const SUPERVISOR_CONTACT_REASONS = ["decision_needed", "clarification", "approval", "error_escalation", "custom"] as const;
|
|
41
|
+
|
|
42
|
+
/**
|
|
43
|
+
* Validate a parsed event object as a supervisor-contact payload. Shared by the
|
|
44
|
+
* event-based (current) and line-based (deprecated) entry points. Returns the
|
|
45
|
+
* normalized payload, or undefined if the event is not a supervisor contact.
|
|
46
|
+
*/
|
|
47
|
+
export function supervisorContactFromEvent(event: unknown): Omit<SupervisorContactPayload, "timestamp" | "runId"> | undefined {
|
|
48
|
+
if (!event || typeof event !== "object" || Array.isArray(event)) return undefined;
|
|
49
|
+
const record = event as Record<string, unknown>;
|
|
50
50
|
if (record.type !== "supervisor_contact" && record.type !== "crew_supervisor_contact") return undefined;
|
|
51
51
|
return {
|
|
52
52
|
taskId: typeof record.taskId === "string" ? record.taskId : "",
|
|
53
53
|
reason:
|
|
54
|
-
typeof record.reason === "string" &&
|
|
55
|
-
["decision_needed", "clarification", "approval", "error_escalation", "custom"].includes(record.reason)
|
|
54
|
+
typeof record.reason === "string" && (SUPERVISOR_CONTACT_REASONS as readonly string[]).includes(record.reason)
|
|
56
55
|
? (record.reason as SupervisorContactPayload["reason"])
|
|
57
56
|
: "custom",
|
|
58
57
|
message: typeof record.message === "string" ? record.message : String(record.message ?? ""),
|
|
@@ -62,3 +61,19 @@ export function parseSupervisorContactFromLine(line: string): Omit<SupervisorCon
|
|
|
62
61
|
: undefined,
|
|
63
62
|
};
|
|
64
63
|
}
|
|
64
|
+
|
|
65
|
+
/**
|
|
66
|
+
* @deprecated The compact pipeline now passes `supervisor_contact` events through
|
|
67
|
+
* to `onJsonEvent` with their full payload (P2-25 fix). Prefer
|
|
68
|
+
* `supervisorContactFromEvent` on the parsed event. Kept for backward compat.
|
|
69
|
+
*/
|
|
70
|
+
export function parseSupervisorContactFromLine(line: string): Omit<SupervisorContactPayload, "timestamp" | "runId"> | undefined {
|
|
71
|
+
if (!line.trim()) return undefined;
|
|
72
|
+
let parsed: unknown;
|
|
73
|
+
try {
|
|
74
|
+
parsed = JSON.parse(line);
|
|
75
|
+
} catch {
|
|
76
|
+
return undefined;
|
|
77
|
+
}
|
|
78
|
+
return supervisorContactFromEvent(parsed);
|
|
79
|
+
}
|
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
import * as fs from "node:fs";
|
|
2
2
|
import * as path from "node:path";
|
|
3
3
|
import { DEFAULT_OUTPUT_CONTEXT } from "../config/defaults.ts";
|
|
4
|
-
import { writeArtifact } from "../state/artifact-store.ts";
|
|
5
4
|
import { atomicWriteFile } from "../state/atomic-write.ts";
|
|
5
|
+
import { writeArtifact } from "../state/stores/artifact-store.ts";
|
|
6
6
|
import type { ArtifactDescriptor, TeamRunManifest, TeamTaskState } from "../state/types.ts";
|
|
7
7
|
import { resolveRealContainedPath } from "../utils/safe-paths.ts";
|
|
8
8
|
import type { WorkflowStep } from "../workflows/workflow-config.ts";
|
|
9
|
-
import { applyCompactPipeline } from "./compact-pipeline.ts";
|
|
10
|
-
import { ANSI_STRIP_STAGE, BLANK_COLLAPSE_STAGE, TruncationStage } from "./compact-stages/index.ts";
|
|
11
|
-
import { DEFAULT_PRUNE_CONFIG, type FileEditEvent, pruneToolOutputs, type ToolResultEntry } from "./tool-output-pruner.ts";
|
|
9
|
+
import { applyCompactPipeline } from "./compaction/compact-pipeline.ts";
|
|
10
|
+
import { ANSI_STRIP_STAGE, BLANK_COLLAPSE_STAGE, TruncationStage } from "./compaction/compact-stages/index.ts";
|
|
11
|
+
import { DEFAULT_PRUNE_CONFIG, type FileEditEvent, pruneToolOutputs, type ToolResultEntry } from "./compaction/tool-output-pruner.ts";
|
|
12
12
|
|
|
13
13
|
export interface DependencyContextEntry {
|
|
14
14
|
taskId: string;
|
|
@@ -410,7 +410,9 @@ export function collectDependencyOutputContext(
|
|
|
410
410
|
// (used for recency sort in the trim step). Both are looked up against
|
|
411
411
|
// `task.dependsOn` (the declared order) and `tasks` (finished timestamps).
|
|
412
412
|
const declaredOrder = new Map<string, number>();
|
|
413
|
-
task.dependsOn.forEach((depId, index) =>
|
|
413
|
+
task.dependsOn.forEach((depId, index) => {
|
|
414
|
+
declaredOrder.set(depId, index);
|
|
415
|
+
});
|
|
414
416
|
const recencyByTaskId = new Map<string, number>();
|
|
415
417
|
for (const item of tasks) {
|
|
416
418
|
if (!item.finishedAt) continue;
|
|
@@ -29,13 +29,12 @@ import * as fs from "node:fs";
|
|
|
29
29
|
import * as path from "node:path";
|
|
30
30
|
import { loadConfig } from "../../config/config.ts";
|
|
31
31
|
import { errors } from "../../errors.ts";
|
|
32
|
-
import {
|
|
33
|
-
import {
|
|
32
|
+
import { appendEventAsync, appendEventBuffered } from "../../state/event-log/event-log.ts";
|
|
33
|
+
import { writeArtifact } from "../../state/stores/artifact-store.ts";
|
|
34
34
|
import type { ArtifactDescriptor, OperationTerminalEvidence, TeamRunManifest } from "../../state/types.ts";
|
|
35
35
|
import { logInternalError } from "../../utils/internal-error.ts";
|
|
36
36
|
import { resolveRealContainedPath } from "../../utils/safe-paths.ts";
|
|
37
|
-
import {
|
|
38
|
-
import type { ChildPiLifecycleEvent } from "../child-pi.ts";
|
|
37
|
+
import type { ChildPiLifecycleEvent, ChildPiRunResult } from "../child-pi/child-pi.ts";
|
|
39
38
|
import {
|
|
40
39
|
appendCrewAgentEvent,
|
|
41
40
|
appendCrewAgentOutput,
|
|
@@ -45,21 +44,22 @@ import {
|
|
|
45
44
|
} from "../crew-agent-records.ts";
|
|
46
45
|
import { crewHooks } from "../crew-hooks.ts";
|
|
47
46
|
import { bridgeEventFromJsonEvent } from "../event-stream-bridge.ts";
|
|
47
|
+
import { createWorkerHeartbeat, touchWorkerHeartbeat } from "../heartbeat/worker-heartbeat.ts";
|
|
48
|
+
import { createStartupEvidence } from "../heartbeat/worker-startup.ts";
|
|
48
49
|
import {
|
|
49
50
|
buildConfiguredModelRouting,
|
|
50
51
|
formatModelAttemptNote,
|
|
51
52
|
isRetryableModelFailure,
|
|
52
53
|
type ModelAttemptSummary,
|
|
53
|
-
} from "../model-fallback.ts";
|
|
54
|
-
import { readEnabledModelsPatterns } from "../model-scope.ts";
|
|
55
|
-
import { type ParsedPiJsonOutput, parsePiJsonOutput } from "../pi-json-output.ts";
|
|
56
|
-
import { type ProgressEventSummary, shouldAppendProgressEventUpdate } from "../progress-event-coalescer.ts";
|
|
57
|
-
import {
|
|
54
|
+
} from "../model/model-fallback.ts";
|
|
55
|
+
import { readEnabledModelsPatterns } from "../model/model-scope.ts";
|
|
56
|
+
import { type ParsedPiJsonOutput, parsePiJsonOutput } from "../output/pi-json-output.ts";
|
|
57
|
+
import { type ProgressEventSummary, shouldAppendProgressEventUpdate } from "../output/progress-event-coalescer.ts";
|
|
58
|
+
import { buildSyntheticTerminalEvidence, cancellationReasonFromSignal } from "../process/cancellation.ts";
|
|
59
|
+
import { DEFAULT_RETRY_POLICY } from "../recovery/retry-executor.ts";
|
|
58
60
|
import { runWorker } from "../run-worker.ts";
|
|
59
61
|
import { parseSessionUsage } from "../session-usage.ts";
|
|
60
|
-
import {
|
|
61
|
-
import { createWorkerHeartbeat, touchWorkerHeartbeat } from "../worker-heartbeat.ts";
|
|
62
|
-
import { createStartupEvidence } from "../worker-startup.ts";
|
|
62
|
+
import { recordSupervisorContact, supervisorContactFromEvent } from "../supervisor-contact.ts";
|
|
63
63
|
import type { TaskExecutionResult } from "./post-execution.ts";
|
|
64
64
|
import type { StreamBridgeHandle, TaskExecutionContext } from "./pre-execution.ts";
|
|
65
65
|
import { applyAgentProgressEvent, applyUsageToProgress, progressEventSummary, shouldFlushProgressEvent } from "./progress.ts";
|
|
@@ -115,6 +115,35 @@ async function resolveTaskScopeModelsPatterns(cwd: string): Promise<string[]> {
|
|
|
115
115
|
return readEnabledModelsPatterns(cwd);
|
|
116
116
|
}
|
|
117
117
|
|
|
118
|
+
/**
|
|
119
|
+
* RT-6: resolve the configured retry policy's maxAttempts from the project
|
|
120
|
+
* reliability config (`reliability.retryPolicy.maxAttempts`), falling back to
|
|
121
|
+
* {@link DEFAULT_RETRY_POLICY}.maxAttempts when config is unavailable or the
|
|
122
|
+
* field is unset. Mirrors `retryPolicyFromConfig` in team-runner.ts so the
|
|
123
|
+
* spawn-budget math and the actual retry loop (executeWithRetry) agree on the
|
|
124
|
+
* same ceiling. Best-effort: any config read failure silently falls back to
|
|
125
|
+
* the default so a misconfiguration never blocks the spawn.
|
|
126
|
+
*/
|
|
127
|
+
export function resolveConfiguredMaxAttempts(cwd: string): number {
|
|
128
|
+
try {
|
|
129
|
+
return loadConfig(cwd).config.reliability?.retryPolicy?.maxAttempts ?? DEFAULT_RETRY_POLICY.maxAttempts;
|
|
130
|
+
} catch {
|
|
131
|
+
return DEFAULT_RETRY_POLICY.maxAttempts;
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
/**
|
|
136
|
+
* RT-6: pure spawn-budget max formula. `attemptModelsCount × (maxAttempts + 1)`
|
|
137
|
+
* — always ≥ 1 full attempt above the theoretical max of
|
|
138
|
+
* `maxAttempts × attemptModelsCount`. Exported for direct unit testing so the
|
|
139
|
+
* configured-vs-default maxAttempts distinction is locked independently of
|
|
140
|
+
* the retry loop (previously hard-coded DEFAULT_RETRY_POLICY.maxAttempts = 3,
|
|
141
|
+
* silently halving retries when a higher maxAttempts — up to 10 — was set).
|
|
142
|
+
*/
|
|
143
|
+
export function computeSpawnBudgetMax(attemptModelsCount: number, configuredMaxAttempts: number): number {
|
|
144
|
+
return attemptModelsCount * (configuredMaxAttempts + 1);
|
|
145
|
+
}
|
|
146
|
+
|
|
118
147
|
/**
|
|
119
148
|
* 429/rate-limit detection (PI_CREW_TOOLING_429_NOTE.md).
|
|
120
149
|
*
|
|
@@ -215,8 +244,6 @@ export async function runChildProcessTask(ctx: TaskExecutionContext): Promise<Ta
|
|
|
215
244
|
const collectedJsonEvents = ctx.collectedJsonEvents;
|
|
216
245
|
const streamBridge: StreamBridgeHandle | undefined = ctx.streamBridge;
|
|
217
246
|
|
|
218
|
-
let resultArtifact: ArtifactDescriptor;
|
|
219
|
-
let logArtifact: ArtifactDescriptor | undefined;
|
|
220
247
|
let transcriptArtifact: ArtifactDescriptor | undefined;
|
|
221
248
|
let exitCode: number | null = 0;
|
|
222
249
|
let error: string | undefined;
|
|
@@ -246,8 +273,13 @@ export async function runChildProcessTask(ctx: TaskExecutionContext): Promise<Ta
|
|
|
246
273
|
// Budget = attemptModels.length × (maxAttempts + 1) — always one
|
|
247
274
|
// full attempt-worth above the theoretical maximum of
|
|
248
275
|
// maxAttempts × attemptModels.length. Only computes once (max=0 guard).
|
|
276
|
+
// RT-6: use the configured retry policy's maxAttempts (from project
|
|
277
|
+
// reliability config), NOT DEFAULT_RETRY_POLICY (3). The retry loop in
|
|
278
|
+
// team-runner.ts wraps runTeamTask in executeWithRetry with the same
|
|
279
|
+
// configured maxAttempts (up to 10); hard-coding the default here silently
|
|
280
|
+
// halved the spawn budget relative to the real retry ceiling.
|
|
249
281
|
if (input.spawnBudget && input.spawnBudget.max === 0) {
|
|
250
|
-
input.spawnBudget.max = attemptModels.length
|
|
282
|
+
input.spawnBudget.max = computeSpawnBudgetMax(attemptModels.length, resolveConfiguredMaxAttempts(task.cwd));
|
|
251
283
|
}
|
|
252
284
|
const logs: string[] = [];
|
|
253
285
|
let finalStderr = "";
|
|
@@ -390,7 +422,7 @@ export async function runChildProcessTask(ctx: TaskExecutionContext): Promise<Ta
|
|
|
390
422
|
}, taskTimeoutMs);
|
|
391
423
|
timeoutHandle.unref?.();
|
|
392
424
|
}
|
|
393
|
-
let childResult;
|
|
425
|
+
let childResult: ChildPiRunResult;
|
|
394
426
|
try {
|
|
395
427
|
childResult = await runWorker({
|
|
396
428
|
cwd: task.cwd,
|
|
@@ -419,7 +451,10 @@ export async function runChildProcessTask(ctx: TaskExecutionContext): Promise<Ta
|
|
|
419
451
|
const steeringDir = `${manifest.artifactsRoot}/steering`;
|
|
420
452
|
// Fire-and-forget async write for steering events
|
|
421
453
|
void appendSteeringAsync(steeringDir, task.id, task.pendingSteers);
|
|
422
|
-
|
|
454
|
+
// RT-8: spread before clearing pendingSteers instead of mutating
|
|
455
|
+
// in place — preserves the immutable-snapshot invariant (the same
|
|
456
|
+
// object may already be referenced by the tasks array / snapshots).
|
|
457
|
+
task = { ...task, pendingSteers: [] };
|
|
423
458
|
tasks = persistSingleTaskUpdate(manifest, tasks, task);
|
|
424
459
|
}
|
|
425
460
|
} catch (err) {
|
|
@@ -438,19 +473,15 @@ export async function runChildProcessTask(ctx: TaskExecutionContext): Promise<Ta
|
|
|
438
473
|
onStdoutLine: (line) => {
|
|
439
474
|
appendCrewAgentOutput(manifest, task.id, line);
|
|
440
475
|
persistHeartbeat();
|
|
441
|
-
// Check for supervisor contact requests from child Pi
|
|
442
|
-
const contact = parseSupervisorContactFromLine(line);
|
|
443
|
-
if (contact) {
|
|
444
|
-
recordSupervisorContact(manifest, {
|
|
445
|
-
runId: manifest.runId,
|
|
446
|
-
...contact,
|
|
447
|
-
});
|
|
448
|
-
}
|
|
449
476
|
},
|
|
450
477
|
onJsonEvent: (event) => {
|
|
451
478
|
// Top-level error boundary: prevent any single event from crashing the task.
|
|
452
479
|
// Errors are logged but processing continues so subsequent events still update state.
|
|
453
480
|
try {
|
|
481
|
+
// P2-25: handle supervisor_contact here (compact pipeline now passes
|
|
482
|
+
// the full payload through); was dead on the old displayLine path.
|
|
483
|
+
const contact = supervisorContactFromEvent(event);
|
|
484
|
+
if (contact) recordSupervisorContact(manifest, { runId: manifest.runId, ...contact });
|
|
454
485
|
appendCrewAgentEvent(manifest, task.id, event);
|
|
455
486
|
if (collectedJsonEvents && event && typeof event === "object" && !Array.isArray(event))
|
|
456
487
|
collectedJsonEvents.push(event as Record<string, unknown>);
|
|
@@ -463,10 +494,15 @@ export async function runChildProcessTask(ctx: TaskExecutionContext): Promise<Ta
|
|
|
463
494
|
if (msg?.role === "assistant") {
|
|
464
495
|
const usage = msg.usage as Record<string, number> | undefined;
|
|
465
496
|
if (usage) {
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
|
|
497
|
+
// RT-8: spread before accumulating lifetimeUsage instead of
|
|
498
|
+
// mutating in place — preserves the immutable-snapshot invariant.
|
|
499
|
+
task = {
|
|
500
|
+
...task,
|
|
501
|
+
lifetimeUsage: {
|
|
502
|
+
input: (task.lifetimeUsage?.input ?? 0) + (usage.input ?? 0),
|
|
503
|
+
output: (task.lifetimeUsage?.output ?? 0) + (usage.output ?? 0),
|
|
504
|
+
cacheWrite: (task.lifetimeUsage?.cacheWrite ?? 0) + (usage.cacheWrite ?? 0),
|
|
505
|
+
},
|
|
470
506
|
};
|
|
471
507
|
}
|
|
472
508
|
}
|
|
@@ -680,7 +716,7 @@ export async function runChildProcessTask(ctx: TaskExecutionContext): Promise<Ta
|
|
|
680
716
|
});
|
|
681
717
|
}
|
|
682
718
|
}
|
|
683
|
-
resultArtifact = writeArtifact(manifest.artifactsRoot, {
|
|
719
|
+
const resultArtifact = writeArtifact(manifest.artifactsRoot, {
|
|
684
720
|
kind: "result",
|
|
685
721
|
relativePath: `results/${task.id}.txt`,
|
|
686
722
|
content:
|
|
@@ -699,7 +735,7 @@ export async function runChildProcessTask(ctx: TaskExecutionContext): Promise<Ta
|
|
|
699
735
|
"(no output)",
|
|
700
736
|
producer: task.id,
|
|
701
737
|
});
|
|
702
|
-
logArtifact = writeArtifact(manifest.artifactsRoot, {
|
|
738
|
+
const logArtifact = writeArtifact(manifest.artifactsRoot, {
|
|
703
739
|
kind: "log",
|
|
704
740
|
relativePath: `logs/${task.id}.log`,
|
|
705
741
|
content: [
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
import * as fs from "node:fs";
|
|
2
2
|
import type { AgentConfig } from "../../agents/agent-config.ts";
|
|
3
3
|
import type { CrewRuntimeConfig } from "../../config/config.ts";
|
|
4
|
-
import {
|
|
5
|
-
import {
|
|
6
|
-
import { loadRunManifestById } from "../../state/state-store.ts";
|
|
4
|
+
import { appendEventFireAndForget } from "../../state/event-log/event-log.ts";
|
|
5
|
+
import { writeArtifact } from "../../state/stores/artifact-store.ts";
|
|
6
|
+
import { loadRunManifestById } from "../../state/stores/state-store.ts";
|
|
7
7
|
import type { ArtifactDescriptor, TeamRunManifest, TeamTaskState } from "../../state/types.ts";
|
|
8
8
|
import type { WorkflowStep } from "../../workflows/workflow-config.ts";
|
|
9
9
|
import {
|
|
@@ -13,11 +13,11 @@ import {
|
|
|
13
13
|
recordFromTask,
|
|
14
14
|
upsertCrewAgent,
|
|
15
15
|
} from "../crew-agent-records.ts";
|
|
16
|
-
import {
|
|
17
|
-
import type
|
|
18
|
-
import {
|
|
19
|
-
import {
|
|
20
|
-
import {
|
|
16
|
+
import { createWorkerHeartbeat, touchWorkerHeartbeat } from "../heartbeat/worker-heartbeat.ts";
|
|
17
|
+
import { createStartupEvidence, type WorkerStartupEvidence } from "../heartbeat/worker-startup.ts";
|
|
18
|
+
import { runLiveSessionTask } from "../live-session/live-session-runtime.ts";
|
|
19
|
+
import type { ParsedPiJsonOutput } from "../output/pi-json-output.ts";
|
|
20
|
+
import { type ProgressEventSummary, shouldAppendProgressEventUpdate } from "../output/progress-event-coalescer.ts";
|
|
21
21
|
import { applyAgentProgressEvent, applyUsageToProgress, progressEventSummary, shouldFlushProgressEvent } from "./progress.ts";
|
|
22
22
|
import { persistSingleTaskUpdate } from "./state-helpers.ts";
|
|
23
23
|
|
|
@@ -15,10 +15,10 @@
|
|
|
15
15
|
* exactly (char scenarios 5-7, 9, 10 cover them).
|
|
16
16
|
*/
|
|
17
17
|
import { appendHookEvent, executeHook } from "../../hooks/registry.ts";
|
|
18
|
-
import {
|
|
19
|
-
import { appendEventAsync } from "../../state/event-log.ts";
|
|
20
|
-
import {
|
|
21
|
-
import { saveRunManifestAsync } from "../../state/state-store.ts";
|
|
18
|
+
import { withRunLock } from "../../state/coordination/locks.ts";
|
|
19
|
+
import { appendEventAsync } from "../../state/event-log/event-log.ts";
|
|
20
|
+
import { writeArtifact } from "../../state/stores/artifact-store.ts";
|
|
21
|
+
import { saveRunManifestAsync } from "../../state/stores/state-store.ts";
|
|
22
22
|
import type {
|
|
23
23
|
ArtifactDescriptor,
|
|
24
24
|
OperationTerminalEvidence,
|
|
@@ -29,16 +29,16 @@ import type {
|
|
|
29
29
|
import { captureWorktreeDiffAsync, captureWorktreeDiffStatAsync } from "../../worktree/worktree-manager.ts";
|
|
30
30
|
import { appendTaskAttentionEvent } from "../attention-events.ts";
|
|
31
31
|
import { extractCommandTrace } from "../command-trace.ts";
|
|
32
|
-
import { evaluateCompletionMutationGuard } from "../completion-guard.ts";
|
|
33
32
|
import { emptyCrewAgentProgress, recordFromTask, upsertCrewAgent } from "../crew-agent-records.ts";
|
|
34
33
|
import { crewHooks } from "../crew-hooks.ts";
|
|
35
|
-
import {
|
|
36
|
-
import type { ModelAttemptSummary } from "../model-fallback.ts";
|
|
37
|
-
import { type OutputValidationResult, validateWorkerOutput } from "../output-validator.ts";
|
|
38
|
-
import type { ParsedPiJsonOutput } from "../pi-json-output.ts";
|
|
34
|
+
import { createWorkerHeartbeat, touchWorkerHeartbeat } from "../heartbeat/worker-heartbeat.ts";
|
|
35
|
+
import type { ModelAttemptSummary } from "../model/model-fallback.ts";
|
|
36
|
+
import { type OutputValidationResult, validateWorkerOutput } from "../output/output-validator.ts";
|
|
37
|
+
import type { ParsedPiJsonOutput } from "../output/pi-json-output.ts";
|
|
39
38
|
import { writeTaskSharedOutput } from "../task-output-context.ts";
|
|
40
|
-
import {
|
|
41
|
-
import {
|
|
39
|
+
import { evaluateCompletionMutationGuard } from "../verification/completion-guard.ts";
|
|
40
|
+
import { createVerificationEvidence } from "../verification/green-contract.ts";
|
|
41
|
+
import { computeGreenLevelFromResults, executeVerificationCommands } from "../verification/verification-gates.ts";
|
|
42
42
|
import { extractYieldResult, hasYieldInOutput, isYieldEvent, type YieldResult } from "../yield-handler.ts";
|
|
43
43
|
import { buildWorkerCapabilityInventory } from "./capabilities.ts";
|
|
44
44
|
import type { TaskExecutionContext } from "./pre-execution.ts";
|
|
@@ -64,7 +64,7 @@ export interface TaskExecutionResult {
|
|
|
64
64
|
finalStdout: string;
|
|
65
65
|
transcriptPath: string | undefined;
|
|
66
66
|
terminalEvidence: OperationTerminalEvidence[];
|
|
67
|
-
startupEvidence: import("../worker-startup.ts").WorkerStartupEvidence;
|
|
67
|
+
startupEvidence: import("../heartbeat/worker-startup.ts").WorkerStartupEvidence;
|
|
68
68
|
}
|
|
69
69
|
|
|
70
70
|
/** Final persisted task state returned by finalizeTaskResult. */
|