pi-crew 0.2.3 → 0.2.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/AGENTS.md +57 -32
- package/CHANGELOG.md +466 -448
- package/LICENSE +21 -21
- package/NOTICE.md +16 -16
- package/README.md +323 -323
- package/docs/FEATURE_INTAKE.md +126 -0
- package/docs/HARNESS.md +86 -0
- package/docs/HARNESS_BACKLOG.md +41 -0
- package/docs/TEST_MATRIX.md +49 -0
- package/docs/actions-reference.md +595 -595
- package/docs/architecture.md +180 -180
- package/docs/code-review-2026-05-11.md +592 -592
- package/docs/commands-reference.md +347 -347
- package/docs/comparison-pi-subagents-vs-pi-crew.md +303 -0
- package/docs/decisions/0001-durable-state.md +41 -0
- package/docs/decisions/0002-child-process-for-async.md +42 -0
- package/docs/decisions/0003-depth-guard.md +36 -0
- package/docs/decisions/0004-execfile-over-exec.md +34 -0
- package/docs/decisions/0005-no-parameter-properties.md +49 -0
- package/docs/decisions/0006-publish-bundled-esm.md +63 -0
- package/docs/decisions/0007-active-run-binary-index.md +54 -0
- package/docs/decisions/0008-child-pi-warm-pool.md +61 -0
- package/docs/decisions/README.md +23 -0
- package/docs/followup-review-round4-2026-05-13.md +107 -0
- package/docs/implementation-plan-top3.md +333 -0
- package/docs/live-mailbox-runtime.md +36 -36
- package/docs/next-upgrade-roadmap.md +808 -808
- package/docs/oh-my-pi-research.md +509 -0
- package/docs/perf/baseline-2026-05.md +113 -0
- package/docs/perf/final-report-2026-05.md +206 -0
- package/docs/perf/sprint-1-report.md +71 -0
- package/docs/perf/sprint-2-report.md +81 -0
- package/docs/perf/sprint-2.5-report.md +53 -0
- package/docs/perf/sprint-3-report.md +36 -0
- package/docs/perf/sprint-4-report.md +47 -0
- package/docs/perf/sprint-5-report.md +51 -0
- package/docs/perf/sprint-6-report.md +94 -0
- package/docs/perf/sprint-7-report.md +74 -0
- package/docs/perf/upgrade-plan-2026-05.md +147 -0
- package/docs/pi-subagents3-deep-analysis.md +508 -0
- package/docs/product/README.md +31 -0
- package/docs/product/platform.md +27 -0
- package/docs/product/runtime-safety.md +37 -0
- package/docs/product/team-run.md +39 -0
- package/docs/product/team-tool.md +37 -0
- package/docs/publishing.md +65 -65
- package/docs/resource-formats.md +134 -134
- package/docs/runtime-analysis-child-vs-live.md +171 -0
- package/docs/runtime-flow.md +148 -148
- package/docs/runtime-migration-in-process-analysis.md +250 -0
- package/docs/stories/README.md +30 -0
- package/docs/stories/backlog.md +36 -0
- package/docs/templates/decision.md +27 -0
- package/docs/templates/story.md +44 -0
- package/docs/templates/validation-report.md +32 -0
- package/docs/usage.md +238 -238
- package/index.ts +7 -6
- package/install.mjs +65 -65
- package/package.json +107 -100
- package/schema.json +222 -222
- package/skills/child-pi-spawning/SKILL.md +213 -0
- package/skills/context-artifact-hygiene/SKILL.md +32 -0
- package/skills/event-log-tracing/SKILL.md +299 -0
- package/skills/git-master/SKILL.md +225 -24
- package/skills/live-agent-lifecycle/SKILL.md +192 -0
- package/skills/mailbox-interactive/SKILL.md +300 -19
- package/skills/model-routing-context/SKILL.md +94 -0
- package/skills/multi-perspective-review/SKILL.md +88 -0
- package/skills/read-only-explorer/SKILL.md +250 -26
- package/skills/safe-bash/SKILL.md +307 -21
- package/skills/verification-before-done/SKILL.md +11 -2
- package/skills/widget-rendering/SKILL.md +258 -0
- package/skills/workspace-isolation/SKILL.md +202 -0
- package/skills/worktree-isolation/SKILL.md +202 -18
- package/src/adapters/claude-adapter.ts +25 -25
- package/src/adapters/codex-adapter.ts +21 -21
- package/src/adapters/cursor-adapter.ts +17 -17
- package/src/adapters/export-util.ts +137 -137
- package/src/adapters/index.ts +15 -15
- package/src/adapters/registry.ts +18 -18
- package/src/adapters/types.ts +23 -23
- package/src/agents/agent-config.ts +38 -38
- package/src/agents/agent-serializer.ts +38 -38
- package/src/agents/discover-agents.ts +121 -118
- package/src/config/config.ts +740 -858
- package/src/config/defaults.ts +96 -96
- package/src/config/drift-detector.ts +211 -211
- package/src/config/markers.ts +327 -327
- package/src/config/resilient-parser.ts +109 -108
- package/src/config/suggestions.ts +74 -74
- package/src/config/types.ts +199 -0
- package/src/extension/async-notifier.ts +123 -89
- package/src/extension/autonomous-policy.ts +169 -169
- package/src/extension/cross-extension-rpc.ts +104 -104
- package/src/extension/help.ts +47 -47
- package/src/extension/import-index.ts +69 -69
- package/src/extension/management.ts +395 -382
- package/src/extension/notification-router.ts +116 -116
- package/src/extension/notification-sink.ts +51 -51
- package/src/extension/project-init.ts +168 -168
- package/src/extension/register.ts +859 -668
- package/src/extension/registration/artifact-cleanup.ts +15 -15
- package/src/extension/registration/command-utils.ts +54 -54
- package/src/extension/registration/commands.ts +559 -452
- package/src/extension/registration/compaction-guard.ts +125 -125
- package/src/extension/registration/subagent-helpers.ts +102 -102
- package/src/extension/registration/subagent-tools.ts +220 -159
- package/src/extension/registration/team-tool.ts +159 -99
- package/src/extension/registration/viewers.ts +29 -0
- package/src/extension/result-watcher.ts +128 -128
- package/src/extension/run-bundle-schema.ts +89 -89
- package/src/extension/run-export.ts +73 -73
- package/src/extension/run-import.ts +84 -84
- package/src/extension/run-index.ts +94 -94
- package/src/extension/run-maintenance.ts +142 -142
- package/src/extension/session-summary.ts +8 -8
- package/src/extension/team-manager-command.ts +96 -96
- package/src/extension/team-recommendation.ts +188 -188
- package/src/extension/team-tool/api.ts +5 -2
- package/src/extension/team-tool/cancel.ts +224 -209
- package/src/extension/team-tool/config-patch.ts +36 -36
- package/src/extension/team-tool/context.ts +60 -60
- package/src/extension/team-tool/doctor.ts +242 -242
- package/src/extension/team-tool/handle-settings.ts +421 -195
- package/src/extension/team-tool/inspect.ts +41 -41
- package/src/extension/team-tool/lifecycle-actions.ts +139 -139
- package/src/extension/team-tool/parallel-dispatch.ts +156 -156
- package/src/extension/team-tool/plan.ts +19 -19
- package/src/extension/team-tool/respond.ts +112 -111
- package/src/extension/team-tool/run.ts +246 -229
- package/src/extension/team-tool/status.ts +110 -110
- package/src/extension/team-tool-types.ts +13 -13
- package/src/extension/team-tool.ts +344 -344
- package/src/extension/tool-result.ts +16 -16
- package/src/extension/validate-resources.ts +77 -77
- package/src/hooks/registry.ts +61 -61
- package/src/hooks/types.ts +40 -40
- package/src/i18n.ts +184 -184
- package/src/observability/correlation.ts +35 -35
- package/src/observability/event-to-metric.ts +68 -68
- package/src/observability/exporters/adapter.ts +30 -30
- package/src/observability/exporters/otlp-exporter.ts +106 -92
- package/src/observability/exporters/prometheus-exporter.ts +54 -54
- package/src/observability/metric-registry.ts +87 -87
- package/src/observability/metric-retention.ts +54 -54
- package/src/observability/metric-sink.ts +81 -56
- package/src/observability/metrics-primitives.ts +167 -167
- package/src/prompt/prompt-runtime.ts +72 -72
- package/src/runtime/adaptive-plan.ts +338 -0
- package/src/runtime/agent-control.ts +169 -169
- package/src/runtime/agent-memory.ts +72 -72
- package/src/runtime/agent-observability.ts +114 -114
- package/src/runtime/async-marker.ts +26 -26
- package/src/runtime/async-runner.ts +153 -153
- package/src/runtime/attention-events.ts +28 -28
- package/src/runtime/auto-resume.ts +100 -100
- package/src/runtime/background-runner.ts +122 -89
- package/src/runtime/cancellation.ts +61 -61
- package/src/runtime/capability-inventory.ts +116 -116
- package/src/runtime/child-pi-pool.ts +68 -0
- package/src/runtime/child-pi.ts +541 -461
- package/src/runtime/code-summary.ts +247 -247
- package/src/runtime/compaction-summary.ts +271 -271
- package/src/runtime/concurrency.ts +58 -58
- package/src/runtime/crash-recovery.ts +317 -301
- package/src/runtime/crew-agent-records.ts +379 -281
- package/src/runtime/crew-agent-runtime.ts +60 -60
- package/src/runtime/cross-extension-rpc.ts +72 -0
- package/src/runtime/custom-tools/irc-tool.ts +201 -201
- package/src/runtime/custom-tools/submit-result-tool.ts +90 -90
- package/src/runtime/deadletter.ts +47 -47
- package/src/runtime/delivery-coordinator.ts +176 -176
- package/src/runtime/delta-conflict.ts +360 -360
- package/src/runtime/diagnostic-export.ts +102 -102
- package/src/runtime/direct-run.ts +35 -35
- package/src/runtime/effectiveness.ts +82 -81
- package/src/runtime/errors/crew-errors.ts +166 -0
- package/src/runtime/event-stream-bridge.ts +92 -92
- package/src/runtime/foreground-control.ts +82 -82
- package/src/runtime/green-contract.ts +46 -46
- package/src/runtime/group-join.ts +234 -106
- package/src/runtime/heartbeat-watcher.ts +145 -124
- package/src/runtime/iteration-hooks.ts +267 -267
- package/src/runtime/live-agent-control.ts +88 -88
- package/src/runtime/live-agent-manager.ts +377 -179
- package/src/runtime/live-control-realtime.ts +36 -36
- package/src/runtime/live-session-runtime.ts +676 -600
- package/src/runtime/loop-gates.ts +129 -129
- package/src/runtime/manifest-cache.ts +263 -263
- package/src/runtime/mcp-proxy.ts +113 -113
- package/src/runtime/metric-parser.ts +40 -40
- package/src/runtime/model-fallback.ts +282 -274
- package/src/runtime/model-resolver.ts +118 -0
- package/src/runtime/output-validator.ts +187 -187
- package/src/runtime/overflow-recovery.ts +175 -175
- package/src/runtime/parallel-research.ts +44 -44
- package/src/runtime/parallel-utils.ts +156 -156
- package/src/runtime/parent-guard.ts +80 -80
- package/src/runtime/phase-progress.ts +217 -217
- package/src/runtime/pi-args.ts +165 -165
- package/src/runtime/pi-json-output.ts +111 -111
- package/src/runtime/pi-spawn.ts +167 -167
- package/src/runtime/policy-engine.ts +79 -79
- package/src/runtime/post-checks.ts +125 -125
- package/src/runtime/post-exit-stdio-guard.ts +86 -86
- package/src/runtime/process-status.ts +97 -73
- package/src/runtime/progress-event-coalescer.ts +43 -43
- package/src/runtime/recovery-recipes.ts +74 -74
- package/src/runtime/retry-executor.ts +81 -81
- package/src/runtime/role-permission.ts +39 -39
- package/src/runtime/run-tracker.ts +99 -0
- package/src/runtime/runtime-policy.ts +21 -0
- package/src/runtime/runtime-resolver.ts +94 -91
- package/src/runtime/scheduler.ts +294 -0
- package/src/runtime/semaphore.ts +131 -131
- package/src/runtime/sensitive-paths.ts +92 -92
- package/src/runtime/session-usage.ts +79 -79
- package/src/runtime/settings-store.ts +103 -0
- package/src/runtime/sidechain-output.ts +29 -29
- package/src/runtime/skill-instructions.ts +222 -222
- package/src/runtime/stale-reconciler.ts +198 -189
- package/src/runtime/streaming-output.ts +47 -0
- package/src/runtime/subagent-manager.ts +404 -400
- package/src/runtime/subprocess-tool-registry.ts +67 -67
- package/src/runtime/task-display.ts +38 -38
- package/src/runtime/task-graph-scheduler.ts +122 -122
- package/src/runtime/task-graph.ts +207 -207
- package/src/runtime/task-output-context.ts +177 -177
- package/src/runtime/task-packet.ts +93 -93
- package/src/runtime/task-quality.ts +207 -207
- package/src/runtime/task-runner/capabilities.ts +78 -78
- package/src/runtime/task-runner/live-executor.ts +131 -113
- package/src/runtime/task-runner/progress.ts +119 -119
- package/src/runtime/task-runner/prompt-builder.ts +139 -139
- package/src/runtime/task-runner/prompt-pipeline.ts +64 -64
- package/src/runtime/task-runner/result-utils.ts +14 -14
- package/src/runtime/task-runner/run-projection.ts +103 -103
- package/src/runtime/task-runner/state-helpers.ts +22 -22
- package/src/runtime/task-runner.ts +469 -459
- package/src/runtime/team-runner.ts +693 -945
- package/src/runtime/usage-tracker.ts +71 -0
- package/src/runtime/worker-heartbeat.ts +21 -21
- package/src/runtime/worker-startup.ts +57 -57
- package/src/runtime/workflow-state.ts +187 -187
- package/src/runtime/yield-handler.ts +190 -190
- package/src/schema/config-schema.ts +172 -168
- package/src/schema/team-tool-schema.ts +126 -126
- package/src/schema/validation-types.ts +151 -148
- package/src/skills/discover-skills.ts +67 -67
- package/src/skills/skill-templates.ts +374 -374
- package/src/state/active-run-registry.ts +227 -191
- package/src/state/artifact-store.ts +130 -129
- package/src/state/atomic-write.ts +262 -195
- package/src/state/blob-store.ts +116 -116
- package/src/state/contracts.ts +111 -111
- package/src/state/event-log-rotation.ts +161 -158
- package/src/state/event-log.ts +383 -303
- package/src/state/event-reconstructor.ts +217 -217
- package/src/state/jsonl-writer.ts +82 -82
- package/src/state/locks.ts +146 -146
- package/src/state/mailbox.ts +446 -405
- package/src/state/state-store.ts +364 -351
- package/src/state/task-claims.ts +44 -44
- package/src/state/types.ts +285 -285
- package/src/state/usage.ts +29 -29
- package/src/subagents/async-entry.ts +1 -1
- package/src/subagents/index.ts +3 -3
- package/src/subagents/live/control.ts +1 -1
- package/src/subagents/live/manager.ts +1 -1
- package/src/subagents/live/realtime.ts +1 -1
- package/src/subagents/live/session-runtime.ts +1 -1
- package/src/subagents/manager.ts +1 -1
- package/src/subagents/spawn.ts +1 -1
- package/src/teams/discover-teams.ts +116 -116
- package/src/teams/team-config.ts +27 -27
- package/src/teams/team-serializer.ts +38 -38
- package/src/types/diff.d.ts +18 -18
- package/src/ui/agent-management-overlay.ts +144 -144
- package/src/ui/crew-widget.ts +487 -370
- package/src/ui/dashboard-panes/agents-pane.ts +109 -28
- package/src/ui/dashboard-panes/cancellation-pane.ts +42 -42
- package/src/ui/dashboard-panes/capability-pane.ts +59 -59
- package/src/ui/dashboard-panes/health-pane.ts +30 -30
- package/src/ui/dashboard-panes/mailbox-pane.ts +35 -35
- package/src/ui/dashboard-panes/progress-pane.ts +30 -30
- package/src/ui/dashboard-panes/transcript-pane.ts +10 -10
- package/src/ui/heartbeat-aggregator.ts +63 -63
- package/src/ui/keybinding-map.ts +97 -94
- package/src/ui/live-conversation-overlay.ts +152 -0
- package/src/ui/live-run-sidebar.ts +180 -180
- package/src/ui/mascot.ts +442 -442
- package/src/ui/overlays/agent-picker-overlay.ts +57 -57
- package/src/ui/overlays/confirm-overlay.ts +58 -58
- package/src/ui/overlays/mailbox-compose-overlay.ts +144 -144
- package/src/ui/overlays/mailbox-compose-preview.ts +63 -63
- package/src/ui/overlays/mailbox-detail-overlay.ts +122 -122
- package/src/ui/pi-ui-compat.ts +57 -57
- package/src/ui/powerbar-publisher.ts +221 -197
- package/src/ui/render-scheduler.ts +216 -143
- package/src/ui/run-action-dispatcher.ts +118 -118
- package/src/ui/run-dashboard.ts +526 -464
- package/src/ui/run-event-bus.ts +208 -208
- package/src/ui/run-snapshot-cache.ts +826 -777
- package/src/ui/settings-overlay.ts +721 -0
- package/src/ui/snapshot-types.ts +86 -70
- package/src/ui/theme-adapter.ts +190 -190
- package/src/ui/tool-progress-formatter.ts +89 -0
- package/src/ui/transcript-cache.ts +94 -94
- package/src/ui/transcript-viewer.ts +335 -335
- package/src/utils/conflict-detect.ts +662 -0
- package/src/utils/file-coalescer.ts +86 -86
- package/src/utils/frontmatter.ts +68 -68
- package/src/utils/fs-watch.ts +88 -31
- package/src/utils/gh-protocol.ts +479 -0
- package/src/utils/ids.ts +17 -17
- package/src/utils/incremental-reader.ts +104 -104
- package/src/utils/internal-error.ts +6 -6
- package/src/utils/names.ts +27 -27
- package/src/utils/paths.ts +102 -63
- package/src/utils/redaction.ts +44 -44
- package/src/utils/safe-paths.ts +47 -47
- package/src/utils/scan-cache.ts +136 -136
- package/src/utils/sse-parser.ts +134 -134
- package/src/utils/task-name-generator.ts +337 -337
- package/src/utils/timings.ts +33 -33
- package/src/utils/visual.ts +243 -198
- package/src/workflows/discover-workflows.ts +139 -139
- package/src/workflows/validate-workflow.ts +40 -40
- package/src/workflows/workflow-config.ts +26 -26
- package/src/workflows/workflow-serializer.ts +32 -32
- package/src/worktree/branch-freshness.ts +45 -45
- package/src/worktree/cleanup.ts +75 -75
- package/src/worktree/worktree-manager.ts +188 -188
- package/teams/default.team.md +12 -12
- package/teams/fast-fix.team.md +11 -11
- package/teams/implementation.team.md +18 -18
- package/teams/parallel-research.team.md +14 -14
- package/teams/research.team.md +11 -11
- package/teams/review.team.md +12 -12
- package/tsconfig.json +19 -19
- package/workflows/default.workflow.md +30 -30
- package/workflows/fast-fix.workflow.md +23 -23
- package/workflows/implementation.workflow.md +43 -43
- package/workflows/parallel-research.workflow.md +46 -46
- package/workflows/research.workflow.md +22 -22
- package/workflows/review.workflow.md +30 -30
- package/skills/task-packet/SKILL.md +0 -28
- package/skills/verify-evidence/SKILL.md +0 -27
|
@@ -5,36 +5,317 @@ description: Interactive waiting-task and mailbox workflow. Use when implementin
|
|
|
5
5
|
|
|
6
6
|
# mailbox-interactive
|
|
7
7
|
|
|
8
|
-
Use this skill for live coordination between leader and workers.
|
|
8
|
+
Use this skill for live coordination between leader and workers. Mailbox provides an asynchronous message protocol for steer, follow-up, respond, and nudge operations.
|
|
9
9
|
|
|
10
|
-
##
|
|
10
|
+
## Mailbox Architecture
|
|
11
11
|
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
12
|
+
```
|
|
13
|
+
Worker (waiting) ← mailbox inbox ← Leader (respond)
|
|
14
|
+
Worker (running) ← mailbox follow-ups ← Leader (followUp)
|
|
15
|
+
Leader → Worker: steer, followUp, nudge (non-blocking)
|
|
16
|
+
Worker → Leader: supervisor contact (blocking decision)
|
|
17
|
+
```
|
|
18
|
+
|
|
19
|
+
### Mailbox file structure
|
|
20
|
+
|
|
21
|
+
Each run has a mailbox directory at `.crew/state/runs/<runId>/mailbox/`:
|
|
22
|
+
- `inbox.jsonl` — incoming messages (to worker)
|
|
23
|
+
- `outbox.jsonl` — sent messages (from worker)
|
|
24
|
+
- `steering.jsonl` — steer messages specifically
|
|
25
|
+
|
|
26
|
+
### Message structure
|
|
27
|
+
|
|
28
|
+
```typescript
|
|
29
|
+
interface MailboxMessage {
|
|
30
|
+
id: string;
|
|
31
|
+
direction: "inbox" | "outbox";
|
|
32
|
+
from: string; // taskId or "leader"
|
|
33
|
+
to: string; // taskId or "leader"
|
|
34
|
+
body: string; // message text
|
|
35
|
+
status: "pending" | "delivered" | "acknowledged" | "rejected";
|
|
36
|
+
priority: "low" | "normal" | "high";
|
|
37
|
+
sentAt: string; // ISO timestamp
|
|
38
|
+
deliveredAt?: string;
|
|
39
|
+
data?: Record<string, unknown>; // source, correlation, etc.
|
|
40
|
+
}
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
## Core Operations
|
|
44
|
+
|
|
45
|
+
### 1. respond — Leader responds to waiting worker
|
|
46
|
+
|
|
47
|
+
```typescript
|
|
48
|
+
// Respond writes to inbox and transitions task back to running
|
|
49
|
+
async function respond(runId: string, taskId: string, body: string, priority = "normal") {
|
|
50
|
+
// 1. Write inbox message
|
|
51
|
+
const message = appendInboxMessage(manifest, { taskId, body, priority });
|
|
52
|
+
|
|
53
|
+
// 2. Re-read state inside lock
|
|
54
|
+
const { tasks } = loadRunManifestById(cwd, runId);
|
|
55
|
+
const task = tasks.find(t => t.id === taskId);
|
|
56
|
+
|
|
57
|
+
// 3. Verify task is waiting
|
|
58
|
+
if (task.status !== "waiting") {
|
|
59
|
+
throw new Error(`Cannot respond to non-waiting task: ${task.status}`);
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
// 4. Transition task back to running
|
|
63
|
+
const updated = { ...task, status: "running", waitingSince: undefined };
|
|
64
|
+
saveRunTasks(manifest, [updated]);
|
|
65
|
+
|
|
66
|
+
// 5. Emit event
|
|
67
|
+
appendEvent(eventsPath, { type: "task.responded", taskId, message: body });
|
|
68
|
+
|
|
69
|
+
return message;
|
|
70
|
+
}
|
|
71
|
+
```
|
|
72
|
+
|
|
73
|
+
### 2. steer — Live agent steering (non-blocking)
|
|
74
|
+
|
|
75
|
+
```typescript
|
|
76
|
+
// Steer sends a message to a running live agent
|
|
77
|
+
async function steerLiveAgent(agentId: string, message: string) {
|
|
78
|
+
const handle = getLiveAgent(agentId);
|
|
79
|
+
if (!handle) throw new Error(`Live agent '${agentId}' not found`);
|
|
80
|
+
|
|
81
|
+
// If session.steer is available, deliver immediately
|
|
82
|
+
if (typeof handle.session.steer === "function") {
|
|
83
|
+
await handle.session.steer(message);
|
|
84
|
+
handle.updatedAt = new Date().toISOString();
|
|
85
|
+
return handle;
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
// Otherwise, queue for delivery when session becomes ready
|
|
89
|
+
handle.pendingSteers.push(message);
|
|
90
|
+
return handle;
|
|
91
|
+
}
|
|
92
|
+
```
|
|
93
|
+
|
|
94
|
+
### 3. followUp — Non-blocking follow-up to running agent
|
|
95
|
+
|
|
96
|
+
```typescript
|
|
97
|
+
async function followUpLiveAgent(agentId: string, prompt: string) {
|
|
98
|
+
const handle = getLiveAgent(agentId);
|
|
99
|
+
if (!handle) throw new Error(`Live agent '${agentId}' not found`);
|
|
100
|
+
|
|
101
|
+
if (typeof handle.session.prompt === "function") {
|
|
102
|
+
await handle.session.prompt(prompt, { source: "api", expandPromptTemplates: false });
|
|
103
|
+
handle.updatedAt = new Date().toISOString();
|
|
104
|
+
return handle;
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
handle.pendingFollowUps.push(prompt);
|
|
108
|
+
return handle;
|
|
109
|
+
}
|
|
110
|
+
```
|
|
111
|
+
|
|
112
|
+
### 4. nudge — Ask agent to report status
|
|
113
|
+
|
|
114
|
+
```typescript
|
|
115
|
+
function nudgeAgent(manifest: TeamRunManifest, agentId: string, message?: string) {
|
|
116
|
+
const agent = readCrewAgents(manifest).find(a => a.id === agentId || a.taskId === agentId);
|
|
117
|
+
if (!agent) throw new Error(`Agent '${agentId}' not found`);
|
|
118
|
+
|
|
119
|
+
const text = message ?? "Please report your current status, blocker, or smallest next step.";
|
|
120
|
+
|
|
121
|
+
// Write to mailbox
|
|
122
|
+
const mailboxMessage = appendSteeringMessage(manifest, {
|
|
123
|
+
taskId: agent.taskId,
|
|
124
|
+
body: text,
|
|
125
|
+
priority: "normal",
|
|
126
|
+
data: { source: "nudge-agent" }
|
|
127
|
+
});
|
|
128
|
+
|
|
129
|
+
// Emit event
|
|
130
|
+
appendEvent(manifest.eventsPath, {
|
|
131
|
+
type: "agent.nudged",
|
|
132
|
+
runId: manifest.runId,
|
|
133
|
+
taskId: agent.taskId,
|
|
134
|
+
message: text,
|
|
135
|
+
data: { agentId: agent.id, mailboxMessageId: mailboxMessage.id }
|
|
136
|
+
});
|
|
137
|
+
|
|
138
|
+
return mailboxMessage;
|
|
139
|
+
}
|
|
140
|
+
```
|
|
141
|
+
|
|
142
|
+
## Supervisor Contact
|
|
143
|
+
|
|
144
|
+
Workers can contact the leader for blocking decisions:
|
|
145
|
+
|
|
146
|
+
```typescript
|
|
147
|
+
// Worker stdout contains supervisor contact pattern:
|
|
148
|
+
// @supervisor need_confirmation: <decision-type>
|
|
149
|
+
// @supervisor need_input: <input-prompt>
|
|
150
|
+
|
|
151
|
+
// Parsed by parseSupervisorContactFromLine() in supervisor-contact.ts
|
|
152
|
+
function parseSupervisorContact(line: string): SupervisorContact | null {
|
|
153
|
+
const match = line.match(/@supervisor\s+(\w+):\s*(.*)/);
|
|
154
|
+
if (!match) return null;
|
|
155
|
+
return { type: match[1], prompt: match[2] };
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
// Recorded as events and surfaced in UI
|
|
159
|
+
appendEvent(eventsPath, {
|
|
160
|
+
type: "supervisor.contact",
|
|
161
|
+
runId: manifest.runId,
|
|
162
|
+
taskId: task.id,
|
|
163
|
+
message: contact.prompt,
|
|
164
|
+
data: { contactType: contact.type }
|
|
165
|
+
});
|
|
166
|
+
```
|
|
167
|
+
|
|
168
|
+
**Contact types:**
|
|
169
|
+
- `need_confirmation` — worker needs explicit approval
|
|
170
|
+
- `need_input` — worker needs a text response
|
|
171
|
+
- `need_selection` — worker needs to choose from options
|
|
172
|
+
|
|
173
|
+
## Queue Depth and Backpressure
|
|
174
|
+
|
|
175
|
+
Mailbox queues can grow large with pending messages:
|
|
176
|
+
|
|
177
|
+
```typescript
|
|
178
|
+
const MAX_PENDING_STEERS = 50;
|
|
179
|
+
const MAX_PENDING_FOLLOWUPS = 50;
|
|
180
|
+
|
|
181
|
+
// When queue exceeds limit, oldest messages are dropped
|
|
182
|
+
if (handle.pendingSteers.length >= MAX_PENDING_STEERS) {
|
|
183
|
+
handle.pendingSteers.shift(); // drop oldest
|
|
184
|
+
}
|
|
185
|
+
```
|
|
186
|
+
|
|
187
|
+
**Backpressure signals:**
|
|
188
|
+
- If `pendingSteers.length > 20`, warn in UI
|
|
189
|
+
- If `pendingFollowUps.length > 20`, warn in UI
|
|
190
|
+
|
|
191
|
+
## Corrupt JSONL Handling
|
|
192
|
+
|
|
193
|
+
Mailbox JSONL files can become corrupt on crash. Handle gracefully:
|
|
194
|
+
|
|
195
|
+
```typescript
|
|
196
|
+
function readMailboxMessages(path: string): MailboxMessage[] {
|
|
197
|
+
if (!fs.existsSync(path)) return [];
|
|
198
|
+
|
|
199
|
+
const lines = fs.readFileSync(path, "utf-8").split("\n");
|
|
200
|
+
const messages: MailboxMessage[] = [];
|
|
201
|
+
|
|
202
|
+
for (const line of lines) {
|
|
203
|
+
if (!line.trim()) continue;
|
|
204
|
+
try {
|
|
205
|
+
messages.push(JSON.parse(line) as MailboxMessage);
|
|
206
|
+
} catch {
|
|
207
|
+
// Skip corrupt lines: partial write from crash
|
|
208
|
+
// Try to recover by reading up to the last valid JSON object
|
|
209
|
+
continue;
|
|
210
|
+
}
|
|
211
|
+
}
|
|
212
|
+
|
|
213
|
+
return messages;
|
|
214
|
+
}
|
|
215
|
+
```
|
|
216
|
+
|
|
217
|
+
## Timeout Patterns
|
|
218
|
+
|
|
219
|
+
### Responding with timeout
|
|
220
|
+
|
|
221
|
+
```typescript
|
|
222
|
+
async function respondWithTimeout(
|
|
223
|
+
runId: string,
|
|
224
|
+
taskId: string,
|
|
225
|
+
body: string,
|
|
226
|
+
timeoutMs = 30_000
|
|
227
|
+
): Promise<MailboxMessage> {
|
|
228
|
+
const controller = new AbortController();
|
|
229
|
+
const timeout = setTimeout(() => controller.abort(), timeoutMs);
|
|
230
|
+
|
|
231
|
+
try {
|
|
232
|
+
const message = await respond(runId, taskId, body);
|
|
233
|
+
clearTimeout(timeout);
|
|
234
|
+
return message;
|
|
235
|
+
} catch (error) {
|
|
236
|
+
clearTimeout(timeout);
|
|
237
|
+
if (error.name === "AbortError") {
|
|
238
|
+
throw new Error(`Respond timed out after ${timeoutMs}ms`);
|
|
239
|
+
}
|
|
240
|
+
throw error;
|
|
241
|
+
}
|
|
242
|
+
}
|
|
243
|
+
```
|
|
244
|
+
|
|
245
|
+
### Non-blocking follow-up (no wait)
|
|
246
|
+
|
|
247
|
+
```typescript
|
|
248
|
+
// Fire-and-forget: send message and return immediately
|
|
249
|
+
function followUpAsync(agentId: string, prompt: string): void {
|
|
250
|
+
const handle = getLiveAgent(agentId);
|
|
251
|
+
if (!handle) return;
|
|
252
|
+
|
|
253
|
+
if (typeof handle.session.prompt === "function") {
|
|
254
|
+
// Non-awaited: delivery happens in background
|
|
255
|
+
void handle.session.prompt(prompt, { source: "api", expandPromptTemplates: false })
|
|
256
|
+
.catch(() => { /* log if needed */ });
|
|
257
|
+
} else {
|
|
258
|
+
handle.pendingFollowUps.push(prompt);
|
|
259
|
+
}
|
|
260
|
+
}
|
|
261
|
+
```
|
|
15
262
|
|
|
16
|
-
##
|
|
263
|
+
## Run Ownership Enforcement
|
|
17
264
|
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
265
|
+
Foreign sessions cannot mutate a run's mailbox:
|
|
266
|
+
|
|
267
|
+
```typescript
|
|
268
|
+
// In respond.ts / cancel.ts
|
|
269
|
+
function verifyRunOwnership(manifest: TeamRunManifest, sessionId: string, force = false) {
|
|
270
|
+
if (!force && manifest.ownerSessionId && manifest.ownerSessionId !== sessionId) {
|
|
271
|
+
throw new Error(
|
|
272
|
+
`Run ${manifest.runId} is owned by session ${manifest.ownerSessionId}. ` +
|
|
273
|
+
`Cannot mutate from session ${sessionId}. Use force=true to override.`
|
|
274
|
+
);
|
|
275
|
+
}
|
|
276
|
+
}
|
|
277
|
+
```
|
|
25
278
|
|
|
26
279
|
## Anti-patterns
|
|
27
280
|
|
|
28
|
-
- Resuming non-waiting tasks
|
|
29
|
-
- Injecting mailbox messages into
|
|
30
|
-
- Treating every progress update as
|
|
31
|
-
- Reading large mailbox files
|
|
281
|
+
- **Resuming non-waiting tasks**: `respond` only works on `waiting` tasks. Resuming `running` tasks corrupts state.
|
|
282
|
+
- **Injecting mailbox messages into foreign runs**: Always verify `ownerSessionId` before mutating.
|
|
283
|
+
- **Treating every progress update as blocking**: Use `followUp` (non-blocking) instead of `respond` for status updates.
|
|
284
|
+
- **Reading large mailbox files in hot paths**: Cache mailbox counts; don't read JSONL on every render tick.
|
|
285
|
+
- **Not handling corrupt JSONL**: Skip malformed lines; don't fail the whole read.
|
|
286
|
+
- **Losing pending messages on session switch**: Pending steers/followups are stored in-memory in the handle. They survive session fork but not session death.
|
|
287
|
+
|
|
288
|
+
---
|
|
289
|
+
|
|
290
|
+
## Source patterns
|
|
291
|
+
|
|
292
|
+
- `src/state/mailbox.ts` — appendInboxMessage, appendSteeringMessage, readMailboxMessages
|
|
293
|
+
- `src/extension/team-tool/respond.ts` — respond tool handler, ownership verification
|
|
294
|
+
- `src/extension/team-tool/cancel.ts` — cancel with mailbox cleanup
|
|
295
|
+
- `src/extension/team-tool/api.ts` — steer-agent, follow-up-agent, nudge-agent
|
|
296
|
+
- `src/runtime/live-agent-manager.ts` — pendingSteers, pendingFollowUps, steerLiveAgent, followUpLiveAgent
|
|
297
|
+
- `src/runtime/supervisor-contact.ts` — parseSupervisorContactFromLine, recordSupervisorContact
|
|
298
|
+
- `src/ui/overlays/mailbox-detail-overlay.ts` — mailbox UI
|
|
299
|
+
|
|
300
|
+
---
|
|
32
301
|
|
|
33
302
|
## Verification
|
|
34
303
|
|
|
35
304
|
```bash
|
|
36
305
|
cd pi-crew
|
|
306
|
+
|
|
307
|
+
# Verify mailbox structure
|
|
308
|
+
ls .crew/state/runs/<runId>/mailbox/ 2>/dev/null || echo "No mailbox yet"
|
|
309
|
+
|
|
310
|
+
# Test respond tool
|
|
311
|
+
node --experimental-strip-types --test test/unit/respond-tool.test.ts
|
|
312
|
+
|
|
313
|
+
# Test mailbox overlay
|
|
314
|
+
node --experimental-strip-types --test test/unit/mailbox-detail-overlay.test.ts
|
|
315
|
+
|
|
316
|
+
# TypeScript
|
|
37
317
|
npx tsc --noEmit
|
|
38
|
-
|
|
318
|
+
|
|
319
|
+
# All tests
|
|
39
320
|
npm test
|
|
40
|
-
```
|
|
321
|
+
```
|
|
@@ -29,6 +29,100 @@ Use this skill when working on model/context propagation.
|
|
|
29
29
|
- Passing full session transcripts to every child by default.
|
|
30
30
|
- Losing thinking level or model changes across session switch/fork flows.
|
|
31
31
|
|
|
32
|
+
## Worked Examples
|
|
33
|
+
|
|
34
|
+
### Model precedence chain with all fields
|
|
35
|
+
|
|
36
|
+
When every level provides a model:
|
|
37
|
+
|
|
38
|
+
```typescript
|
|
39
|
+
// Requested by user/tool: "sonnet-4-2025-01-16"
|
|
40
|
+
// Step model (workflow): undefined
|
|
41
|
+
// Team role model: undefined
|
|
42
|
+
// Agent model: "haiku-4"
|
|
43
|
+
// Parent model: "sonnet-4-2025-01-16"
|
|
44
|
+
// Model registry: { default: "claude-sonnet-4" }
|
|
45
|
+
|
|
46
|
+
const result = buildConfiguredModelRouting({
|
|
47
|
+
overrideModel: "sonnet-4-2025-01-16", // tool override wins
|
|
48
|
+
stepModel: undefined,
|
|
49
|
+
teamRoleModel: undefined,
|
|
50
|
+
agentModel: "haiku-4",
|
|
51
|
+
fallbackModels: ["haiku-3"],
|
|
52
|
+
parentModel: "sonnet-4-2025-01-16",
|
|
53
|
+
modelRegistry: { default: "claude-sonnet-4" },
|
|
54
|
+
cwd,
|
|
55
|
+
});
|
|
56
|
+
|
|
57
|
+
// Result: candidates = ["sonnet-4-2025-01-16"]
|
|
58
|
+
// resolved = "sonnet-4-2025-01-16" (override wins)
|
|
59
|
+
// reason = "tool override"
|
|
60
|
+
```
|
|
61
|
+
|
|
62
|
+
### Override at each level
|
|
63
|
+
|
|
64
|
+
```typescript
|
|
65
|
+
// Level 1: tool override (highest)
|
|
66
|
+
buildConfiguredModelRouting({ overrideModel: "sonnet-4-2025-01-16" });
|
|
67
|
+
// → candidates = ["sonnet-4-2025-01-16"]
|
|
68
|
+
|
|
69
|
+
// Level 2: step model
|
|
70
|
+
buildConfiguredModelRouting({ overrideModel: undefined, stepModel: "haiku-4" });
|
|
71
|
+
// → candidates = ["haiku-4"]
|
|
72
|
+
|
|
73
|
+
// Level 3: team role model
|
|
74
|
+
buildConfiguredModelRouting({ overrideModel: undefined, stepModel: undefined, teamRoleModel: "sonnet-3.5" });
|
|
75
|
+
// → candidates = ["sonnet-3.5"]
|
|
76
|
+
|
|
77
|
+
// Level 4: agent model with fallback
|
|
78
|
+
buildConfiguredModelRouting({ overrideModel: undefined, stepModel: undefined, teamRoleModel: undefined, agentModel: "haiku-3", fallbackModels: ["claude-3-5-haiku-20241022"] });
|
|
79
|
+
// → candidates = ["haiku-3", "claude-3-5-haiku-20241022"]
|
|
80
|
+
```
|
|
81
|
+
|
|
82
|
+
### Empty/whitespace/null handling
|
|
83
|
+
|
|
84
|
+
```typescript
|
|
85
|
+
// Empty string treated as absent
|
|
86
|
+
buildConfiguredModelRouting({ agentModel: "" });
|
|
87
|
+
// → agentModel ignored, falls through to parent
|
|
88
|
+
|
|
89
|
+
// Whitespace treated as absent
|
|
90
|
+
buildConfiguredModelRouting({ agentModel: " " });
|
|
91
|
+
// → agentModel ignored
|
|
92
|
+
|
|
93
|
+
// null/undefined treated as absent
|
|
94
|
+
buildConfiguredModelRouting({ agentModel: undefined });
|
|
95
|
+
// → agentModel ignored
|
|
96
|
+
|
|
97
|
+
// With thinking level suffix
|
|
98
|
+
applyThinkingSuffix("sonnet-4-2025-01-16", "medium")
|
|
99
|
+
// → "sonnet-4-2025-01-16:medium"
|
|
100
|
+
|
|
101
|
+
// Invalid thinking level falls back to model without suffix
|
|
102
|
+
applyThinkingSuffix("sonnet-4-2025-01-16", "invalid")
|
|
103
|
+
// → "sonnet-4-2025-01-16" (suffix ignored)
|
|
104
|
+
```
|
|
105
|
+
|
|
106
|
+
## Common Mistakes
|
|
107
|
+
|
|
108
|
+
1. **Empty string blocking parent fallback**:
|
|
109
|
+
```typescript
|
|
110
|
+
// ❌ agentModel: "" blocks parent fallback
|
|
111
|
+
buildConfiguredModelRouting({ agentModel: "" });
|
|
112
|
+
|
|
113
|
+
// ✅ Empty string treated as absent
|
|
114
|
+
buildConfiguredModelRouting({ agentModel: undefined });
|
|
115
|
+
```
|
|
116
|
+
|
|
117
|
+
2. **Losing thinking level on session switch**:
|
|
118
|
+
```typescript
|
|
119
|
+
// ❌ Thinking level not persisted in config
|
|
120
|
+
const config = { model: "sonnet-4" }; // no thinking
|
|
121
|
+
|
|
122
|
+
// ✅ Thinking level in model suffix
|
|
123
|
+
const config = { model: "sonnet-4:medium" };
|
|
124
|
+
```
|
|
125
|
+
|
|
32
126
|
## Verification
|
|
33
127
|
|
|
34
128
|
```bash
|
|
@@ -39,6 +39,94 @@ Severity:
|
|
|
39
39
|
- medium: important regression, flaky test, confusing recoverable behavior;
|
|
40
40
|
- low: polish, maintainability, docs.
|
|
41
41
|
|
|
42
|
+
## Example Findings by Perspective
|
|
43
|
+
|
|
44
|
+
### Spec Compliance
|
|
45
|
+
|
|
46
|
+
```
|
|
47
|
+
[medium] src/runtime/task-runner.ts:89
|
|
48
|
+
Issue: `executeWorkers` is checked once at top of runTeamTask but the value
|
|
49
|
+
is passed through an untyped parameter. The function comment says "workers
|
|
50
|
+
are disabled in scaffold mode" but the actual behavior is driven by `runtimeKind`.
|
|
51
|
+
Impact: If someone changes the comment but not the code, the mismatch is invisible.
|
|
52
|
+
Fix: Add a runtimeKind guard and deprecate the executeWorkers parameter.
|
|
53
|
+
Verification: `npx tsc --noEmit` passes; test with `PI_TEAMS_MOCK_CHILD_PI=scaffold`.
|
|
54
|
+
```
|
|
55
|
+
|
|
56
|
+
### Correctness
|
|
57
|
+
|
|
58
|
+
```
|
|
59
|
+
[high] src/runtime/live-agent-manager.ts:47
|
|
60
|
+
Issue: `registerLiveAgent` returns the new handle but callers may use the
|
|
61
|
+
old handle reference if they captured it before the call.
|
|
62
|
+
Impact: Status updates may apply to the wrong handle if the agent re-registers.
|
|
63
|
+
Fix: Always call `getLiveAgent` after `registerLiveAgent` to get the canonical handle.
|
|
64
|
+
Verification: Add test that verifies status after re-registration.
|
|
65
|
+
```
|
|
66
|
+
|
|
67
|
+
### Regression Risk
|
|
68
|
+
|
|
69
|
+
```
|
|
70
|
+
[medium] src/state/state-store.ts:150
|
|
71
|
+
Issue: `saveRunTasks` uses `atomicWriteJson` but the file may grow large.
|
|
72
|
+
No pagination or archiving strategy for long-running runs.
|
|
73
|
+
Impact: Tasks file could exceed 10MB with many updates, causing slow I/O.
|
|
74
|
+
Fix: Consider splitting into per-task files or adding a size warning.
|
|
75
|
+
Verification: Load test with 10,000 task updates.
|
|
76
|
+
```
|
|
77
|
+
|
|
78
|
+
### Security
|
|
79
|
+
|
|
80
|
+
```
|
|
81
|
+
[critical] src/utils/safe-paths.ts:20
|
|
82
|
+
Issue: `resolveRealContainedPath` follows symlinks but doesn't verify the
|
|
83
|
+
resolved path stays under the allowed base.
|
|
84
|
+
Impact: A malicious symlink could escape the workspace boundary.
|
|
85
|
+
Fix: Compare resolved path against allowed base after following symlinks.
|
|
86
|
+
Verification: Unit test with malicious symlink pointing outside workspace.
|
|
87
|
+
```
|
|
88
|
+
|
|
89
|
+
### Tests
|
|
90
|
+
|
|
91
|
+
```
|
|
92
|
+
[medium] test/unit/live-agent-manager.test.ts:45
|
|
93
|
+
Issue: Test only checks the happy path. Missing: re-registration, workspaceId
|
|
94
|
+
mismatch, evict on timeout, cross-workspace access prevention.
|
|
95
|
+
Impact: Edge cases are not covered; future changes could break silently.
|
|
96
|
+
Fix: Add tests for re-registration, cross-workspace rejection, stale eviction.
|
|
97
|
+
Verification: `npm test` with new test cases.
|
|
98
|
+
```
|
|
99
|
+
|
|
100
|
+
### Maintainability
|
|
101
|
+
|
|
102
|
+
```
|
|
103
|
+
[low] src/runtime/task-runner.ts:250
|
|
104
|
+
Issue: `runTeamTask` is 400+ lines with deeply nested if/else. Hard to follow.
|
|
105
|
+
Impact: Future changes require understanding all branches simultaneously.
|
|
106
|
+
Fix: Extract inner logic into helper functions (spawn, execute, complete).
|
|
107
|
+
Verification: No functional change; `npx tsc --noEmit` passes.
|
|
108
|
+
```
|
|
109
|
+
|
|
110
|
+
### Operator Experience
|
|
111
|
+
|
|
112
|
+
```
|
|
113
|
+
[medium] src/extension/team-tool/api.ts:80
|
|
114
|
+
Issue: Error message for missing `agentId` doesn't show available agent IDs.
|
|
115
|
+
Impact: Operator must manually look up agent IDs to fix the error.
|
|
116
|
+
Fix: Include list of available agent IDs in the error message.
|
|
117
|
+
Verification: Call steer-agent without agentId and verify error lists IDs.
|
|
118
|
+
```
|
|
119
|
+
|
|
120
|
+
### Compatibility
|
|
121
|
+
|
|
122
|
+
```
|
|
123
|
+
[high] src/runtime/child-pi.ts:45
|
|
124
|
+
Issue: `spawn("cmd", ["/c", ...])` on Windows fails with `&&` in commands.
|
|
125
|
+
Impact: Background runs with multiple commands silently fail on Windows.
|
|
126
|
+
Fix: Use explicit argv array instead of shell string concatenation.
|
|
127
|
+
Verification: Test background run with multiple commands on Windows.
|
|
128
|
+
```
|
|
129
|
+
|
|
42
130
|
## Handling Review Feedback
|
|
43
131
|
|
|
44
132
|
When receiving feedback:
|