@chllming/wave-orchestration 0.6.2 → 0.7.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +64 -1
- package/README.md +44 -8
- package/docs/agents/wave-orchestrator-role.md +50 -0
- package/docs/agents/wave-planner-role.md +39 -0
- package/docs/context7/bundles.json +9 -0
- package/docs/context7/planner-agent/README.md +25 -0
- package/docs/context7/planner-agent/manifest.json +83 -0
- package/docs/context7/planner-agent/papers/cooperbench-why-coding-agents-cannot-be-your-teammates-yet.md +3283 -0
- package/docs/context7/planner-agent/papers/dova-deliberation-first-multi-agent-orchestration-for-autonomous-research-automation.md +1699 -0
- package/docs/context7/planner-agent/papers/dpbench-large-language-models-struggle-with-simultaneous-coordination.md +2251 -0
- package/docs/context7/planner-agent/papers/incremental-planning-to-control-a-blackboard-based-problem-solver.md +1729 -0
- package/docs/context7/planner-agent/papers/silo-bench-a-scalable-environment-for-evaluating-distributed-coordination-in-multi-agent-llm-systems.md +3747 -0
- package/docs/context7/planner-agent/papers/todoevolve-learning-to-architect-agent-planning-systems.md +1675 -0
- package/docs/context7/planner-agent/papers/verified-multi-agent-orchestration-a-plan-execute-verify-replan-framework-for-complex-query-resolution.md +1173 -0
- package/docs/context7/planner-agent/papers/why-do-multi-agent-llm-systems-fail.md +5211 -0
- package/docs/context7/planner-agent/topics/planning-and-orchestration.md +24 -0
- package/docs/evals/README.md +96 -1
- package/docs/evals/arm-templates/README.md +13 -0
- package/docs/evals/arm-templates/full-wave.json +15 -0
- package/docs/evals/arm-templates/single-agent.json +15 -0
- package/docs/evals/benchmark-catalog.json +7 -0
- package/docs/evals/cases/README.md +47 -0
- package/docs/evals/cases/wave-blackboard-inbox-targeting.json +73 -0
- package/docs/evals/cases/wave-contradiction-conflict.json +104 -0
- package/docs/evals/cases/wave-expert-routing-preservation.json +69 -0
- package/docs/evals/cases/wave-hidden-profile-private-evidence.json +81 -0
- package/docs/evals/cases/wave-premature-closure-guard.json +71 -0
- package/docs/evals/cases/wave-silo-cross-agent-state.json +77 -0
- package/docs/evals/cases/wave-simultaneous-lockstep.json +92 -0
- package/docs/evals/cooperbench/real-world-mitigation.md +341 -0
- package/docs/evals/external-benchmarks.json +85 -0
- package/docs/evals/external-command-config.sample.json +9 -0
- package/docs/evals/external-command-config.swe-bench-pro.json +8 -0
- package/docs/evals/pilots/README.md +47 -0
- package/docs/evals/pilots/swe-bench-pro-public-full-wave-review-10.json +64 -0
- package/docs/evals/pilots/swe-bench-pro-public-pilot.json +111 -0
- package/docs/evals/wave-benchmark-program.md +302 -0
- package/docs/guides/planner.md +48 -11
- package/docs/plans/context7-wave-orchestrator.md +20 -0
- package/docs/plans/current-state.md +9 -1
- package/docs/plans/examples/wave-benchmark-improvement.md +108 -0
- package/docs/plans/examples/wave-example-live-proof.md +1 -1
- package/docs/plans/examples/wave-example-rollout-fidelity.md +340 -0
- package/docs/plans/wave-orchestrator.md +73 -11
- package/docs/plans/waves/reviews/wave-1-benchmark-operator.md +118 -0
- package/docs/reference/coordination-and-closure.md +436 -0
- package/docs/reference/live-proof-waves.md +25 -3
- package/docs/reference/npmjs-trusted-publishing.md +3 -3
- package/docs/reference/proof-metrics.md +90 -0
- package/docs/reference/runtime-config/README.md +61 -0
- package/docs/reference/sample-waves.md +29 -18
- package/docs/reference/wave-control.md +164 -0
- package/docs/reference/wave-planning-lessons.md +131 -0
- package/package.json +5 -4
- package/releases/manifest.json +33 -0
- package/scripts/research/agent-context-archive.mjs +18 -0
- package/scripts/research/manifests/agent-context-expanded-2026-03-22.mjs +17 -0
- package/scripts/research/sync-planner-context7-bundle.mjs +133 -0
- package/scripts/wave-autonomous.mjs +2 -4
- package/scripts/wave-orchestrator/adhoc.mjs +32 -11
- package/scripts/wave-orchestrator/artifact-schemas.mjs +232 -0
- package/scripts/wave-orchestrator/autonomous.mjs +27 -6
- package/scripts/wave-orchestrator/benchmark-cases.mjs +374 -0
- package/scripts/wave-orchestrator/benchmark-external.mjs +1384 -0
- package/scripts/wave-orchestrator/benchmark.mjs +972 -0
- package/scripts/wave-orchestrator/clarification-triage.mjs +78 -12
- package/scripts/wave-orchestrator/config.mjs +175 -0
- package/scripts/wave-orchestrator/control-cli.mjs +1123 -0
- package/scripts/wave-orchestrator/control-plane.mjs +697 -0
- package/scripts/wave-orchestrator/coord-cli.mjs +360 -2
- package/scripts/wave-orchestrator/coordination-store.mjs +211 -9
- package/scripts/wave-orchestrator/coordination.mjs +84 -0
- package/scripts/wave-orchestrator/dashboard-renderer.mjs +38 -3
- package/scripts/wave-orchestrator/dashboard-state.mjs +22 -0
- package/scripts/wave-orchestrator/evals.mjs +23 -0
- package/scripts/wave-orchestrator/executors.mjs +3 -2
- package/scripts/wave-orchestrator/feedback.mjs +55 -0
- package/scripts/wave-orchestrator/install.mjs +253 -26
- package/scripts/wave-orchestrator/launcher-closure.mjs +4 -1
- package/scripts/wave-orchestrator/launcher-runtime.mjs +24 -21
- package/scripts/wave-orchestrator/launcher.mjs +800 -35
- package/scripts/wave-orchestrator/package-update-notice.mjs +230 -0
- package/scripts/wave-orchestrator/package-version.mjs +32 -0
- package/scripts/wave-orchestrator/planner-context.mjs +75 -0
- package/scripts/wave-orchestrator/planner.mjs +2270 -136
- package/scripts/wave-orchestrator/proof-cli.mjs +195 -0
- package/scripts/wave-orchestrator/proof-registry.mjs +317 -0
- package/scripts/wave-orchestrator/replay.mjs +10 -4
- package/scripts/wave-orchestrator/retry-cli.mjs +184 -0
- package/scripts/wave-orchestrator/retry-control.mjs +225 -0
- package/scripts/wave-orchestrator/shared.mjs +26 -0
- package/scripts/wave-orchestrator/swe-bench-pro-task.mjs +1004 -0
- package/scripts/wave-orchestrator/traces.mjs +157 -2
- package/scripts/wave-orchestrator/wave-control-client.mjs +532 -0
- package/scripts/wave-orchestrator/wave-control-schema.mjs +309 -0
- package/scripts/wave-orchestrator/wave-files.mjs +17 -5
- package/scripts/wave.mjs +39 -2
- package/skills/repo-coding-rules/SKILL.md +1 -0
- package/skills/role-cont-eval/SKILL.md +1 -0
- package/skills/role-cont-qa/SKILL.md +13 -6
- package/skills/role-deploy/SKILL.md +1 -0
- package/skills/role-documentation/SKILL.md +4 -0
- package/skills/role-implementation/SKILL.md +4 -0
- package/skills/role-infra/SKILL.md +2 -1
- package/skills/role-integration/SKILL.md +15 -8
- package/skills/role-planner/SKILL.md +39 -0
- package/skills/role-planner/skill.json +21 -0
- package/skills/role-research/SKILL.md +1 -0
- package/skills/role-security/SKILL.md +2 -2
- package/skills/runtime-claude/SKILL.md +2 -1
- package/skills/runtime-codex/SKILL.md +1 -0
- package/skills/runtime-local/SKILL.md +2 -0
- package/skills/runtime-opencode/SKILL.md +1 -0
- package/skills/wave-core/SKILL.md +25 -6
- package/skills/wave-core/references/marker-syntax.md +16 -8
- package/wave.config.json +45 -0
|
@@ -2,7 +2,10 @@ import crypto from "node:crypto";
|
|
|
2
2
|
import fs from "node:fs";
|
|
3
3
|
import path from "node:path";
|
|
4
4
|
import {
|
|
5
|
+
DEFAULT_COORDINATION_ACK_TIMEOUT_MS,
|
|
6
|
+
DEFAULT_COORDINATION_RESOLUTION_STALE_MS,
|
|
5
7
|
REPO_ROOT,
|
|
8
|
+
buildLanePaths,
|
|
6
9
|
compactSingleLine,
|
|
7
10
|
ensureDirectory,
|
|
8
11
|
readJsonOrNull,
|
|
@@ -10,6 +13,7 @@ import {
|
|
|
10
13
|
truncate,
|
|
11
14
|
writeTextAtomic,
|
|
12
15
|
} from "./shared.mjs";
|
|
16
|
+
import { safeQueueWaveControlEvent } from "./wave-control-client.mjs";
|
|
13
17
|
|
|
14
18
|
export const COORDINATION_KIND_VALUES = [
|
|
15
19
|
"request",
|
|
@@ -147,6 +151,50 @@ export function appendCoordinationRecord(filePath, rawRecord, defaults = {}) {
|
|
|
147
151
|
const record = normalizeCoordinationRecord(rawRecord, defaults);
|
|
148
152
|
ensureDirectory(path.dirname(filePath));
|
|
149
153
|
fs.appendFileSync(filePath, `${JSON.stringify(record)}\n`, "utf8");
|
|
154
|
+
const runIdHint = normalizeString(rawRecord?.runId ?? defaults.runId, "");
|
|
155
|
+
try {
|
|
156
|
+
const lanePaths = buildLanePaths(record.lane, {
|
|
157
|
+
...(runIdHint ? { adhocRunId: runIdHint } : {}),
|
|
158
|
+
});
|
|
159
|
+
if (lanePaths?.waveControl?.captureCoordinationRecords !== false) {
|
|
160
|
+
safeQueueWaveControlEvent(lanePaths, {
|
|
161
|
+
category: "coordination",
|
|
162
|
+
entityType: "coordination_record",
|
|
163
|
+
entityId: record.id,
|
|
164
|
+
action: "recorded",
|
|
165
|
+
source: record.source,
|
|
166
|
+
actor: record.agentId,
|
|
167
|
+
recordedAt: record.updatedAt || record.createdAt,
|
|
168
|
+
identity: {
|
|
169
|
+
lane: record.lane,
|
|
170
|
+
wave: record.wave,
|
|
171
|
+
attempt: record.attempt,
|
|
172
|
+
agentId: record.agentId,
|
|
173
|
+
runKind: lanePaths.runKind,
|
|
174
|
+
runId: lanePaths.runId,
|
|
175
|
+
},
|
|
176
|
+
tags: [`kind:${record.kind}`, `status:${record.status}`],
|
|
177
|
+
data: {
|
|
178
|
+
kind: record.kind,
|
|
179
|
+
status: record.status,
|
|
180
|
+
priority: record.priority,
|
|
181
|
+
confidence: record.confidence,
|
|
182
|
+
summary: record.summary,
|
|
183
|
+
detail: record.detail,
|
|
184
|
+
targets: record.targets,
|
|
185
|
+
artifactRefs: record.artifactRefs,
|
|
186
|
+
dependsOn: record.dependsOn,
|
|
187
|
+
closureCondition: record.closureCondition,
|
|
188
|
+
required: record.required,
|
|
189
|
+
executorId: record.executorId || null,
|
|
190
|
+
requesterLane: record.requesterLane || null,
|
|
191
|
+
ownerLane: record.ownerLane || null,
|
|
192
|
+
},
|
|
193
|
+
});
|
|
194
|
+
}
|
|
195
|
+
} catch {
|
|
196
|
+
// Telemetry is best-effort and must never block canonical coordination writes.
|
|
197
|
+
}
|
|
150
198
|
return record;
|
|
151
199
|
}
|
|
152
200
|
|
|
@@ -311,11 +359,137 @@ export function serializeCoordinationState(state) {
|
|
|
311
359
|
};
|
|
312
360
|
}
|
|
313
361
|
|
|
314
|
-
function
|
|
362
|
+
function parseRecordStartMs(record) {
|
|
363
|
+
const createdAtMs = Date.parse(record?.createdAt || "");
|
|
364
|
+
if (Number.isFinite(createdAtMs)) {
|
|
365
|
+
return createdAtMs;
|
|
366
|
+
}
|
|
367
|
+
const updatedAtMs = Date.parse(record?.updatedAt || "");
|
|
368
|
+
return Number.isFinite(updatedAtMs) ? updatedAtMs : null;
|
|
369
|
+
}
|
|
370
|
+
|
|
371
|
+
function formatAgeMs(ageMs) {
|
|
372
|
+
if (!Number.isFinite(ageMs)) {
|
|
373
|
+
return "n/a";
|
|
374
|
+
}
|
|
375
|
+
const totalSeconds = Math.max(0, Math.floor(ageMs / 1000));
|
|
376
|
+
if (totalSeconds < 60) {
|
|
377
|
+
return `${totalSeconds}s`;
|
|
378
|
+
}
|
|
379
|
+
const minutes = Math.floor(totalSeconds / 60);
|
|
380
|
+
if (minutes < 60) {
|
|
381
|
+
return `${minutes}m`;
|
|
382
|
+
}
|
|
383
|
+
const hours = Math.floor(minutes / 60);
|
|
384
|
+
return `${hours}h ${minutes % 60}m`;
|
|
385
|
+
}
|
|
386
|
+
|
|
387
|
+
function isAckTrackedRecord(record) {
|
|
388
|
+
if (!record || typeof record !== "object") {
|
|
389
|
+
return false;
|
|
390
|
+
}
|
|
391
|
+
if (["clarification-request", "human-feedback", "human-escalation"].includes(record.kind)) {
|
|
392
|
+
return true;
|
|
393
|
+
}
|
|
394
|
+
if (record.kind !== "request") {
|
|
395
|
+
return false;
|
|
396
|
+
}
|
|
397
|
+
return record.source !== "launcher" || isClarificationLinkedRequest(record);
|
|
398
|
+
}
|
|
399
|
+
|
|
400
|
+
export function buildCoordinationResponseMetrics(state, options = {}) {
|
|
401
|
+
const nowMs = Number.isFinite(options.nowMs) ? options.nowMs : Date.now();
|
|
402
|
+
const ackTimeoutMs = Number.isFinite(options.ackTimeoutMs)
|
|
403
|
+
? options.ackTimeoutMs
|
|
404
|
+
: DEFAULT_COORDINATION_ACK_TIMEOUT_MS;
|
|
405
|
+
const resolutionStaleMs = Number.isFinite(options.resolutionStaleMs)
|
|
406
|
+
? options.resolutionStaleMs
|
|
407
|
+
: DEFAULT_COORDINATION_RESOLUTION_STALE_MS;
|
|
408
|
+
const recordMetricsById = new Map();
|
|
409
|
+
const overdueAckRecordIds = [];
|
|
410
|
+
const overdueClarificationIds = new Set();
|
|
411
|
+
let oldestOpenCoordinationAgeMs = null;
|
|
412
|
+
let oldestUnackedRequestAgeMs = null;
|
|
413
|
+
|
|
414
|
+
for (const record of state?.openRecords || []) {
|
|
415
|
+
const startMs = parseRecordStartMs(record);
|
|
416
|
+
const ageMs = Number.isFinite(startMs) ? Math.max(0, nowMs - startMs) : null;
|
|
417
|
+
const ackTracked = isAckTrackedRecord(record);
|
|
418
|
+
const ackPending = ackTracked && record.status === "open";
|
|
419
|
+
const clarificationLinked =
|
|
420
|
+
record.kind === "clarification-request" || isClarificationLinkedRequest(record);
|
|
421
|
+
const overdueAck = ackPending && Number.isFinite(ageMs) && ageMs >= ackTimeoutMs;
|
|
422
|
+
const staleClarification =
|
|
423
|
+
clarificationLinked && Number.isFinite(ageMs) && ageMs >= resolutionStaleMs;
|
|
424
|
+
|
|
425
|
+
if (Number.isFinite(ageMs)) {
|
|
426
|
+
oldestOpenCoordinationAgeMs =
|
|
427
|
+
oldestOpenCoordinationAgeMs === null
|
|
428
|
+
? ageMs
|
|
429
|
+
: Math.max(oldestOpenCoordinationAgeMs, ageMs);
|
|
430
|
+
if (ackPending) {
|
|
431
|
+
oldestUnackedRequestAgeMs =
|
|
432
|
+
oldestUnackedRequestAgeMs === null
|
|
433
|
+
? ageMs
|
|
434
|
+
: Math.max(oldestUnackedRequestAgeMs, ageMs);
|
|
435
|
+
}
|
|
436
|
+
}
|
|
437
|
+
if (overdueAck) {
|
|
438
|
+
overdueAckRecordIds.push(record.id);
|
|
439
|
+
}
|
|
440
|
+
if (staleClarification) {
|
|
441
|
+
overdueClarificationIds.add(
|
|
442
|
+
record.kind === "clarification-request"
|
|
443
|
+
? record.id
|
|
444
|
+
: clarificationIdFromClosureCondition(record.closureCondition) || record.id,
|
|
445
|
+
);
|
|
446
|
+
}
|
|
447
|
+
recordMetricsById.set(record.id, {
|
|
448
|
+
ageMs,
|
|
449
|
+
ageLabel: formatAgeMs(ageMs),
|
|
450
|
+
ackTracked,
|
|
451
|
+
ackPending,
|
|
452
|
+
overdueAck,
|
|
453
|
+
clarificationLinked,
|
|
454
|
+
staleClarification,
|
|
455
|
+
});
|
|
456
|
+
}
|
|
457
|
+
|
|
458
|
+
return {
|
|
459
|
+
ackTimeoutMs,
|
|
460
|
+
resolutionStaleMs,
|
|
461
|
+
oldestOpenCoordinationAgeMs,
|
|
462
|
+
oldestUnackedRequestAgeMs,
|
|
463
|
+
overdueAckCount: overdueAckRecordIds.length,
|
|
464
|
+
overdueClarificationCount: overdueClarificationIds.size,
|
|
465
|
+
overdueAckRecordIds: overdueAckRecordIds.toSorted((a, b) => a.localeCompare(b)),
|
|
466
|
+
overdueClarificationIds: Array.from(overdueClarificationIds).toSorted((a, b) =>
|
|
467
|
+
a.localeCompare(b),
|
|
468
|
+
),
|
|
469
|
+
openHumanEscalationCount: (state?.humanEscalations || []).filter((record) =>
|
|
470
|
+
isOpenCoordinationStatus(record.status),
|
|
471
|
+
).length,
|
|
472
|
+
recordMetricsById,
|
|
473
|
+
};
|
|
474
|
+
}
|
|
475
|
+
|
|
476
|
+
function renderOpenRecord(record, responseMetrics = null) {
|
|
315
477
|
const targets = record.targets.length > 0 ? ` -> ${record.targets.join(", ")}` : "";
|
|
316
478
|
const artifacts =
|
|
317
479
|
record.artifactRefs.length > 0 ? ` [artifacts: ${record.artifactRefs.join(", ")}]` : "";
|
|
318
|
-
|
|
480
|
+
const recordMetrics = responseMetrics?.recordMetricsById?.get?.(record.id) || null;
|
|
481
|
+
const tags = [];
|
|
482
|
+
if (recordMetrics?.ageLabel && recordMetrics.ageLabel !== "n/a") {
|
|
483
|
+
tags.push(`age=${recordMetrics.ageLabel}`);
|
|
484
|
+
}
|
|
485
|
+
if (recordMetrics?.overdueAck) {
|
|
486
|
+
tags.push("overdue-ack");
|
|
487
|
+
}
|
|
488
|
+
if (recordMetrics?.staleClarification) {
|
|
489
|
+
tags.push("stale-clarification");
|
|
490
|
+
}
|
|
491
|
+
const timing = tags.length > 0 ? ` [${tags.join(", ")}]` : "";
|
|
492
|
+
return `- [${record.priority}] ${record.kind}/${record.status} ${record.agentId}${targets}${timing} id=${record.id}: ${compactSingleLine(record.summary || record.detail || "no summary", 160)}${artifacts}`;
|
|
319
493
|
}
|
|
320
494
|
|
|
321
495
|
function renderActivityRecord(record) {
|
|
@@ -345,6 +519,7 @@ export function renderCoordinationBoardProjection({
|
|
|
345
519
|
state,
|
|
346
520
|
capabilityAssignments = [],
|
|
347
521
|
dependencySnapshot = null,
|
|
522
|
+
timingOptions = null,
|
|
348
523
|
}) {
|
|
349
524
|
const latestRecords = Array.isArray(state?.latestRecords) ? state.latestRecords : [];
|
|
350
525
|
const openRecords = latestRecords.filter((record) => OPEN_COORDINATION_STATUSES.has(record.status));
|
|
@@ -352,16 +527,29 @@ export function renderCoordinationBoardProjection({
|
|
|
352
527
|
const openAssignments = (capabilityAssignments || []).filter((assignment) => assignment.blocking);
|
|
353
528
|
const openInboundDependencies = dependencySnapshot?.openInbound || [];
|
|
354
529
|
const openOutboundDependencies = dependencySnapshot?.openOutbound || [];
|
|
530
|
+
const responseMetrics = buildCoordinationResponseMetrics(state, timingOptions || {});
|
|
531
|
+
const oldestOpenAge =
|
|
532
|
+
responseMetrics.oldestOpenCoordinationAgeMs === null
|
|
533
|
+
? "none"
|
|
534
|
+
: formatAgeMs(responseMetrics.oldestOpenCoordinationAgeMs);
|
|
535
|
+
const oldestUnackedAge =
|
|
536
|
+
responseMetrics.oldestUnackedRequestAgeMs === null
|
|
537
|
+
? "none"
|
|
538
|
+
: formatAgeMs(responseMetrics.oldestUnackedRequestAgeMs);
|
|
355
539
|
return [
|
|
356
540
|
`# Wave ${wave} Message Board`,
|
|
357
541
|
"",
|
|
358
542
|
`- Wave file: \`${waveFile}\``,
|
|
359
543
|
`- Agents: ${(agents || []).map((agent) => agent.agentId).join(", ")}`,
|
|
360
544
|
`- Generated: ${toIsoTimestamp()}`,
|
|
545
|
+
`- Oldest open coordination age: ${oldestOpenAge}`,
|
|
546
|
+
`- Oldest unacknowledged request age: ${oldestUnackedAge}`,
|
|
547
|
+
`- Overdue acknowledgements: ${responseMetrics.overdueAckCount}`,
|
|
548
|
+
`- Overdue clarification chains: ${responseMetrics.overdueClarificationCount}`,
|
|
361
549
|
"",
|
|
362
550
|
"## Open Coordination State",
|
|
363
551
|
...(openRecords.length > 0
|
|
364
|
-
? openRecords.map((record) => renderOpenRecord(record))
|
|
552
|
+
? openRecords.map((record) => renderOpenRecord(record, responseMetrics))
|
|
365
553
|
: ["- None."]),
|
|
366
554
|
"",
|
|
367
555
|
"## Helper Assignments",
|
|
@@ -457,6 +645,7 @@ export function compileSharedSummary({
|
|
|
457
645
|
capabilityAssignments = [],
|
|
458
646
|
dependencySnapshot = null,
|
|
459
647
|
maxChars = 4000,
|
|
648
|
+
timingOptions = null,
|
|
460
649
|
}) {
|
|
461
650
|
const openBlockers = state.blockers.filter((record) => OPEN_COORDINATION_STATUSES.has(record.status));
|
|
462
651
|
const openRequests = state.requests.filter((record) => OPEN_COORDINATION_STATUSES.has(record.status));
|
|
@@ -469,6 +658,7 @@ export function compileSharedSummary({
|
|
|
469
658
|
const openHelperAssignments = (capabilityAssignments || []).filter((assignment) => assignment.blocking);
|
|
470
659
|
const openInboundDependencies = dependencySnapshot?.openInbound || [];
|
|
471
660
|
const openOutboundDependencies = dependencySnapshot?.openOutbound || [];
|
|
661
|
+
const responseMetrics = buildCoordinationResponseMetrics(state, timingOptions || {});
|
|
472
662
|
const summary = [
|
|
473
663
|
`# Wave ${wave.wave} Shared Summary`,
|
|
474
664
|
"",
|
|
@@ -480,6 +670,10 @@ export function compileSharedSummary({
|
|
|
480
670
|
`- Open helper assignments: ${openHelperAssignments.length}`,
|
|
481
671
|
`- Open inbound dependencies: ${openInboundDependencies.length}`,
|
|
482
672
|
`- Open outbound dependencies: ${openOutboundDependencies.length}`,
|
|
673
|
+
`- Oldest open coordination age: ${responseMetrics.oldestOpenCoordinationAgeMs === null ? "none" : formatAgeMs(responseMetrics.oldestOpenCoordinationAgeMs)}`,
|
|
674
|
+
`- Oldest unacknowledged request age: ${responseMetrics.oldestUnackedRequestAgeMs === null ? "none" : formatAgeMs(responseMetrics.oldestUnackedRequestAgeMs)}`,
|
|
675
|
+
`- Overdue acknowledgements: ${responseMetrics.overdueAckCount}`,
|
|
676
|
+
`- Overdue clarification chains: ${responseMetrics.overdueClarificationCount}`,
|
|
483
677
|
...(integrationSummary
|
|
484
678
|
? [`- Integration recommendation: ${integrationSummary.recommendation || "n/a"}`]
|
|
485
679
|
: []),
|
|
@@ -498,12 +692,12 @@ export function compileSharedSummary({
|
|
|
498
692
|
"",
|
|
499
693
|
"## Current blockers",
|
|
500
694
|
...(openBlockers.length > 0
|
|
501
|
-
? openBlockers.map((record) => renderOpenRecord(record))
|
|
695
|
+
? openBlockers.map((record) => renderOpenRecord(record, responseMetrics))
|
|
502
696
|
: ["- None."]),
|
|
503
697
|
"",
|
|
504
698
|
"## Current clarifications",
|
|
505
699
|
...(openClarifications.length > 0
|
|
506
|
-
? openClarifications.map((record) => renderOpenRecord(record))
|
|
700
|
+
? openClarifications.map((record) => renderOpenRecord(record, responseMetrics))
|
|
507
701
|
: ["- None."]),
|
|
508
702
|
"",
|
|
509
703
|
"## Helper assignments",
|
|
@@ -588,6 +782,7 @@ export function compileAgentInbox({
|
|
|
588
782
|
capabilityAssignments = [],
|
|
589
783
|
dependencySnapshot = null,
|
|
590
784
|
maxChars = 8000,
|
|
785
|
+
timingOptions = null,
|
|
591
786
|
}) {
|
|
592
787
|
const targetedRecords = state.openRecords.filter((record) => isTargetedToAgent(record, agent));
|
|
593
788
|
const ownedRecords = (state.recordsByAgentId.get(agent.agentId) || []).filter((record) =>
|
|
@@ -624,6 +819,7 @@ export function compileAgentInbox({
|
|
|
624
819
|
const helperAssignments = (capabilityAssignments || []).filter(
|
|
625
820
|
(assignment) => assignment.blocking && assignment.assignedAgentId === agent.agentId,
|
|
626
821
|
);
|
|
822
|
+
const responseMetrics = buildCoordinationResponseMetrics(state, timingOptions || {});
|
|
627
823
|
const dependencyItems = [
|
|
628
824
|
...((dependencySnapshot?.inbound || []).filter(
|
|
629
825
|
(record) =>
|
|
@@ -641,24 +837,30 @@ export function compileAgentInbox({
|
|
|
641
837
|
const text = [
|
|
642
838
|
`# Wave ${wave.wave} Inbox for ${agent.agentId}`,
|
|
643
839
|
"",
|
|
840
|
+
"## Response timing",
|
|
841
|
+
`- Oldest open coordination age: ${responseMetrics.oldestOpenCoordinationAgeMs === null ? "none" : formatAgeMs(responseMetrics.oldestOpenCoordinationAgeMs)}`,
|
|
842
|
+
`- Oldest unacknowledged request age: ${responseMetrics.oldestUnackedRequestAgeMs === null ? "none" : formatAgeMs(responseMetrics.oldestUnackedRequestAgeMs)}`,
|
|
843
|
+
`- Overdue acknowledgements: ${responseMetrics.overdueAckCount}`,
|
|
844
|
+
`- Overdue clarification chains: ${responseMetrics.overdueClarificationCount}`,
|
|
845
|
+
"",
|
|
644
846
|
"## Targeted open coordination",
|
|
645
847
|
...(targetedRecords.length > 0
|
|
646
|
-
? targetedRecords.map((record) => renderOpenRecord(record))
|
|
848
|
+
? targetedRecords.map((record) => renderOpenRecord(record, responseMetrics))
|
|
647
849
|
: ["- None."]),
|
|
648
850
|
"",
|
|
649
851
|
"## Your open coordination items",
|
|
650
852
|
...(ownedRecords.length > 0
|
|
651
|
-
? ownedRecords.map((record) => renderOpenRecord(record))
|
|
853
|
+
? ownedRecords.map((record) => renderOpenRecord(record, responseMetrics))
|
|
652
854
|
: ["- None."]),
|
|
653
855
|
"",
|
|
654
856
|
"## Clarifications",
|
|
655
857
|
...(clarificationRecords.length > 0
|
|
656
|
-
? clarificationRecords.map((record) => renderOpenRecord(record))
|
|
858
|
+
? clarificationRecords.map((record) => renderOpenRecord(record, responseMetrics))
|
|
657
859
|
: ["- None."]),
|
|
658
860
|
"",
|
|
659
861
|
"## Relevant open coordination",
|
|
660
862
|
...(relevantRecords.length > 0
|
|
661
|
-
? relevantRecords.map((record) => renderOpenRecord(record))
|
|
863
|
+
? relevantRecords.map((record) => renderOpenRecord(record, responseMetrics))
|
|
662
864
|
: ["- None."]),
|
|
663
865
|
"",
|
|
664
866
|
"## Helper assignments",
|
|
@@ -455,6 +455,7 @@ export function buildExecutionPrompt({
|
|
|
455
455
|
"- Follow repository instructions in AGENTS.md and CLAUDE.md if present.",
|
|
456
456
|
"- Read the compiled shared summary and your compiled inbox before taking action on every turn.",
|
|
457
457
|
"- Post a coordination record on every meaningful turn with progress, decisions, blockers, handoffs, evidence, or explicit acknowledgement.",
|
|
458
|
+
"- If your inbox or the coordination log shows a targeted open request for you, your first durable action is to acknowledge it, resolve it, or emit a clarification or human-feedback request. Silent targeted requests are treated as active blockers.",
|
|
458
459
|
"- Re-read the generated board projection before major edits, before commit or push, and before your final report.",
|
|
459
460
|
"- If you change interfaces or contracts, include exact files and exact keys or fields affected.",
|
|
460
461
|
"- If your task touches persisted state, implement the required schema or migration work instead of leaving TODOs.",
|
|
@@ -511,6 +512,89 @@ export function buildExecutionPrompt({
|
|
|
511
512
|
].join("\n");
|
|
512
513
|
}
|
|
513
514
|
|
|
515
|
+
export function buildResidentOrchestratorPrompt({
|
|
516
|
+
lane,
|
|
517
|
+
wave,
|
|
518
|
+
waveFile,
|
|
519
|
+
orchestratorId,
|
|
520
|
+
coordinationLogPath,
|
|
521
|
+
messageBoardPath,
|
|
522
|
+
sharedSummaryPath,
|
|
523
|
+
dashboardPath,
|
|
524
|
+
triagePath = null,
|
|
525
|
+
rolePrompt = "",
|
|
526
|
+
}) {
|
|
527
|
+
const coordinationCommand = [
|
|
528
|
+
"pnpm exec wave coord post",
|
|
529
|
+
`--lane ${lane}`,
|
|
530
|
+
`--wave ${wave}`,
|
|
531
|
+
'--agent "launcher"',
|
|
532
|
+
'--kind "<request|ack|decision|blocker|clarification-request|orchestrator-guidance|resolved-by-policy|human-escalation|human-feedback>"',
|
|
533
|
+
'--summary "<one-line summary>"',
|
|
534
|
+
'--detail "<short detail>"',
|
|
535
|
+
].join(" ");
|
|
536
|
+
const feedbackCommand = [
|
|
537
|
+
"pnpm exec wave-feedback ask",
|
|
538
|
+
`--lane ${lane}`,
|
|
539
|
+
`--wave ${wave}`,
|
|
540
|
+
'--agent "launcher"',
|
|
541
|
+
`--orchestrator-id ${orchestratorId}`,
|
|
542
|
+
'--question "<specific clarification needed>"',
|
|
543
|
+
'--context "<why repo-state or routed ownership was insufficient>"',
|
|
544
|
+
"--timeout-seconds 30",
|
|
545
|
+
].join(" ");
|
|
546
|
+
const roleSection = String(rolePrompt || "").trim();
|
|
547
|
+
return [
|
|
548
|
+
`Working directory: ${REPO_ROOT}`,
|
|
549
|
+
"",
|
|
550
|
+
`You are the resident Wave orchestrator for lane ${lane}, wave ${wave}.`,
|
|
551
|
+
"Your job is to stay alive for the duration of the wave, monitor coordination state, and intervene when timing, routing, or escalation policy requires it.",
|
|
552
|
+
"The launcher remains the scheduler truth and closure authority. You are an intervention and triage role, not a product-code owner.",
|
|
553
|
+
"",
|
|
554
|
+
"Hard limits:",
|
|
555
|
+
"- Do not edit product code, test code, docs, or owned deliverables.",
|
|
556
|
+
"- Do not claim another agent's ownership slice or emit proof markers for owned implementation work.",
|
|
557
|
+
"- Do not declare the wave complete or override launcher gate results.",
|
|
558
|
+
"",
|
|
559
|
+
"Primary responsibilities:",
|
|
560
|
+
"- Monitor the canonical coordination log, shared summary, wave dashboard, and feedback triage artifacts.",
|
|
561
|
+
"- Keep clarification handling orchestrator-first: resolve from repo state, ownership, prior decisions, or targeted rerouting before opening human escalation.",
|
|
562
|
+
"- Watch for overdue acknowledgements, stale clarification chains, and pending human tickets.",
|
|
563
|
+
"- Post durable coordination records and orchestrator notes when you intervene.",
|
|
564
|
+
"- Stay available. If there is no immediate action to take, keep monitoring instead of exiting early.",
|
|
565
|
+
"",
|
|
566
|
+
"Files for this run:",
|
|
567
|
+
`- Wave file: ${waveFile}`,
|
|
568
|
+
`- Coordination log: ${coordinationLogPath}`,
|
|
569
|
+
`- Shared summary: ${sharedSummaryPath}`,
|
|
570
|
+
`- Wave dashboard: ${dashboardPath}`,
|
|
571
|
+
`- Message board projection: ${messageBoardPath}`,
|
|
572
|
+
...(triagePath ? [`- Feedback triage log: ${triagePath}`] : []),
|
|
573
|
+
"",
|
|
574
|
+
"Action surface:",
|
|
575
|
+
`- Coordination command: \`${coordinationCommand}\``,
|
|
576
|
+
`- Human feedback command: \`${feedbackCommand}\``,
|
|
577
|
+
"- Use repository inspection and read-only analysis aggressively before escalating anything to a human.",
|
|
578
|
+
"- When you route or reroute work, name the owner, exact unblock condition, and the artifact or decision needed.",
|
|
579
|
+
"",
|
|
580
|
+
"Operating loop:",
|
|
581
|
+
"1. Read the shared summary, dashboard, and coordination log.",
|
|
582
|
+
"2. Identify open clarifications, open clarification-linked requests, overdue acknowledgements, and human-feedback state.",
|
|
583
|
+
"3. If action is needed, write a durable coordination update and explain the policy basis for the action.",
|
|
584
|
+
"4. If nothing needs action, continue monitoring. Do not exit until the wave is clearly terminal or the launcher stops the session.",
|
|
585
|
+
"",
|
|
586
|
+
...(roleSection
|
|
587
|
+
? [
|
|
588
|
+
"Resident orchestrator role prompt:",
|
|
589
|
+
"```text",
|
|
590
|
+
roleSection,
|
|
591
|
+
"```",
|
|
592
|
+
"",
|
|
593
|
+
]
|
|
594
|
+
: []),
|
|
595
|
+
].join("\n");
|
|
596
|
+
}
|
|
597
|
+
|
|
514
598
|
export function buildOrchestratorBoardTemplate(boardPath) {
|
|
515
599
|
const now = toIsoTimestamp();
|
|
516
600
|
return [
|
|
@@ -182,6 +182,22 @@ function paintWaveAgentSummary(summary, wave, colorize = false) {
|
|
|
182
182
|
return paint(summary, color, colorize);
|
|
183
183
|
}
|
|
184
184
|
|
|
185
|
+
function formatDurationMs(value) {
|
|
186
|
+
if (!Number.isFinite(value)) {
|
|
187
|
+
return "n/a";
|
|
188
|
+
}
|
|
189
|
+
const totalSeconds = Math.max(0, Math.floor(value / 1000));
|
|
190
|
+
if (totalSeconds < 60) {
|
|
191
|
+
return `${totalSeconds}s`;
|
|
192
|
+
}
|
|
193
|
+
const minutes = Math.floor(totalSeconds / 60);
|
|
194
|
+
if (minutes < 60) {
|
|
195
|
+
return `${minutes}m`;
|
|
196
|
+
}
|
|
197
|
+
const hours = Math.floor(minutes / 60);
|
|
198
|
+
return `${hours}h ${minutes % 60}m`;
|
|
199
|
+
}
|
|
200
|
+
|
|
185
201
|
function renderWaveDashboard({ state, dashboardPath, messageBoardPath, lane, colorize = false }) {
|
|
186
202
|
if (!state) {
|
|
187
203
|
return `Dashboard file not found or invalid: ${dashboardPath}`;
|
|
@@ -200,15 +216,21 @@ function renderWaveDashboard({ state, dashboardPath, messageBoardPath, lane, col
|
|
|
200
216
|
);
|
|
201
217
|
lines.push(`Run tag: ${state.runTag || "n/a"} | Wave file: ${state.waveFile || "n/a"}`);
|
|
202
218
|
lines.push(`Counts: ${renderColoredCountsByState(state.agents || [], colorize) || "none"}`);
|
|
219
|
+
lines.push(
|
|
220
|
+
`Coordination: open=${state.coordinationOpen ?? 0} clarifications=${state.openClarifications ?? 0} human=${state.openHumanEscalations ?? 0} overdue-ack=${state.overdueAckCount ?? 0} overdue-clarification=${state.overdueClarificationCount ?? 0}`,
|
|
221
|
+
);
|
|
222
|
+
lines.push(
|
|
223
|
+
`Coordination age: oldest-open=${formatDurationMs(state.oldestOpenCoordinationAgeMs)} oldest-unack=${formatDurationMs(state.oldestUnackedRequestAgeMs)}`,
|
|
224
|
+
);
|
|
203
225
|
const comms = analyzeMessageBoardCommunication(messageBoardPath);
|
|
204
226
|
if (!comms.available) {
|
|
205
|
-
lines.push(`
|
|
227
|
+
lines.push(`Board comms: unavailable ${comms.reason || ""}`.trim());
|
|
206
228
|
} else {
|
|
207
229
|
lines.push(
|
|
208
|
-
`
|
|
230
|
+
`Board comms: requests=${comms.actionableRequests} unresolved=${comms.unresolvedRequests} unacknowledged=${comms.unacknowledgedRequests} malformed=${comms.malformedEntries} placeholder-ts=${comms.placeholderTimestampEntries}`,
|
|
209
231
|
);
|
|
210
232
|
lines.push(
|
|
211
|
-
`
|
|
233
|
+
`Board comms age: last-ack=${commsAgeSummary(comms.lastAcknowledgementTimestamp)} oldest-unack=${commsAgeSummary(comms.oldestUnacknowledgedTimestamp)}`,
|
|
212
234
|
);
|
|
213
235
|
}
|
|
214
236
|
lines.push("");
|
|
@@ -306,6 +328,19 @@ function renderGlobalDashboard({ state, dashboardPath, lane, colorize = false })
|
|
|
306
328
|
12,
|
|
307
329
|
)} ${truncate(wave.lastMessage || "", 70)}`,
|
|
308
330
|
);
|
|
331
|
+
if (
|
|
332
|
+
Number(wave?.coordinationOpen ?? 0) > 0 ||
|
|
333
|
+
Number(wave?.overdueAckCount ?? 0) > 0 ||
|
|
334
|
+
Number(wave?.overdueClarificationCount ?? 0) > 0 ||
|
|
335
|
+
Number(wave?.openHumanEscalations ?? 0) > 0
|
|
336
|
+
) {
|
|
337
|
+
lines.push(
|
|
338
|
+
` Coord: open ${wave.coordinationOpen ?? 0} clarifications ${wave.openClarifications ?? 0} human ${wave.openHumanEscalations ?? 0} overdue-ack ${wave.overdueAckCount ?? 0} overdue-clarification ${wave.overdueClarificationCount ?? 0}`,
|
|
339
|
+
);
|
|
340
|
+
lines.push(
|
|
341
|
+
` Ages: oldest-open ${formatDurationMs(wave.oldestOpenCoordinationAgeMs)} oldest-unack ${formatDurationMs(wave.oldestUnackedRequestAgeMs)}`,
|
|
342
|
+
);
|
|
343
|
+
}
|
|
309
344
|
const deployments = Array.isArray(wave.deployments) ? wave.deployments : [];
|
|
310
345
|
if (deployments.length > 0) {
|
|
311
346
|
const deployLine = deployments
|
|
@@ -149,6 +149,13 @@ export function buildWaveDashboardState({
|
|
|
149
149
|
helperAssignmentsOpen: 0,
|
|
150
150
|
inboundDependenciesOpen: 0,
|
|
151
151
|
outboundDependenciesOpen: 0,
|
|
152
|
+
coordinationOpen: 0,
|
|
153
|
+
openClarifications: 0,
|
|
154
|
+
openHumanEscalations: 0,
|
|
155
|
+
oldestOpenCoordinationAgeMs: null,
|
|
156
|
+
oldestUnackedRequestAgeMs: null,
|
|
157
|
+
overdueAckCount: 0,
|
|
158
|
+
overdueClarificationCount: 0,
|
|
152
159
|
agents: agentRuns.map((run) => ({
|
|
153
160
|
agentId: run.agent.agentId,
|
|
154
161
|
title: run.agent.title,
|
|
@@ -200,6 +207,7 @@ export function buildGlobalDashboardState({
|
|
|
200
207
|
maxRetriesPerWave: options.maxRetriesPerWave,
|
|
201
208
|
dashboard: options.dashboard,
|
|
202
209
|
cleanupSessions: options.cleanupSessions,
|
|
210
|
+
residentOrchestrator: options.residentOrchestrator === true,
|
|
203
211
|
orchestratorId: options.orchestratorId,
|
|
204
212
|
orchestratorBoardPath: options.orchestratorBoardPath
|
|
205
213
|
? path.relative(REPO_ROOT, options.orchestratorBoardPath)
|
|
@@ -235,6 +243,13 @@ export function buildGlobalDashboardState({
|
|
|
235
243
|
helperAssignmentsOpen: 0,
|
|
236
244
|
inboundDependenciesOpen: 0,
|
|
237
245
|
outboundDependenciesOpen: 0,
|
|
246
|
+
coordinationOpen: 0,
|
|
247
|
+
openClarifications: 0,
|
|
248
|
+
openHumanEscalations: 0,
|
|
249
|
+
oldestOpenCoordinationAgeMs: null,
|
|
250
|
+
oldestUnackedRequestAgeMs: null,
|
|
251
|
+
overdueAckCount: 0,
|
|
252
|
+
overdueClarificationCount: 0,
|
|
238
253
|
lastMessage: "",
|
|
239
254
|
deployments: [],
|
|
240
255
|
infraFindings: [],
|
|
@@ -323,6 +338,13 @@ export function syncGlobalWaveFromWaveDashboard(globalState, waveDashboard) {
|
|
|
323
338
|
entry.helperAssignmentsOpen = waveDashboard.helperAssignmentsOpen || 0;
|
|
324
339
|
entry.inboundDependenciesOpen = waveDashboard.inboundDependenciesOpen || 0;
|
|
325
340
|
entry.outboundDependenciesOpen = waveDashboard.outboundDependenciesOpen || 0;
|
|
341
|
+
entry.coordinationOpen = waveDashboard.coordinationOpen || 0;
|
|
342
|
+
entry.openClarifications = waveDashboard.openClarifications || 0;
|
|
343
|
+
entry.openHumanEscalations = waveDashboard.openHumanEscalations || 0;
|
|
344
|
+
entry.oldestOpenCoordinationAgeMs = waveDashboard.oldestOpenCoordinationAgeMs ?? null;
|
|
345
|
+
entry.oldestUnackedRequestAgeMs = waveDashboard.oldestUnackedRequestAgeMs ?? null;
|
|
346
|
+
entry.overdueAckCount = waveDashboard.overdueAckCount || 0;
|
|
347
|
+
entry.overdueClarificationCount = waveDashboard.overdueClarificationCount || 0;
|
|
326
348
|
entry.deployments = agents
|
|
327
349
|
.filter((agent) => agent.deploymentState)
|
|
328
350
|
.map((agent) => ({
|
|
@@ -351,6 +351,12 @@ export function loadBenchmarkCatalog(options = {}) {
|
|
|
351
351
|
id: benchmarkId,
|
|
352
352
|
title: cleanText(benchmark.title) || benchmarkId,
|
|
353
353
|
summary: cleanText(benchmark.summary) || null,
|
|
354
|
+
localCases: normalizeStringArray(
|
|
355
|
+
benchmark.localCases,
|
|
356
|
+
`families.${familyId}.benchmarks.${benchmarkId}.localCases`,
|
|
357
|
+
).map((entry, index) =>
|
|
358
|
+
normalizeEvalTargetId(entry, `families.${familyId}.benchmarks.${benchmarkId}.localCases[${index}]`),
|
|
359
|
+
),
|
|
354
360
|
goal: cleanText(benchmark.goal) || null,
|
|
355
361
|
failureModes: normalizeStringArray(
|
|
356
362
|
benchmark.failureModes,
|
|
@@ -380,6 +386,12 @@ export function loadBenchmarkCatalog(options = {}) {
|
|
|
380
386
|
id: familyId,
|
|
381
387
|
title: cleanText(rawFamily.title) || familyId,
|
|
382
388
|
summary: cleanText(rawFamily.summary) || null,
|
|
389
|
+
localCases: normalizeStringArray(
|
|
390
|
+
rawFamily.localCases,
|
|
391
|
+
`families.${familyId}.localCases`,
|
|
392
|
+
).map((entry, index) =>
|
|
393
|
+
normalizeEvalTargetId(entry, `families.${familyId}.localCases[${index}]`),
|
|
394
|
+
),
|
|
383
395
|
category: cleanText(rawFamily.category) || null,
|
|
384
396
|
coordinationModel: cleanText(rawFamily.coordinationModel) || null,
|
|
385
397
|
primaryMetric: familyPrimaryMetric,
|
|
@@ -395,6 +407,17 @@ export function loadBenchmarkCatalog(options = {}) {
|
|
|
395
407
|
absolutePath,
|
|
396
408
|
families,
|
|
397
409
|
benchmarkIndex,
|
|
410
|
+
localCaseIndex: Object.fromEntries(
|
|
411
|
+
Object.values(families).flatMap((family) => [
|
|
412
|
+
...(family.localCases || []).map((caseId) => [caseId, { familyId: family.id, benchmarkId: null }]),
|
|
413
|
+
...Object.values(family.benchmarks).flatMap((benchmark) =>
|
|
414
|
+
(benchmark.localCases || []).map((caseId) => [
|
|
415
|
+
caseId,
|
|
416
|
+
{ familyId: family.id, benchmarkId: benchmark.id },
|
|
417
|
+
]),
|
|
418
|
+
),
|
|
419
|
+
]),
|
|
420
|
+
),
|
|
398
421
|
};
|
|
399
422
|
}
|
|
400
423
|
|
|
@@ -210,7 +210,8 @@ function buildClaudeLaunchSpec({ agent, promptPath, logPath, overlayDir }) {
|
|
|
210
210
|
systemPromptPath,
|
|
211
211
|
`${renderHarnessSystemPrompt(agent, "claude")}${skillText ? `\n\n${skillText}` : ""}\n`,
|
|
212
212
|
);
|
|
213
|
-
const
|
|
213
|
+
const command = executor?.claude?.command || "claude";
|
|
214
|
+
const tokens = [command, "-p", "--no-session-persistence"];
|
|
214
215
|
const settingsPath = buildClaudeSettingsPath(executor, overlayDir);
|
|
215
216
|
appendSingleValueFlag(tokens, "--output-format", executor.claude.outputFormat || "text");
|
|
216
217
|
appendSingleValueFlag(tokens, "--model", executor.claude.model || executor.model);
|
|
@@ -234,7 +235,7 @@ function buildClaudeLaunchSpec({ agent, promptPath, logPath, overlayDir }) {
|
|
|
234
235
|
);
|
|
235
236
|
return {
|
|
236
237
|
executorId: "claude",
|
|
237
|
-
command
|
|
238
|
+
command,
|
|
238
239
|
useRateLimitRetries: true,
|
|
239
240
|
invocationLines: [
|
|
240
241
|
`task_prompt=$(cat ${shellQuote(promptPath)})`,
|