pi-crew 0.9.56 → 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 +29 -0
- package/README.md +53 -5
- package/dist/index.mjs +5350 -4350
- package/docs/README.md +54 -0
- package/package.json +12 -12
- 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 +108 -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 +24 -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 +11 -5
- 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 +1 -1
- 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} +11 -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} +28 -72
- package/src/runtime/{compact-stages → compaction/compact-stages}/bounded-tail.ts +1 -1
- 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/custom-tools/irc-tool.ts +2 -2
- package/src/runtime/delivery-coordinator.ts +0 -3
- package/src/runtime/diagnostic-export.ts +3 -3
- 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 +1 -1
- 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} +1 -1
- 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/{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 +1 -1
- package/src/runtime/task-output-context.ts +7 -5
- package/src/runtime/task-runner/child-executor.ts +62 -22
- 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 +380 -139
- 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 +133 -177
- 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} +161 -31
- package/src/state/{event-log.ts → event-log/event-log.ts} +38 -26
- 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} +236 -17
- 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/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 +88 -39
- package/workflows/chain.workflow.md +2 -2
- 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/smoke-team-perf.ts +0 -43
- 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/{semaphore.ts → scheduling/semaphore.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,25 +1,31 @@
|
|
|
1
1
|
import { loadConfig } from "../../config/config.ts";
|
|
2
2
|
import { applyAttentionState, formatActivityAge, resolveCrewControlConfig } from "../../runtime/agent-control.ts";
|
|
3
3
|
import { extractCommandTrace } from "../../runtime/command-trace.ts";
|
|
4
|
-
import { verifyTaskCompletion } from "../../runtime/completion-guard.ts";
|
|
5
4
|
import { readCrewAgents } from "../../runtime/crew-agent-records.ts";
|
|
6
5
|
import { evaluateRunEffectiveness } from "../../runtime/effectiveness.ts";
|
|
7
6
|
import { computePhaseProgress } from "../../runtime/phase-progress.ts";
|
|
8
7
|
import { checkProcessLiveness, isActiveRunStatus } from "../../runtime/process-status.ts";
|
|
9
8
|
import { formatTaskGraphLines, waitingReason } from "../../runtime/task-display.ts";
|
|
9
|
+
import { verifyTaskCompletion } from "../../runtime/verification/completion-guard.ts";
|
|
10
10
|
import type { TeamToolParamsValue } from "../../schema/team-tool-schema.ts";
|
|
11
|
-
import {
|
|
12
|
-
import {
|
|
13
|
-
import { loadRunManifestById, saveRunTasks, updateRunStatus } from "../../state/state-store.ts";
|
|
11
|
+
import { readDeliveryState, readMailbox } from "../../state/coordination/mailbox.ts";
|
|
12
|
+
import { appendEvent, readEvents } from "../../state/event-log/event-log.ts";
|
|
13
|
+
import { loadRunManifestById, saveRunTasks, updateRunStatus } from "../../state/stores/state-store.ts";
|
|
14
14
|
import { aggregateUsage, formatCost, formatUsage } from "../../state/usage.ts";
|
|
15
15
|
import { formatDuration } from "../../ui/format-helpers.ts";
|
|
16
16
|
import { locateRunCwd } from "../team-tool.ts";
|
|
17
17
|
import type { PiTeamsToolResult } from "../tool-result.ts";
|
|
18
18
|
import { result, type TeamContext } from "./context.ts";
|
|
19
|
+
import { paramRequired } from "./param-error.ts";
|
|
19
20
|
import { RUN_NOT_FOUND_HINT } from "./run-not-found.ts";
|
|
20
21
|
|
|
21
22
|
export function handleStatus(params: TeamToolParamsValue, ctx: TeamContext): PiTeamsToolResult {
|
|
22
|
-
if (!params.runId)
|
|
23
|
+
if (!params.runId)
|
|
24
|
+
return result(
|
|
25
|
+
paramRequired("status", "runId", "{ action: 'status', runId: 'team_...' }"),
|
|
26
|
+
{ action: "status", status: "error" },
|
|
27
|
+
true,
|
|
28
|
+
);
|
|
23
29
|
const runCwd = locateRunCwd(params.runId, ctx.cwd);
|
|
24
30
|
if (!runCwd) return result(`Run '${params.runId}' not found.${RUN_NOT_FOUND_HINT}`, { action: "status", status: "error" }, true);
|
|
25
31
|
const loaded = loadRunManifestById(runCwd, params.runId); // NOTE: no withRunLock - best-effort only; concurrent writes may cause inconsistency
|
|
@@ -7,12 +7,12 @@ import { loadConfig } from "../config/config.ts";
|
|
|
7
7
|
// executeTeamRun is only called when a team run actually executes.
|
|
8
8
|
import type { executeTeamRun as _executeTeamRunFn } from "../runtime/team-runner.ts";
|
|
9
9
|
import type { TeamToolParamsValue } from "../schema/team-tool-schema.ts";
|
|
10
|
-
import { writeArtifact } from "../state/artifact-store.ts";
|
|
11
10
|
import { TEAM_TERMINAL_TASK_STATUSES } from "../state/contracts.ts";
|
|
12
|
-
import {
|
|
13
|
-
import {
|
|
14
|
-
import {
|
|
15
|
-
import {
|
|
11
|
+
import { withRunLock } from "../state/coordination/locks.ts";
|
|
12
|
+
import { replayPendingMailboxMessages } from "../state/coordination/mailbox.ts";
|
|
13
|
+
import { appendEvent, appendEventFireAndForget } from "../state/event-log/event-log.ts";
|
|
14
|
+
import { writeArtifact } from "../state/stores/artifact-store.ts";
|
|
15
|
+
import { loadRunManifestById, saveRunManifestAsync, saveRunTasks, updateRunStatus } from "../state/stores/state-store.ts";
|
|
16
16
|
import type { ArtifactDescriptor, TeamRunManifest, TeamTaskState } from "../state/types.ts";
|
|
17
17
|
import { allTeams, discoverTeams } from "../teams/discover-teams.ts";
|
|
18
18
|
import { resolveRealContainedPath } from "../utils/safe-paths.ts";
|
|
@@ -32,8 +32,8 @@ async function executeTeamRun(...args: Parameters<ExecuteTeamRunFn>): Promise<Aw
|
|
|
32
32
|
}
|
|
33
33
|
|
|
34
34
|
import { directTeamAndWorkflowFromRun } from "../runtime/direct-run.ts";
|
|
35
|
-
import {
|
|
36
|
-
import {
|
|
35
|
+
import { resolveCrewRuntime, runtimeResolutionState } from "../runtime/model/runtime-resolver.ts";
|
|
36
|
+
import { parsePiJsonOutput } from "../runtime/output/pi-json-output.ts";
|
|
37
37
|
import { effectiveRunConfig } from "./team-tool/config-patch.ts";
|
|
38
38
|
import { buildParentContext, formatScoped, result, type TeamContext } from "./team-tool/context.ts";
|
|
39
39
|
// Lazy-loaded: run.ts pulls in spawnBackgroundTeamRun, resolveCrewRuntime, etc.
|
|
@@ -51,6 +51,7 @@ async function handleRun(...args: Parameters<HandleRunFn>): Promise<Awaited<Retu
|
|
|
51
51
|
return _cachedHandleRun(...args);
|
|
52
52
|
}
|
|
53
53
|
|
|
54
|
+
import { t } from "../i18n.ts";
|
|
54
55
|
import { waitForRun } from "../runtime/run-tracker.ts";
|
|
55
56
|
import { normalizeSkillOverride } from "../runtime/skill-instructions.ts";
|
|
56
57
|
import { formatActionSuggestion } from "./action-suggestions.ts";
|
|
@@ -638,10 +639,9 @@ export async function handleTeamTool(params: TeamToolParamsValue, ctx: TeamConte
|
|
|
638
639
|
return handleManageDomain(params, ctx);
|
|
639
640
|
case "automate":
|
|
640
641
|
return handleAutomateDomain(params, ctx);
|
|
641
|
-
case undefined:
|
|
642
642
|
default:
|
|
643
643
|
return result(
|
|
644
|
-
|
|
644
|
+
t("team.unknownAction", { action: String(action) }) + formatActionSuggestion(String(action)),
|
|
645
645
|
{ action: "unknown", status: "error" },
|
|
646
646
|
true,
|
|
647
647
|
);
|
|
@@ -649,11 +649,15 @@ export async function handleTeamTool(params: TeamToolParamsValue, ctx: TeamConte
|
|
|
649
649
|
}
|
|
650
650
|
|
|
651
651
|
/**
|
|
652
|
-
*
|
|
653
|
-
*
|
|
654
|
-
*
|
|
652
|
+
* Module-scoped RPC registry for access to pi-crew's team orchestrator.
|
|
653
|
+
*
|
|
654
|
+
* EXT-9: Previously this used a `globalThis[Symbol.for("pi-crew:registry")]`
|
|
655
|
+
* singleton — fragile (cross-realm, no lifecycle, peer extensions could
|
|
656
|
+
* read/overwrite it). It is now a module-level variable: exactly one instance
|
|
657
|
+
* per extension load (one per pi session), invisible to peer extensions.
|
|
658
|
+
* Cross-extension consumers should use the `pi.events` RPC channel
|
|
659
|
+
* (`registerPiCrewRpc`) instead of poking globalThis.
|
|
655
660
|
*/
|
|
656
|
-
const CREW_REGISTRY_KEY = Symbol.for("pi-crew:registry");
|
|
657
661
|
interface CrewRegistry {
|
|
658
662
|
version: 2;
|
|
659
663
|
getRecord: (runId: string) => TeamRunManifest | undefined;
|
|
@@ -674,13 +678,16 @@ interface CrewRegistry {
|
|
|
674
678
|
// discovery results with highest priority. The CrewRegistry interface exposes
|
|
675
679
|
// registerAgent/unregisterAgent/listDynamicAgents for cross-extension access.
|
|
676
680
|
|
|
681
|
+
// Module-scoped singleton instance — one per extension load (EXT-9).
|
|
682
|
+
let crewRegistryInstance: CrewRegistry | undefined;
|
|
683
|
+
|
|
677
684
|
export function registerCrewGlobalRegistry(registry: CrewRegistry): void {
|
|
678
|
-
|
|
685
|
+
crewRegistryInstance = registry;
|
|
679
686
|
}
|
|
680
687
|
|
|
681
|
-
/** @internal */
|
|
682
|
-
function getCrewGlobalRegistry(): CrewRegistry | undefined {
|
|
683
|
-
return
|
|
688
|
+
/** @internal — exported for lifecycle tests. */
|
|
689
|
+
export function getCrewGlobalRegistry(): CrewRegistry | undefined {
|
|
690
|
+
return crewRegistryInstance;
|
|
684
691
|
}
|
|
685
692
|
|
|
686
693
|
/** Manifest cache shape needed to construct the global registry's read-side. */
|
|
@@ -744,7 +751,7 @@ export function installCrewGlobalRegistry(deps?: { manifestCache: ManifestCacheF
|
|
|
744
751
|
registerCrewGlobalRegistry(registry);
|
|
745
752
|
}
|
|
746
753
|
|
|
747
|
-
/** Remove the
|
|
754
|
+
/** Remove the CrewRegistry singleton. Call during session cleanup. */
|
|
748
755
|
export function uninstallCrewGlobalRegistry(): void {
|
|
749
|
-
|
|
756
|
+
crewRegistryInstance = undefined;
|
|
750
757
|
}
|
package/src/hooks/registry.ts
CHANGED
|
@@ -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 { runEventBus } from "../ui/run-event-bus.ts";
|
|
4
4
|
import type { HookContext, HookDefinition, HookExecutionReport, HookName, HookResult } from "./types.ts";
|
package/src/i18n.ts
CHANGED
|
@@ -24,6 +24,13 @@ const fallback = {
|
|
|
24
24
|
"steer.noted": "Steering request noted for {id}.",
|
|
25
25
|
"steer.unavailable": "Current default pi-crew backend is child-process, so mid-turn session.steer is not available yet.",
|
|
26
26
|
"steer.cancelHint": "Use team cancel runId={runId} if the agent must be interrupted.",
|
|
27
|
+
// PR-F12 (EXT-12): team tool user-facing strings routed through t() for
|
|
28
|
+
// consistency with the subagent tools (Agent / get_subagent_result).
|
|
29
|
+
"team.run.created": "Created pi-crew run {runId}.",
|
|
30
|
+
"team.run.completed": "pi-crew run {status}: {runId} ({team})",
|
|
31
|
+
"team.run.allCompleted": "All tasks completed successfully.",
|
|
32
|
+
"team.run.tasksFailed": "{count} task(s) failed: {ids}. Consider retrying.",
|
|
33
|
+
"team.unknownAction": "Unknown action: {action}",
|
|
27
34
|
} as const;
|
|
28
35
|
|
|
29
36
|
type Key = keyof typeof fallback;
|
|
@@ -50,6 +57,11 @@ const translations: Record<string, Partial<Record<Key, string>>> = {
|
|
|
50
57
|
"steer.unavailable":
|
|
51
58
|
"El backend predeterminado actual de pi-crew es child-process, así que session.steer a mitad de turno aún no está disponible.",
|
|
52
59
|
"steer.cancelHint": "Usa team cancel runId={runId} si hay que interrumpir el agente.",
|
|
60
|
+
"team.run.created": "Ejecución de pi-crew creada {runId}.",
|
|
61
|
+
"team.run.completed": "Ejecución de pi-crew {status}: {runId} ({team})",
|
|
62
|
+
"team.run.allCompleted": "Todas las tareas se completaron con éxito.",
|
|
63
|
+
"team.run.tasksFailed": "{count} tarea(s) fallaron: {ids}. Considera reintentar.",
|
|
64
|
+
"team.unknownAction": "Acción desconocida: {action}",
|
|
53
65
|
},
|
|
54
66
|
fr: {
|
|
55
67
|
"agent.requiresPrompt": "Agent nécessite un prompt.",
|
|
@@ -71,6 +83,11 @@ const translations: Record<string, Partial<Record<Key, string>>> = {
|
|
|
71
83
|
"steer.unavailable":
|
|
72
84
|
"Le backend pi-crew par défaut actuel est child-process, donc session.steer en milieu de tour n'est pas encore disponible.",
|
|
73
85
|
"steer.cancelHint": "Utilisez team cancel runId={runId} si l'agent doit être interrompu.",
|
|
86
|
+
"team.run.created": "Exécution pi-crew créée {runId}.",
|
|
87
|
+
"team.run.completed": "Exécution pi-crew {status} : {runId} ({team})",
|
|
88
|
+
"team.run.allCompleted": "Toutes les tâches ont été effectuées avec succès.",
|
|
89
|
+
"team.run.tasksFailed": "{count} tâche(s) ont échoué : {ids}. Envisagez de réessayer.",
|
|
90
|
+
"team.unknownAction": "Action inconnue : {action}",
|
|
74
91
|
},
|
|
75
92
|
"pt-BR": {
|
|
76
93
|
"agent.requiresPrompt": "Agent requer prompt.",
|
|
@@ -92,6 +109,11 @@ const translations: Record<string, Partial<Record<Key, string>>> = {
|
|
|
92
109
|
"steer.unavailable":
|
|
93
110
|
"O backend padrão atual do pi-crew é child-process, então session.steer no meio do turno ainda não está disponível.",
|
|
94
111
|
"steer.cancelHint": "Use team cancel runId={runId} se o agente precisar ser interrompido.",
|
|
112
|
+
"team.run.created": "Execução do pi-crew criada {runId}.",
|
|
113
|
+
"team.run.completed": "Execução do pi-crew {status}: {runId} ({team})",
|
|
114
|
+
"team.run.allCompleted": "Todas as tarefas foram concluídas com sucesso.",
|
|
115
|
+
"team.run.tasksFailed": "{count} tarefa(s) falharam: {ids}. Considere tentar novamente.",
|
|
116
|
+
"team.unknownAction": "Ação desconhecida: {action}",
|
|
95
117
|
},
|
|
96
118
|
};
|
|
97
119
|
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { AgentProgress } from "../runtime/progress-tracker.ts";
|
|
1
|
+
import type { AgentProgress } from "../runtime/output/progress-tracker.ts";
|
|
2
2
|
import { logInternalError } from "../utils/internal-error.ts";
|
|
3
3
|
|
|
4
4
|
export type CrewEventType = "agent:progress" | "agent:complete" | "agent:error" | "run:start" | "run:complete";
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import * as fs from "node:fs";
|
|
2
2
|
import * as path from "node:path";
|
|
3
3
|
import type { ExtensionAPI } from "@earendil-works/pi-coding-agent";
|
|
4
|
-
import { startChildBrokerClient } from "../runtime/crew-broker-child.ts";
|
|
4
|
+
import { startChildBrokerClient } from "../runtime/broker/crew-broker-child.ts";
|
|
5
5
|
import { logInternalError } from "../utils/internal-error.ts";
|
|
6
6
|
import { resolveRealContainedPath } from "../utils/safe-paths.ts";
|
|
7
7
|
|
|
@@ -362,7 +362,7 @@ export default function registerPiTeamsPromptRuntime(pi: ExtensionAPI): void {
|
|
|
362
362
|
// already .unref()'d so it never blocks event-loop exit; errors are
|
|
363
363
|
// swallowed because teardown failures during shutdown are harmless.
|
|
364
364
|
pi.on("session_shutdown", () => {
|
|
365
|
-
void brokerHandle.close().catch(() =>
|
|
365
|
+
void brokerHandle.close().catch(() => undefined);
|
|
366
366
|
});
|
|
367
367
|
|
|
368
368
|
// ── Prompt rewriting (existing) ────────────────────────────────────────
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
# src/runtime/ — runtime cluster map
|
|
2
|
+
|
|
3
|
+
This directory holds the team-run execution machinery. After the v0.9.x reorg, the largest
|
|
4
|
+
clusters are extracted into subdirectories; the remaining files stay at the root.
|
|
5
|
+
|
|
6
|
+
## Extracted subdirectories (navigable clusters)
|
|
7
|
+
|
|
8
|
+
| Subdir | Phase | Cluster | Key files |
|
|
9
|
+
|--------|-------|---------|-----------|
|
|
10
|
+
| [`child-pi/`](./child-pi/) | B-1 | child Pi worker spawn/lifecycle/steering/transcript | `child-pi.ts`, `child-pi-spawn.ts`, `child-pi-kill.ts`, `child-pi-constants.ts`, `child-pi-steering.ts`, `child-pi-streams.ts`, `child-pi-transcript.ts`, `child-pi-pool.ts` |
|
|
11
|
+
| [`broker/`](./broker/) | B-2 | crew broker server/client/auth (child-pi ↔ parent IPC) | `crew-broker.ts`, `crew-broker-client.ts`, `crew-broker-child.ts`, `crew-broker-tokens.ts`, `broker-issuer.ts` |
|
|
12
|
+
| [`task-runner/`](./task-runner/) | (pre-existing) | per-task execution (pre-execution, child-executor) | `child-executor.ts`, `pre-execution.ts`, ... |
|
|
13
|
+
| [`live-session/`](./live-session/) | 3 | live agent control/manager, session runtime, IRC, health, extension bridge | `live-session-runtime.ts`, `live-agent-manager.ts`, `live-agent-control.ts`, `live-control-realtime.ts`, `live-irc.ts`, `live-session-health.ts`, `live-extension-bridge.ts`, `intercom-bridge.ts` |
|
|
14
|
+
| [`recovery/`](./recovery/) | 4 | crash recovery, retry, checkpoint | `crash-recovery.ts`, `crash-classification.ts`, `recovery-recipes.ts`, `overflow-recovery.ts`, `retry-executor.ts`, `retry-runner.ts`, `checkpoint.ts` |
|
|
15
|
+
| [`scheduling/`](./scheduling/) | 5 | scheduler, concurrency, task-graph, batch-barrier, parallel utils | `scheduler.ts`, `semaphore.ts`, `concurrency.ts`, `task-graph.ts`, `task-graph-scheduler.ts`, `batch-barrier.ts`, `coalesce-tasks.ts`, `run-coalesced-task-group.ts`, `global-worker-cap.ts`, `parallel-research.ts`, `parallel-utils.ts` |
|
|
16
|
+
| [`verification/`](./verification/) | 6a | verification gates, green-contract, post-checks, completion-guard | `verification-gates.ts`, `verification-integrity.ts`, `verification-worktree.ts`, `green-contract.ts`, `post-checks.ts`, `completion-guard.ts` |
|
|
17
|
+
| [`model/`](./model/) | 6b | model fallback/resolver/scope, pi-args, runtime policy/resolver/warmup | `model-fallback.ts`, `model-resolver.ts`, `model-scope.ts`, `pi-args.ts`, `runtime-policy.ts`, `runtime-resolver.ts`, `runtime-warmup.ts` |
|
|
18
|
+
| [`output/`](./output/) | 6c | streaming output, progress tracking, sidechain, result extraction | `streaming-output.ts`, `stream-preview.ts`, `output-validator.ts`, `pi-json-output.ts`, `tool-progress.ts`, `progress-event-coalescer.ts`, `progress-tracker.ts`, `result-extractor.ts`, `sidechain-output.ts` |
|
|
19
|
+
| [`heartbeat/`](./heartbeat/) | 6d | heartbeat gradient/watcher, worker heartbeat/startup | `heartbeat-gradient.ts`, `heartbeat-watcher.ts`, `worker-heartbeat.ts`, `worker-startup.ts` |
|
|
20
|
+
| [`process/`](./process/) | 6e | cancellation, process lifecycle, zombie scanner, stdio guard | `cancellation-token.ts`, `cancellation.ts`, `process-lifecycle.ts`, `zombie-scanner.ts`, `post-exit-stdio-guard.ts` |
|
|
21
|
+
| [`goal-workflow/`](./goal-workflow/) | 6f | goal achievement/evaluation/loop, dynamic-workflow, adaptive plan | `goal-achievement.ts`, `goal-evaluator.ts`, `goal-loop-runner.ts`, `goal-state-store.ts`, `dynamic-workflow-context.ts`, `dynamic-workflow-runner.ts`, `adaptive-plan.ts`, `plan-templates.ts` |
|
|
22
|
+
| [`compaction/`](./compaction/) | 6g | compaction pipeline, tool-output-pruner, important-line-classifier, compact-stages | `compact-pipeline.ts`, `compaction-summary.ts`, `tool-output-pruner.ts`, `important-line-classifier.ts`, [`compact-stages/`](./compaction/compact-stages/) |
|
|
23
|
+
| [`custom-tools/`](./custom-tools/) | (pre-existing) | custom tool definitions | `irc-tool.ts`, `submit-result-tool.ts`, ... |
|
|
24
|
+
| [`errors/`](./errors/) | (pre-existing) | error types | ... |
|
|
25
|
+
|
|
26
|
+
## Remaining flat files at root (~77)
|
|
27
|
+
|
|
28
|
+
- **team-runner** — `team-runner.ts` (the orchestrator) + `run-worker.ts`, `run-tracker.ts`
|
|
29
|
+
- **chain/pipeline runners** — `chain-parser.ts`, `chain-runner.ts`, `pipeline-runner.ts`, `direct-run.ts`
|
|
30
|
+
- **foreground/background runners** — `foreground-control.ts`, `foreground-watchdog.ts`, `async-runner.ts`, `background-runner.ts`
|
|
31
|
+
- **crew agent** — `crew-agent-records.ts`, `crew-agent-runtime.ts`, `crew-hooks.ts`, `single-agent-compose.ts`
|
|
32
|
+
- **observability** — `effectiveness.ts`, `agent-observability.ts`, `command-trace.ts`, `metric-parser.ts`
|
|
33
|
+
- **misc** — `stale-reconciler.ts`, `parent-guard.ts`, `manifest-cache.ts`, `event-stream-bridge.ts`, `policy-engine.ts`, `role-permission.ts`, `workspace-lock.ts`, `workspace-tree.ts`, `session-*.ts`, ...
|
|
34
|
+
|
|
35
|
+
See `docs/COVERAGE-ASSESSMENT-2026-08-01.md` § "Source reorganization" for the reorg history + remaining-cluster plan.
|
|
@@ -32,7 +32,7 @@ export function resolveCrewControlConfig(config: PiTeamsConfig | undefined): Cre
|
|
|
32
32
|
})
|
|
33
33
|
| undefined;
|
|
34
34
|
return {
|
|
35
|
-
enabled: raw?.control?.enabled
|
|
35
|
+
enabled: raw?.control?.enabled !== false,
|
|
36
36
|
needsAttentionAfterMs: positiveInt(raw?.control?.needsAttentionAfterMs) ?? DEFAULT_NEEDS_ATTENTION_MS,
|
|
37
37
|
consecutiveFailureThreshold: positiveInt(raw?.control?.consecutiveFailureThreshold) ?? DEFAULT_CONSECUTIVE_FAILURE_THRESHOLD,
|
|
38
38
|
longRunningMinutes: positiveInt(raw?.control?.longRunningMinutes) ?? DEFAULT_LONG_RUNNING_MINUTES,
|
|
@@ -16,8 +16,6 @@ const MAX_HANDOFFS_PER_ANCHOR = 100;
|
|
|
16
16
|
* - accumulateHandoff() adds handoffs to the anchor
|
|
17
17
|
* - clearAnchor() finalizes and returns accumulated summaries
|
|
18
18
|
* - getAnchorHandoff() retrieves accumulated summary without clearing
|
|
19
|
-
*
|
|
20
|
-
* @see docs/pi-boomerang-integration-plan.md
|
|
21
19
|
*/
|
|
22
20
|
|
|
23
21
|
import type { HandoffSummary } from "./handoff-manager.ts";
|
|
@@ -3,7 +3,7 @@ import * as fs from "node:fs";
|
|
|
3
3
|
import { createRequire } from "node:module";
|
|
4
4
|
import * as path from "node:path";
|
|
5
5
|
import { fileURLToPath, pathToFileURL } from "node:url";
|
|
6
|
-
import { appendEventAsync } from "../state/event-log.ts";
|
|
6
|
+
import { appendEventAsync } from "../state/event-log/event-log.ts";
|
|
7
7
|
import type { TeamRunManifest } from "../state/types.ts";
|
|
8
8
|
import { WINDOWS_ESSENTIAL_ENV_VARS } from "../utils/env-allowlist.ts";
|
|
9
9
|
import { sanitizeEnvSecrets } from "../utils/env-filter.ts";
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { appendEvent, type TeamEvent } from "../state/event-log.ts";
|
|
1
|
+
import { appendEvent, type TeamEvent } from "../state/event-log/event-log.ts";
|
|
2
2
|
import type { CrewAttentionEventData, TeamRunManifest } from "../state/types.ts";
|
|
3
3
|
import { readJsonlTail } from "../utils/incremental-reader.ts";
|
|
4
4
|
|
|
@@ -5,8 +5,6 @@
|
|
|
5
5
|
* - toggle() enables/disables auto-summarization
|
|
6
6
|
* - shouldAutoSummarize() checks if task should auto-summarize
|
|
7
7
|
* - Token and tool thresholds control when summarization triggers
|
|
8
|
-
*
|
|
9
|
-
* @see docs/pi-boomerang-integration-plan.md
|
|
10
8
|
*/
|
|
11
9
|
|
|
12
10
|
import type { TaskPacket, TaskResult } from "./handoff-manager.ts";
|
|
@@ -3,9 +3,9 @@ import * as path from "node:path";
|
|
|
3
3
|
import { allAgents, discoverAgents } from "../agents/discover-agents.ts";
|
|
4
4
|
import { loadConfig } from "../config/config.ts";
|
|
5
5
|
import { atomicWriteFile } from "../state/atomic-write.ts";
|
|
6
|
-
import {
|
|
7
|
-
import {
|
|
8
|
-
import { createRunPaths, loadRunManifestById, saveRunManifestAsync, updateRunStatus } from "../state/state-store.ts";
|
|
6
|
+
import { withRunLockSync } from "../state/coordination/locks.ts";
|
|
7
|
+
import { appendEvent, appendEventFireAndForget } from "../state/event-log/event-log.ts";
|
|
8
|
+
import { createRunPaths, loadRunManifestById, saveRunManifestAsync, updateRunStatus } from "../state/stores/state-store.ts";
|
|
9
9
|
import type { TeamRunManifest, TeamTaskState } from "../state/types.ts";
|
|
10
10
|
import { allTeams, discoverTeams } from "../teams/discover-teams.ts";
|
|
11
11
|
import { errorMessage } from "../utils/guards.ts";
|
|
@@ -35,7 +35,7 @@ async function executeTeamRun(...args: Parameters<typeof ExecuteTeamRunFn>): Pro
|
|
|
35
35
|
// FIX (split-scope install): prime the ESM peer dep BEFORE team-runner is
|
|
36
36
|
// imported, so its transitive skill-instructions.ts can read getAgentDir()
|
|
37
37
|
// from the primed cache instead of crashing on `Cannot find module`.
|
|
38
|
-
await primePeerDep().catch(() =>
|
|
38
|
+
await primePeerDep().catch(() => undefined);
|
|
39
39
|
// LAZY: avoid pulling team-runner into background-runner at module load time.
|
|
40
40
|
const mod = await import("./team-runner.ts");
|
|
41
41
|
_cachedExecuteTeamRun = mod.executeTeamRun;
|
|
@@ -45,12 +45,12 @@ async function executeTeamRun(...args: Parameters<typeof ExecuteTeamRunFn>): Pro
|
|
|
45
45
|
|
|
46
46
|
import { logInternalError } from "../utils/internal-error.ts";
|
|
47
47
|
import { writeAsyncStartMarker } from "./async-marker.ts";
|
|
48
|
-
import { terminateActiveChildPiProcesses } from "./child-pi.ts";
|
|
48
|
+
import { terminateActiveChildPiProcesses } from "./child-pi/child-pi.ts";
|
|
49
49
|
import { directTeamAndWorkflowFromRun } from "./direct-run.ts";
|
|
50
|
+
import { resolveCrewRuntime, runtimeResolutionState } from "./model/runtime-resolver.ts";
|
|
50
51
|
import { unregisterWorker } from "./orphan-worker-registry.ts";
|
|
51
|
-
import { expandParallelResearchWorkflow } from "./parallel-research.ts";
|
|
52
52
|
import { startParentGuard, stopParentGuard } from "./parent-guard.ts";
|
|
53
|
-
import {
|
|
53
|
+
import { expandParallelResearchWorkflow } from "./scheduling/parallel-research.ts";
|
|
54
54
|
|
|
55
55
|
/**
|
|
56
56
|
* Debug logger gated behind PI_CREW_DEBUG env var. Writes to background.log
|
|
@@ -110,7 +110,47 @@ function argValue(name: string): string | undefined {
|
|
|
110
110
|
return process.argv[index + 1];
|
|
111
111
|
}
|
|
112
112
|
|
|
113
|
-
|
|
113
|
+
/**
|
|
114
|
+
* Fire-and-forget event log for signal handlers. Extracted to module level
|
|
115
|
+
* (from inside main()) so the exported SIGINT handler installer (test seam)
|
|
116
|
+
* and the inline signal-handler loop inside main() can both use it.
|
|
117
|
+
* Pure function of its arguments — no closure captures from main().
|
|
118
|
+
*/
|
|
119
|
+
function signalLog(sig: string, eventsPath: string): void {
|
|
120
|
+
const runId = argValue("--run-id");
|
|
121
|
+
if (runId && eventsPath) {
|
|
122
|
+
appendEventFireAndForget(eventsPath, {
|
|
123
|
+
type: "async.failed",
|
|
124
|
+
runId,
|
|
125
|
+
message: `Background runner received ${sig} — exiting.`,
|
|
126
|
+
data: { signal: sig, pid: process.pid },
|
|
127
|
+
});
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
/**
|
|
132
|
+
* RT-2 SIGINT handler installer — exported as a test seam so integration tests
|
|
133
|
+
* can exercise the REAL handler logic (process.exitCode = 130, NOT
|
|
134
|
+
* process.exit(130)) without re-implementing it in a harness copy.
|
|
135
|
+
*
|
|
136
|
+
* Behavior is IDENTICAL to the previous inline handler in main() — pure
|
|
137
|
+
* extraction, zero logic change.
|
|
138
|
+
*/
|
|
139
|
+
export function installBackgroundRunnerSigintHandler(abortController: AbortController, eventsPath: string): void {
|
|
140
|
+
process.on("SIGINT", () => {
|
|
141
|
+
signalLog("SIGINT", eventsPath);
|
|
142
|
+
// RT-2 FIX: Mirror the CORE-7 pattern at the interrupt guard (:146-151).
|
|
143
|
+
// Do NOT call process.exit(130) — it bypasses the finally/runCleanup block
|
|
144
|
+
// in main(), orphaning child-pi workers (they have no parent-guard, see
|
|
145
|
+
// RT-19). Setting exitCode lets the event loop drain naturally so main()'s
|
|
146
|
+
// finally block runs terminateActiveChildPiProcesses + unregisterWorker.
|
|
147
|
+
abortController.abort();
|
|
148
|
+
stopParentGuard();
|
|
149
|
+
process.exitCode = 130;
|
|
150
|
+
});
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
export function startInterruptGuard(
|
|
114
154
|
manifest: { runId: string; stateRoot: string; eventsPath: string },
|
|
115
155
|
abortController: AbortController,
|
|
116
156
|
stopParentGuard: () => void,
|
|
@@ -119,6 +159,13 @@ function startInterruptGuard(
|
|
|
119
159
|
// FIX: Made configurable via PI_CREW_INTERRUPT_GUARD_INTERVAL_MS env var.
|
|
120
160
|
// Default 250ms balances fast SIGINT response against filesystem overhead.
|
|
121
161
|
const interruptGuardInterval = Number(process.env.PI_CREW_INTERRUPT_GUARD_INTERVAL_MS) || 250;
|
|
162
|
+
// RT-4 FIX: Module-local gate so the interrupt body runs only once per
|
|
163
|
+
// interrupt request. Without this, the guard re-fires every
|
|
164
|
+
// interruptGuardInterval (250ms) — each tick does a full
|
|
165
|
+
// terminateActiveChildPiProcesses sweep + sync appendEvent = ~4×/s steady
|
|
166
|
+
// state. The ack write stops the re-fire; this gate is defense-in-depth if
|
|
167
|
+
// the ack write fails (e.g. transient fs error).
|
|
168
|
+
let interruptHandled = false;
|
|
122
169
|
const interval = setInterval(() => {
|
|
123
170
|
try {
|
|
124
171
|
if (!fs.existsSync(controlPath)) return;
|
|
@@ -127,6 +174,25 @@ function startInterruptGuard(
|
|
|
127
174
|
};
|
|
128
175
|
const last = parsed.requests?.at(-1);
|
|
129
176
|
if (last?.type === "interrupt" && last?.acknowledged !== true) {
|
|
177
|
+
// RT-4 FIX: Gate ensures the interrupt body runs only once even if
|
|
178
|
+
// the synchronous ack write below fails.
|
|
179
|
+
if (interruptHandled) return;
|
|
180
|
+
interruptHandled = true;
|
|
181
|
+
|
|
182
|
+
// RT-4 FIX: Write acknowledged:true back to foreground-control.json
|
|
183
|
+
// SYNCHRONOUSLY. This stops the guard from re-firing on the next tick
|
|
184
|
+
// (250ms). Must be sync because this is a setInterval polling callback
|
|
185
|
+
// — we cannot await in a polling callback.
|
|
186
|
+
try {
|
|
187
|
+
const reqs = parsed.requests ?? [];
|
|
188
|
+
if (reqs.length > 0) {
|
|
189
|
+
reqs[reqs.length - 1].acknowledged = true;
|
|
190
|
+
atomicWriteFile(controlPath, JSON.stringify(parsed, null, 2));
|
|
191
|
+
}
|
|
192
|
+
} catch {
|
|
193
|
+
/* best-effort ack — interruptHandled gate prevents re-fire */
|
|
194
|
+
}
|
|
195
|
+
|
|
130
196
|
appendEvent(manifest.eventsPath, {
|
|
131
197
|
type: "async.interrupt_detected",
|
|
132
198
|
runId: manifest.runId,
|
|
@@ -335,19 +401,8 @@ async function main(): Promise<void> {
|
|
|
335
401
|
|
|
336
402
|
// Scrub macOS malloc vars BEFORE anything else — must be clean for all child processes
|
|
337
403
|
scrubProcessEnv();
|
|
338
|
-
//
|
|
339
|
-
//
|
|
340
|
-
const signalLog = (sig: string, eventsPath: string): void => {
|
|
341
|
-
const runId = argValue("--run-id");
|
|
342
|
-
if (runId && eventsPath) {
|
|
343
|
-
appendEvent(eventsPath, {
|
|
344
|
-
type: "async.failed",
|
|
345
|
-
runId,
|
|
346
|
-
message: `Background runner received ${sig} — exiting.`,
|
|
347
|
-
data: { signal: sig, pid: process.pid },
|
|
348
|
-
});
|
|
349
|
-
}
|
|
350
|
-
};
|
|
404
|
+
// signalLog is now defined at module level (shared by the exported SIGINT
|
|
405
|
+
// handler installer and the inline signal-handler loop below).
|
|
351
406
|
// BUG #17 FIX: Compute exitCodePath at module load time using args,
|
|
352
407
|
// NOT by referencing `manifest` (declared inside main() and not in scope at module load).
|
|
353
408
|
const exitCodePath = ((): string | undefined => {
|
|
@@ -422,10 +477,7 @@ async function main(): Promise<void> {
|
|
|
422
477
|
// Trigger graceful shutdown via abort signal so finally block runs
|
|
423
478
|
abortController.abort();
|
|
424
479
|
});
|
|
425
|
-
|
|
426
|
-
signalLog("SIGINT", manifest.eventsPath);
|
|
427
|
-
process.exit(130);
|
|
428
|
-
});
|
|
480
|
+
installBackgroundRunnerSigintHandler(abortController, manifest.eventsPath);
|
|
429
481
|
// BUG #17: Catch ALL signals to identify what kills the background runner
|
|
430
482
|
for (const sig of [
|
|
431
483
|
"SIGHUP",
|
|
@@ -527,7 +579,7 @@ async function main(): Promise<void> {
|
|
|
527
579
|
// compilation of team-runner.ts, the event loop must not drain prematurely.
|
|
528
580
|
// The interval is always cleared in the finally block, so the delay is
|
|
529
581
|
// bounded by the 5s interval. The event loop exit is deferred at most 5s.
|
|
530
|
-
const keepAlive = setInterval(() =>
|
|
582
|
+
const keepAlive = setInterval(() => undefined, 5000);
|
|
531
583
|
|
|
532
584
|
// WATCHDOG (anti-zombie): if the run exceeds MAX_BACKGROUND_RUN_MS without
|
|
533
585
|
// completing, abort it and force-exit. Without this, a hung team run
|
|
@@ -598,9 +650,9 @@ async function main(): Promise<void> {
|
|
|
598
650
|
debugLog(`[background-runner] short-circuiting ${manifest.runKind} (synthetic team/workflow)`);
|
|
599
651
|
if (manifest.runKind === "goal-loop") {
|
|
600
652
|
// LAZY: defer dynamic import of ./goal-loop-runner.ts to its call site.
|
|
601
|
-
const { runGoalLoop } = await import("./goal-loop-runner.ts");
|
|
653
|
+
const { runGoalLoop } = await import("./goal-workflow/goal-loop-runner.ts");
|
|
602
654
|
// LAZY: defer dynamic import of ./goal-state-store.ts to its call site.
|
|
603
|
-
const { GoalStore } = await import("./goal-state-store.ts");
|
|
655
|
+
const { GoalStore } = await import("./goal-workflow/goal-state-store.ts");
|
|
604
656
|
// LAZY: defer dynamic import of ../agents/discover-agents.ts to its call site.
|
|
605
657
|
const { discoverAgents, allAgents } = await import("../agents/discover-agents.ts");
|
|
606
658
|
const store = new GoalStore(manifest.cwd);
|
|
@@ -639,7 +691,7 @@ async function main(): Promise<void> {
|
|
|
639
691
|
};
|
|
640
692
|
} else {
|
|
641
693
|
// LAZY: defer dynamic import of ./dynamic-workflow-runner.ts to its call site.
|
|
642
|
-
const { runDynamicWorkflow } = await import("./dynamic-workflow-runner.ts");
|
|
694
|
+
const { runDynamicWorkflow } = await import("./goal-workflow/dynamic-workflow-runner.ts");
|
|
643
695
|
// LAZY: defer dynamic import of ../workflows/discover-workflows.ts to its call site.
|
|
644
696
|
const { allWorkflows, discoverWorkflows } = await import("../workflows/discover-workflows.ts");
|
|
645
697
|
const wf = allWorkflows(discoverWorkflows(manifest.cwd)).find((w) => w.name === manifest.workflow);
|
|
@@ -774,7 +826,7 @@ async function main(): Promise<void> {
|
|
|
774
826
|
const manifestToUse = loaded?.manifest ?? manifest;
|
|
775
827
|
if (manifestToUse) {
|
|
776
828
|
// LAZY: live-agent-manager only needed on failure cleanup path; avoid module load at hot path.
|
|
777
|
-
const { terminateLiveAgentsForRun } = await import("./live-agent-manager.ts");
|
|
829
|
+
const { terminateLiveAgentsForRun } = await import("./live-session/live-agent-manager.ts");
|
|
778
830
|
void terminateLiveAgentsForRun(manifestToUse.runId, "failed", appendEvent, manifestToUse.eventsPath).catch((error) =>
|
|
779
831
|
logInternalError("background-runner.terminate", error, `runId=${manifestToUse.runId}`),
|
|
780
832
|
);
|
|
@@ -832,6 +884,27 @@ try {
|
|
|
832
884
|
// called process.exit(1) directly, bypassing the finally block and leaving
|
|
833
885
|
// orphaned child processes.
|
|
834
886
|
exitDueToRejection = true;
|
|
887
|
+
// RT-3 FIX: Startup failures (lock-fail, missing manifest, pre-try throws)
|
|
888
|
+
// previously wrote NO event and left exitCode at 0. The run stayed 'queued'
|
|
889
|
+
// until the stale reconciler reaped it. Now write async.failed so the
|
|
890
|
+
// notifier/foreground detects the failure immediately, and set exitCode=1
|
|
891
|
+
// so the process exits non-zero.
|
|
892
|
+
try {
|
|
893
|
+
const mCwd = argValue("--cwd");
|
|
894
|
+
const mRunId = argValue("--run-id");
|
|
895
|
+
if (mCwd && mRunId) {
|
|
896
|
+
const mEventsPath = createRunPaths(mCwd, mRunId).eventsPath;
|
|
897
|
+
appendEvent(mEventsPath, {
|
|
898
|
+
type: "async.failed",
|
|
899
|
+
runId: mRunId,
|
|
900
|
+
message: errorMessage(err),
|
|
901
|
+
data: { stack: err instanceof Error ? err.stack : undefined },
|
|
902
|
+
});
|
|
903
|
+
}
|
|
904
|
+
} catch {
|
|
905
|
+
/* best-effort — don't let event-write failure mask the original error */
|
|
906
|
+
}
|
|
907
|
+
process.exitCode = 1;
|
|
835
908
|
// FIX: Call stopParentGuard directly here as a safety net in case the
|
|
836
909
|
// finally block (which calls runCleanup→stopParentGuard) does not complete.
|
|
837
910
|
// This ensures the parent guard is stopped in ALL exit paths: normal
|
|
@@ -41,7 +41,7 @@ export interface StartChildBrokerClientOptions {
|
|
|
41
41
|
|
|
42
42
|
const NOOP_HANDLE: ChildBrokerClientHandle = {
|
|
43
43
|
active: false,
|
|
44
|
-
close: async () =>
|
|
44
|
+
close: async () => undefined,
|
|
45
45
|
};
|
|
46
46
|
|
|
47
47
|
export function startChildBrokerClient(options: StartChildBrokerClientOptions = {}): ChildBrokerClientHandle {
|
|
@@ -75,7 +75,7 @@ export function startChildBrokerClient(options: StartChildBrokerClientOptions =
|
|
|
75
75
|
// Establish the persistent connection so the broker can push events. This
|
|
76
76
|
// is fire-and-forget: on any failure the client becomes sticky-fallback and
|
|
77
77
|
// the file-poll steering path remains fully functional.
|
|
78
|
-
void client.reconnect().catch(() =>
|
|
78
|
+
void client.reconnect().catch(() => undefined);
|
|
79
79
|
|
|
80
80
|
return {
|
|
81
81
|
get active() {
|
|
@@ -24,9 +24,9 @@
|
|
|
24
24
|
import { randomUUID } from "node:crypto";
|
|
25
25
|
import * as net from "node:net";
|
|
26
26
|
|
|
27
|
-
import { logInternalError } from "
|
|
28
|
-
import { BrokerError, encodeBrokerFrame, NdjsonDecoder } from "
|
|
29
|
-
import { redactSecretString } from "
|
|
27
|
+
import { logInternalError } from "../../utils/internal-error.ts";
|
|
28
|
+
import { BrokerError, encodeBrokerFrame, NdjsonDecoder } from "../../utils/ndjson.ts";
|
|
29
|
+
import { redactSecretString } from "../../utils/redaction.ts";
|
|
30
30
|
|
|
31
31
|
/** Shape of an unsolicited event frame pushed by the broker (mailbox.message,
|
|
32
32
|
* team.event, etc.). */
|
|
@@ -95,7 +95,6 @@ export class CrewBrokerClient {
|
|
|
95
95
|
private socket: net.Socket | null = null;
|
|
96
96
|
private decoder: NdjsonDecoder | null = null;
|
|
97
97
|
private readonly pending = new Map<string, PendingRequest>();
|
|
98
|
-
private attempts = 0;
|
|
99
98
|
/** Listeners attached to the current socket; kept for explicit close(). */
|
|
100
99
|
private readonly socketListeners: Array<{
|
|
101
100
|
event: string;
|
|
@@ -234,7 +233,6 @@ export class CrewBrokerClient {
|
|
|
234
233
|
async reconnect(): Promise<boolean> {
|
|
235
234
|
// Close the current socket if any.
|
|
236
235
|
this.teardownSocket();
|
|
237
|
-
this.attempts = 0;
|
|
238
236
|
this._mode = "unstarted";
|
|
239
237
|
const res = await this.request("ping", null);
|
|
240
238
|
return res.ok;
|
|
@@ -309,7 +307,6 @@ export class CrewBrokerClient {
|
|
|
309
307
|
if (this.closed) {
|
|
310
308
|
return { ok: false, fallback: true, errorCode: "closed" };
|
|
311
309
|
}
|
|
312
|
-
this.attempts = attempt + 1;
|
|
313
310
|
const result = await this.attemptHello(netModule);
|
|
314
311
|
if (result.ok) {
|
|
315
312
|
// Belt-and-suspenders: a successful hello can still race
|
|
@@ -460,7 +457,7 @@ export class CrewBrokerClient {
|
|
|
460
457
|
return;
|
|
461
458
|
}
|
|
462
459
|
// Hello ack: must include `result.ok === true` and matching id.
|
|
463
|
-
if (frame.id
|
|
460
|
+
if (frame.id?.startsWith("hello-")) {
|
|
464
461
|
if (frame.error) {
|
|
465
462
|
const code = (frame.error as { code?: string }).code ?? "auth";
|
|
466
463
|
finish({ ok: false, fallback: true, errorCode: code });
|