diff --git a/CHANGELOG.md b/CHANGELOG.md index 94239f0a0cc4..7d5088fb6687 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -19,6 +19,7 @@ Docs: https://docs.openclaw.ai - Slack: keep downloaded read-only files out of reply media so Slack file reads do not echo files back to the conversation. (#86318) Thanks @neeravmakwana. - Cron: accept leading-plus relative durations such as `+5m` for one-shot `--at` schedules. (#86341) Thanks @mushuiyu886. - Agents/media: preserve async-started media tool metadata so background generation starts no longer surface generic incomplete-turn warnings while replay stays unsafe. (#85933) Thanks @fuller-stack-dev. +- Docker E2E: dedupe scheduler lane resources so npm/service package lanes are not over-counted and serialized unnecessarily. - xAI/LM Studio: avoid buffering ordinary bracketed or `final` prose until stream completion while watching for plain-text tool-call fallbacks. - Discord: suppress a bot's previous reply body and referenced media from prompt context when a user replies to that bot message, while keeping reply metadata for routing. (#86238) Thanks @fuller-stack-dev. - Docker E2E: avoid rebuilding the Control UI twice while preparing the shared OpenClaw package tarball for package-backed scenario runs. diff --git a/scripts/lib/docker-e2e-plan.mjs b/scripts/lib/docker-e2e-plan.mjs index 16fc89399f12..a828d8190023 100644 --- a/scripts/lib/docker-e2e-plan.mjs +++ b/scripts/lib/docker-e2e-plan.mjs @@ -290,7 +290,7 @@ export function laneWeight(poolLane) { } export function laneResources(poolLane) { - return ["docker", ...(poolLane.resources ?? [])]; + return [...new Set(["docker", ...(poolLane.resources ?? [])])]; } export function laneSummary(poolLane) { diff --git a/test/scripts/docker-e2e-plan.test.ts b/test/scripts/docker-e2e-plan.test.ts index 5b4ec31584bb..7940c2c6ae76 100644 --- a/test/scripts/docker-e2e-plan.test.ts +++ b/test/scripts/docker-e2e-plan.test.ts @@ -771,6 +771,23 @@ describe("scripts/lib/docker-e2e-plan", () => { expect(plan.needs.package).toBe(true); }); + it("dedupes scheduler resources from lane wrappers and explicit lane metadata", () => { + const plan = planFor({ + selectedLaneNames: ["release-user-journey", "release-plugin-marketplace"], + }); + + expect(plan.lanes.map((lane) => ({ name: lane.name, resources: lane.resources }))).toEqual([ + { + name: "release-user-journey", + resources: ["docker", "npm", "service"], + }, + { + name: "release-plugin-marketplace", + resources: ["docker", "npm"], + }, + ]); + }); + it("plans the Droid ACP bind live lane as Factory-auth proof", () => { const plan = planFor({ selectedLaneNames: ["live-acp-bind-droid"] });