diff --git a/docs/vi/ci.md b/docs/vi/ci.md index f7638cfbb..24063a119 100644 --- a/docs/vi/ci.md +++ b/docs/vi/ci.md @@ -1,75 +1,75 @@ --- read_when: - Bạn cần hiểu lý do một tác vụ CI đã chạy hoặc không chạy - - Bạn đang gỡ lỗi một lượt kiểm tra GitHub Actions không thành công + - Bạn đang gỡ lỗi một kiểm tra GitHub Actions không thành công - Bạn đang điều phối một lượt chạy hoặc chạy lại xác thực bản phát hành -summary: Đồ thị công việc CI, các cổng phạm vi, nhóm bao quát phát hành và các lệnh cục bộ tương đương +summary: Sơ đồ công việc CI, các cổng theo phạm vi, các nhóm bao quát phát hành và các lệnh cục bộ tương đương title: Quy trình CI x-i18n: - generated_at: "2026-04-30T09:34:52Z" + generated_at: "2026-04-30T18:38:49Z" model: gpt-5.5 provider: openai - source_hash: a9c18f0801864ca1030aac9ea81117b011bd7936388984a1809ce3ae6e906e62 + source_hash: a24afc27606ac7f4e9ead89acdd319bffa23336610f8a6cd8b576ea1a5b233dd source_path: ci.md workflow: 16 --- -OpenClaw CI chạy trên mọi lần push vào `main` và mọi pull request. Job `preflight` phân loại diff và tắt các lane tốn kém khi chỉ có các khu vực không liên quan thay đổi. Các lần chạy thủ công bằng `workflow_dispatch` cố ý bỏ qua phạm vi thông minh và mở rộng toàn bộ đồ thị cho release candidate và xác thực diện rộng. Các lane Android vẫn là tùy chọn thông qua `include_android`. Phạm vi kiểm tra Plugin chỉ dành cho phát hành nằm trong workflow [`Plugin Prerelease`](#plugin-prerelease) riêng và chỉ chạy từ [`Full Release Validation`](#full-release-validation) hoặc một lần dispatch thủ công rõ ràng. +OpenClaw CI chạy trên mọi lần push vào `main` và mọi pull request. Job `preflight` phân loại diff và tắt các lane tốn kém khi chỉ những khu vực không liên quan thay đổi. Các lần chạy `workflow_dispatch` thủ công cố ý bỏ qua phạm vi thông minh và mở rộng toàn bộ đồ thị cho các release candidate và kiểm định rộng. Các lane Android vẫn là tùy chọn thông qua `include_android`. Phạm vi kiểm thử Plugin chỉ dành cho phát hành nằm trong workflow [`Plugin Tiền phát hành`](#plugin-prerelease) riêng và chỉ chạy từ [`Kiểm định Bản phát hành Đầy đủ`](#full-release-validation) hoặc một dispatch thủ công rõ ràng. ## Tổng quan pipeline -| Job | Mục đích | Khi chạy | -| -------------------------------- | -------------------------------------------------------------------------------------------- | ---------------------------------- | -| `preflight` | Phát hiện thay đổi chỉ trong tài liệu, phạm vi đã thay đổi, extension đã thay đổi và xây dựng manifest CI | Luôn chạy trên push và PR không phải draft | -| `security-scm-fast` | Phát hiện khóa riêng tư và kiểm toán workflow qua `zizmor` | Luôn chạy trên push và PR không phải draft | -| `security-dependency-audit` | Kiểm toán lockfile production không cần dependency dựa trên advisory npm | Luôn chạy trên push và PR không phải draft | -| `security-fast` | Tổng hợp bắt buộc cho các job bảo mật nhanh | Luôn chạy trên push và PR không phải draft | -| `check-dependencies` | Lượt kiểm tra Knip chỉ dành cho dependency production cùng bộ bảo vệ danh sách cho phép tệp không dùng | Thay đổi liên quan đến Node | -| `build-artifacts` | Build `dist/`, Control UI, kiểm tra artifact đã build và artifact downstream có thể tái sử dụng | Thay đổi liên quan đến Node | -| `checks-fast-core` | Các lane kiểm tra đúng đắn nhanh trên Linux như kiểm tra bundled/plugin-contract/protocol | Thay đổi liên quan đến Node | -| `checks-fast-contracts-channels` | Kiểm tra contract channel được chia shard với kết quả kiểm tra tổng hợp ổn định | Thay đổi liên quan đến Node | -| `checks-node-core-test` | Các shard kiểm thử Node lõi, loại trừ lane channel, bundled, contract và extension | Thay đổi liên quan đến Node | -| `check` | Tương đương cổng local chính được chia shard: kiểu production, lint, guard, kiểu test và smoke nghiêm ngặt | Thay đổi liên quan đến Node | -| `check-additional` | Các shard kiến trúc, boundary, guard bề mặt extension, package-boundary và gateway-watch | Thay đổi liên quan đến Node | -| `build-smoke` | Kiểm thử smoke CLI đã build và smoke bộ nhớ khởi động | Thay đổi liên quan đến Node | -| `checks` | Bộ xác minh cho kiểm thử channel artifact đã build | Thay đổi liên quan đến Node | -| `checks-node-compat-node22` | Lane build và smoke tương thích Node 22 | Dispatch CI thủ công cho phát hành | -| `check-docs` | Định dạng tài liệu, lint và kiểm tra liên kết hỏng | Tài liệu thay đổi | -| `skills-python` | Ruff + pytest cho Skills dựa trên Python | Thay đổi liên quan đến Python-skill | -| `checks-windows` | Kiểm thử process/path riêng cho Windows cùng hồi quy specifier import runtime dùng chung | Thay đổi liên quan đến Windows | -| `macos-node` | Lane kiểm thử TypeScript trên macOS dùng artifact đã build dùng chung | Thay đổi liên quan đến macOS | -| `macos-swift` | Swift lint, build và test cho ứng dụng macOS | Thay đổi liên quan đến macOS | -| `android` | Kiểm thử đơn vị Android cho cả hai flavor cộng một bản build debug APK | Thay đổi liên quan đến Android | -| `test-performance-agent` | Tối ưu hóa kiểm thử chậm hằng ngày bằng Codex sau hoạt động đáng tin cậy | CI main thành công hoặc dispatch thủ công | +| Job | Mục đích | Khi chạy | +| -------------------------------- | -------------------------------------------------------------------------------------------- | ----------------------------------- | +| `preflight` | Phát hiện thay đổi chỉ ở docs, phạm vi đã thay đổi, plugin đã thay đổi, và xây dựng manifest CI | Luôn chạy trên push và PR không phải draft | +| `security-scm-fast` | Phát hiện khóa riêng tư và kiểm toán workflow qua `zizmor` | Luôn chạy trên push và PR không phải draft | +| `security-dependency-audit` | Kiểm toán lockfile production không cần dependency theo advisory của npm | Luôn chạy trên push và PR không phải draft | +| `security-fast` | Tổng hợp bắt buộc cho các job bảo mật nhanh | Luôn chạy trên push và PR không phải draft | +| `check-dependencies` | Lượt kiểm tra Knip chỉ dành cho dependency production cộng với guard allowlist tệp không dùng | Thay đổi liên quan đến Node | +| `build-artifacts` | Build `dist/`, Control UI, kiểm tra artifact đã build, và artifact dùng lại cho downstream | Thay đổi liên quan đến Node | +| `checks-fast-core` | Các lane tính đúng đắn nhanh trên Linux như kiểm tra bundled/plugin-contract/protocol | Thay đổi liên quan đến Node | +| `checks-fast-contracts-channels` | Kiểm tra contract channel theo shard với kết quả kiểm tra tổng hợp ổn định | Thay đổi liên quan đến Node | +| `checks-node-core-test` | Các shard test Node lõi, loại trừ lane channel, bundled, contract, và plugin | Thay đổi liên quan đến Node | +| `check` | Tương đương gate cục bộ chính theo shard: type prod, lint, guard, type test, và smoke nghiêm ngặt | Thay đổi liên quan đến Node | +| `check-additional` | Các shard architecture, boundary, guard bề mặt plugin, package-boundary, và gateway-watch | Thay đổi liên quan đến Node | +| `build-smoke` | Smoke test CLI đã build và smoke bộ nhớ khởi động | Thay đổi liên quan đến Node | +| `checks` | Bộ xác minh cho các test channel artifact đã build | Thay đổi liên quan đến Node | +| `checks-node-compat-node22` | Lane build và smoke tương thích Node 22 | Dispatch CI thủ công cho phát hành | +| `check-docs` | Định dạng docs, lint, và kiểm tra link hỏng | Docs thay đổi | +| `skills-python` | Ruff + pytest cho skills dựa trên Python | Thay đổi liên quan đến skill Python | +| `checks-windows` | Test process/path riêng cho Windows cộng với hồi quy shared runtime import specifier | Thay đổi liên quan đến Windows | +| `macos-node` | Lane test TypeScript macOS dùng các artifact đã build dùng chung | Thay đổi liên quan đến macOS | +| `macos-swift` | Swift lint, build, và test cho ứng dụng macOS | Thay đổi liên quan đến macOS | +| `android` | Unit test Android cho cả hai flavor cộng với một bản build debug APK | Thay đổi liên quan đến Android | +| `test-performance-agent` | Tối ưu hóa test chậm hằng ngày bằng Codex sau hoạt động tin cậy | CI main thành công hoặc dispatch thủ công | ## Thứ tự fail-fast -1. `preflight` quyết định những lane nào tồn tại. Logic `docs-scope` và `changed-scope` là các bước bên trong job này, không phải các job độc lập. -2. `security-scm-fast`, `security-dependency-audit`, `security-fast`, `check`, `check-additional`, `check-docs` và `skills-python` thất bại nhanh mà không chờ các job artifact và ma trận nền tảng nặng hơn. -3. `build-artifacts` chạy chồng lấp với các lane Linux nhanh để consumer downstream có thể bắt đầu ngay khi bản build dùng chung sẵn sàng. -4. Các lane nền tảng và runtime nặng hơn mở rộng sau đó: `checks-fast-core`, `checks-fast-contracts-channels`, `checks-node-core-test`, `checks`, `checks-windows`, `macos-node`, `macos-swift` và `android`. +1. `preflight` quyết định lane nào tồn tại. Logic `docs-scope` và `changed-scope` là các bước bên trong job này, không phải job độc lập. +2. `security-scm-fast`, `security-dependency-audit`, `security-fast`, `check`, `check-additional`, `check-docs`, và `skills-python` thất bại nhanh mà không chờ các job artifact và ma trận nền tảng nặng hơn. +3. `build-artifacts` chạy chồng lấp với các lane Linux nhanh để downstream consumer có thể bắt đầu ngay khi bản build dùng chung sẵn sàng. +4. Các lane nền tảng và runtime nặng hơn mở rộng sau đó: `checks-fast-core`, `checks-fast-contracts-channels`, `checks-node-core-test`, `checks`, `checks-windows`, `macos-node`, `macos-swift`, và `android`. -GitHub có thể đánh dấu các job bị thay thế là `cancelled` khi một push mới hơn được đưa lên cùng PR hoặc ref `main`. Hãy xem đó là nhiễu CI trừ khi lần chạy mới nhất cho cùng ref cũng đang thất bại. Các kiểm tra shard tổng hợp dùng `!cancelled() && always()` để vẫn báo cáo lỗi shard bình thường nhưng không xếp hàng sau khi toàn bộ workflow đã bị thay thế. Khóa đồng thời CI tự động được version hóa (`CI-v7-*`) để một zombie phía GitHub trong nhóm hàng đợi cũ không thể chặn vô thời hạn các lần chạy main mới hơn. Các lần chạy thủ công toàn bộ bộ kiểm thử dùng `CI-manual-v1-*` và không hủy các lần chạy đang tiến hành. +GitHub có thể đánh dấu các job bị thay thế là `cancelled` khi có push mới hơn vào cùng PR hoặc ref `main`. Hãy coi đó là nhiễu CI trừ khi lần chạy mới nhất cho cùng ref cũng đang thất bại. Các kiểm tra shard tổng hợp dùng `!cancelled() && always()` để vẫn báo lỗi shard bình thường nhưng không xếp hàng sau khi toàn bộ workflow đã bị thay thế. Khóa concurrency CI tự động được đánh phiên bản (`CI-v7-*`) để một zombie phía GitHub trong nhóm hàng đợi cũ không thể chặn vô hạn các lần chạy main mới hơn. Các lần chạy full-suite thủ công dùng `CI-manual-v1-*` và không hủy các lần chạy đang tiến hành. ## Phạm vi và định tuyến -Logic phạm vi nằm trong `scripts/ci-changed-scope.mjs` và được bao phủ bởi kiểm thử đơn vị trong `src/scripts/ci-changed-scope.test.ts`. Dispatch thủ công bỏ qua phát hiện changed-scope và khiến manifest preflight hoạt động như thể mọi khu vực có phạm vi đều đã thay đổi. +Logic phạm vi nằm trong `scripts/ci-changed-scope.mjs` và được bao phủ bởi unit test trong `src/scripts/ci-changed-scope.test.ts`. Dispatch thủ công bỏ qua phát hiện changed-scope và khiến manifest preflight hoạt động như thể mọi khu vực có phạm vi đều đã thay đổi. -- **Chỉnh sửa workflow CI** xác thực đồ thị CI Node cộng với lint workflow, nhưng tự chúng không ép build native Windows, Android hoặc macOS; các lane nền tảng đó vẫn được giới hạn theo thay đổi mã nguồn nền tảng. -- **Chỉnh sửa chỉ định tuyến CI, một số chỉnh sửa fixture core-test rẻ được chọn và chỉnh sửa helper/test-routing contract Plugin hẹp** dùng đường dẫn manifest nhanh chỉ dành cho Node: `preflight`, bảo mật và một tác vụ `checks-fast-core` duy nhất. Đường dẫn đó bỏ qua build artifact, tương thích Node 22, contract channel, toàn bộ shard lõi, shard bundled-plugin và các ma trận guard bổ sung khi thay đổi chỉ giới hạn ở các bề mặt định tuyến hoặc helper mà tác vụ nhanh trực tiếp thực thi. -- **Kiểm tra Node trên Windows** được giới hạn vào wrapper process/path riêng cho Windows, helper runner npm/pnpm/UI, cấu hình trình quản lý package và các bề mặt workflow CI thực thi lane đó; mã nguồn, Plugin, install-smoke và thay đổi chỉ dành cho test không liên quan vẫn nằm trên các lane Node Linux. +- **Chỉnh sửa workflow CI** xác thực đồ thị CI Node cộng với lint workflow, nhưng tự chúng không ép build native Windows, Android, hoặc macOS; các lane nền tảng đó vẫn được giới hạn theo thay đổi mã nguồn nền tảng. +- **Chỉnh sửa chỉ định tuyến CI, chỉnh sửa fixture core-test rẻ được chọn, và chỉnh sửa helper/test-routing contract Plugin hẹp** dùng đường dẫn manifest nhanh chỉ dành cho Node: `preflight`, bảo mật, và một task `checks-fast-core` duy nhất. Đường dẫn đó bỏ qua build artifact, tương thích Node 22, contract channel, shard lõi đầy đủ, shard bundled-plugin, và ma trận guard bổ sung khi thay đổi chỉ giới hạn ở các bề mặt định tuyến hoặc helper mà task nhanh trực tiếp thực thi. +- **Kiểm tra Node Windows** được giới hạn ở wrapper process/path riêng cho Windows, helper runner npm/pnpm/UI, cấu hình package manager, và các bề mặt workflow CI thực thi lane đó; các thay đổi mã nguồn, Plugin, install-smoke, và chỉ test không liên quan vẫn ở các lane Node Linux. -Các nhóm kiểm thử Node chậm nhất được tách hoặc cân bằng để mỗi job vẫn nhỏ mà không giữ runner quá mức: contract channel chạy thành ba shard có trọng số, các lane unit lõi nhỏ được ghép cặp, auto-reply chạy thành bốn worker cân bằng (với subtree reply được tách thành các shard agent-runner, dispatch và commands/state-routing), và cấu hình agentic gateway/plugin được phân bổ trên các job Node agentic chỉ dùng mã nguồn hiện có thay vì chờ artifact đã build. Các kiểm thử trình duyệt, QA, media và Plugin khác diện rộng dùng cấu hình Vitest chuyên dụng thay vì catch-all Plugin dùng chung. Các shard include-pattern ghi lại mục timing bằng tên shard CI, để `.artifacts/vitest-shard-timings.json` có thể phân biệt toàn bộ cấu hình với một shard đã lọc. `check-additional` giữ công việc compile/canary package-boundary cùng nhau và tách kiến trúc topology runtime khỏi phạm vi gateway watch; shard boundary guard chạy đồng thời các guard độc lập nhỏ của nó trong một job. Gateway watch, kiểm thử channel và shard support-boundary lõi chạy đồng thời bên trong `build-artifacts` sau khi `dist/` và `dist-runtime/` đã được build. +Các họ test Node chậm nhất được tách hoặc cân bằng để mỗi job vẫn nhỏ mà không giữ runner quá mức: contract channel chạy dưới dạng ba shard có trọng số, các lane unit lõi nhỏ được ghép đôi, auto-reply chạy dưới dạng bốn worker cân bằng (với subtree reply được tách thành các shard agent-runner, dispatch, và commands/state-routing), và cấu hình gateway/Plugin có tính agentic được phân bổ trên các job Node agentic chỉ nguồn hiện có thay vì chờ artifact đã build. Các test trình duyệt rộng, QA, media, và Plugin linh tinh dùng cấu hình Vitest chuyên dụng của chúng thay vì catch-all Plugin dùng chung. Các shard include-pattern ghi mục timing bằng tên shard CI, để `.artifacts/vitest-shard-timings.json` có thể phân biệt cả một cấu hình với một shard đã lọc. `check-additional` giữ công việc compile/canary package-boundary cùng nhau và tách architecture topology runtime khỏi phạm vi gateway watch; shard guard boundary chạy các guard độc lập nhỏ của nó đồng thời trong một job. Gateway watch, test channel, và shard support-boundary lõi chạy đồng thời bên trong `build-artifacts` sau khi `dist/` và `dist-runtime/` đã được build. -Android CI chạy cả `testPlayDebugUnitTest` và `testThirdPartyDebugUnitTest` rồi build Play debug APK. Flavor bên thứ ba không có source set hoặc manifest riêng; lane unit-test của nó vẫn compile flavor với các cờ BuildConfig SMS/call-log, đồng thời tránh một job đóng gói debug APK trùng lặp trên mỗi push liên quan đến Android. +Android CI chạy cả `testPlayDebugUnitTest` và `testThirdPartyDebugUnitTest` rồi build Play debug APK. Flavor bên thứ ba không có source set hoặc manifest riêng; lane unit-test của nó vẫn compile flavor với các cờ BuildConfig SMS/call-log, trong khi tránh job đóng gói debug APK trùng lặp trên mỗi push liên quan đến Android. -Shard `check-dependencies` chạy `pnpm deadcode:dependencies` (một lượt Knip chỉ dành cho dependency production được pin vào phiên bản Knip mới nhất, với tuổi phát hành tối thiểu của pnpm bị tắt cho cài đặt `dlx`) và `pnpm deadcode:unused-files`, so sánh các phát hiện tệp production không dùng của Knip với `scripts/deadcode-unused-files.allowlist.mjs`. Guard tệp không dùng thất bại khi một PR thêm tệp không dùng mới chưa được review hoặc để lại mục allowlist đã lỗi thời, đồng thời giữ lại các bề mặt Plugin động có chủ ý, generated, build, live-test và package bridge mà Knip không thể phân giải tĩnh. +Shard `check-dependencies` chạy `pnpm deadcode:dependencies` (một lượt kiểm tra Knip chỉ dành cho dependency production được ghim vào phiên bản Knip mới nhất, với tuổi phát hành tối thiểu của pnpm bị tắt cho cài đặt `dlx`) và `pnpm deadcode:unused-files`, so sánh phát hiện tệp production không dùng của Knip với `scripts/deadcode-unused-files.allowlist.mjs`. Guard tệp không dùng thất bại khi một PR thêm tệp không dùng mới chưa được review hoặc để lại mục allowlist lỗi thời, trong khi vẫn giữ các bề mặt Plugin động có chủ ý, được tạo sinh, build, live-test, và cầu nối package mà Knip không thể phân giải tĩnh. ## Dispatch thủ công -Các dispatch CI thủ công chạy cùng đồ thị job như CI bình thường nhưng buộc mọi lane có phạm vi không phải Android bật: shard Node Linux, shard bundled-plugin, contract channel, tương thích Node 22, `check`, `check-additional`, build smoke, kiểm tra tài liệu, Python skills, Windows, macOS và Control UI i18n. Dispatch CI thủ công độc lập chỉ chạy Android với `include_android=true`; umbrella phát hành đầy đủ bật Android bằng cách truyền `include_android=true`. Kiểm tra tĩnh prerelease Plugin, shard `agentic-plugins` chỉ dành cho phát hành, lượt quét batch extension đầy đủ và lane Docker prerelease Plugin bị loại khỏi CI. Bộ Docker prerelease chỉ chạy khi `Full Release Validation` dispatch workflow `Plugin Prerelease` riêng với cổng release-validation được bật. +Các dispatch CI thủ công chạy cùng đồ thị job như CI bình thường nhưng ép mọi lane có phạm vi không phải Android bật: shard Linux Node, shard bundled-plugin, contract channel, tương thích Node 22, `check`, `check-additional`, build smoke, kiểm tra docs, Python skills, Windows, macOS, và Control UI i18n. Các dispatch CI thủ công độc lập chỉ chạy Android với `include_android=true`; umbrella phát hành đầy đủ bật Android bằng cách truyền `include_android=true`. Kiểm tra tĩnh Plugin prerelease, shard `agentic-plugins` chỉ dành cho phát hành, lượt quét batch Plugin đầy đủ, và các lane Docker Plugin prerelease bị loại khỏi CI. Bộ Docker prerelease chỉ chạy khi `Full Release Validation` dispatch workflow `Plugin Prerelease` riêng với gate release-validation được bật. -Các lần chạy thủ công dùng một nhóm đồng thời duy nhất để một bộ kiểm thử đầy đủ cho release-candidate không bị hủy bởi một lần push hoặc PR khác trên cùng ref. Input tùy chọn `target_ref` cho phép caller đáng tin cậy chạy đồ thị đó trên một nhánh, tag hoặc SHA commit đầy đủ trong khi dùng tệp workflow từ ref dispatch đã chọn. +Các lần chạy thủ công dùng một nhóm concurrency duy nhất để full suite release-candidate không bị hủy bởi một lần chạy push hoặc PR khác trên cùng ref. Input `target_ref` tùy chọn cho phép caller đáng tin cậy chạy đồ thị đó trên một branch, tag, hoặc SHA commit đầy đủ trong khi dùng tệp workflow từ ref dispatch đã chọn. ```bash gh workflow run ci.yml --ref release/YYYY.M.D @@ -79,17 +79,17 @@ gh workflow run full-release-validation.yml --ref main -f ref= ## Runner -| Bộ chạy | Công việc | -| -------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -| `ubuntu-24.04` | `preflight`, các công việc bảo mật nhanh và tổng hợp (`security-scm-fast`, `security-dependency-audit`, `security-fast`), các kiểm tra protocol/contract/bundled nhanh, kiểm tra contract kênh theo shard, các shard `check` trừ lint, các shard và tổng hợp `check-additional`, trình xác minh tổng hợp kiểm thử Node, kiểm tra tài liệu, Python skills, workflow-sanity, labeler, auto-response; preflight install-smoke cũng dùng Ubuntu do GitHub lưu trữ để ma trận Blacksmith có thể xếp hàng sớm hơn | -| `blacksmith-4vcpu-ubuntu-2404` | `CodeQL Critical Quality`, các shard extension nhẹ hơn, `checks-fast-core`, `checks-node-compat-node22`, `check-prod-types`, và `check-test-types` | -| `blacksmith-8vcpu-ubuntu-2404` | `build-artifacts`, build-smoke, các shard kiểm thử Linux Node, các shard kiểm thử plugin bundled, `android` | -| `blacksmith-16vcpu-ubuntu-2404` | `check-lint` (nhạy với CPU đến mức 8 vCPU tốn nhiều chi phí hơn phần tiết kiệm được); các bản dựng Docker install-smoke (thời gian xếp hàng 32-vCPU tốn nhiều chi phí hơn phần tiết kiệm được) | -| `blacksmith-16vcpu-windows-2025` | `checks-windows` | -| `blacksmith-6vcpu-macos-latest` | `macos-node` trên `openclaw/openclaw`; các fork quay về dùng `macos-latest` | -| `blacksmith-12vcpu-macos-latest` | `macos-swift` trên `openclaw/openclaw`; các fork quay về dùng `macos-latest` | +| Trình chạy | Công việc | +| -------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | +| `ubuntu-24.04` | `preflight`, các công việc bảo mật nhanh và các tổng hợp (`security-scm-fast`, `security-dependency-audit`, `security-fast`), các kiểm tra nhanh về giao thức/hợp đồng/đóng gói sẵn, các kiểm tra hợp đồng kênh được chia shard, các shard `check` ngoại trừ lint, các shard và tổng hợp `check-additional`, các bộ xác minh tổng hợp kiểm thử Node, kiểm tra tài liệu, Python skills, workflow-sanity, labeler, auto-response; preflight install-smoke cũng dùng Ubuntu do GitHub lưu trữ để ma trận Blacksmith có thể xếp hàng sớm hơn | +| `blacksmith-4vcpu-ubuntu-2404` | `CodeQL Critical Quality`, các shard Plugin có trọng lượng thấp hơn, `checks-fast-core`, `checks-node-compat-node22`, `check-prod-types`, và `check-test-types` | +| `blacksmith-8vcpu-ubuntu-2404` | `build-artifacts`, build-smoke, các shard kiểm thử Node trên Linux, các shard kiểm thử Plugin đóng gói sẵn, `android` | +| `blacksmith-16vcpu-ubuntu-2404` | `check-lint` (đủ nhạy với CPU đến mức 8 vCPU tốn nhiều hơn phần tiết kiệm được); các bản dựng Docker install-smoke (thời gian xếp hàng 32-vCPU tốn nhiều hơn phần tiết kiệm được) | +| `blacksmith-16vcpu-windows-2025` | `checks-windows` | +| `blacksmith-6vcpu-macos-latest` | `macos-node` trên `openclaw/openclaw`; các fork quay về `macos-latest` | +| `blacksmith-12vcpu-macos-latest` | `macos-swift` trên `openclaw/openclaw`; các fork quay về `macos-latest` | -## Lệnh tương đương cục bộ +## Các lệnh tương đương cục bộ ```bash pnpm changed:lanes # inspect the local changed-lane classifier for origin/main...HEAD @@ -117,27 +117,27 @@ pnpm test:perf:groups:compare .artifacts/test-perf/baseline-before.json .artifac ## Xác thực phát hành đầy đủ -`Full Release Validation` là workflow bao trùm thủ công cho việc "chạy mọi thứ trước khi phát hành." Nó nhận một nhánh, tag hoặc SHA commit đầy đủ, dispatch workflow `CI` thủ công với mục tiêu đó, dispatch `Plugin Prerelease` cho bằng chứng chỉ dành cho phát hành về plugin/package/static/Docker, và dispatch `OpenClaw Release Checks` cho install smoke, package acceptance, các bộ kiểm thử đường dẫn phát hành Docker, live/E2E, OpenWebUI, QA Lab parity, Matrix và các lane Telegram. Nó cũng có thể chạy workflow hậu xuất bản `NPM Telegram Beta E2E` khi một thông số gói đã xuất bản được cung cấp. +`Full Release Validation` là workflow bao trùm thủ công cho việc "chạy mọi thứ trước khi phát hành." Nó chấp nhận một nhánh, thẻ hoặc SHA commit đầy đủ, dispatch workflow `CI` thủ công với đích đó, dispatch `Plugin Prerelease` cho bằng chứng chỉ dành cho phát hành về Plugin/gói/tĩnh/Docker, và dispatch `OpenClaw Release Checks` cho kiểm tra cài đặt, chấp nhận gói, các bộ kiểm thử đường dẫn phát hành Docker, live/E2E, OpenWebUI, tương đồng QA Lab, Matrix và các làn Telegram. Nó cũng có thể chạy workflow `NPM Telegram Beta E2E` sau phát hành khi có thông số gói đã phát hành được cung cấp. -`release_profile` kiểm soát độ rộng live/provider được truyền vào release checks: +`release_profile` kiểm soát phạm vi live/nhà cung cấp được truyền vào kiểm tra phát hành: -- `minimum` giữ các lane OpenAI/core nhanh nhất và trọng yếu cho phát hành. -- `stable` thêm tập provider/backend ổn định. -- `full` chạy ma trận provider/media tư vấn rộng. +- `minimum` giữ các làn OpenAI/lõi quan trọng với phát hành nhanh nhất. +- `stable` thêm tập nhà cung cấp/backend ổn định. +- `full` chạy ma trận nhà cung cấp/phương tiện tư vấn rộng. -Workflow bao trùm ghi lại id của các lần chạy con đã dispatch, và công việc cuối cùng `Verify full validation` kiểm tra lại kết luận hiện tại của các lần chạy con rồi nối thêm các bảng công việc chậm nhất cho từng lần chạy con. Nếu một workflow con được chạy lại và chuyển xanh, chỉ chạy lại công việc xác minh cha để làm mới kết quả bao trùm và bản tóm tắt thời gian. +Workflow bao trùm ghi lại các id lần chạy con đã dispatch, và công việc `Verify full validation` cuối cùng kiểm tra lại kết luận hiện tại của các lần chạy con rồi thêm các bảng công việc chậm nhất cho từng lần chạy con. Nếu một workflow con được chạy lại và chuyển xanh, chỉ chạy lại công việc xác minh cha để làm mới kết quả bao trùm và tóm tắt thời gian. -Để khôi phục, cả `Full Release Validation` và `OpenClaw Release Checks` đều nhận `rerun_group`. Dùng `all` cho một release candidate, `ci` chỉ cho CI con đầy đủ thông thường, `release-checks` cho mọi công việc con phát hành, hoặc một nhóm hẹp hơn: `install-smoke`, `cross-os`, `live-e2e`, `package`, `qa`, `qa-parity`, `qa-live`, hoặc `npm-telegram` trên workflow bao trùm. Cách này giữ phạm vi chạy lại của một hộp phát hành bị lỗi sau một bản sửa tập trung. +Để khôi phục, cả `Full Release Validation` và `OpenClaw Release Checks` đều chấp nhận `rerun_group`. Dùng `all` cho một ứng viên phát hành, `ci` chỉ cho phần con CI đầy đủ thông thường, `release-checks` cho mọi phần con phát hành, hoặc một nhóm hẹp hơn: `install-smoke`, `cross-os`, `live-e2e`, `package`, `qa`, `qa-parity`, `qa-live`, hoặc `npm-telegram` trên workflow bao trùm. Cách này giữ việc chạy lại hộp phát hành bị lỗi trong phạm vi giới hạn sau một bản sửa tập trung. -`OpenClaw Release Checks` dùng workflow ref đáng tin cậy để phân giải ref đã chọn một lần thành tarball `release-package-under-test`, rồi truyền artifact đó cho cả workflow Docker đường dẫn phát hành live/E2E và shard package acceptance. Điều đó giữ byte của gói nhất quán trên các hộp phát hành và tránh đóng gói lại cùng một ứng viên trong nhiều công việc con. +`OpenClaw Release Checks` dùng ref workflow đáng tin cậy để phân giải ref đã chọn một lần thành tarball `release-package-under-test`, rồi truyền artifact đó cho cả workflow Docker live/E2E theo đường dẫn phát hành và shard chấp nhận gói. Điều đó giữ byte của gói nhất quán trên các hộp phát hành và tránh đóng gói lại cùng một ứng viên trong nhiều công việc con. -## Các shard live và E2E +## Các shard Live và E2E -Công việc con live/E2E của bản phát hành giữ độ phủ rộng của `pnpm test:live` native, nhưng chạy nó dưới dạng các shard có tên thông qua `scripts/test-live-shard.mjs` thay vì một công việc nối tiếp: +Phần con live/E2E của phát hành giữ phạm vi bao phủ `pnpm test:live` gốc rộng, nhưng chạy nó dưới dạng các shard có tên thông qua `scripts/test-live-shard.mjs` thay vì một công việc tuần tự: - `native-live-src-agents` - `native-live-src-gateway-core` -- các công việc `native-live-src-gateway-profiles` được lọc theo provider +- các công việc `native-live-src-gateway-profiles` được lọc theo nhà cung cấp - `native-live-src-gateway-backends` - `native-live-test` - `native-live-extensions-a-k` @@ -145,57 +145,57 @@ Công việc con live/E2E của bản phát hành giữ độ phủ rộng của - `native-live-extensions-openai` - `native-live-extensions-o-z-other` - `native-live-extensions-xai` -- các shard media audio/video được tách riêng và các shard music được lọc theo provider +- các shard phương tiện âm thanh/video được tách riêng và các shard nhạc được lọc theo nhà cung cấp -Cách này giữ cùng độ phủ tệp trong khi giúp các lỗi provider live chậm dễ chạy lại và chẩn đoán hơn. Các tên shard tổng hợp `native-live-extensions-o-z`, `native-live-extensions-media`, và `native-live-extensions-media-music` vẫn hợp lệ cho các lần chạy lại thủ công một lần. +Cách này giữ nguyên phạm vi bao phủ tệp trong khi giúp các lỗi nhà cung cấp live chậm dễ chạy lại và chẩn đoán hơn. Các tên shard tổng hợp `native-live-extensions-o-z`, `native-live-extensions-media`, và `native-live-extensions-media-music` vẫn hợp lệ cho các lần chạy lại thủ công một lần. -Các shard media live native chạy trong `ghcr.io/openclaw/openclaw-live-media-runner:ubuntu-24.04`, được dựng bởi workflow `Live Media Runner Image`. Image đó cài sẵn `ffmpeg` và `ffprobe`; các công việc media chỉ xác minh binary trước khi thiết lập. Giữ các bộ kiểm thử live dựa trên Docker trên runner Blacksmith bình thường — công việc container không phải nơi phù hợp để khởi chạy kiểm thử Docker lồng nhau. +Các shard phương tiện live gốc chạy trong `ghcr.io/openclaw/openclaw-live-media-runner:ubuntu-24.04`, được xây dựng bởi workflow `Live Media Runner Image`. Image đó cài sẵn `ffmpeg` và `ffprobe`; các công việc phương tiện chỉ xác minh các binary trước khi thiết lập. Giữ các bộ kiểm thử live dựa trên Docker trên các runner Blacksmith thông thường - công việc container không phải là nơi phù hợp để khởi chạy kiểm thử Docker lồng nhau. -Các shard model/backend live dựa trên Docker dùng một image dùng chung riêng `ghcr.io/openclaw/openclaw-live-test:` cho mỗi commit đã chọn. Workflow phát hành live dựng và đẩy image đó một lần, sau đó các shard Docker live model, gateway, CLI backend, ACP bind và Codex harness chạy với `OPENCLAW_SKIP_DOCKER_BUILD=1`. Nếu các shard đó tự dựng lại target Docker nguồn đầy đủ một cách độc lập, lần chạy phát hành đã cấu hình sai và sẽ lãng phí thời gian thực trên các bản dựng image trùng lặp. +Các shard live model/backend dựa trên Docker dùng một image dùng chung riêng `ghcr.io/openclaw/openclaw-live-test:` cho mỗi commit đã chọn. Workflow phát hành live xây dựng và đẩy image đó một lần, sau đó các shard Docker live model, Gateway, CLI backend, ACP bind và Codex harness chạy với `OPENCLAW_SKIP_DOCKER_BUILD=1`. Nếu các shard đó tự xây dựng lại đích Docker nguồn đầy đủ, lần chạy phát hành bị cấu hình sai và sẽ lãng phí thời gian thực trên các bản dựng image trùng lặp. -## Package Acceptance +## Chấp nhận gói -Dùng `Package Acceptance` khi câu hỏi là "gói OpenClaw có thể cài đặt này có hoạt động như một sản phẩm không?" Nó khác với CI thông thường: CI thông thường xác thực cây nguồn, còn package acceptance xác thực một tarball duy nhất thông qua cùng harness Docker E2E mà người dùng thực hiện sau khi cài đặt hoặc cập nhật. +Dùng `Package Acceptance` khi câu hỏi là "gói OpenClaw có thể cài đặt này có hoạt động như một sản phẩm không?" Nó khác với CI thông thường: CI thông thường xác thực cây nguồn, còn chấp nhận gói xác thực một tarball duy nhất thông qua cùng harness Docker E2E mà người dùng thực hiện sau khi cài đặt hoặc cập nhật. ### Công việc -1. `resolve_package` checkout `workflow_ref`, phân giải một ứng viên gói, ghi `.artifacts/docker-e2e-package/openclaw-current.tgz`, ghi `.artifacts/docker-e2e-package/package-candidate.json`, tải cả hai lên dưới dạng artifact `package-under-test`, và in nguồn, workflow ref, package ref, phiên bản, SHA-256, và profile trong bản tóm tắt bước GitHub. -2. `docker_acceptance` gọi `openclaw-live-and-e2e-checks-reusable.yml` với `ref=workflow_ref` và `package_artifact_name=package-under-test`. Workflow tái sử dụng tải artifact đó xuống, xác thực inventory tarball, chuẩn bị image Docker package-digest khi cần, và chạy các lane Docker đã chọn với gói đó thay vì đóng gói checkout của workflow. Khi một profile chọn nhiều `docker_lanes` được nhắm mục tiêu, workflow tái sử dụng chuẩn bị gói và image dùng chung một lần, rồi fan out các lane đó thành các công việc Docker nhắm mục tiêu song song với artifact duy nhất. -3. `package_telegram` tùy chọn gọi `NPM Telegram Beta E2E`. Nó chạy khi `telegram_mode` không phải `none` và cài đặt cùng artifact `package-under-test` khi Package Acceptance đã phân giải một gói; dispatch Telegram độc lập vẫn có thể cài đặt một thông số npm đã xuất bản. -4. `summary` làm workflow thất bại nếu phân giải gói, Docker acceptance, hoặc lane Telegram tùy chọn thất bại. +1. `resolve_package` checkout `workflow_ref`, phân giải một ứng viên gói, ghi `.artifacts/docker-e2e-package/openclaw-current.tgz`, ghi `.artifacts/docker-e2e-package/package-candidate.json`, tải cả hai lên làm artifact `package-under-test`, và in nguồn, ref workflow, ref gói, phiên bản, SHA-256, và hồ sơ trong tóm tắt bước GitHub. +2. `docker_acceptance` gọi `openclaw-live-and-e2e-checks-reusable.yml` với `ref=workflow_ref` và `package_artifact_name=package-under-test`. Workflow tái sử dụng tải xuống artifact đó, xác thực danh mục tarball, chuẩn bị các image Docker package-digest khi cần, và chạy các làn Docker đã chọn trên gói đó thay vì đóng gói checkout workflow. Khi một hồ sơ chọn nhiều `docker_lanes` có mục tiêu, workflow tái sử dụng chuẩn bị gói và image dùng chung một lần, rồi tỏa các làn đó ra thành các công việc Docker có mục tiêu chạy song song với artifact riêng. +3. `package_telegram` tùy chọn gọi `NPM Telegram Beta E2E`. Nó chạy khi `telegram_mode` không phải `none` và cài đặt cùng artifact `package-under-test` khi Package Acceptance đã phân giải một gói; dispatch Telegram độc lập vẫn có thể cài đặt một thông số npm đã phát hành. +4. `summary` làm workflow thất bại nếu phân giải gói, chấp nhận Docker, hoặc làn Telegram tùy chọn thất bại. ### Nguồn ứng viên -- `source=npm` chỉ chấp nhận `openclaw@beta`, `openclaw@latest`, hoặc một phiên bản phát hành OpenClaw chính xác như `openclaw@2026.4.27-beta.2`. Dùng mục này cho quá trình chấp nhận beta/ổn định đã phát hành. -- `source=ref` đóng gói một nhánh, thẻ, hoặc SHA commit đầy đủ `package_ref` đáng tin cậy. Bộ phân giải lấy các nhánh/thẻ OpenClaw, xác minh commit được chọn có thể truy ngược từ lịch sử nhánh kho lưu trữ hoặc thẻ phát hành, cài đặt phụ thuộc trong một worktree tách rời, rồi đóng gói bằng `scripts/package-openclaw-for-docker.mjs`. -- `source=url` tải xuống một `.tgz` HTTPS; bắt buộc có `package_sha256`. -- `source=artifact` tải xuống một `.tgz` từ `artifact_run_id` và `artifact_name`; `package_sha256` là tùy chọn nhưng nên được cung cấp cho các artifact được chia sẻ bên ngoài. +- `source=npm` chỉ chấp nhận `openclaw@beta`, `openclaw@latest`, hoặc một phiên bản phát hành OpenClaw chính xác như `openclaw@2026.4.27-beta.2`. Dùng tùy chọn này cho việc chấp nhận bản beta/ổn định đã xuất bản. +- `source=ref` đóng gói một nhánh, thẻ hoặc SHA commit đầy đủ đáng tin cậy của `package_ref`. Bộ phân giải tìm nạp các nhánh/thẻ OpenClaw, xác minh commit được chọn có thể truy cập từ lịch sử nhánh kho lưu trữ hoặc thẻ phát hành, cài đặt các phần phụ thuộc trong một worktree tách rời, rồi đóng gói bằng `scripts/package-openclaw-for-docker.mjs`. +- `source=url` tải xuống một tệp HTTPS `.tgz`; bắt buộc phải có `package_sha256`. +- `source=artifact` tải xuống một tệp `.tgz` từ `artifact_run_id` và `artifact_name`; `package_sha256` là tùy chọn nhưng nên được cung cấp cho các artifact được chia sẻ bên ngoài. -Giữ `workflow_ref` và `package_ref` riêng biệt. `workflow_ref` là mã workflow/harness đáng tin cậy chạy bài kiểm thử. `package_ref` là commit nguồn được đóng gói khi `source=ref`. Điều này cho phép harness kiểm thử hiện tại xác thực các commit nguồn đáng tin cậy cũ hơn mà không chạy logic workflow cũ. +Giữ `workflow_ref` và `package_ref` tách biệt. `workflow_ref` là mã workflow/harness đáng tin cậy chạy kiểm thử. `package_ref` là commit nguồn được đóng gói khi `source=ref`. Điều này cho phép harness kiểm thử hiện tại xác thực các commit nguồn đáng tin cậy cũ hơn mà không chạy logic workflow cũ. ### Hồ sơ bộ kiểm thử - `smoke` — `npm-onboard-channel-agent`, `gateway-network`, `config-reload` -- `package` — `npm-onboard-channel-agent`, `doctor-switch`, `update-channel-switch`, `bundled-channel-deps-compat`, `plugins-offline`, `plugin-update` -- `product` — `package` cộng với `mcp-channels`, `cron-mcp-cleanup`, `openai-web-search-minimal`, `openwebui` -- `full` — các phần đường dẫn phát hành Docker đầy đủ với OpenWebUI +- `package` — `npm-onboard-channel-agent`, `doctor-switch`, `update-channel-switch`, `upgrade-survivor`, `bundled-channel-deps-compat`, `plugins-offline`, `plugin-update` +- `product` — `package` cộng thêm `mcp-channels`, `cron-mcp-cleanup`, `openai-web-search-minimal`, `openwebui` +- `full` — các phần release-path Docker đầy đủ với OpenWebUI - `custom` — `docker_lanes` chính xác; bắt buộc khi `suite_profile=custom` -Hồ sơ `package` dùng phạm vi phủ Plugin ngoại tuyến để quá trình xác thực gói đã phát hành không bị chặn bởi khả năng sẵn sàng trực tiếp của ClawHub. Lane Telegram tùy chọn dùng lại artifact `package-under-test` trong `NPM Telegram Beta E2E`, với đường dẫn spec npm đã phát hành được giữ cho các lần dispatch độc lập. +Hồ sơ `package` dùng phạm vi kiểm thử Plugin ngoại tuyến để việc xác thực gói đã xuất bản không bị phụ thuộc vào tính khả dụng trực tiếp của ClawHub. Lane Telegram tùy chọn tái sử dụng artifact `package-under-test` trong `NPM Telegram Beta E2E`, với đường dẫn đặc tả npm đã xuất bản được giữ cho các lần dispatch độc lập. -Kiểm tra phát hành gọi Package Acceptance với `source=ref`, `package_ref=`, `workflow_ref=`, `suite_profile=custom`, `docker_lanes='bundled-channel-deps-compat plugins-offline'`, và `telegram_mode=mock-openai`. Các phần Docker đường dẫn phát hành bao phủ các lane package/update/plugin trùng lặp; Package Acceptance giữ bằng chứng compat kênh tích hợp sẵn theo artifact gốc, Plugin ngoại tuyến, và Telegram trên cùng tarball gói đã phân giải. Kiểm tra phát hành đa hệ điều hành vẫn bao phủ onboarding, trình cài đặt, và hành vi nền tảng đặc thù hệ điều hành; xác thực sản phẩm package/update nên bắt đầu bằng Package Acceptance. Các lane Windows packaged và installer fresh cũng xác minh rằng một gói đã cài đặt có thể import một browser-control override từ đường dẫn Windows tuyệt đối thô. Smoke agent-turn OpenAI đa hệ điều hành mặc định dùng `OPENCLAW_CROSS_OS_OPENAI_MODEL` khi được đặt, nếu không thì dùng `openai/gpt-5.4-mini`, để bằng chứng cài đặt và Gateway vẫn nhanh và xác định. +Các kiểm tra phát hành gọi Package Acceptance với `source=ref`, `package_ref=`, `workflow_ref=`, `suite_profile=custom`, `docker_lanes='bundled-channel-deps-compat plugins-offline'`, và `telegram_mode=mock-openai`. Các phần Docker release-path bao phủ các lane package/update/plugin chồng lắp; Package Acceptance giữ bằng chứng compat bundled-channel gốc theo artifact, Plugin ngoại tuyến và Telegram trên cùng tarball gói đã phân giải. Các kiểm tra phát hành cross-OS vẫn bao phủ hành vi onboarding, trình cài đặt và nền tảng dành riêng cho từng hệ điều hành; xác thực sản phẩm package/update nên bắt đầu với Package Acceptance. Các lane Windows packaged và installer fresh cũng xác minh rằng một gói đã cài đặt có thể import một override browser-control từ một đường dẫn Windows tuyệt đối thô. Smoke agent-turn cross-OS của OpenAI mặc định dùng `OPENCLAW_CROSS_OS_OPENAI_MODEL` khi được đặt, nếu không thì dùng `openai/gpt-5.4-mini`, để bằng chứng cài đặt và Gateway vẫn nhanh và xác định. ### Khoảng tương thích cũ -Package Acceptance có các khoảng tương thích cũ có giới hạn cho những gói đã phát hành. Các gói đến hết `2026.4.25`, bao gồm `2026.4.25-beta.*`, có thể dùng đường dẫn tương thích: +Package Acceptance có các khoảng tương thích cũ có giới hạn cho các gói đã được xuất bản. Các gói đến `2026.4.25`, bao gồm `2026.4.25-beta.*`, có thể dùng đường dẫn tương thích: -- các mục QA riêng tư đã biết trong `dist/postinstall-inventory.json` có thể trỏ đến những tệp bị bỏ khỏi tarball; -- `doctor-switch` có thể bỏ qua trường hợp con về tính bền vững `gateway install --wrapper` khi gói không cung cấp cờ đó; -- `update-channel-switch` có thể lược bỏ `pnpm.patchedDependencies` bị thiếu khỏi fixture git giả bắt nguồn từ tarball và có thể ghi log `update.channel` đã lưu bền vững bị thiếu; -- các smoke Plugin có thể đọc vị trí install-record cũ hoặc chấp nhận thiếu tính bền vững install-record của marketplace; -- `plugin-update` có thể cho phép di trú siêu dữ liệu cấu hình trong khi vẫn yêu cầu install record và hành vi không cài đặt lại giữ nguyên. +- các mục QA riêng tư đã biết trong `dist/postinstall-inventory.json` có thể trỏ đến các tệp bị lược khỏi tarball; +- `doctor-switch` có thể bỏ qua subcase lưu bền `gateway install --wrapper` khi gói không cung cấp cờ đó; +- `update-channel-switch` có thể cắt bỏ các `pnpm.patchedDependencies` bị thiếu khỏi fixture git giả được tạo từ tarball và có thể ghi log thiếu `update.channel` đã lưu bền; +- các smoke Plugin có thể đọc các vị trí install-record cũ hoặc chấp nhận thiếu lưu bền install-record marketplace; +- `plugin-update` có thể cho phép di chuyển siêu dữ liệu cấu hình trong khi vẫn yêu cầu install record và hành vi không cài đặt lại không đổi. -Gói `2026.4.26` đã phát hành cũng có thể cảnh báo về các tệp dấu mốc siêu dữ liệu build cục bộ đã được phát hành. Các gói sau đó phải thỏa mãn các hợp đồng hiện đại; cùng những điều kiện đó sẽ thất bại thay vì cảnh báo hoặc bỏ qua. +Gói `2026.4.26` đã xuất bản cũng có thể cảnh báo về các tệp dấu siêu dữ liệu bản dựng cục bộ đã được phát hành. Các gói về sau phải đáp ứng các hợp đồng hiện đại; cùng các điều kiện đó sẽ thất bại thay vì cảnh báo hoặc bỏ qua. ### Ví dụ @@ -238,111 +238,111 @@ gh workflow run package-acceptance.yml \ -f docker_lanes='install-e2e plugin-update' ``` -Khi gỡ lỗi một lần chạy chấp nhận gói thất bại, hãy bắt đầu từ phần tóm tắt `resolve_package` để xác nhận nguồn gói, phiên bản, và SHA-256. Sau đó kiểm tra lần chạy con `docker_acceptance` và các artifact Docker của nó: `.artifacts/docker-tests/**/summary.json`, `failures.json`, log lane, thời lượng pha, và lệnh chạy lại. Ưu tiên chạy lại hồ sơ gói thất bại hoặc các lane Docker chính xác thay vì chạy lại toàn bộ xác thực phát hành. +Khi gỡ lỗi một lần chạy package acceptance thất bại, hãy bắt đầu từ phần tóm tắt `resolve_package` để xác nhận nguồn gói, phiên bản và SHA-256. Sau đó kiểm tra lần chạy con `docker_acceptance` và các artifact Docker của nó: `.artifacts/docker-tests/**/summary.json`, `failures.json`, log lane, thời gian từng pha và các lệnh chạy lại. Ưu tiên chạy lại hồ sơ gói thất bại hoặc các lane Docker chính xác thay vì chạy lại toàn bộ xác thực phát hành. ## Smoke cài đặt -Workflow `Install Smoke` riêng biệt dùng lại cùng script phạm vi thông qua job `preflight` riêng của nó. Nó chia phạm vi smoke thành `run_fast_install_smoke` và `run_full_install_smoke`. +Workflow `Install Smoke` riêng biệt tái sử dụng cùng script phạm vi thông qua job `preflight` riêng. Nó chia phạm vi smoke thành `run_fast_install_smoke` và `run_full_install_smoke`. -- **Đường dẫn nhanh** chạy cho các pull request chạm tới bề mặt Docker/package, thay đổi gói/manifest Plugin tích hợp sẵn, hoặc các bề mặt core plugin/channel/gateway/Plugin SDK mà các job smoke Docker thực thi. Các thay đổi chỉ ở nguồn Plugin tích hợp sẵn, chỉnh sửa chỉ kiểm thử, và chỉnh sửa chỉ tài liệu không đặt trước worker Docker. Đường dẫn nhanh build image Dockerfile gốc một lần, kiểm tra CLI, chạy smoke CLI agents delete shared-workspace, chạy e2e gateway-network trong container, xác minh một build arg phần mở rộng tích hợp sẵn, và chạy hồ sơ Docker Plugin tích hợp sẵn có giới hạn dưới timeout lệnh tổng hợp 240 giây (mỗi lần chạy Docker của từng kịch bản được giới hạn riêng). -- **Đường dẫn đầy đủ** giữ cài đặt gói QR và phạm vi Docker/update của trình cài đặt cho các lần chạy theo lịch hằng đêm, dispatch thủ công, kiểm tra phát hành workflow-call, và các pull request thực sự chạm tới bề mặt installer/package/Docker. Ở chế độ đầy đủ, install-smoke chuẩn bị hoặc dùng lại một image smoke Dockerfile gốc GHCR theo target-SHA, rồi chạy cài đặt gói QR, smoke Dockerfile/gateway gốc, smoke installer/update, và Docker E2E Plugin tích hợp sẵn nhanh dưới dạng các job riêng để công việc trình cài đặt không phải chờ sau các smoke image gốc. +- **Đường dẫn nhanh** chạy cho pull request chạm đến các bề mặt Docker/package, thay đổi package/manifest của Plugin đi kèm, hoặc các bề mặt Plugin/kênh/Gateway/Plugin SDK lõi mà các job smoke Docker thực thi. Các thay đổi Plugin đi kèm chỉ ở nguồn, chỉnh sửa chỉ kiểm thử và chỉnh sửa chỉ tài liệu không giữ trước worker Docker. Đường dẫn nhanh dựng image Dockerfile gốc một lần, kiểm tra CLI, chạy smoke CLI agents delete shared-workspace, chạy e2e gateway-network trong container, xác minh build arg extension đi kèm, và chạy hồ sơ Docker bundled-plugin có giới hạn dưới timeout lệnh tổng hợp 240 giây (mỗi lần chạy Docker của từng kịch bản được giới hạn riêng). +- **Đường dẫn đầy đủ** giữ phạm vi cài đặt package QR và Docker/update trình cài đặt cho các lần chạy lịch hằng đêm, dispatch thủ công, kiểm tra phát hành workflow-call và pull request thực sự chạm đến các bề mặt installer/package/Docker. Ở chế độ đầy đủ, install-smoke chuẩn bị hoặc tái sử dụng một image smoke Dockerfile gốc GHCR theo target-SHA, rồi chạy cài đặt package QR, smoke Dockerfile/gateway gốc, smoke installer/update và Docker E2E bundled-plugin nhanh dưới dạng các job riêng để công việc installer không phải chờ sau các smoke image gốc. -Các push lên `main` (bao gồm merge commit) không ép buộc đường dẫn đầy đủ; khi logic phạm vi thay đổi yêu cầu phạm vi phủ đầy đủ trên một push, workflow giữ smoke Docker nhanh và để smoke cài đặt đầy đủ cho xác thực hằng đêm hoặc phát hành. +Các lần push lên `main` (bao gồm merge commit) không bắt buộc đường dẫn đầy đủ; khi logic phạm vi thay đổi yêu cầu phạm vi đầy đủ trên một lần push, workflow giữ smoke Docker nhanh và để smoke cài đặt đầy đủ cho xác thực hằng đêm hoặc phát hành. -Smoke image-provider cài đặt toàn cục Bun chậm được kiểm soát riêng bởi `run_bun_global_install_smoke`. Nó chạy theo lịch hằng đêm và từ workflow kiểm tra phát hành, và các dispatch `Install Smoke` thủ công có thể chọn bật nó, nhưng pull request và push lên `main` thì không. Các kiểm thử Docker QR và trình cài đặt giữ các Dockerfile tập trung vào cài đặt riêng của chúng. +Smoke image-provider cài đặt toàn cục Bun chậm được kiểm soát riêng bằng `run_bun_global_install_smoke`. Nó chạy theo lịch hằng đêm và từ workflow kiểm tra phát hành, và các dispatch `Install Smoke` thủ công có thể chọn bật nó, nhưng pull request và các lần push lên `main` thì không. Các kiểm thử Docker QR và installer giữ các Dockerfile tập trung vào cài đặt của riêng chúng. ## Docker E2E cục bộ -`pnpm test:docker:all` dựng sẵn một image live-test dùng chung, đóng gói OpenClaw một lần dưới dạng tarball npm, và build hai image `scripts/e2e/Dockerfile` dùng chung: +`pnpm test:docker:all` dựng trước một image live-test dùng chung, đóng gói OpenClaw một lần dưới dạng tarball npm, và dựng hai image `scripts/e2e/Dockerfile` dùng chung: - một runner Node/Git tối giản cho các lane installer/update/plugin-dependency; -- một image chức năng cài đặt cùng tarball đó vào `/app` cho các lane chức năng thông thường. +- một image chức năng cài cùng tarball đó vào `/app` cho các lane chức năng thông thường. -Định nghĩa lane Docker nằm trong `scripts/lib/docker-e2e-scenarios.mjs`, logic planner nằm trong `scripts/lib/docker-e2e-plan.mjs`, và runner chỉ thực thi kế hoạch đã chọn. Bộ lập lịch chọn image cho mỗi lane bằng `OPENCLAW_DOCKER_E2E_BARE_IMAGE` và `OPENCLAW_DOCKER_E2E_FUNCTIONAL_IMAGE`, rồi chạy các lane với `OPENCLAW_SKIP_DOCKER_BUILD=1`. +Định nghĩa lane Docker nằm trong `scripts/lib/docker-e2e-scenarios.mjs`, logic planner nằm trong `scripts/lib/docker-e2e-plan.mjs`, và runner chỉ thực thi plan đã chọn. Scheduler chọn image cho từng lane bằng `OPENCLAW_DOCKER_E2E_BARE_IMAGE` và `OPENCLAW_DOCKER_E2E_FUNCTIONAL_IMAGE`, rồi chạy các lane với `OPENCLAW_SKIP_DOCKER_BUILD=1`. ### Tùy chỉnh -| Biến | Mặc định | Mục đích | -| -------------------------------------- | -------- | --------------------------------------------------------------------------------------------- | -| `OPENCLAW_DOCKER_ALL_PARALLELISM` | 10 | Số slot nhóm chính cho các lane thông thường. | -| `OPENCLAW_DOCKER_ALL_TAIL_PARALLELISM` | 10 | Số slot nhóm đuôi nhạy với nhà cung cấp. | -| `OPENCLAW_DOCKER_ALL_LIVE_LIMIT` | 9 | Giới hạn lane live đồng thời để các nhà cung cấp không điều tiết. | -| `OPENCLAW_DOCKER_ALL_NPM_LIMIT` | 10 | Giới hạn lane cài đặt npm đồng thời. | -| `OPENCLAW_DOCKER_ALL_SERVICE_LIMIT` | 7 | Giới hạn lane đa dịch vụ đồng thời. | -| `OPENCLAW_DOCKER_ALL_START_STAGGER_MS` | 2000 | Độ giãn cách giữa các lần khởi động lane để tránh bão tạo Docker daemon; đặt `0` để không giãn cách. | -| `OPENCLAW_DOCKER_ALL_LANE_TIMEOUT_MS` | 7200000 | Timeout dự phòng cho mỗi lane (120 phút); các lane live/tail được chọn dùng giới hạn chặt hơn. | -| `OPENCLAW_DOCKER_ALL_DRY_RUN` | chưa đặt | `1` in kế hoạch bộ lập lịch mà không chạy lane. | -| `OPENCLAW_DOCKER_ALL_LANES` | chưa đặt | Danh sách lane chính xác, phân tách bằng dấu phẩy; bỏ qua smoke dọn dẹp để agent có thể tái hiện một lane thất bại. | +| Biến | Mặc định | Mục đích | +| -------------------------------------- | -------- | -------------------------------------------------------------------------------------------- | +| `OPENCLAW_DOCKER_ALL_PARALLELISM` | 10 | Số slot main-pool cho các lane thông thường. | +| `OPENCLAW_DOCKER_ALL_TAIL_PARALLELISM` | 10 | Số slot tail-pool nhạy cảm với provider. | +| `OPENCLAW_DOCKER_ALL_LIVE_LIMIT` | 9 | Giới hạn lane live đồng thời để provider không throttle. | +| `OPENCLAW_DOCKER_ALL_NPM_LIMIT` | 10 | Giới hạn lane cài đặt npm đồng thời. | +| `OPENCLAW_DOCKER_ALL_SERVICE_LIMIT` | 7 | Giới hạn lane đa dịch vụ đồng thời. | +| `OPENCLAW_DOCKER_ALL_START_STAGGER_MS` | 2000 | Độ trễ giữa các lần bắt đầu lane để tránh bão tạo Docker daemon; đặt `0` để không tạo trễ. | +| `OPENCLAW_DOCKER_ALL_LANE_TIMEOUT_MS` | 7200000 | Timeout dự phòng mỗi lane (120 phút); các lane live/tail được chọn dùng giới hạn chặt hơn. | +| `OPENCLAW_DOCKER_ALL_DRY_RUN` | chưa đặt | `1` in plan scheduler mà không chạy lane. | +| `OPENCLAW_DOCKER_ALL_LANES` | chưa đặt | Danh sách lane chính xác phân tách bằng dấu phẩy; bỏ qua smoke dọn dẹp để agent có thể tái tạo một lane thất bại. | -Một lane nặng hơn giới hạn hiệu dụng của nó vẫn có thể bắt đầu từ một nhóm trống, rồi chạy một mình cho đến khi giải phóng dung lượng. Tổng hợp cục bộ preflight Docker, xóa các container OpenClaw E2E cũ, phát trạng thái lane đang hoạt động, lưu thời lượng lane để sắp xếp dài nhất trước, và mặc định dừng lập lịch các lane trong nhóm mới sau lỗi đầu tiên. +Một lane nặng hơn giới hạn hiệu dụng của nó vẫn có thể bắt đầu từ một pool trống, rồi chạy một mình cho đến khi nhả dung lượng. Tổng hợp cục bộ preflight Docker, xóa các container OpenClaw E2E cũ, phát trạng thái lane đang hoạt động, lưu bền thời gian lane để sắp xếp dài nhất trước, và mặc định dừng lên lịch các lane pooled mới sau lỗi đầu tiên. ### Workflow live/E2E tái sử dụng -Workflow live/E2E tái sử dụng hỏi `scripts/test-docker-all.mjs --plan-json` xem cần gói, loại image, image live, lane, và phạm vi thông tin xác thực nào. Sau đó `scripts/docker-e2e.mjs` chuyển kế hoạch đó thành GitHub outputs và tóm tắt. Nó hoặc đóng gói OpenClaw thông qua `scripts/package-openclaw-for-docker.mjs`, tải xuống artifact gói của lần chạy hiện tại, hoặc tải xuống artifact gói từ `package_artifact_run_id`; xác thực inventory tarball; build và push image Docker E2E bare/functional GHCR được gắn thẻ theo digest gói thông qua cache lớp Docker của Blacksmith khi kế hoạch cần các lane đã cài gói; và dùng lại các input `docker_e2e_bare_image`/`docker_e2e_functional_image` đã cung cấp hoặc các image theo digest gói hiện có thay vì build lại. Các lần pull image Docker được thử lại với timeout mỗi lần thử có giới hạn 180 giây để một luồng registry/cache bị kẹt được thử lại nhanh chóng thay vì tiêu tốn phần lớn đường găng CI. +Workflow live/E2E tái sử dụng hỏi `scripts/test-docker-all.mjs --plan-json` xem cần phạm vi package, loại image, image live, lane và credential nào. Sau đó `scripts/docker-e2e.mjs` chuyển plan đó thành output và tóm tắt GitHub. Nó hoặc đóng gói OpenClaw thông qua `scripts/package-openclaw-for-docker.mjs`, tải xuống artifact package của lần chạy hiện tại, hoặc tải xuống artifact package từ `package_artifact_run_id`; xác thực inventory tarball; dựng và push các image Docker E2E bare/functional GHCR được gắn thẻ theo package-digest thông qua cache lớp Docker của Blacksmith khi plan cần các lane đã cài package; và tái sử dụng input `docker_e2e_bare_image`/`docker_e2e_functional_image` được cung cấp hoặc các image package-digest hiện có thay vì dựng lại. Các lần pull image Docker được thử lại với timeout mỗi lần thử có giới hạn 180 giây để một luồng registry/cache bị kẹt sẽ thử lại nhanh thay vì tiêu thụ phần lớn đường găng CI. -### Các phần đường dẫn phát hành +### Các phần release-path -Phạm vi Docker phát hành chạy các job nhỏ hơn theo từng phần với `OPENCLAW_SKIP_DOCKER_BUILD=1` để mỗi phần chỉ pull loại image nó cần và thực thi nhiều lane thông qua cùng bộ lập lịch có trọng số: +Phạm vi Docker phát hành chạy các job chia nhỏ hơn với `OPENCLAW_SKIP_DOCKER_BUILD=1` để mỗi phần chỉ pull loại image nó cần và thực thi nhiều lane thông qua cùng scheduler có trọng số: - `OPENCLAW_DOCKER_ALL_PROFILE=release-path` - `OPENCLAW_DOCKER_ALL_CHUNK=core | package-update-openai | package-update-anthropic | package-update-core | plugins-runtime-plugins | plugins-runtime-services | plugins-runtime-install-a..h | bundled-channels` -Các khối Docker của bản phát hành hiện tại là `core`, `package-update-openai`, `package-update-anthropic`, `package-update-core`, `plugins-runtime-plugins`, `plugins-runtime-services`, `plugins-runtime-install-a` đến `plugins-runtime-install-h`, `bundled-channels-core`, `bundled-channels-update-a`, `bundled-channels-update-discord`, `bundled-channels-update-b`, và `bundled-channels-contracts`. Khối tổng hợp `bundled-channels` vẫn khả dụng cho các lần chạy lại thủ công một lần, còn `plugins-runtime-core`, `plugins-runtime`, và `plugins-integrations` vẫn là các bí danh plugin/runtime tổng hợp. Bí danh làn `install-e2e` vẫn là bí danh chạy lại thủ công tổng hợp cho cả hai làn trình cài đặt nhà cung cấp. Khối `bundled-channels` chạy các làn tách `bundled-channel-*` và `bundled-channel-update-*` thay vì làn tuần tự tất cả trong một `bundled-channel-deps`. +Các chunk Docker của bản phát hành hiện tại là `core`, `package-update-openai`, `package-update-anthropic`, `package-update-core`, `plugins-runtime-plugins`, `plugins-runtime-services`, `plugins-runtime-install-a` đến `plugins-runtime-install-h`, `bundled-channels-core`, `bundled-channels-update-a`, `bundled-channels-update-discord`, `bundled-channels-update-b`, và `bundled-channels-contracts`. Chunk tổng hợp `bundled-channels` vẫn khả dụng cho các lần chạy lại thủ công một lần, và `plugins-runtime-core`, `plugins-runtime`, cùng `plugins-integrations` vẫn là các bí danh Plugin/runtime tổng hợp. Bí danh lane `install-e2e` vẫn là bí danh chạy lại thủ công tổng hợp cho cả hai lane trình cài đặt provider. Chunk `bundled-channels` chạy các lane `bundled-channel-*` và `bundled-channel-update-*` đã tách, thay vì lane `bundled-channel-deps` nối tiếp gộp tất cả trong một. -OpenWebUI được gộp vào `plugins-runtime-services` khi phạm vi phủ đường dẫn phát hành đầy đủ yêu cầu, và chỉ giữ một khối độc lập `openwebui` cho các lượt dispatch chỉ dành cho OpenWebUI. Các làn cập nhật kênh đi kèm thử lại một lần đối với lỗi mạng npm tạm thời. +OpenWebUI được gộp vào `plugins-runtime-services` khi phạm vi bao phủ đường dẫn phát hành đầy đủ yêu cầu, và chỉ giữ chunk độc lập `openwebui` cho các dispatch chỉ dành cho OpenWebUI. Các lane cập nhật kênh đi kèm thử lại một lần đối với lỗi mạng npm nhất thời. -Mỗi khối tải lên `.artifacts/docker-tests/` với nhật ký làn, thời gian chạy, `summary.json`, `failures.json`, thời gian từng pha, JSON kế hoạch của bộ lập lịch, bảng làn chậm, và các lệnh chạy lại theo từng làn. Đầu vào `docker_lanes` của workflow chạy các làn đã chọn trên các image đã chuẩn bị thay vì các job khối, giúp việc gỡ lỗi làn thất bại được giới hạn trong một job Docker có mục tiêu và chuẩn bị, tải xuống, hoặc tái sử dụng artifact gói cho lần chạy đó; nếu một làn được chọn là làn Docker live, job có mục tiêu sẽ build image kiểm thử live cục bộ cho lần chạy lại đó. Các lệnh chạy lại GitHub được tạo theo từng làn bao gồm `package_artifact_run_id`, `package_artifact_name`, và các đầu vào image đã chuẩn bị khi những giá trị đó tồn tại, để một làn thất bại có thể tái sử dụng đúng gói và image từ lần chạy thất bại. +Mỗi chunk tải lên `.artifacts/docker-tests/` cùng với nhật ký lane, thời gian chạy, `summary.json`, `failures.json`, thời gian từng pha, JSON kế hoạch bộ lập lịch, bảng lane chậm, và lệnh chạy lại cho từng lane. Input `docker_lanes` của workflow chạy các lane đã chọn trên các image đã chuẩn bị thay vì các job chunk, nhờ đó việc gỡ lỗi lane lỗi được giới hạn trong một job Docker mục tiêu và chuẩn bị, tải xuống, hoặc tái sử dụng artifact gói cho lần chạy đó; nếu một lane đã chọn là lane Docker live, job mục tiêu sẽ build image kiểm thử live cục bộ cho lần chạy lại đó. Các lệnh chạy lại GitHub được tạo cho từng lane bao gồm `package_artifact_run_id`, `package_artifact_name`, và các input image đã chuẩn bị khi những giá trị đó tồn tại, để một lane lỗi có thể tái sử dụng đúng gói và image từ lần chạy lỗi. ```bash -pnpm test:docker:rerun # tải xuống artifact Docker và in các lệnh chạy lại có mục tiêu dạng kết hợp/theo từng làn -pnpm test:docker:timings # tóm tắt làn chậm và đường găng theo pha +pnpm test:docker:rerun # download Docker artifacts and print combined/per-lane targeted rerun commands +pnpm test:docker:timings # slow-lane and phase critical-path summaries ``` -Workflow live/E2E theo lịch chạy toàn bộ bộ Docker đường dẫn phát hành hằng ngày. +Workflow live/E2E theo lịch chạy bộ kiểm thử Docker đầy đủ của đường dẫn phát hành hằng ngày. ## Bản phát hành trước Plugin -`Plugin Prerelease` là phạm vi phủ sản phẩm/gói tốn kém hơn, nên đây là workflow riêng được dispatch bởi `Full Release Validation` hoặc bởi một người vận hành rõ ràng. Các pull request thông thường, lượt push lên `main`, và các lượt dispatch CI thủ công độc lập không bật bộ này. Nó cân bằng các bài kiểm thử plugin đi kèm trên tám worker tiện ích mở rộng; các job shard tiện ích mở rộng đó chạy tối đa hai nhóm cấu hình plugin cùng lúc với một worker Vitest cho mỗi nhóm và heap Node lớn hơn để các lô plugin nặng về import không tạo thêm job CI. +`Plugin Prerelease` có phạm vi bao phủ sản phẩm/gói tốn kém hơn, nên đây là một workflow riêng được dispatch bởi `Full Release Validation` hoặc bởi một operator rõ ràng. Các pull request thông thường, push lên `main`, và dispatch CI thủ công độc lập không chạy bộ kiểm thử đó. Workflow này cân bằng các kiểm thử Plugin đi kèm trên tám worker extension; các job shard extension đó chạy tối đa hai nhóm cấu hình Plugin cùng lúc, với một worker Vitest cho mỗi nhóm và heap Node lớn hơn để các batch Plugin nặng về import không tạo thêm job CI. -## QA Lab +## Phòng kiểm thử QA -QA Lab có các làn CI chuyên dụng nằm ngoài workflow chính có phạm vi thông minh. +Phòng kiểm thử QA có các lane CI riêng nằm ngoài workflow scoped thông minh chính. -- Workflow `Parity gate` chạy trên các thay đổi PR khớp và dispatch thủ công; nó build runtime QA riêng tư và so sánh các gói agentic GPT-5.5 và Opus 4.6 giả lập. -- Workflow `QA-Lab - All Lanes` chạy hằng đêm trên `main` và khi dispatch thủ công; nó tỏa ra cổng parity giả lập, làn Matrix live, và các làn Telegram và Discord live dưới dạng các job song song. Các job live dùng môi trường `qa-live-shared`, còn Telegram/Discord dùng lease Convex. +- Workflow `Parity gate` chạy trên các thay đổi PR khớp điều kiện và dispatch thủ công; nó build runtime QA riêng và so sánh các pack agentic GPT-5.5 và Opus 4.6 mô phỏng. +- Workflow `QA-Lab - All Lanes` chạy hằng đêm trên `main` và khi dispatch thủ công; nó phân tán cổng parity mô phỏng, lane Matrix live, và các lane Telegram cùng Discord live thành các job song song. Các job live dùng môi trường `qa-live-shared`, còn Telegram/Discord dùng lease Convex. -Các kiểm tra phát hành chạy các làn truyền tải Matrix và Telegram live với nhà cung cấp giả lập xác định và các model đủ điều kiện giả lập (`mock-openai/gpt-5.5` và `mock-openai/gpt-5.5-alt`) để hợp đồng kênh được cô lập khỏi độ trễ model live và khởi động plugin nhà cung cấp thông thường. Gateway truyền tải live tắt tìm kiếm bộ nhớ vì QA parity bao phủ riêng hành vi bộ nhớ; kết nối nhà cung cấp được bao phủ bởi các bộ model live, nhà cung cấp native, và nhà cung cấp Docker riêng biệt. +Các kiểm tra phát hành chạy các lane vận chuyển live Matrix và Telegram với provider mô phỏng xác định và các model đủ điều kiện mô phỏng (`mock-openai/gpt-5.5` và `mock-openai/gpt-5.5-alt`) để hợp đồng kênh được tách biệt khỏi độ trễ model live và quá trình khởi động Plugin provider thông thường. Gateway vận chuyển live tắt tìm kiếm bộ nhớ vì parity QA bao phủ riêng hành vi bộ nhớ; khả năng kết nối provider được bao phủ bởi các bộ kiểm thử riêng cho model live, provider native, và provider Docker. -Matrix dùng `--profile fast` cho các cổng theo lịch và phát hành, chỉ thêm `--fail-fast` khi CLI đã checkout hỗ trợ nó. Mặc định CLI và đầu vào workflow thủ công vẫn là `all`; dispatch thủ công `matrix_profile=all` luôn chia nhỏ phạm vi phủ Matrix đầy đủ thành các job `transport`, `media`, `e2ee-smoke`, `e2ee-deep`, và `e2ee-cli`. +Matrix dùng `--profile fast` cho các cổng theo lịch và phát hành, chỉ thêm `--fail-fast` khi CLI đã checkout hỗ trợ. Mặc định CLI và input workflow thủ công vẫn là `all`; dispatch thủ công `matrix_profile=all` luôn shard phạm vi bao phủ Matrix đầy đủ thành các job `transport`, `media`, `e2ee-smoke`, `e2ee-deep`, và `e2ee-cli`. -`OpenClaw Release Checks` cũng chạy các làn QA Lab trọng yếu cho phát hành trước khi phê duyệt phát hành; cổng QA parity của nó chạy các gói ứng viên và baseline dưới dạng các job làn song song, rồi tải xuống cả hai artifact vào một job báo cáo nhỏ cho phép so sánh parity cuối cùng. +`OpenClaw Release Checks` cũng chạy các lane QA Lab quan trọng cho phát hành trước khi phê duyệt phát hành; cổng parity QA của nó chạy các pack ứng viên và baseline dưới dạng job lane song song, rồi tải cả hai artifact xuống một job báo cáo nhỏ để so sánh parity cuối cùng. -Không đặt đường dẫn landing PR sau `Parity gate` trừ khi thay đổi thực sự chạm tới runtime QA, parity gói model, hoặc một bề mặt do workflow parity sở hữu. Với các bản sửa kênh, cấu hình, tài liệu, hoặc kiểm thử đơn vị thông thường, hãy xem đó là tín hiệu tùy chọn và đi theo bằng chứng CI/kiểm tra có phạm vi. +Không đặt đường dẫn landing PR phía sau `Parity gate` trừ khi thay đổi thực sự chạm đến runtime QA, parity model-pack, hoặc một bề mặt do workflow parity sở hữu. Với các bản sửa kênh, cấu hình, tài liệu, hoặc kiểm thử đơn vị thông thường, hãy xem đó là tín hiệu tùy chọn và làm theo bằng chứng CI/kiểm tra theo phạm vi. ## CodeQL -Workflow `CodeQL` cố ý là trình quét bảo mật lượt đầu có phạm vi hẹp, không phải quét toàn bộ kho lưu trữ. Các lần chạy bảo vệ hằng ngày, thủ công, và pull request không phải draft quét mã workflow Actions cùng các bề mặt JavaScript/TypeScript rủi ro cao nhất bằng các truy vấn bảo mật độ tin cậy cao được lọc theo `security-severity` cao/nghiêm trọng. +Workflow `CodeQL` cố ý là trình quét bảo mật lượt đầu phạm vi hẹp, không phải quét toàn bộ repository. Các lần chạy hằng ngày, thủ công, và bảo vệ pull request không phải draft quét mã workflow Actions cùng các bề mặt JavaScript/TypeScript rủi ro cao nhất bằng các truy vấn bảo mật độ tin cậy cao được lọc theo `security-severity` cao/nghiêm trọng. -Bảo vệ pull request vẫn nhẹ: nó chỉ khởi động cho các thay đổi dưới `.github/actions`, `.github/codeql`, `.github/workflows`, `packages`, hoặc `src`, và chạy cùng ma trận bảo mật độ tin cậy cao như workflow theo lịch. CodeQL Android và macOS không nằm trong mặc định PR. +Bảo vệ pull request vẫn nhẹ: nó chỉ bắt đầu với các thay đổi dưới `.github/actions`, `.github/codeql`, `.github/workflows`, `packages`, hoặc `src`, và chạy cùng ma trận bảo mật độ tin cậy cao như workflow theo lịch. CodeQL Android và macOS không nằm trong mặc định PR. ### Danh mục bảo mật | Danh mục | Bề mặt | | ------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------- | -| `/codeql-security-high/core-auth-secrets` | Xác thực, secret, sandbox, cron, và baseline gateway | -| `/codeql-security-high/channel-runtime-boundary` | Hợp đồng triển khai kênh lõi cùng runtime plugin kênh, Gateway, Plugin SDK, secret, các điểm chạm kiểm toán | -| `/codeql-security-high/network-ssrf-boundary` | Các bề mặt SSRF lõi, phân tích IP, bảo vệ mạng, web-fetch, và chính sách SSRF của Plugin SDK | -| `/codeql-security-high/mcp-process-tool-boundary` | Máy chủ MCP, helper thực thi tiến trình, phân phối gửi ra ngoài, và cổng thực thi công cụ của agent | -| `/codeql-security-high/plugin-trust-boundary` | Các bề mặt tin cậy của cài đặt Plugin, loader, manifest, registry, staging phụ thuộc runtime, tải nguồn, và hợp đồng gói Plugin SDK | +| `/codeql-security-high/core-auth-secrets` | Auth, secret, sandbox, cron, và baseline Gateway | +| `/codeql-security-high/channel-runtime-boundary` | Các hợp đồng triển khai kênh lõi cộng với runtime Plugin kênh, Gateway, Plugin SDK, secret, điểm chạm audit | +| `/codeql-security-high/network-ssrf-boundary` | Các bề mặt SSRF lõi, phân tích IP, bảo vệ mạng, web-fetch, và chính sách SSRF Plugin SDK | +| `/codeql-security-high/mcp-process-tool-boundary` | Máy chủ MCP, helper thực thi tiến trình, gửi outbound, và cổng thực thi công cụ agent | +| `/codeql-security-high/plugin-trust-boundary` | Các bề mặt tin cậy của cài đặt Plugin, loader, manifest, registry, staging dependency runtime, tải nguồn, và hợp đồng gói Plugin SDK | ### Shard bảo mật theo nền tảng - `CodeQL Android Critical Security` — shard bảo mật Android theo lịch. Build ứng dụng Android thủ công cho CodeQL trên runner Blacksmith Linux nhỏ nhất được workflow sanity chấp nhận. Tải lên dưới `/codeql-critical-security/android`. -- `CodeQL macOS Critical Security` — shard bảo mật macOS hằng tuần/thủ công. Build ứng dụng macOS thủ công cho CodeQL trên Blacksmith macOS, lọc kết quả build phụ thuộc khỏi SARIF được tải lên, và tải lên dưới `/codeql-critical-security/macos`. Được giữ ngoài mặc định hằng ngày vì build macOS chiếm phần lớn thời gian chạy ngay cả khi sạch. +- `CodeQL macOS Critical Security` — shard bảo mật macOS hằng tuần/thủ công. Build ứng dụng macOS thủ công cho CodeQL trên Blacksmith macOS, lọc kết quả build dependency ra khỏi SARIF đã tải lên, và tải lên dưới `/codeql-critical-security/macos`. Được giữ ngoài mặc định hằng ngày vì build macOS chiếm phần lớn thời gian chạy ngay cả khi sạch. ### Danh mục Chất lượng Nghiêm trọng -`CodeQL Critical Quality` là shard không liên quan đến bảo mật tương ứng. Nó chỉ chạy các truy vấn chất lượng JavaScript/TypeScript không bảo mật, mức độ lỗi, trên các bề mặt hẹp có giá trị cao trên runner Blacksmith Linux nhỏ hơn. Bảo vệ pull request của nó cố ý nhỏ hơn profile theo lịch: các PR không phải draft chỉ chạy các shard `agent-runtime-boundary`, `config-boundary`, `core-auth-secrets`, `channel-runtime-boundary`, `gateway-runtime-boundary`, `memory-runtime-boundary`, `mcp-process-runtime-boundary`, `provider-runtime-boundary`, `session-diagnostics-boundary`, `plugin-boundary`, `plugin-sdk-package-contract`, và `plugin-sdk-reply-runtime` tương ứng cho mã thực thi lệnh/model/công cụ của agent và dispatch phản hồi, mã schema/cấu hình/di trú/IO, mã auth/secret/sandbox/bảo mật, runtime kênh lõi và plugin kênh đi kèm, giao thức Gateway/phương thức máy chủ, runtime bộ nhớ/glue SDK, MCP/tiến trình/phân phối gửi ra ngoài, runtime nhà cung cấp/danh mục model, chẩn đoán phiên/hàng đợi phân phối, loader plugin, hợp đồng Plugin SDK/gói, hoặc thay đổi runtime phản hồi Plugin SDK. Các thay đổi cấu hình CodeQL và workflow chất lượng chạy cả mười hai shard chất lượng PR. +`CodeQL Critical Quality` là shard phi bảo mật tương ứng. Nó chỉ chạy các truy vấn chất lượng JavaScript/TypeScript không phải bảo mật, mức nghiêm trọng lỗi, trên các bề mặt giá trị cao phạm vi hẹp trên runner Blacksmith Linux nhỏ hơn. Bảo vệ pull request của nó cố ý nhỏ hơn profile theo lịch: PR không phải draft chỉ chạy các shard `agent-runtime-boundary`, `config-boundary`, `core-auth-secrets`, `channel-runtime-boundary`, `gateway-runtime-boundary`, `memory-runtime-boundary`, `mcp-process-runtime-boundary`, `provider-runtime-boundary`, `session-diagnostics-boundary`, `plugin-boundary`, `plugin-sdk-package-contract`, và `plugin-sdk-reply-runtime` tương ứng cho các thay đổi trong mã thực thi lệnh/model/công cụ agent và dispatch phản hồi, mã schema/cấu hình/migration/IO, mã auth/secret/sandbox/bảo mật, runtime Plugin kênh lõi và kênh đi kèm, protocol Gateway/server-method, runtime bộ nhớ/liên kết SDK, MCP/tiến trình/gửi outbound, runtime provider/catalog model, chẩn đoán phiên/hàng đợi gửi, loader Plugin, hợp đồng Plugin SDK/gói, hoặc runtime phản hồi Plugin SDK. Các thay đổi cấu hình CodeQL và workflow chất lượng chạy toàn bộ mười hai shard chất lượng PR. Dispatch thủ công chấp nhận: @@ -350,40 +350,40 @@ Dispatch thủ công chấp nhận: profile=all|agent-runtime-boundary|config-boundary|core-auth-secrets|channel-runtime-boundary|gateway-runtime-boundary|memory-runtime-boundary|mcp-process-runtime-boundary|plugin-boundary|plugin-sdk-package-contract|plugin-sdk-reply-runtime|provider-runtime-boundary|session-diagnostics-boundary ``` -Các profile hẹp là các hook hướng dẫn/lặp để chạy một shard chất lượng riêng lẻ. +Các profile hẹp là hook hướng dẫn/lặp để chạy một shard chất lượng riêng lẻ. -| Danh mục | Bề mặt | -| ------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------- | -| `/codeql-critical-quality/core-auth-secrets` | Mã ranh giới bảo mật cho xác thực, bí mật, sandbox, Cron và Gateway | -| `/codeql-critical-quality/config-boundary` | Hợp đồng về lược đồ cấu hình, di chuyển, chuẩn hóa và IO | -| `/codeql-critical-quality/gateway-runtime-boundary` | Lược đồ giao thức Gateway và hợp đồng phương thức máy chủ | -| `/codeql-critical-quality/channel-runtime-boundary` | Hợp đồng triển khai kênh lõi và Plugin kênh đi kèm | -| `/codeql-critical-quality/agent-runtime-boundary` | Hợp đồng runtime cho thực thi lệnh, điều phối model/provider, điều phối và hàng đợi tự động trả lời, cùng control plane ACP | -| `/codeql-critical-quality/mcp-process-runtime-boundary` | Máy chủ MCP và cầu nối công cụ, helper giám sát tiến trình, và hợp đồng gửi đi | -| `/codeql-critical-quality/memory-runtime-boundary` | SDK máy chủ bộ nhớ, facade runtime bộ nhớ, bí danh SDK Plugin bộ nhớ, phần nối kích hoạt runtime bộ nhớ, và lệnh doctor bộ nhớ | -| `/codeql-critical-quality/session-diagnostics-boundary` | Nội bộ hàng đợi trả lời, hàng đợi gửi phiên, helper liên kết/gửi phiên ra ngoài, bề mặt gói sự kiện/nhật ký chẩn đoán, và hợp đồng CLI doctor phiên | -| `/codeql-critical-quality/plugin-sdk-reply-runtime` | Điều phối trả lời đến SDK Plugin, helper payload/chunking/runtime cho trả lời, tùy chọn trả lời kênh, hàng đợi gửi, và helper liên kết phiên/luồng | -| `/codeql-critical-quality/provider-runtime-boundary` | Chuẩn hóa danh mục model, xác thực và khám phá provider, đăng ký runtime provider, mặc định/danh mục provider, và registry web/search/fetch/embedding | -| `/codeql-critical-quality/ui-control-plane` | Bootstrap giao diện điều khiển, lưu trữ cục bộ, luồng điều khiển Gateway, và hợp đồng runtime control plane tác vụ | -| `/codeql-critical-quality/web-media-runtime-boundary` | Hợp đồng runtime cho web fetch/search lõi, IO media, hiểu media, tạo hình ảnh, và tạo media | -| `/codeql-critical-quality/plugin-boundary` | Hợp đồng loader, registry, bề mặt công khai, và entrypoint SDK Plugin | -| `/codeql-critical-quality/plugin-sdk-package-contract` | Mã nguồn SDK Plugin phía gói đã phát hành và helper hợp đồng gói plugin | +| Danh mục | Bề mặt | +| ------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| `/codeql-critical-quality/core-auth-secrets` | Mã ranh giới bảo mật cho xác thực, bí mật, sandbox, Cron và Gateway | +| `/codeql-critical-quality/config-boundary` | Hợp đồng lược đồ cấu hình, di trú, chuẩn hóa và IO | +| `/codeql-critical-quality/gateway-runtime-boundary` | Lược đồ giao thức Gateway và hợp đồng phương thức máy chủ | +| `/codeql-critical-quality/channel-runtime-boundary` | Hợp đồng triển khai kênh lõi và Plugin kênh đi kèm | +| `/codeql-critical-quality/agent-runtime-boundary` | Hợp đồng runtime cho thực thi lệnh, điều phối model/provider, điều phối và hàng đợi tự động trả lời, và mặt phẳng điều khiển ACP | +| `/codeql-critical-quality/mcp-process-runtime-boundary` | Máy chủ MCP và cầu nối công cụ, helper giám sát tiến trình, và hợp đồng gửi đi | +| `/codeql-critical-quality/memory-runtime-boundary` | Memory host SDK, facade runtime bộ nhớ, bí danh Plugin SDK bộ nhớ, phần gắn kích hoạt runtime bộ nhớ, và lệnh doctor bộ nhớ | +| `/codeql-critical-quality/session-diagnostics-boundary` | Nội bộ hàng đợi trả lời, hàng đợi gửi phiên, helper liên kết/gửi phiên đi, bề mặt gói sự kiện/nhật ký chẩn đoán, và hợp đồng CLI doctor phiên | +| `/codeql-critical-quality/plugin-sdk-reply-runtime` | Điều phối trả lời đầu vào Plugin SDK, helper payload/chia khúc/runtime trả lời, tùy chọn trả lời kênh, hàng đợi gửi, và helper liên kết phiên/luồng | +| `/codeql-critical-quality/provider-runtime-boundary` | Chuẩn hóa danh mục model, xác thực và khám phá provider, đăng ký runtime provider, mặc định/danh mục provider, và registry web/search/fetch/embedding | +| `/codeql-critical-quality/ui-control-plane` | Khởi động Control UI, lưu trữ cục bộ, luồng điều khiển Gateway, và hợp đồng runtime mặt phẳng điều khiển tác vụ | +| `/codeql-critical-quality/web-media-runtime-boundary` | Hợp đồng runtime cho web fetch/search lõi, media IO, hiểu media, tạo ảnh, và tạo media | +| `/codeql-critical-quality/plugin-boundary` | Hợp đồng loader, registry, bề mặt công khai, và điểm vào Plugin SDK | +| `/codeql-critical-quality/plugin-sdk-package-contract` | Mã nguồn Plugin SDK phía gói đã xuất bản và helper hợp đồng gói Plugin | -Chất lượng được tách riêng khỏi bảo mật để các phát hiện về chất lượng có thể được lên lịch, đo lường, vô hiệu hóa hoặc mở rộng mà không che khuất tín hiệu bảo mật. Việc mở rộng CodeQL cho Swift, Python và Plugin đi kèm chỉ nên được thêm lại dưới dạng công việc tiếp nối có phạm vi hoặc được chia mảnh sau khi các hồ sơ hẹp đã có runtime và tín hiệu ổn định. +Chất lượng được tách riêng khỏi bảo mật để các phát hiện về chất lượng có thể được lên lịch, đo lường, vô hiệu hóa hoặc mở rộng mà không che khuất tín hiệu bảo mật. Việc mở rộng CodeQL cho Swift, Python và Plugin đi kèm chỉ nên được thêm lại dưới dạng công việc tiếp theo có phạm vi hoặc được chia shard sau khi các hồ sơ hẹp có runtime và tín hiệu ổn định. ## Quy trình bảo trì ### Docs Agent -Quy trình `Docs Agent` là một làn bảo trì Codex theo sự kiện để giữ tài liệu hiện có đồng bộ với các thay đổi vừa được merge. Nó không có lịch thuần túy: một lượt chạy CI push không phải bot thành công trên `main` có thể kích hoạt nó, và dispatch thủ công có thể chạy trực tiếp. Các lần gọi workflow-run sẽ bỏ qua khi `main` đã tiến lên hoặc khi một lượt chạy Docs Agent không bị bỏ qua khác đã được tạo trong giờ trước đó. Khi chạy, nó xem xét dải commit từ SHA nguồn Docs Agent không bị bỏ qua trước đó đến `main` hiện tại, vì vậy một lượt chạy hằng giờ có thể bao phủ mọi thay đổi trên main đã tích lũy kể từ lần rà soát tài liệu gần nhất. +Quy trình `Docs Agent` là một lane bảo trì Codex theo sự kiện để giữ tài liệu hiện có đồng bộ với các thay đổi vừa được merge. Nó không có lịch chạy thuần túy: một lượt chạy CI push không phải bot thành công trên `main` có thể kích hoạt nó, và thao tác dispatch thủ công có thể chạy trực tiếp. Các lượt gọi workflow-run sẽ bỏ qua khi `main` đã tiến lên hoặc khi một lượt chạy Docs Agent không bị bỏ qua khác đã được tạo trong giờ vừa qua. Khi chạy, nó xem xét phạm vi commit từ SHA nguồn Docs Agent không bị bỏ qua trước đó đến `main` hiện tại, nên một lượt chạy mỗi giờ có thể bao phủ toàn bộ thay đổi trên main tích lũy kể từ lượt rà soát tài liệu gần nhất. ### Test Performance Agent -Quy trình `Test Performance Agent` là một làn bảo trì Codex theo sự kiện dành cho các bài kiểm thử chậm. Nó không có lịch thuần túy: một lượt chạy CI push không phải bot thành công trên `main` có thể kích hoạt nó, nhưng nó sẽ bỏ qua nếu một lần gọi workflow-run khác đã chạy hoặc đang chạy trong ngày UTC đó. Dispatch thủ công bỏ qua cổng hoạt động hằng ngày này. Làn này tạo báo cáo hiệu năng Vitest toàn bộ bộ kiểm thử theo nhóm, cho phép Codex chỉ thực hiện các bản sửa hiệu năng kiểm thử nhỏ vẫn giữ nguyên độ bao phủ thay vì refactor rộng, rồi chạy lại báo cáo toàn bộ bộ kiểm thử và từ chối các thay đổi làm giảm số lượng bài kiểm thử baseline đang pass. Nếu baseline có bài kiểm thử thất bại, Codex chỉ được sửa các lỗi rõ ràng và báo cáo toàn bộ bộ kiểm thử sau agent phải pass trước khi bất cứ thứ gì được commit. Khi `main` tiến lên trước khi bot push được merge, làn này rebase bản vá đã xác thực, chạy lại `pnpm check:changed`, và thử push lại; các bản vá cũ có xung đột sẽ bị bỏ qua. Nó dùng Ubuntu do GitHub-hosted cung cấp để action Codex có thể giữ cùng tư thế an toàn drop-sudo như docs agent. +Quy trình `Test Performance Agent` là một lane bảo trì Codex theo sự kiện dành cho các kiểm thử chậm. Nó không có lịch chạy thuần túy: một lượt chạy CI push không phải bot thành công trên `main` có thể kích hoạt nó, nhưng nó sẽ bỏ qua nếu một lượt gọi workflow-run khác đã chạy hoặc đang chạy trong cùng ngày UTC đó. Dispatch thủ công bỏ qua cổng hoạt động hằng ngày này. Lane tạo báo cáo hiệu năng Vitest toàn bộ bộ kiểm thử theo nhóm, cho phép Codex chỉ thực hiện các sửa đổi hiệu năng kiểm thử nhỏ vẫn giữ nguyên coverage thay vì refactor rộng, sau đó chạy lại báo cáo toàn bộ bộ kiểm thử và từ chối các thay đổi làm giảm số lượng kiểm thử baseline đang pass. Nếu baseline có kiểm thử đang fail, Codex chỉ có thể sửa các lỗi hiển nhiên và báo cáo toàn bộ bộ kiểm thử sau-agent phải pass trước khi bất kỳ thứ gì được commit. Khi `main` tiến lên trước khi lượt push của bot được đưa lên, lane rebase bản vá đã xác thực, chạy lại `pnpm check:changed`, và thử push lại; các bản vá cũ xung đột sẽ bị bỏ qua. Nó dùng Ubuntu do GitHub host để action Codex có thể giữ cùng tư thế an toàn drop-sudo như docs agent. ### PR trùng lặp sau khi merge -Quy trình `Duplicate PRs After Merge` là một quy trình maintainer thủ công để dọn dẹp trùng lặp sau khi merge. Mặc định là dry-run và chỉ đóng các PR được liệt kê rõ ràng khi `apply=true`. Trước khi thay đổi GitHub, nó xác minh rằng PR đã landed đã được merge và mỗi bản trùng lặp có issue được tham chiếu chung hoặc các hunk thay đổi chồng lấn. +Quy trình `Duplicate PRs After Merge` là quy trình maintainer thủ công để dọn dẹp bản trùng lặp sau khi land. Mặc định là dry-run và chỉ đóng các PR được liệt kê rõ ràng khi `apply=true`. Trước khi thay đổi GitHub, nó xác minh rằng PR đã land đã được merge và mỗi bản trùng lặp có một issue được tham chiếu chung hoặc các hunk thay đổi chồng lấp. ```bash gh workflow run duplicate-after-merge.yml \ @@ -396,23 +396,23 @@ gh workflow run duplicate-after-merge.yml \ Logic changed-lane cục bộ nằm trong `scripts/changed-lanes.mjs` và được thực thi bởi `scripts/check-changed.mjs`. Cổng kiểm tra cục bộ đó nghiêm ngặt hơn về ranh giới kiến trúc so với phạm vi nền tảng CI rộng: -- các thay đổi production lõi chạy typecheck prod lõi và test lõi cộng với lint/guard lõi; -- các thay đổi chỉ dành cho test lõi chỉ chạy typecheck test lõi cộng với lint lõi; -- các thay đổi production extension chạy typecheck prod extension và test extension cộng với lint extension; -- các thay đổi chỉ dành cho test extension chạy typecheck test extension cộng với lint extension; -- các thay đổi SDK Plugin công khai hoặc hợp đồng plugin mở rộng sang typecheck extension vì extensions phụ thuộc vào các hợp đồng lõi đó (các đợt quét Vitest extension vẫn là công việc kiểm thử rõ ràng); -- các bump phiên bản chỉ metadata phát hành chạy các kiểm tra phiên bản/cấu hình/phụ thuộc root có mục tiêu; -- các thay đổi root/cấu hình không xác định fail safe sang tất cả làn kiểm tra. +- thay đổi production lõi chạy typecheck core prod và core test cùng lint/guard lõi; +- thay đổi chỉ kiểm thử lõi chỉ chạy typecheck core test cùng lint lõi; +- thay đổi production extension chạy typecheck extension prod và extension test cùng lint extension; +- thay đổi chỉ kiểm thử extension chạy typecheck extension test cùng lint extension; +- thay đổi Plugin SDK công khai hoặc hợp đồng Plugin mở rộng sang typecheck extension vì các extension phụ thuộc vào những hợp đồng lõi đó (các lượt quét extension Vitest vẫn là công việc kiểm thử rõ ràng); +- bump phiên bản chỉ metadata phát hành chạy các kiểm tra phiên bản/cấu hình/phụ thuộc gốc có mục tiêu; +- thay đổi root/config không xác định fail safe sang mọi lane kiểm tra. -Định tuyến changed-test cục bộ nằm trong `scripts/test-projects.test-support.mjs` và cố ý nhẹ hơn `check:changed`: các chỉnh sửa test trực tiếp tự chạy chính chúng, chỉnh sửa source ưu tiên ánh xạ rõ ràng, rồi đến test anh em và các phần phụ thuộc theo import-graph. Cấu hình gửi group-room dùng chung là một trong các ánh xạ rõ ràng: thay đổi đối với cấu hình trả lời hiển thị trong nhóm, chế độ gửi trả lời nguồn, hoặc prompt hệ thống của message-tool sẽ đi qua các test trả lời lõi cộng với các hồi quy gửi Discord và Slack để một thay đổi mặc định dùng chung thất bại trước lần push PR đầu tiên. Chỉ dùng `OPENCLAW_TEST_CHANGED_BROAD=1 pnpm test:changed` khi thay đổi đủ rộng trên toàn harness đến mức tập ánh xạ rẻ không phải là proxy đáng tin cậy. +Định tuyến changed-test cục bộ nằm trong `scripts/test-projects.test-support.mjs` và được cố ý giữ rẻ hơn `check:changed`: chỉnh sửa kiểm thử trực tiếp chạy chính chúng, chỉnh sửa nguồn ưu tiên mapping rõ ràng, sau đó đến kiểm thử sibling và các phụ thuộc import-graph. Cấu hình gửi group-room dùng chung là một trong các mapping rõ ràng: thay đổi đối với cấu hình visible-reply nhóm, chế độ gửi trả lời nguồn, hoặc prompt hệ thống message-tool sẽ đi qua các kiểm thử trả lời lõi cùng regression gửi Discord và Slack để một thay đổi mặc định dùng chung fail trước lượt push PR đầu tiên. Chỉ dùng `OPENCLAW_TEST_CHANGED_BROAD=1 pnpm test:changed` khi thay đổi đủ rộng trên toàn harness đến mức tập mapped rẻ không còn là proxy đáng tin cậy. ## Xác thực Testbox -Chạy Testbox từ root repo và ưu tiên một box mới đã được warm cho bằng chứng rộng. Trước khi dùng một cổng chậm trên một box đã được tái sử dụng, hết hạn, hoặc vừa báo cáo một lượt đồng bộ lớn bất ngờ, hãy chạy `pnpm testbox:sanity` bên trong box trước. +Chạy Testbox từ root repo và ưu tiên một box mới đã được warm cho bằng chứng rộng. Trước khi dành một cổng chậm cho một box đã được tái sử dụng, hết hạn, hoặc vừa báo cáo một lượt sync lớn bất thường, hãy chạy `pnpm testbox:sanity` bên trong box trước. -Kiểm tra sanity thất bại nhanh khi các file root bắt buộc như `pnpm-lock.yaml` biến mất hoặc khi `git status --short` hiển thị ít nhất 200 file đã theo dõi bị xóa. Điều đó thường có nghĩa trạng thái đồng bộ từ xa không phải là bản sao đáng tin cậy của PR; hãy dừng box đó và warm một box mới thay vì gỡ lỗi thất bại test sản phẩm. Với các PR xóa lớn có chủ ý, đặt `OPENCLAW_TESTBOX_ALLOW_MASS_DELETIONS=1` cho lần chạy sanity đó. +Kiểm tra sanity fail nhanh khi các tệp root bắt buộc như `pnpm-lock.yaml` biến mất hoặc khi `git status --short` hiển thị ít nhất 200 lượt xóa tracked. Điều đó thường có nghĩa trạng thái sync từ xa không phải là bản sao đáng tin cậy của PR; hãy dừng box đó và warm một box mới thay vì gỡ lỗi thất bại kiểm thử sản phẩm. Với các PR cố ý xóa số lượng lớn, đặt `OPENCLAW_TESTBOX_ALLOW_MASS_DELETIONS=1` cho lượt chạy sanity đó. -`pnpm testbox:run` cũng kết thúc một lần gọi Blacksmith CLI cục bộ nếu nó ở trong giai đoạn đồng bộ quá năm phút mà không có output sau đồng bộ. Đặt `OPENCLAW_TESTBOX_SYNC_TIMEOUT_MS=0` để vô hiệu hóa guard đó, hoặc dùng một giá trị mili giây lớn hơn cho các diff cục bộ lớn bất thường. +`pnpm testbox:run` cũng chấm dứt một lượt gọi Blacksmith CLI cục bộ nếu nó ở pha sync hơn năm phút mà không có output sau sync. Đặt `OPENCLAW_TESTBOX_SYNC_TIMEOUT_MS=0` để tắt guard đó, hoặc dùng giá trị mili giây lớn hơn cho các diff cục bộ lớn bất thường. ## Liên quan diff --git a/docs/vi/concepts/agent-loop.md b/docs/vi/concepts/agent-loop.md index 7794c2c10..73c78283e 100644 --- a/docs/vi/concepts/agent-loop.md +++ b/docs/vi/concepts/agent-loop.md @@ -1,190 +1,191 @@ --- read_when: - - Bạn cần hướng dẫn từng bước chính xác về vòng lặp tác nhân hoặc các sự kiện vòng đời - - Bạn đang thay đổi cơ chế xếp hàng phiên, việc ghi bản ghi phiên, hoặc hành vi khóa ghi phiên -summary: Vòng đời vòng lặp tác tử, luồng và ngữ nghĩa chờ + - Bạn cần một hướng dẫn từng bước chính xác về vòng lặp tác nhân hoặc các sự kiện vòng đời + - Bạn đang thay đổi hành vi xếp hàng phiên, ghi bản ghi hội thoại hoặc khóa ghi phiên +summary: Vòng đời vòng lặp tác nhân, luồng và ngữ nghĩa chờ title: Vòng lặp tác nhân x-i18n: - generated_at: "2026-04-29T22:35:41Z" + generated_at: "2026-04-30T18:38:51Z" model: gpt-5.5 provider: openai - source_hash: 902d543bd71dd517a810d825cbe92e244fe89230f47eeada72477c657a2bec32 + source_hash: 5466893253e1f82482284ff82db56f4c3fca018bf12e4114fad76d37cad954df source_path: concepts/agent-loop.md workflow: 16 --- -Vòng lặp agentic là toàn bộ lượt chạy “thực” của một tác tử: tiếp nhận → lắp ráp ngữ cảnh → suy luận của mô hình → -thực thi công cụ → truyền trực tuyến phản hồi → lưu bền vững. Đây là đường dẫn có thẩm quyền biến một tin nhắn -thành hành động và phản hồi cuối cùng, đồng thời giữ trạng thái phiên nhất quán. +Vòng lặp tác tử là toàn bộ lượt chạy “thực” của một tác tử: tiếp nhận → lắp ráp ngữ cảnh → suy luận mô hình → +thực thi công cụ → truyền phát phản hồi → lưu trữ bền vững. Đây là đường dẫn có thẩm quyền biến một tin nhắn +thành các hành động và phản hồi cuối cùng, đồng thời giữ trạng thái phiên nhất quán. -Trong OpenClaw, một vòng lặp là một lượt chạy đơn, được tuần tự hóa theo từng phiên, phát ra các sự kiện luồng và vòng đời -khi mô hình suy nghĩ, gọi công cụ và truyền trực tuyến đầu ra. Tài liệu này giải thích cách vòng lặp xác thực đó được -kết nối đầu-cuối. +Trong OpenClaw, một vòng lặp là một lượt chạy đơn lẻ, được tuần tự hóa theo từng phiên, phát ra các sự kiện vòng đời và luồng +khi mô hình suy nghĩ, gọi công cụ và truyền phát đầu ra. Tài liệu này giải thích cách vòng lặp xác thực đó +được nối dây từ đầu đến cuối. ## Điểm vào - Gateway RPC: `agent` và `agent.wait`. - CLI: lệnh `agent`. -## Cách hoạt động (cấp cao) +## Cách hoạt động (mức cao) -1. RPC `agent` xác thực tham số, phân giải phiên (sessionKey/sessionId), lưu bền vững siêu dữ liệu phiên, trả về `{ runId, acceptedAt }` ngay lập tức. +1. RPC `agent` xác thực tham số, phân giải phiên (sessionKey/sessionId), lưu metadata phiên, trả về `{ runId, acceptedAt }` ngay lập tức. 2. `agentCommand` chạy tác tử: - - phân giải mô hình + giá trị mặc định cho suy nghĩ/chi tiết/dấu vết - - tải ảnh chụp Skills + - phân giải mô hình + các mặc định thinking/verbose/trace + - tải snapshot Skills - gọi `runEmbeddedPiAgent` (runtime pi-agent-core) - - phát **kết thúc/lỗi vòng đời** nếu vòng lặp nhúng không phát một sự kiện như vậy + - phát ra **vòng đời kết thúc/lỗi** nếu vòng lặp nhúng không phát ra một sự kiện như vậy 3. `runEmbeddedPiAgent`: - - tuần tự hóa các lượt chạy qua hàng đợi theo từng phiên + hàng đợi toàn cục - - phân giải mô hình + hồ sơ xác thực và dựng phiên pi - - đăng ký sự kiện pi và truyền trực tuyến các delta của trợ lý/công cụ - - áp đặt thời gian chờ -> hủy lượt chạy nếu vượt quá - - trả về payload + siêu dữ liệu sử dụng -4. `subscribeEmbeddedPiSession` bắc cầu sự kiện pi-agent-core sang luồng `agent` của OpenClaw: + - tuần tự hóa các lượt chạy qua hàng đợi theo phiên + toàn cục + - phân giải mô hình + hồ sơ xác thực và xây dựng phiên pi + - đăng ký nhận sự kiện pi và truyền phát các delta của trợ lý/công cụ + - áp dụng timeout -> hủy lượt chạy nếu vượt quá + - với các lượt Codex app-server, hủy một lượt đã được chấp nhận nếu nó ngừng tạo tiến trình app-server trước một sự kiện kết thúc + - trả về payload + metadata sử dụng +4. `subscribeEmbeddedPiSession` nối các sự kiện pi-agent-core với luồng `agent` của OpenClaw: - sự kiện công cụ => `stream: "tool"` - delta của trợ lý => `stream: "assistant"` - sự kiện vòng đời => `stream: "lifecycle"` (`phase: "start" | "end" | "error"`) 5. `agent.wait` dùng `waitForAgentRun`: - - chờ **kết thúc/lỗi vòng đời** cho `runId` + - chờ **vòng đời kết thúc/lỗi** cho `runId` - trả về `{ status: ok|error|timeout, startedAt, endedAt, error? }` ## Xếp hàng + đồng thời -- Các lượt chạy được tuần tự hóa theo khóa phiên (làn phiên) và tùy chọn qua một làn toàn cục. -- Điều này ngăn tranh chấp công cụ/phiên và giữ lịch sử phiên nhất quán. -- Các kênh nhắn tin có thể chọn chế độ hàng đợi (thu thập/điều hướng/theo dõi) để đưa vào hệ thống làn này. +- Các lượt chạy được tuần tự hóa theo từng khóa phiên (làn phiên) và tùy chọn qua một làn toàn cục. +- Điều này ngăn các race về công cụ/phiên và giữ lịch sử phiên nhất quán. +- Các kênh nhắn tin có thể chọn chế độ hàng đợi (collect/steer/followup) để đưa vào hệ thống làn này. Xem [Hàng đợi lệnh](/vi/concepts/queue). -- Việc ghi bản ghi hội thoại cũng được bảo vệ bằng khóa ghi phiên trên tệp phiên. Khóa này - nhận biết tiến trình và dựa trên tệp, nên phát hiện được các trình ghi đi vòng qua hàng đợi trong tiến trình hoặc đến từ +- Các lượt ghi transcript cũng được bảo vệ bằng khóa ghi phiên trên tệp phiên. Khóa này + nhận biết tiến trình và dựa trên tệp, nên phát hiện được các trình ghi bỏ qua hàng đợi trong tiến trình hoặc đến từ tiến trình khác. -- Theo mặc định, khóa ghi phiên không tái nhập. Nếu một helper cố ý lồng việc lấy - cùng một khóa trong khi vẫn giữ một trình ghi logic duy nhất, nó phải chọn tham gia rõ ràng bằng +- Khóa ghi phiên mặc định không tái nhập. Nếu một helper cố ý lồng việc lấy + cùng một khóa trong khi vẫn giữ một trình ghi logic duy nhất, helper đó phải bật rõ ràng bằng `allowReentrant: true`. ## Chuẩn bị phiên + workspace -- Workspace được phân giải và tạo; các lượt chạy trong sandbox có thể được chuyển hướng tới gốc workspace sandbox. -- Skills được tải (hoặc tái sử dụng từ ảnh chụp) và tiêm vào env và prompt. -- Các tệp bootstrap/ngữ cảnh được phân giải và tiêm vào báo cáo system prompt. -- Khóa ghi phiên được lấy; `SessionManager` được mở và chuẩn bị trước khi truyền trực tuyến. Bất kỳ - đường dẫn ghi lại bản ghi hội thoại, Compaction hoặc cắt bớt nào về sau đều phải lấy cùng khóa đó trước khi mở hoặc - sửa đổi tệp bản ghi hội thoại. +- Workspace được phân giải và tạo; các lượt chạy trong sandbox có thể chuyển hướng đến root workspace sandbox. +- Skills được tải (hoặc dùng lại từ snapshot) và được chèn vào env và prompt. +- Các tệp bootstrap/ngữ cảnh được phân giải và chèn vào báo cáo system prompt. +- Khóa ghi phiên được lấy; `SessionManager` được mở và chuẩn bị trước khi truyền phát. Mọi + đường dẫn viết lại transcript, Compaction hoặc cắt bớt về sau đều phải lấy cùng khóa đó trước khi mở hoặc + thay đổi tệp transcript. ## Lắp ráp prompt + system prompt -- System prompt được dựng từ prompt cơ sở của OpenClaw, prompt Skills, ngữ cảnh bootstrap và các override theo từng lượt chạy. -- Các giới hạn theo mô hình và token dự trữ cho Compaction được áp đặt. -- Xem [System prompt](/vi/concepts/system-prompt) để biết mô hình thấy gì. +- System prompt được xây dựng từ prompt nền của OpenClaw, prompt Skills, ngữ cảnh bootstrap và các override theo lượt chạy. +- Các giới hạn theo mô hình và token dự trữ cho Compaction được áp dụng. +- Xem [System prompt](/vi/concepts/system-prompt) để biết mô hình nhìn thấy gì. -## Điểm hook (nơi bạn có thể can thiệp) +## Điểm hook (nơi bạn có thể chặn) OpenClaw có hai hệ thống hook: -- **Hook nội bộ** (hook Gateway): script hướng sự kiện cho lệnh và sự kiện vòng đời. +- **Hook nội bộ** (hook Gateway): script theo sự kiện cho lệnh và sự kiện vòng đời. - **Hook Plugin**: điểm mở rộng bên trong vòng đời tác tử/công cụ và pipeline Gateway. ### Hook nội bộ (hook Gateway) -- **`agent:bootstrap`**: chạy trong khi dựng tệp bootstrap trước khi system prompt được hoàn tất. - Dùng để thêm/xóa các tệp ngữ cảnh bootstrap. -- **Hook lệnh**: `/new`, `/reset`, `/stop`, và các sự kiện lệnh khác (xem tài liệu Hook). +- **`agent:bootstrap`**: chạy trong khi xây dựng tệp bootstrap trước khi system prompt được hoàn tất. + Dùng hook này để thêm/xóa tệp ngữ cảnh bootstrap. +- **Hook lệnh**: `/new`, `/reset`, `/stop` và các sự kiện lệnh khác (xem tài liệu Hooks). -Xem [Hook](/vi/automation/hooks) để biết cách thiết lập và ví dụ. +Xem [Hooks](/vi/automation/hooks) để biết cách thiết lập và ví dụ. -### Hook Plugin (vòng đời tác tử + gateway) +### Hook Plugin (vòng đời tác tử + Gateway) -Các hook này chạy bên trong vòng lặp tác tử hoặc pipeline gateway: +Các hook này chạy bên trong vòng lặp tác tử hoặc pipeline Gateway: -- **`before_model_resolve`**: chạy trước phiên (không có `messages`) để ghi đè nhà cung cấp/mô hình một cách tất định trước khi phân giải mô hình. -- **`before_prompt_build`**: chạy sau khi tải phiên (có `messages`) để tiêm `prependContext`, `systemPrompt`, `prependSystemContext`, hoặc `appendSystemContext` trước khi gửi prompt. Dùng `prependContext` cho văn bản động theo từng lượt và các trường ngữ cảnh hệ thống cho hướng dẫn ổn định nên nằm trong không gian system prompt. -- **`before_agent_start`**: hook tương thích cũ có thể chạy ở một trong hai pha; ưu tiên các hook rõ ràng ở trên. -- **`before_agent_reply`**: chạy sau các hành động inline và trước lệnh gọi LLM, cho phép Plugin nhận lượt và trả về phản hồi tổng hợp hoặc làm im lặng toàn bộ lượt. -- **`agent_end`**: kiểm tra danh sách tin nhắn cuối cùng và siêu dữ liệu lượt chạy sau khi hoàn tất. +- **`before_model_resolve`**: chạy trước phiên (không có `messages`) để override provider/model một cách tất định trước khi phân giải mô hình. +- **`before_prompt_build`**: chạy sau khi tải phiên (có `messages`) để chèn `prependContext`, `systemPrompt`, `prependSystemContext` hoặc `appendSystemContext` trước khi gửi prompt. Dùng `prependContext` cho văn bản động theo lượt và các trường system-context cho hướng dẫn ổn định nên nằm trong không gian system prompt. +- **`before_agent_start`**: hook tương thích kế thừa có thể chạy trong một trong hai pha; ưu tiên các hook rõ ràng ở trên. +- **`before_agent_reply`**: chạy sau inline actions và trước lệnh gọi LLM, cho phép Plugin nhận lượt và trả về phản hồi tổng hợp hoặc im lặng hoàn toàn lượt đó. +- **`agent_end`**: kiểm tra danh sách tin nhắn cuối cùng và metadata lượt chạy sau khi hoàn tất. - **`before_compaction` / `after_compaction`**: quan sát hoặc chú thích các chu kỳ Compaction. -- **`before_tool_call` / `after_tool_call`**: chặn và xử lý tham số/kết quả công cụ. -- **`before_install`**: kiểm tra phát hiện quét tích hợp và tùy chọn chặn cài đặt skill hoặc Plugin. -- **`tool_result_persist`**: biến đổi đồng bộ kết quả công cụ trước khi chúng được ghi vào bản ghi hội thoại phiên do OpenClaw sở hữu. +- **`before_tool_call` / `after_tool_call`**: chặn tham số/kết quả công cụ. +- **`before_install`**: kiểm tra các phát hiện quét tích hợp sẵn và tùy chọn chặn cài đặt skill hoặc Plugin. +- **`tool_result_persist`**: biến đổi đồng bộ kết quả công cụ trước khi chúng được ghi vào transcript phiên do OpenClaw sở hữu. - **`message_received` / `message_sending` / `message_sent`**: hook tin nhắn đến + đi. - **`session_start` / `session_end`**: ranh giới vòng đời phiên. - **`gateway_start` / `gateway_stop`**: sự kiện vòng đời gateway. -Quy tắc quyết định hook cho bảo vệ gửi đi/công cụ: +Quy tắc quyết định hook cho guard đầu ra/công cụ: - `before_tool_call`: `{ block: true }` là kết thúc và dừng các handler ưu tiên thấp hơn. -- `before_tool_call`: `{ block: false }` là không thao tác và không xóa chặn trước đó. +- `before_tool_call`: `{ block: false }` là no-op và không xóa block trước đó. - `before_install`: `{ block: true }` là kết thúc và dừng các handler ưu tiên thấp hơn. -- `before_install`: `{ block: false }` là không thao tác và không xóa chặn trước đó. +- `before_install`: `{ block: false }` là no-op và không xóa block trước đó. - `message_sending`: `{ cancel: true }` là kết thúc và dừng các handler ưu tiên thấp hơn. -- `message_sending`: `{ cancel: false }` là không thao tác và không xóa hủy trước đó. +- `message_sending`: `{ cancel: false }` là no-op và không xóa cancel trước đó. Xem [Hook Plugin](/vi/plugins/hooks) để biết API hook và chi tiết đăng ký. -Các harness có thể điều chỉnh các hook này theo cách khác. Harness app-server Codex giữ -hook Plugin OpenClaw làm hợp đồng tương thích cho các bề mặt phản chiếu đã được tài liệu hóa, -trong khi hook gốc Codex vẫn là một cơ chế Codex cấp thấp riêng biệt. +Harness có thể điều chỉnh các hook này theo cách khác. Harness Codex app-server giữ +hook Plugin OpenClaw làm hợp đồng tương thích cho các bề mặt được mirror có tài liệu, +trong khi hook native của Codex vẫn là một cơ chế Codex cấp thấp riêng biệt. -## Truyền trực tuyến + phản hồi từng phần +## Truyền phát + phản hồi một phần -- Delta của trợ lý được truyền trực tuyến từ pi-agent-core và phát ra dưới dạng sự kiện `assistant`. -- Truyền trực tuyến theo khối có thể phát phản hồi từng phần trên `text_end` hoặc `message_end`. -- Truyền trực tuyến phần suy luận có thể được phát dưới dạng một luồng riêng hoặc dưới dạng phản hồi khối. -- Xem [Truyền trực tuyến](/vi/concepts/streaming) để biết hành vi chia đoạn và phản hồi khối. +- Delta của trợ lý được truyền phát từ pi-agent-core và phát ra dưới dạng sự kiện `assistant`. +- Truyền phát block có thể phát ra phản hồi một phần ở `text_end` hoặc `message_end`. +- Truyền phát reasoning có thể được phát ra dưới dạng một luồng riêng hoặc dưới dạng phản hồi block. +- Xem [Truyền phát](/vi/concepts/streaming) để biết hành vi chia chunk và phản hồi block. ## Thực thi công cụ + công cụ nhắn tin - Sự kiện bắt đầu/cập nhật/kết thúc công cụ được phát trên luồng `tool`. - Kết quả công cụ được làm sạch về kích thước và payload hình ảnh trước khi ghi log/phát ra. -- Các lần gửi của công cụ nhắn tin được theo dõi để chặn xác nhận trợ lý trùng lặp. +- Các lượt gửi bằng công cụ nhắn tin được theo dõi để ngăn xác nhận trợ lý trùng lặp. -## Định hình + chặn phản hồi +## Định hình phản hồi + triệt tiêu - Payload cuối cùng được lắp ráp từ: - - văn bản trợ lý (và phần suy luận tùy chọn) - - tóm tắt công cụ inline (khi chi tiết + được phép) - - văn bản lỗi trợ lý khi mô hình gặp lỗi + - văn bản trợ lý (và reasoning tùy chọn) + - tóm tắt công cụ inline (khi verbose + được phép) + - văn bản lỗi trợ lý khi mô hình lỗi - Token im lặng chính xác `NO_REPLY` / `no_reply` được lọc khỏi payload gửi đi. -- Bản sao trùng lặp của công cụ nhắn tin bị loại bỏ khỏi danh sách payload cuối cùng. -- Nếu không còn payload có thể hiển thị và một công cụ gặp lỗi, một phản hồi lỗi công cụ dự phòng được phát ra +- Bản trùng lặp của công cụ nhắn tin bị xóa khỏi danh sách payload cuối cùng. +- Nếu không còn payload có thể render và một công cụ bị lỗi, phản hồi lỗi công cụ dự phòng được phát ra (trừ khi công cụ nhắn tin đã gửi phản hồi người dùng có thể thấy). ## Compaction + thử lại -- Compaction tự động phát sự kiện luồng `compaction` và có thể kích hoạt thử lại. -- Khi thử lại, bộ đệm trong bộ nhớ và tóm tắt công cụ được đặt lại để tránh đầu ra trùng lặp. +- Auto-compaction phát ra sự kiện luồng `compaction` và có thể kích hoạt thử lại. +- Khi thử lại, buffer trong bộ nhớ và tóm tắt công cụ được đặt lại để tránh đầu ra trùng lặp. - Xem [Compaction](/vi/concepts/compaction) để biết pipeline Compaction. -## Luồng sự kiện (hiện nay) +## Luồng sự kiện (hiện tại) -- `lifecycle`: do `subscribeEmbeddedPiSession` phát ra (và như một phương án dự phòng bởi `agentCommand`) -- `assistant`: delta truyền trực tuyến từ pi-agent-core -- `tool`: sự kiện công cụ truyền trực tuyến từ pi-agent-core +- `lifecycle`: do `subscribeEmbeddedPiSession` phát ra (và do `agentCommand` phát ra làm dự phòng) +- `assistant`: delta được truyền phát từ pi-agent-core +- `tool`: sự kiện công cụ được truyền phát từ pi-agent-core ## Xử lý kênh chat -- Delta của trợ lý được đệm thành tin nhắn `delta` của chat. -- Một `final` của chat được phát khi **kết thúc/lỗi vòng đời**. +- Delta của trợ lý được buffer thành tin nhắn chat `delta`. +- Một chat `final` được phát ra khi **vòng đời kết thúc/lỗi**. -## Thời gian chờ +## Timeout -- Mặc định của `agent.wait`: 30 giây (chỉ phần chờ). Tham số `timeoutMs` ghi đè. -- Runtime tác tử: mặc định `agents.defaults.timeoutSeconds` là 172800 giây (48 giờ); được áp đặt trong bộ hẹn giờ hủy của `runEmbeddedPiAgent`. -- Runtime Cron: `timeoutSeconds` cho lượt tác tử cô lập do cron sở hữu. Bộ lập lịch bắt đầu bộ hẹn giờ đó khi thực thi bắt đầu, hủy lượt chạy nền ở hạn chót đã cấu hình, rồi chạy dọn dẹp có giới hạn trước khi ghi nhận thời gian chờ để một phiên con lỗi thời không thể khiến làn bị kẹt. -- Khôi phục phiên bị kẹt: khi bật chẩn đoán, `diagnostics.stuckSessionWarnMs` phát hiện các phiên `processing` kéo dài. Các lượt chạy nhúng đang hoạt động, thao tác phản hồi đang hoạt động và tác vụ làn phiên đang hoạt động mặc định chỉ cảnh báo; nếu chẩn đoán cho thấy không có công việc đang hoạt động cho phiên, watchdog giải phóng làn phiên bị ảnh hưởng để công việc khởi động đang xếp hàng có thể thoát. -- Thời gian chờ nhàn rỗi của mô hình: OpenClaw hủy yêu cầu mô hình khi không có đoạn phản hồi nào đến trước cửa sổ nhàn rỗi. `models.providers..timeoutSeconds` mở rộng watchdog nhàn rỗi này cho các nhà cung cấp cục bộ/tự lưu trữ chậm; nếu không, OpenClaw dùng `agents.defaults.timeoutSeconds` khi được cấu hình, mặc định giới hạn ở 120 giây. Các lượt chạy do Cron kích hoạt không có thời gian chờ mô hình hoặc tác tử rõ ràng sẽ tắt watchdog nhàn rỗi và dựa vào thời gian chờ ngoài của cron. -- Thời gian chờ yêu cầu HTTP của nhà cung cấp: `models.providers..timeoutSeconds` áp dụng cho các lần fetch HTTP mô hình của nhà cung cấp đó, bao gồm kết nối, header, body, thời gian chờ yêu cầu SDK, xử lý hủy guarded-fetch tổng thể và watchdog nhàn rỗi luồng mô hình. Dùng thiết lập này cho các nhà cung cấp cục bộ/tự lưu trữ chậm như Ollama trước khi tăng thời gian chờ runtime của toàn bộ tác tử. +- Mặc định của `agent.wait`: 30 giây (chỉ phần chờ). Tham số `timeoutMs` override. +- Runtime tác tử: mặc định `agents.defaults.timeoutSeconds` là 172800 giây (48 giờ); được áp dụng trong timer hủy của `runEmbeddedPiAgent`. +- Runtime Cron: `timeoutSeconds` của lượt tác tử biệt lập do Cron sở hữu. Bộ lập lịch bắt đầu timer đó khi thực thi bắt đầu, hủy lượt chạy nền bên dưới tại deadline đã cấu hình, rồi chạy cleanup có giới hạn trước khi ghi nhận timeout để phiên con cũ không thể làm kẹt làn. +- Khôi phục phiên bị kẹt: khi bật diagnostics, `diagnostics.stuckSessionWarnMs` phát hiện các phiên `processing` kéo dài. Các lượt chạy nhúng đang hoạt động, thao tác phản hồi đang hoạt động và tác vụ làn phiên đang hoạt động mặc định chỉ cảnh báo; nếu diagnostics cho thấy không có công việc đang hoạt động cho phiên, watchdog sẽ nhả làn phiên bị ảnh hưởng để công việc khởi động đang xếp hàng có thể thoát. +- Timeout rỗi của mô hình: OpenClaw hủy một yêu cầu mô hình khi không có chunk phản hồi nào đến trước cửa sổ rỗi. `models.providers..timeoutSeconds` mở rộng watchdog rỗi này cho các provider local/tự host chậm; nếu không, OpenClaw dùng `agents.defaults.timeoutSeconds` khi được cấu hình, mặc định bị giới hạn ở 120 giây. Các lượt chạy do Cron kích hoạt không có timeout mô hình hoặc tác tử rõ ràng sẽ tắt watchdog rỗi và dựa vào timeout ngoài của Cron. +- Timeout yêu cầu HTTP của provider: `models.providers..timeoutSeconds` áp dụng cho các lượt fetch HTTP mô hình của provider đó, bao gồm connect, header, body, timeout yêu cầu SDK, xử lý hủy guarded-fetch tổng thể và watchdog rỗi luồng mô hình. Dùng mục này cho các provider local/tự host chậm như Ollama trước khi tăng timeout runtime toàn bộ tác tử. -## Những nơi có thể kết thúc sớm +## Nơi mọi thứ có thể kết thúc sớm -- Thời gian chờ tác tử (hủy) +- Timeout tác tử (hủy) - AbortSignal (hủy) -- Gateway ngắt kết nối hoặc RPC hết thời gian chờ -- `agent.wait` hết thời gian chờ (chỉ chờ, không dừng tác tử) +- Gateway ngắt kết nối hoặc timeout RPC +- Timeout `agent.wait` (chỉ chờ, không dừng tác tử) ## Liên quan - [Công cụ](/vi/tools) — công cụ tác tử có sẵn -- [Hook](/vi/automation/hooks) — script hướng sự kiện được kích hoạt bởi sự kiện vòng đời tác tử -- [Compaction](/vi/concepts/compaction) — cách tóm tắt các cuộc trò chuyện dài +- [Hooks](/vi/automation/hooks) — script theo sự kiện được kích hoạt bởi các sự kiện vòng đời tác tử +- [Compaction](/vi/concepts/compaction) — cách tóm tắt các cuộc hội thoại dài - [Phê duyệt Exec](/vi/tools/exec-approvals) — cổng phê duyệt cho lệnh shell -- [Suy nghĩ](/vi/tools/thinking) — cấu hình cấp độ suy nghĩ/suy luận +- [Thinking](/vi/tools/thinking) — cấu hình mức thinking/reasoning diff --git a/docs/vi/concepts/queue.md b/docs/vi/concepts/queue.md index 1d91326bb..1f276be27 100644 --- a/docs/vi/concepts/queue.md +++ b/docs/vi/concepts/queue.md @@ -1,60 +1,60 @@ --- read_when: - - Thay đổi cách thực thi hoặc tính đồng thời của tự động trả lời + - Thay đổi cách thực thi hoặc mức độ đồng thời của tính năng trả lời tự động - Giải thích các chế độ /queue hoặc hành vi điều hướng tin nhắn -summary: Các chế độ hàng đợi tự động trả lời, giá trị mặc định và ghi đè theo từng phiên +summary: Chế độ hàng đợi tự động trả lời, giá trị mặc định và ghi đè theo từng phiên title: Hàng đợi lệnh x-i18n: - generated_at: "2026-04-30T09:36:09Z" + generated_at: "2026-04-30T18:38:39Z" model: gpt-5.5 provider: openai - source_hash: 2ac0c0ded9558b080714fa4b8be0d552f985911bf19b427020f9654ae4955b2d + source_hash: fbf1bb1ffd4ce06fa138f63e31651b8821226d9c95dd6b93d68326a5fb91fdd0 source_path: concepts/queue.md workflow: 16 --- -Chúng tôi tuần tự hóa các lượt chạy tự động trả lời đến (mọi kênh) qua một hàng đợi nhỏ trong tiến trình để ngăn nhiều lượt chạy agent va chạm nhau, đồng thời vẫn cho phép xử lý song song an toàn giữa các phiên. +Chúng tôi tuần tự hóa các lượt chạy tự động trả lời đến (tất cả các kênh) thông qua một hàng đợi nhỏ trong tiến trình để ngăn nhiều lượt chạy tác nhân va chạm với nhau, trong khi vẫn cho phép song song an toàn giữa các phiên. -## Lý do +## Vì sao -- Các lượt chạy tự động trả lời có thể tốn kém (lệnh gọi LLM) và có thể va chạm khi nhiều tin nhắn đến gần như cùng lúc. -- Tuần tự hóa giúp tránh tranh chấp tài nguyên dùng chung (tệp phiên, nhật ký, stdin của CLI) và giảm khả năng gặp giới hạn tốc độ từ upstream. +- Các lượt chạy tự động trả lời có thể tốn kém (lệnh gọi LLM) và có thể va chạm khi nhiều tin nhắn đến gần nhau. +- Tuần tự hóa giúp tránh cạnh tranh tài nguyên dùng chung (tệp phiên, nhật ký, stdin của CLI) và giảm khả năng gặp giới hạn tốc độ từ thượng nguồn. ## Cách hoạt động -- Một hàng đợi FIFO nhận biết lane sẽ xả từng lane với giới hạn đồng thời có thể cấu hình (mặc định là 1 cho các lane chưa cấu hình; main mặc định là 4, subagent là 8). +- Một hàng đợi FIFO có nhận biết lane xả từng lane với giới hạn đồng thời có thể cấu hình (mặc định là 1 cho các lane chưa cấu hình; main mặc định là 4, subagent là 8). - `runEmbeddedPiAgent` đưa vào hàng đợi theo **khóa phiên** (lane `session:`) để bảo đảm mỗi phiên chỉ có một lượt chạy đang hoạt động. -- Sau đó, mỗi lượt chạy phiên được đưa vào một **lane toàn cục** (`main` theo mặc định) để mức song song tổng thể được giới hạn bởi `agents.defaults.maxConcurrent`. -- Khi bật ghi nhật ký chi tiết, các lượt chạy trong hàng đợi sẽ phát một thông báo ngắn nếu đã chờ hơn khoảng 2 giây trước khi bắt đầu. -- Chỉ báo đang nhập vẫn kích hoạt ngay khi đưa vào hàng đợi (khi kênh hỗ trợ), nên trải nghiệm người dùng không đổi trong lúc chờ đến lượt. +- Sau đó, mỗi lượt chạy phiên được đưa vào một **lane toàn cục** (`main` theo mặc định) để tổng mức song song được giới hạn bởi `agents.defaults.maxConcurrent`. +- Khi bật ghi nhật ký chi tiết, các lượt chạy trong hàng đợi sẽ phát ra một thông báo ngắn nếu chúng chờ hơn khoảng 2 giây trước khi bắt đầu. +- Chỉ báo đang nhập vẫn kích hoạt ngay khi đưa vào hàng đợi (khi kênh hỗ trợ), nên trải nghiệm người dùng không đổi trong lúc chúng tôi chờ đến lượt. ## Mặc định -Khi chưa đặt, mọi bề mặt kênh đến dùng: +Khi chưa đặt, tất cả bề mặt kênh đến dùng: - `mode: "steer"` - `debounceMs: 500` - `cap: 20` - `drop: "summarize"` -`steer` là mặc định vì nó giữ lượt mô hình đang hoạt động phản hồi nhanh mà không +`steer` là mặc định vì nó giữ cho lượt mô hình đang hoạt động phản hồi nhanh mà không khởi động lượt chạy phiên thứ hai. Nó xả tất cả tin nhắn điều hướng đã đến -trước ranh giới mô hình tiếp theo. Nếu lượt chạy hiện tại không thể nhận điều hướng, -OpenClaw sẽ quay về một mục hàng đợi followup. +trước ranh giới mô hình tiếp theo. Nếu lượt chạy hiện tại không thể chấp nhận điều hướng, +OpenClaw quay về một mục hàng đợi followup. ## Chế độ hàng đợi -Tin nhắn đến có thể điều hướng lượt chạy hiện tại, chờ một lượt followup, hoặc cả hai: +Tin nhắn đến có thể điều hướng lượt chạy hiện tại, chờ một lượt followup, hoặc làm cả hai: -- `steer`: đưa tin nhắn điều hướng vào runtime đang hoạt động. Pi chuyển tất cả tin nhắn điều hướng đang chờ **sau khi lượt assistant hiện tại thực thi xong các lệnh gọi công cụ**, trước lệnh gọi LLM tiếp theo; Codex app-server nhận một `turn/steer` được gom lô. Nếu lượt chạy không chủ động streaming hoặc không hỗ trợ điều hướng, OpenClaw sẽ quay về một mục hàng đợi followup. -- `queue` (cũ): điều hướng từng tin nhắn một kiểu cũ. Pi chuyển một tin nhắn điều hướng trong hàng đợi tại mỗi ranh giới mô hình; Codex app-server nhận các yêu cầu `turn/steer` riêng biệt. Ưu tiên `steer` trừ khi bạn cần hành vi tuần tự hóa trước đây. -- `followup`: đưa từng tin nhắn vào hàng đợi cho một lượt agent về sau sau khi lượt chạy hiện tại kết thúc. -- `collect`: gộp các tin nhắn trong hàng đợi thành một lượt followup **duy nhất** sau khoảng lặng. Nếu tin nhắn nhắm đến các kênh/luồng khác nhau, chúng được xả riêng để giữ đúng định tuyến. -- `steer-backlog` (còn gọi là `steer+backlog`): điều hướng ngay **và** giữ cùng tin nhắn đó cho một lượt followup. -- `interrupt` (cũ): hủy lượt chạy đang hoạt động cho phiên đó, rồi chạy tin nhắn mới nhất. +- `steer`: đưa tin nhắn điều hướng vào runtime đang hoạt động. Pi gửi tất cả tin nhắn điều hướng đang chờ **sau khi lượt trợ lý hiện tại thực thi xong các lệnh gọi công cụ của nó**, trước lệnh gọi LLM tiếp theo; Codex app-server nhận một `turn/steer` được gom lô. Nếu lượt chạy không đang stream chủ động hoặc không có điều hướng, OpenClaw quay về một mục hàng đợi followup. +- `queue` (kế thừa): điều hướng cũ theo từng tin nhắn một. Pi gửi một tin nhắn điều hướng trong hàng đợi tại mỗi ranh giới mô hình; Codex app-server nhận các yêu cầu `turn/steer` riêng biệt. Ưu tiên `steer` trừ khi bạn cần hành vi tuần tự hóa trước đó. +- `followup`: đưa từng tin nhắn vào hàng đợi cho một lượt tác nhân sau này sau khi lượt chạy hiện tại kết thúc. +- `collect`: gộp các tin nhắn trong hàng đợi thành một lượt followup **duy nhất** sau khoảng lặng. Nếu tin nhắn nhắm đến các kênh/luồng khác nhau, chúng sẽ được xả riêng lẻ để bảo toàn định tuyến. +- `steer-backlog` (còn gọi là `steer+backlog`): điều hướng ngay **và** giữ lại cùng tin nhắn đó cho một lượt followup. +- `interrupt` (kế thừa): hủy lượt chạy đang hoạt động cho phiên đó, rồi chạy tin nhắn mới nhất. -Steer-backlog nghĩa là bạn có thể nhận một phản hồi followup sau lượt chạy đã được điều hướng, nên -các bề mặt streaming có thể trông như bị trùng lặp. Ưu tiên `collect`/`steer` nếu bạn muốn +Steer-backlog nghĩa là bạn có thể nhận phản hồi followup sau lượt chạy đã được điều hướng, nên +các bề mặt streaming có thể trông giống như bị trùng lặp. Ưu tiên `collect`/`steer` nếu bạn muốn một phản hồi cho mỗi tin nhắn đến. Để biết thời điểm và hành vi phụ thuộc theo từng runtime, xem @@ -78,12 +78,12 @@ Cấu hình toàn cục hoặc theo kênh qua `messages.queue`: ## Tùy chọn hàng đợi -Các tùy chọn áp dụng cho `followup`, `collect`, và `steer-backlog` (và cho `steer` hoặc `queue` cũ khi điều hướng quay về followup): +Các tùy chọn áp dụng cho `followup`, `collect`, và `steer-backlog` (và cho `steer` hoặc `queue` kế thừa khi điều hướng quay về followup): -- `debounceMs`: khoảng lặng trước khi xả các followup trong hàng đợi. Số thuần là mili giây; các đơn vị `ms`, `s`, `m`, `h`, và `d` được tùy chọn `/queue` chấp nhận. -- `cap`: số tin nhắn tối đa trong hàng đợi mỗi phiên. Giá trị dưới `1` bị bỏ qua. -- `drop: "summarize"`: mặc định. Bỏ các mục cũ nhất trong hàng đợi khi cần, giữ bản tóm tắt gọn, và chèn chúng như một prompt followup tổng hợp. -- `drop: "old"`: bỏ các mục cũ nhất trong hàng đợi khi cần, không giữ bản tóm tắt. +- `debounceMs`: khoảng lặng trước khi xả các followup trong hàng đợi. Số trần là mili giây; các đơn vị `ms`, `s`, `m`, `h`, và `d` được tùy chọn `/queue` chấp nhận. +- `cap`: số tin nhắn tối đa trong hàng đợi mỗi phiên. Các giá trị dưới `1` bị bỏ qua. +- `drop: "summarize"`: mặc định. Bỏ các mục cũ nhất trong hàng đợi khi cần, giữ lại tóm tắt cô đọng và chèn chúng dưới dạng prompt followup tổng hợp. +- `drop: "old"`: bỏ các mục cũ nhất trong hàng đợi khi cần, không giữ lại tóm tắt. - `drop: "new"`: từ chối tin nhắn mới nhất khi hàng đợi đã đầy. Mặc định: `debounceMs: 500`, `cap: 20`, `drop: summarize`. @@ -92,35 +92,36 @@ Mặc định: `debounceMs: 500`, `cap: 20`, `drop: summarize`. Để chọn chế độ, OpenClaw phân giải: -1. Ghi đè `/queue` nội tuyến hoặc đã lưu cho từng phiên. +1. Ghi đè `/queue` nội tuyến hoặc đã lưu theo phiên. 2. `messages.queue.byChannel.`. 3. `messages.queue.mode`. 4. Mặc định `steer`. Đối với tùy chọn, các tùy chọn `/queue` nội tuyến hoặc đã lưu thắng cấu hình. Sau đó -debounce theo kênh (`messages.queue.debounceMsByChannel`), mặc định debounce của plugin, -các tùy chọn `messages.queue` toàn cục, và mặc định tích hợp sẵn được -áp dụng. `cap` và `drop` là tùy chọn toàn cục/phiên, không phải khóa cấu hình theo kênh. +áp dụng debounce theo kênh (`messages.queue.debounceMsByChannel`), mặc định debounce của plugin, +các tùy chọn `messages.queue` toàn cục, và mặc định tích hợp sẵn. +`cap` và `drop` là tùy chọn toàn cục/phiên, không phải khóa cấu hình theo kênh. ## Ghi đè theo phiên -- Gửi `/queue ` dưới dạng lệnh độc lập để lưu chế độ cho phiên hiện tại. +- Gửi `/queue ` như một lệnh độc lập để lưu chế độ cho phiên hiện tại. - Có thể kết hợp các tùy chọn: `/queue collect debounce:0.5s cap:25 drop:summarize` -- `/queue default` hoặc `/queue reset` xóa ghi đè của phiên. +- `/queue default` hoặc `/queue reset` xóa ghi đè phiên. ## Phạm vi và bảo đảm -- Áp dụng cho các lượt chạy agent tự động trả lời trên mọi kênh đến dùng pipeline trả lời của Gateway (WhatsApp web, Telegram, Slack, Discord, Signal, iMessage, webchat, v.v.). +- Áp dụng cho các lượt chạy tác nhân tự động trả lời trên tất cả các kênh đến dùng pipeline trả lời Gateway (WhatsApp web, Telegram, Slack, Discord, Signal, iMessage, webchat, v.v.). - Lane mặc định (`main`) là toàn tiến trình cho inbound + Heartbeat chính; đặt `agents.defaults.maxConcurrent` để cho phép nhiều phiên chạy song song. -- Có thể tồn tại các lane bổ sung (ví dụ `cron`, `cron-nested`, `nested`, `subagent`) để các tác vụ nền có thể chạy song song mà không chặn trả lời đến. Các lượt agent Cron cô lập giữ một slot `cron` trong khi phần thực thi agent bên trong dùng `cron-nested`; cả hai dùng `cron.maxConcurrentRuns`. Các luồng `nested` không phải Cron và dùng chung giữ hành vi lane riêng. Các lượt chạy tách rời này được theo dõi dưới dạng [tác vụ nền](/vi/automation/tasks). -- Lane theo phiên bảo đảm tại một thời điểm chỉ có một lượt chạy agent chạm vào một phiên nhất định. -- Không có phụ thuộc bên ngoài hoặc luồng worker nền; chỉ TypeScript + promises thuần. +- Có thể tồn tại các lane bổ sung (ví dụ `cron`, `cron-nested`, `nested`, `subagent`) để các công việc nền có thể chạy song song mà không chặn trả lời đến. Các lượt tác nhân cron cô lập giữ một slot `cron` trong khi phần thực thi tác nhân bên trong dùng `cron-nested`; cả hai dùng `cron.maxConcurrentRuns`. Các luồng `nested` không phải cron dùng chung giữ hành vi lane riêng của chúng. Các lượt chạy tách rời này được theo dõi dưới dạng [tác vụ nền](/vi/automation/tasks). +- Lane theo phiên bảo đảm chỉ một lượt chạy tác nhân chạm vào một phiên nhất định tại một thời điểm. +- Không có phụ thuộc bên ngoài hoặc luồng worker nền; chỉ TypeScript + promises. ## Khắc phục sự cố -- Nếu các lệnh có vẻ bị kẹt, bật nhật ký chi tiết và tìm các dòng “queued for …ms” để xác nhận hàng đợi đang xả. +- Nếu lệnh có vẻ bị kẹt, bật nhật ký chi tiết và tìm các dòng “queued for …ms” để xác nhận hàng đợi đang xả. - Nếu bạn cần độ sâu hàng đợi, bật nhật ký chi tiết và theo dõi các dòng thời gian hàng đợi. -- Khi bật chẩn đoán, các phiên còn ở trạng thái `processing` quá `diagnostics.stuckSessionWarnMs` sẽ ghi cảnh báo phiên bị kẹt. Các lượt chạy nhúng đang hoạt động, thao tác trả lời đang hoạt động, và tác vụ lane đang hoạt động mặc định vẫn chỉ cảnh báo; sổ sách khởi động đã cũ mà không có công việc phiên đang hoạt động có thể nhả lane phiên bị ảnh hưởng để công việc trong hàng đợi được xả. +- Các lượt chạy Codex app-server chấp nhận một lượt rồi ngừng phát tiến trình sẽ bị adapter Codex ngắt để lane phiên đang hoạt động có thể được giải phóng thay vì chờ timeout của lượt chạy ngoài. +- Khi bật chẩn đoán, các phiên vẫn ở trạng thái `processing` quá `diagnostics.stuckSessionWarnMs` sẽ ghi cảnh báo phiên bị kẹt. Các lượt chạy nhúng đang hoạt động, thao tác trả lời đang hoạt động và tác vụ lane đang hoạt động mặc định vẫn chỉ cảnh báo; sổ sách khởi động đã cũ mà không có công việc phiên đang hoạt động có thể giải phóng lane phiên bị ảnh hưởng để công việc trong hàng đợi được xả. ## Liên quan diff --git a/docs/vi/help/testing.md b/docs/vi/help/testing.md index e26621b8a..cb3af96c5 100644 --- a/docs/vi/help/testing.md +++ b/docs/vi/help/testing.md @@ -1,203 +1,208 @@ --- read_when: - Chạy kiểm thử cục bộ hoặc trong CI - - Thêm kiểm thử hồi quy cho lỗi của mô hình/nhà cung cấp + - Thêm kiểm thử hồi quy cho các lỗi về mô hình/nhà cung cấp - Gỡ lỗi hành vi của Gateway + tác tử -summary: 'Bộ công cụ kiểm thử: các bộ kiểm thử đơn vị/e2e/live, trình chạy Docker và phạm vi bao quát của từng bài kiểm thử' +summary: 'Bộ công cụ kiểm thử: các bộ kiểm thử đơn vị, e2e và trực tiếp, trình chạy Docker, và phạm vi bao phủ của từng kiểm thử' title: Kiểm thử x-i18n: - generated_at: "2026-04-29T22:49:42Z" + generated_at: "2026-04-30T18:38:55Z" model: gpt-5.5 provider: openai - source_hash: c7b506350f11431195cb55c84cb10e99efb5f43b934079528b982627024d1ffc + source_hash: 470a96c6b47c2708950d05adc4a4efba5fe290f0675a131e2888d2d0032d5953 source_path: help/testing.md workflow: 16 --- -OpenClaw có ba bộ kiểm thử Vitest (unit/integration, e2e, live) và một nhóm nhỏ -các runner Docker. Tài liệu này là hướng dẫn "cách chúng tôi kiểm thử": +OpenClaw có ba bộ kiểm thử Vitest (đơn vị/tích hợp, e2e, live) và một nhóm nhỏ +các trình chạy Docker. Tài liệu này là hướng dẫn "cách chúng tôi kiểm thử": -- Mỗi bộ kiểm thử bao phủ những gì (và những gì nó cố ý _không_ bao phủ). -- Những lệnh cần chạy cho các quy trình phổ biến (cục bộ, trước khi push, gỡ lỗi). -- Cách các kiểm thử live phát hiện thông tin xác thực và chọn mô hình/nhà cung cấp. +- Mỗi bộ kiểm thử bao phủ những gì (và những gì nó chủ ý _không_ bao phủ). +- Các lệnh cần chạy cho những quy trình làm việc phổ biến (cục bộ, trước khi đẩy, gỡ lỗi). +- Cách kiểm thử live phát hiện thông tin xác thực và chọn mô hình/nhà cung cấp. - Cách thêm hồi quy cho các vấn đề mô hình/nhà cung cấp trong thực tế. **Ngăn xếp QA (qa-lab, qa-channel, các lane truyền tải live)** được ghi lại riêng: -- [Tổng quan QA](/vi/concepts/qa-e2e-automation) — kiến trúc, bề mặt lệnh, biên soạn kịch bản. -- [Matrix QA](/vi/concepts/qa-matrix) — tài liệu tham chiếu cho `pnpm openclaw qa matrix`. +- [Tổng quan QA](/vi/concepts/qa-e2e-automation) — kiến trúc, bề mặt lệnh, viết kịch bản. +- [QA ma trận](/vi/concepts/qa-matrix) — tài liệu tham chiếu cho `pnpm openclaw qa matrix`. - [Kênh QA](/vi/channels/qa-channel) — Plugin truyền tải tổng hợp được dùng bởi các kịch bản dựa trên repo. -Trang này bao quát việc chạy các bộ kiểm thử thông thường và các runner Docker/Parallels. Phần runner dành riêng cho QA bên dưới ([Runner dành riêng cho QA](#qa-specific-runners)) liệt kê các lệnh gọi `qa` cụ thể và trỏ lại các tài liệu tham chiếu ở trên. +Trang này bao phủ việc chạy các bộ kiểm thử thông thường và các trình chạy Docker/Parallels. Mục trình chạy riêng cho QA bên dưới ([Trình chạy riêng cho QA](#qa-specific-runners)) liệt kê các lệnh gọi `qa` cụ thể và trỏ lại các tài liệu tham chiếu ở trên. ## Bắt đầu nhanh Hầu hết các ngày: -- Cổng kiểm tra đầy đủ (được kỳ vọng trước khi push): `pnpm build && pnpm check && pnpm check:test-types && pnpm test` -- Chạy toàn bộ bộ kiểm thử cục bộ nhanh hơn trên máy có nhiều tài nguyên: `pnpm test:max` -- Vòng lặp watch Vitest trực tiếp: `pnpm test:watch` -- Nhắm mục tiêu trực tiếp theo tệp hiện cũng định tuyến các đường dẫn extension/channel: `pnpm test extensions/discord/src/monitor/message-handler.preflight.test.ts` -- Ưu tiên chạy có nhắm mục tiêu trước khi bạn đang lặp trên một lỗi đơn lẻ. +- Cổng kiểm tra đầy đủ (dự kiến trước khi đẩy): `pnpm build && pnpm check && pnpm check:test-types && pnpm test` +- Chạy toàn bộ bộ kiểm thử cục bộ nhanh hơn trên máy dư tài nguyên: `pnpm test:max` +- Vòng lặp theo dõi Vitest trực tiếp: `pnpm test:watch` +- Nhắm mục tiêu tệp trực tiếp hiện cũng định tuyến cả đường dẫn phần mở rộng/kênh: `pnpm test extensions/discord/src/monitor/message-handler.preflight.test.ts` +- Ưu tiên các lần chạy nhắm mục tiêu trước khi bạn đang lặp trên một lỗi đơn lẻ. - Site QA dựa trên Docker: `pnpm qa:lab:up` -- Lane QA dựa trên VM Linux: `pnpm openclaw qa suite --runner multipass --scenario channel-chat-baseline` +- Lane QA dựa trên máy ảo Linux: `pnpm openclaw qa suite --runner multipass --scenario channel-chat-baseline` Khi bạn chạm vào kiểm thử hoặc muốn thêm độ tin cậy: -- Cổng coverage: `pnpm test:coverage` +- Cổng kiểm tra độ bao phủ: `pnpm test:coverage` - Bộ E2E: `pnpm test:e2e` -Khi gỡ lỗi nhà cung cấp/mô hình thật (yêu cầu thông tin xác thực thật): +Khi gỡ lỗi các nhà cung cấp/mô hình thực (yêu cầu thông tin xác thực thật): -- Bộ live (mô hình + probe công cụ/hình ảnh Gateway): `pnpm test:live` -- Nhắm vào một tệp live một cách im lặng: `pnpm test:live -- src/agents/models.profiles.live.test.ts` +- Bộ live (mô hình + các phép dò công cụ/hình ảnh Gateway): `pnpm test:live` +- Nhắm một tệp live trong im lặng: `pnpm test:live -- src/agents/models.profiles.live.test.ts` - Quét mô hình live bằng Docker: `pnpm test:docker:live-models` - - Mỗi mô hình được chọn hiện chạy một lượt văn bản cộng với một probe nhỏ kiểu đọc tệp. - Các mô hình có metadata quảng bá đầu vào `image` cũng chạy một lượt hình ảnh nhỏ. - Tắt các probe bổ sung bằng `OPENCLAW_LIVE_MODEL_FILE_PROBE=0` hoặc + - Mỗi mô hình được chọn giờ chạy một lượt văn bản cùng một phép dò nhỏ kiểu đọc tệp. + Các mô hình có siêu dữ liệu quảng bá đầu vào `image` cũng chạy một lượt hình ảnh nhỏ. + Tắt các phép dò bổ sung bằng `OPENCLAW_LIVE_MODEL_FILE_PROBE=0` hoặc `OPENCLAW_LIVE_MODEL_IMAGE_PROBE=0` khi cô lập lỗi nhà cung cấp. - - Coverage CI: `OpenClaw Scheduled Live And E2E Checks` hằng ngày và + - Bao phủ CI: `OpenClaw Scheduled Live And E2E Checks` hằng ngày và `OpenClaw Release Checks` thủ công đều gọi workflow live/E2E tái sử dụng với `include_live_suites: true`, bao gồm các job ma trận mô hình live Docker riêng được chia shard theo nhà cung cấp. - - Với các lần chạy lại CI có trọng tâm, dispatch `OpenClaw Live And E2E Checks (Reusable)` + - Với các lần chạy lại CI có trọng tâm, kích hoạt `OpenClaw Live And E2E Checks (Reusable)` với `include_live_suites: true` và `live_models_only: true`. - - Thêm các secret nhà cung cấp có tín hiệu cao mới vào `scripts/ci-hydrate-live-auth.sh` - cùng với `.github/workflows/openclaw-live-and-e2e-checks-reusable.yml` và các - caller theo lịch/phát hành của nó. -- Smoke trò chuyện bound-chat Codex native: `pnpm test:docker:live-codex-bind` - - Chạy một lane live Docker trên đường dẫn app-server Codex, bind một Slack DM - tổng hợp bằng `/codex bind`, thực thi `/codex fast` và + - Thêm các bí mật nhà cung cấp tín hiệu cao mới vào `scripts/ci-hydrate-live-auth.sh` + cùng `.github/workflows/openclaw-live-and-e2e-checks-reusable.yml` và các + trình gọi theo lịch/phát hành của nó. +- Kiểm thử khói trò chuyện ràng buộc Codex gốc: `pnpm test:docker:live-codex-bind` + - Chạy một lane live Docker trên đường dẫn app-server Codex, ràng buộc một + DM Slack tổng hợp bằng `/codex bind`, thực thi `/codex fast` và `/codex permissions`, rồi xác minh một phản hồi thuần và một tệp đính kèm hình ảnh - định tuyến qua binding Plugin native thay vì ACP. -- Smoke harness app-server Codex: `pnpm test:docker:live-codex-harness` - - Chạy các lượt agent Gateway qua harness app-server Codex do Plugin sở hữu, - xác minh `/codex status` và `/codex models`, và mặc định thực thi các probe hình ảnh, - cron MCP, sub-agent, và Guardian. Tắt probe sub-agent bằng - `OPENCLAW_LIVE_CODEX_HARNESS_SUBAGENT_PROBE=0` khi cô lập các lỗi app-server Codex khác. - Với một kiểm tra sub-agent có trọng tâm, tắt các probe khác: + đi qua ràng buộc Plugin gốc thay vì ACP. +- Kiểm thử khói harness app-server Codex: `pnpm test:docker:live-codex-harness` + - Chạy các lượt tác tử Gateway qua harness app-server Codex do Plugin sở hữu, + xác minh `/codex status` và `/codex models`, và theo mặc định thực thi các phép dò hình ảnh, + cron MCP, sub-agent và Guardian. Tắt phép dò sub-agent bằng + `OPENCLAW_LIVE_CODEX_HARNESS_SUBAGENT_PROBE=0` khi cô lập các lỗi app-server Codex khác. Với một kiểm tra sub-agent có trọng tâm, tắt các phép dò khác: `OPENCLAW_LIVE_CODEX_HARNESS_IMAGE_PROBE=0 OPENCLAW_LIVE_CODEX_HARNESS_MCP_PROBE=0 OPENCLAW_LIVE_CODEX_HARNESS_GUARDIAN_PROBE=0 OPENCLAW_LIVE_CODEX_HARNESS_SUBAGENT_PROBE=1 pnpm test:docker:live-codex-harness`. - Lệnh này thoát sau probe sub-agent trừ khi + Lệnh này thoát sau phép dò sub-agent trừ khi `OPENCLAW_LIVE_CODEX_HARNESS_SUBAGENT_ONLY=0` được đặt. -- Smoke lệnh cứu hộ Crestodian: `pnpm test:live:crestodian-rescue-channel` - - Kiểm tra opt-in nhiều lớp cho bề mặt lệnh cứu hộ kênh tin nhắn. - Nó thực thi `/crestodian status`, xếp hàng một thay đổi mô hình bền vững, - trả lời `/crestodian yes`, và xác minh đường dẫn ghi audit/config. -- Smoke Docker planner Crestodian: `pnpm test:docker:crestodian-planner` - - Chạy Crestodian trong container không có config với một Claude CLI giả trên `PATH` - và xác minh fallback planner mờ được chuyển thành một ghi config có kiểu đã được audit. -- Smoke Docker lần chạy đầu của Crestodian: `pnpm test:docker:crestodian-first-run` +- Kiểm thử khói lệnh cứu hộ Crestodian: `pnpm test:live:crestodian-rescue-channel` + - Kiểm tra chọn tham gia nhiều lớp bảo vệ cho bề mặt lệnh cứu hộ kênh tin nhắn. + Nó thực thi `/crestodian status`, đưa vào hàng đợi một thay đổi mô hình bền vững, + trả lời `/crestodian yes`, và xác minh đường dẫn ghi kiểm toán/cấu hình. +- Kiểm thử khói Docker trình lập kế hoạch Crestodian: `pnpm test:docker:crestodian-planner` + - Chạy Crestodian trong container không có cấu hình với Claude CLI giả trên `PATH` + và xác minh fallback trình lập kế hoạch mờ được chuyển thành thao tác ghi cấu hình + có kiểu và được kiểm toán. +- Kiểm thử khói Docker lần chạy đầu tiên Crestodian: `pnpm test:docker:crestodian-first-run` - Bắt đầu từ thư mục trạng thái OpenClaw trống, định tuyến `openclaw` trần tới - Crestodian, áp dụng thiết lập/mô hình/agent/Plugin Discord + ghi SecretRef, - xác thực config, và xác minh các mục audit. Cùng đường dẫn thiết lập Ring 0 cũng - được bao phủ trong QA Lab bởi + Crestodian, áp dụng thiết lập/mô hình/tác tử/Plugin Discord + các ghi SecretRef, + xác thực cấu hình và xác minh các mục kiểm toán. Cùng đường dẫn thiết lập Ring 0 + cũng được bao phủ trong QA Lab bởi `pnpm openclaw qa suite --scenario crestodian-ring-zero-setup`. -- Smoke chi phí Moonshot/Kimi: với `MOONSHOT_API_KEY` được đặt, chạy +- Kiểm thử khói chi phí Moonshot/Kimi: với `MOONSHOT_API_KEY` được đặt, chạy `openclaw models list --provider moonshot --json`, rồi chạy một `openclaw agent --local --session-id live-kimi-cost --message 'Reply exactly: KIMI_LIVE_OK' --thinking off --json` - cô lập trên `moonshot/kimi-k2.6`. Xác minh JSON báo cáo Moonshot/K2.6 và transcript - assistant lưu `usage.cost` đã chuẩn hóa. + cô lập trên `moonshot/kimi-k2.6`. Xác minh JSON báo cáo Moonshot/K2.6 và bản ghi hội thoại trợ lý lưu `usage.cost` đã chuẩn hóa. Khi bạn chỉ cần một trường hợp lỗi, hãy ưu tiên thu hẹp kiểm thử live qua các biến môi trường allowlist được mô tả bên dưới. -## Runner dành riêng cho QA +## Trình chạy riêng cho QA -Các lệnh này nằm cạnh các bộ kiểm thử chính khi bạn cần độ thực tế của QA-lab: +Các lệnh này nằm cạnh các bộ kiểm thử chính khi bạn cần tính thực tế của QA-lab: -CI chạy QA Lab trong các workflow chuyên dụng. `Parity gate` chạy trên các PR khớp và -từ dispatch thủ công với nhà cung cấp mock. `QA-Lab - All Lanes` chạy hằng đêm trên -`main` và từ dispatch thủ công với mock parity gate, lane Matrix live, -lane Telegram live do Convex quản lý, và lane Discord live do Convex quản lý dưới dạng -các job song song. QA theo lịch và kiểm tra phát hành truyền Matrix `--profile fast` -một cách rõ ràng, trong khi mặc định của Matrix CLI và đầu vào workflow thủ công vẫn là -`all`; dispatch thủ công có thể chia shard `all` thành các job `transport`, `media`, `e2ee-smoke`, -`e2ee-deep`, và `e2ee-cli`. `OpenClaw Release Checks` chạy parity cộng với -các lane Matrix nhanh và Telegram trước phê duyệt phát hành, dùng -`mock-openai/gpt-5.5` cho các kiểm tra truyền tải phát hành để chúng vẫn xác định được -và tránh khởi động provider-plugin thông thường. Các Gateway truyền tải live này tắt -tìm kiếm bộ nhớ; hành vi bộ nhớ vẫn được bao phủ bởi các bộ parity QA. +CI chạy QA Lab trong các workflow chuyên dụng. `Parity gate` chạy trên các PR khớp điều kiện và +từ kích hoạt thủ công với nhà cung cấp giả lập. `QA-Lab - All Lanes` chạy hằng đêm trên +`main` và từ kích hoạt thủ công với cổng tương đồng giả lập, lane Matrix live, +lane Telegram live do Convex quản lý và lane Discord live do Convex quản lý dưới dạng +các job song song. QA theo lịch và các kiểm tra phát hành truyền Matrix `--profile fast` +một cách rõ ràng, trong khi mặc định đầu vào workflow thủ công và Matrix CLI vẫn là +`all`; kích hoạt thủ công có thể chia shard `all` thành các job `transport`, `media`, `e2ee-smoke`, +`e2ee-deep`, và `e2ee-cli`. `OpenClaw Release Checks` chạy tương đồng cùng +các lane Matrix nhanh và Telegram trước khi phê duyệt phát hành, dùng +`mock-openai/gpt-5.5` cho các kiểm tra truyền tải phát hành để chúng duy trì tính xác định +và tránh khởi động Plugin nhà cung cấp thông thường. Các Gateway truyền tải live này tắt +tìm kiếm bộ nhớ; hành vi bộ nhớ vẫn được bao phủ bởi các bộ tương đồng QA. -Các shard media live phát hành đầy đủ dùng +Các shard phương tiện live phát hành đầy đủ dùng `ghcr.io/openclaw/openclaw-live-media-runner:ubuntu-24.04`, vốn đã có `ffmpeg` và `ffprobe`. Các shard mô hình/backend live Docker dùng image dùng chung -`ghcr.io/openclaw/openclaw-live-test:` được build một lần cho mỗi commit được chọn, -sau đó pull nó với `OPENCLAW_SKIP_DOCKER_BUILD=1` thay vì build lại trong từng shard. +`ghcr.io/openclaw/openclaw-live-test:` được xây dựng một lần cho mỗi commit được chọn, +sau đó kéo image đó với `OPENCLAW_SKIP_DOCKER_BUILD=1` thay vì xây dựng lại +bên trong từng shard. - `pnpm openclaw qa suite` - - Chạy trực tiếp các kịch bản QA dựa trên repo trên host. - - Chạy nhiều kịch bản được chọn song song theo mặc định với các worker Gateway cô lập. - `qa-channel` mặc định concurrency là 4 (bị giới hạn bởi số lượng kịch bản được chọn). - Dùng `--concurrency ` để tinh chỉnh số worker, hoặc `--concurrency 1` cho lane tuần tự cũ hơn. - - Thoát khác 0 khi bất kỳ kịch bản nào thất bại. Dùng `--allow-failures` khi bạn - muốn artifact mà không có mã thoát thất bại. + - Chạy trực tiếp các kịch bản QA dựa trên repo trên máy chủ. + - Chạy nhiều kịch bản được chọn song song theo mặc định với các worker Gateway + cô lập. `qa-channel` mặc định concurrency 4 (giới hạn bởi số lượng kịch bản + được chọn). Dùng `--concurrency ` để tinh chỉnh số lượng worker, + hoặc `--concurrency 1` cho lane nối tiếp cũ hơn. + - Thoát khác không khi bất kỳ kịch bản nào thất bại. Dùng `--allow-failures` khi bạn + muốn hiện vật mà không có mã thoát thất bại. - Hỗ trợ các chế độ nhà cung cấp `live-frontier`, `mock-openai`, và `aimock`. - `aimock` khởi động một server nhà cung cấp cục bộ dựa trên AIMock cho coverage fixture - thử nghiệm và protocol-mock mà không thay thế lane `mock-openai` có nhận biết kịch bản. + `aimock` khởi động một máy chủ nhà cung cấp cục bộ dựa trên AIMock cho độ bao phủ + fixture thử nghiệm và mock giao thức mà không thay thế lane `mock-openai` + nhận biết kịch bản. - `pnpm test:gateway:cpu-scenarios` - - Chạy bench khởi động Gateway cộng với một gói kịch bản QA Lab mock nhỏ + - Chạy benchmark khởi động Gateway cùng một gói nhỏ kịch bản QA Lab giả lập (`channel-chat-baseline`, `memory-failure-fallback`, - `gateway-restart-inflight-run`) và ghi một tóm tắt quan sát CPU kết hợp + `gateway-restart-inflight-run`) và ghi một bản tóm tắt quan sát CPU kết hợp dưới `.artifacts/gateway-cpu-scenarios/`. - - Mặc định chỉ gắn cờ các quan sát CPU nóng kéo dài (`--cpu-core-warn` - cộng với `--hot-wall-warn-ms`), nên các đợt tăng ngắn khi khởi động được ghi lại như metric - mà không trông giống hồi quy Gateway peg kéo dài nhiều phút. - - Dùng artifact `dist` đã build; chạy build trước khi checkout chưa có output runtime mới. + - Chỉ gắn cờ các quan sát CPU nóng kéo dài theo mặc định (`--cpu-core-warn` + cộng `--hot-wall-warn-ms`), nên các đợt tăng ngắn khi khởi động được ghi nhận + như số liệu mà không trông giống hồi quy Gateway bị ghim CPU kéo dài nhiều phút. + - Dùng hiện vật `dist` đã xây dựng; hãy chạy build trước khi checkout chưa có + đầu ra runtime mới. - `pnpm openclaw qa suite --runner multipass` - - Chạy cùng bộ QA bên trong một VM Linux Multipass dùng một lần. - - Giữ cùng hành vi chọn kịch bản như `qa suite` trên host. - - Tái sử dụng cùng các flag chọn nhà cung cấp/mô hình như `qa suite`. - - Các lần chạy live chuyển tiếp các đầu vào auth QA được hỗ trợ và thực tế cho guest: - key nhà cung cấp dựa trên env, đường dẫn config nhà cung cấp live QA, và `CODEX_HOME` + - Chạy cùng bộ QA bên trong một máy ảo Linux Multipass dùng một lần. + - Giữ cùng hành vi chọn kịch bản như `qa suite` trên máy chủ. + - Tái sử dụng cùng các cờ chọn nhà cung cấp/mô hình như `qa suite`. + - Các lần chạy live chuyển tiếp những đầu vào xác thực QA được hỗ trợ và khả thi cho máy khách: + khóa nhà cung cấp dựa trên env, đường dẫn cấu hình nhà cung cấp live QA, và `CODEX_HOME` khi có. - - Các thư mục output phải nằm dưới root repo để guest có thể ghi ngược qua + - Thư mục đầu ra phải nằm dưới gốc repo để máy khách có thể ghi ngược qua workspace được mount. - - Ghi báo cáo + tóm tắt QA thông thường cộng với log Multipass dưới + - Ghi báo cáo + tóm tắt QA thông thường cùng nhật ký Multipass dưới `.artifacts/qa-e2e/...`. - `pnpm qa:lab:up` - - Khởi động site QA dựa trên Docker cho công việc QA kiểu operator. + - Khởi động site QA dựa trên Docker cho công việc QA kiểu vận hành viên. - `pnpm test:docker:npm-onboard-channel-agent` - - Build tarball npm từ checkout hiện tại, cài đặt nó toàn cục trong - Docker, chạy onboarding OpenAI API-key không tương tác, cấu hình Telegram - theo mặc định, xác minh việc bật Plugin cài đặt dependency runtime theo - nhu cầu, chạy doctor, và chạy một lượt agent cục bộ trên endpoint OpenAI mock. - - Dùng `OPENCLAW_NPM_ONBOARD_CHANNEL=discord` để chạy cùng lane cài đặt package + - Xây dựng một tarball npm từ checkout hiện tại, cài đặt nó toàn cục trong + Docker, chạy onboarding khóa OpenAI API không tương tác, cấu hình Telegram + theo mặc định, xác minh việc bật Plugin sẽ cài đặt các phụ thuộc runtime theo + nhu cầu, chạy doctor, và chạy một lượt tác tử cục bộ trên endpoint OpenAI + được giả lập. + - Dùng `OPENCLAW_NPM_ONBOARD_CHANNEL=discord` để chạy cùng lane cài đặt gói với Discord. - `pnpm test:docker:session-runtime-context` - - Chạy smoke Docker app đã build xác định cho transcript ngữ cảnh runtime nhúng. - Nó xác minh ngữ cảnh runtime OpenClaw ẩn được lưu bền vững dưới dạng message tùy chỉnh - không hiển thị thay vì rò rỉ vào lượt người dùng hiển thị, rồi seed một JSONL phiên hỏng - bị ảnh hưởng và xác minh `openclaw doctor --fix` ghi lại nó sang nhánh đang hoạt động kèm backup. + - Chạy một kiểm thử khói Docker ứng dụng đã xây dựng có tính xác định cho các + bản ghi hội thoại ngữ cảnh runtime nhúng. Nó xác minh ngữ cảnh runtime OpenClaw + ẩn được lưu bền vững dưới dạng tin nhắn tùy chỉnh không hiển thị thay vì rò rỉ + vào lượt người dùng thấy được, sau đó gieo một JSONL phiên lỗi bị ảnh hưởng và + xác minh `openclaw doctor --fix` viết lại nó về nhánh hoạt động với một bản sao lưu. - `pnpm test:docker:npm-telegram-live` - - Cài đặt một ứng viên package OpenClaw trong Docker, chạy onboarding package đã cài, - cấu hình Telegram qua CLI đã cài, rồi tái sử dụng lane QA Telegram live với package đã cài - đó làm SUT Gateway. + - Cài đặt một ứng viên gói OpenClaw trong Docker, chạy onboarding gói đã cài đặt, + cấu hình Telegram qua CLI đã cài đặt, rồi tái sử dụng lane QA Telegram live với + gói đã cài đặt đó làm Gateway SUT. - Mặc định là `OPENCLAW_NPM_TELEGRAM_PACKAGE_SPEC=openclaw@beta`; đặt `OPENCLAW_NPM_TELEGRAM_PACKAGE_TGZ=/path/to/openclaw-current.tgz` hoặc `OPENCLAW_CURRENT_PACKAGE_TGZ` để kiểm thử một tarball cục bộ đã phân giải thay vì - cài từ registry. + cài đặt từ registry. - Dùng cùng thông tin xác thực env Telegram hoặc nguồn thông tin xác thực Convex như `pnpm openclaw qa telegram`. Với tự động hóa CI/phát hành, đặt - `OPENCLAW_NPM_TELEGRAM_CREDENTIAL_SOURCE=convex` cộng với - `OPENCLAW_QA_CONVEX_SITE_URL` và role secret. Nếu - `OPENCLAW_QA_CONVEX_SITE_URL` và một Convex role secret có trong CI, + `OPENCLAW_NPM_TELEGRAM_CREDENTIAL_SOURCE=convex` cộng + `OPENCLAW_QA_CONVEX_SITE_URL` và bí mật vai trò. Nếu + `OPENCLAW_QA_CONVEX_SITE_URL` và một bí mật vai trò Convex có mặt trong CI, wrapper Docker tự động chọn Convex. - `OPENCLAW_NPM_TELEGRAM_CREDENTIAL_ROLE=ci|maintainer` ghi đè `OPENCLAW_QA_CREDENTIAL_ROLE` dùng chung chỉ cho lane này. - - GitHub Actions hiển thị lane này dưới dạng workflow maintainer thủ công + - GitHub Actions phơi bày lane này dưới dạng workflow maintainer thủ công `NPM Telegram Beta E2E`. Nó không chạy khi merge. Workflow dùng môi trường `qa-live-shared` và các lease thông tin xác thực CI Convex. -- GitHub Actions cũng hiển thị `Package Acceptance` để proof sản phẩm chạy bên cạnh - trên một package ứng viên. Nó chấp nhận ref tin cậy, spec npm đã publish, - URL tarball HTTPS cộng với SHA-256, hoặc artifact tarball từ lần chạy khác, upload - `openclaw-current.tgz` đã chuẩn hóa dưới dạng `package-under-test`, rồi chạy scheduler - Docker E2E hiện có với các profile lane smoke, package, product, full, hoặc custom. +- GitHub Actions cũng phơi bày `Package Acceptance` để chứng minh sản phẩm chạy kèm + trên một gói ứng viên. Nó chấp nhận ref đáng tin cậy, spec npm đã phát hành, + URL tarball HTTPS cộng SHA-256, hoặc hiện vật tarball từ một lần chạy khác, tải lên + `openclaw-current.tgz` đã chuẩn hóa dưới tên `package-under-test`, rồi chạy bộ lập lịch + Docker E2E hiện có với các profile lane khói, gói, sản phẩm, đầy đủ hoặc tùy chỉnh. Đặt `telegram_mode=mock-openai` hoặc `live-frontier` để chạy workflow QA Telegram - trên cùng artifact `package-under-test`. - - Proof sản phẩm beta mới nhất: + trên cùng hiện vật `package-under-test`. + - Bằng chứng sản phẩm beta mới nhất: ```bash gh workflow run package-acceptance.yml --ref main \ @@ -207,7 +212,7 @@ gh workflow run package-acceptance.yml --ref main \ -f telegram_mode=mock-openai ``` -- Proof URL tarball chính xác yêu cầu digest: +- Bằng chứng URL tarball chính xác yêu cầu một digest: ```bash gh workflow run package-acceptance.yml --ref main \ @@ -217,7 +222,7 @@ gh workflow run package-acceptance.yml --ref main \ -f suite_profile=package ``` -- Bằng chứng artifact tải xuống một artifact tarball từ một lần chạy Actions khác: +- Bằng chứng artifact tải xuống artifact dạng tarball từ một lần chạy Actions khác: ```bash gh workflow run package-acceptance.yml --ref main \ @@ -229,69 +234,72 @@ gh workflow run package-acceptance.yml --ref main \ - `pnpm test:docker:bundled-channel-deps` - Đóng gói và cài đặt bản dựng OpenClaw hiện tại trong Docker, khởi động Gateway - với OpenAI đã được cấu hình, rồi bật các kênh/Plugin được đóng gói kèm thông qua các chỉnh sửa cấu hình. - - Xác minh rằng quá trình phát hiện thiết lập để trống các phụ thuộc runtime Plugin chưa cấu hình, - lần chạy Gateway hoặc doctor đầu tiên đã cấu hình sẽ cài đặt phụ thuộc runtime của từng Plugin được đóng gói kèm - theo nhu cầu, và lần khởi động lại thứ hai không cài đặt lại các phụ thuộc đã được kích hoạt. + với OpenAI đã được cấu hình, sau đó bật kênh/Plugin đi kèm thông qua các + chỉnh sửa cấu hình. + - Xác minh quy trình phát hiện thiết lập để trống các phụ thuộc runtime Plugin + chưa cấu hình, lần chạy Gateway đã cấu hình đầu tiên hoặc lần chạy doctor + đầu tiên sẽ cài đặt phụ thuộc runtime của từng Plugin đi kèm theo nhu cầu, + và lần khởi động lại thứ hai không cài đặt lại các phụ thuộc đã được kích hoạt. - Cũng cài đặt một baseline npm cũ đã biết, bật Telegram trước khi chạy - `openclaw update --tag `, và xác minh rằng doctor sau cập nhật của candidate - sửa các phụ thuộc runtime của kênh được đóng gói kèm mà không cần sửa chữa postinstall từ phía harness. + `openclaw update --tag `, và xác minh doctor sau cập nhật của + bản candidate sửa chữa các phụ thuộc runtime kênh đi kèm mà không cần sửa + postinstall phía harness. - `pnpm test:parallels:npm-update` - - Chạy smoke cập nhật cài đặt gói native trên các guest Parallels. Mỗi - nền tảng được chọn trước tiên cài đặt gói baseline được yêu cầu, sau đó chạy - lệnh `openclaw update` đã cài đặt trong cùng guest và xác minh - phiên bản đã cài đặt, trạng thái cập nhật, mức sẵn sàng của gateway, và một lượt agent cục bộ. - - Dùng `--platform macos`, `--platform windows`, hoặc `--platform linux` trong khi - lặp trên một guest. Dùng `--json` để lấy đường dẫn artifact tóm tắt và + - Chạy kiểm thử khói cập nhật bản cài đặt đóng gói native trên các máy khách + Parallels. Mỗi nền tảng được chọn trước tiên cài đặt gói baseline được yêu + cầu, sau đó chạy lệnh `openclaw update` đã cài đặt trong cùng máy khách và + xác minh phiên bản đã cài đặt, trạng thái cập nhật, mức sẵn sàng của Gateway, + và một lượt agent cục bộ. + - Dùng `--platform macos`, `--platform windows`, hoặc `--platform linux` khi + lặp trên một máy khách. Dùng `--json` cho đường dẫn artifact tóm tắt và trạng thái theo từng lane. - - Lane OpenAI dùng `openai/gpt-5.5` theo mặc định cho bằng chứng lượt agent trực tiếp. - Truyền `--model ` hoặc đặt - `OPENCLAW_PARALLELS_OPENAI_MODEL` khi chủ đích xác thực một - mô hình OpenAI khác. - - Bọc các lần chạy cục bộ dài trong timeout của host để các lần treo vận chuyển Parallels không - tiêu tốn phần còn lại của cửa sổ kiểm thử: + - Lane OpenAI dùng `openai/gpt-5.5` cho bằng chứng lượt agent trực tiếp theo + mặc định. Truyền `--model ` hoặc đặt + `OPENCLAW_PARALLELS_OPENAI_MODEL` khi chủ ý xác thực một mô hình OpenAI khác. + - Bọc các lần chạy cục bộ dài trong timeout của host để tình trạng đình trệ + truyền tải Parallels không tiêu tốn phần còn lại của cửa sổ kiểm thử: ```bash timeout --foreground 150m pnpm test:parallels:npm-update -- --json timeout --foreground 90m pnpm test:parallels:npm-update -- --platform windows --json ``` - - Script ghi các log lane lồng nhau dưới `/tmp/openclaw-parallels-npm-update.*`. + - Script ghi log lane lồng nhau dưới `/tmp/openclaw-parallels-npm-update.*`. Kiểm tra `windows-update.log`, `macos-update.log`, hoặc `linux-update.log` trước khi cho rằng wrapper bên ngoài bị treo. - - Cập nhật Windows có thể mất 10 đến 15 phút trong quá trình sửa doctor/runtime - dependency sau cập nhật trên một guest lạnh; điều đó vẫn bình thường khi log debug - npm lồng nhau vẫn đang tiến triển. - - Không chạy wrapper tổng hợp này song song với các lane smoke Parallels - macOS, Windows, hoặc Linux riêng lẻ. Chúng dùng chung trạng thái VM và có thể xung đột khi - khôi phục snapshot, phục vụ gói, hoặc trạng thái gateway của guest. - - Bằng chứng sau cập nhật chạy bề mặt Plugin được đóng gói kèm thông thường vì - các facade capability như giọng nói, tạo ảnh, và hiểu media - được tải qua các API runtime được đóng gói kèm ngay cả khi chính lượt agent - chỉ kiểm tra một phản hồi văn bản đơn giản. + - Cập nhật Windows có thể mất 10 đến 15 phút trong quá trình doctor sau cập + nhật/sửa chữa phụ thuộc runtime trên một máy khách nguội; điều đó vẫn bình + thường khi log debug npm lồng nhau vẫn đang tiến triển. + - Không chạy wrapper tổng hợp này song song với từng lane kiểm thử khói + Parallels macOS, Windows, hoặc Linux riêng lẻ. Chúng chia sẻ trạng thái VM + và có thể xung đột ở bước khôi phục snapshot, phục vụ gói, hoặc trạng thái + Gateway của máy khách. + - Bằng chứng sau cập nhật chạy bề mặt Plugin đi kèm thông thường vì các facade + năng lực như giọng nói, tạo ảnh, và hiểu phương tiện được tải qua API runtime + đi kèm ngay cả khi chính lượt agent chỉ kiểm tra một phản hồi văn bản đơn giản. - `pnpm openclaw qa aimock` - - Chỉ khởi động máy chủ provider AIMock cục bộ để kiểm thử smoke giao thức trực tiếp. + - Chỉ khởi động máy chủ nhà cung cấp AIMock cục bộ để kiểm thử khói giao thức trực tiếp. - `pnpm openclaw qa matrix` - - Chạy lane QA trực tiếp Matrix trên một homeserver Tuwunel tạm thời dựa trên Docker. Chỉ source-checkout — các bản cài đặt đóng gói không phát hành `qa-lab`. - - CLI đầy đủ, danh mục profile/scenario, biến môi trường, và bố cục artifact: [QA Matrix](/vi/concepts/qa-matrix). + - Chạy lane QA trực tiếp Matrix với một homeserver Tuwunel dùng Docker dùng một lần. Chỉ source-checkout — các bản cài đặt đóng gói không phân phối `qa-lab`. + - CLI đầy đủ, catalog profile/kịch bản, biến môi trường, và bố cục artifact: [QA Matrix](/vi/concepts/qa-matrix). - `pnpm openclaw qa telegram` - - Chạy lane QA trực tiếp Telegram trên một nhóm riêng tư thật bằng token bot driver và SUT từ env. - - Yêu cầu `OPENCLAW_QA_TELEGRAM_GROUP_ID`, `OPENCLAW_QA_TELEGRAM_DRIVER_BOT_TOKEN`, và `OPENCLAW_QA_TELEGRAM_SUT_BOT_TOKEN`. Id nhóm phải là id chat Telegram dạng số. - - Hỗ trợ `--credential-source convex` cho thông tin xác thực dùng chung trong pool. Dùng chế độ env theo mặc định, hoặc đặt `OPENCLAW_QA_CREDENTIAL_SOURCE=convex` để chọn dùng lease từ pool. - - Thoát với mã khác không khi bất kỳ scenario nào thất bại. Dùng `--allow-failures` khi bạn + - Chạy lane QA trực tiếp Telegram với một nhóm riêng tư thật bằng token bot driver và SUT từ env. + - Yêu cầu `OPENCLAW_QA_TELEGRAM_GROUP_ID`, `OPENCLAW_QA_TELEGRAM_DRIVER_BOT_TOKEN`, và `OPENCLAW_QA_TELEGRAM_SUT_BOT_TOKEN`. ID nhóm phải là ID trò chuyện Telegram dạng số. + - Hỗ trợ `--credential-source convex` cho thông tin xác thực dùng chung theo pool. Dùng chế độ env theo mặc định, hoặc đặt `OPENCLAW_QA_CREDENTIAL_SOURCE=convex` để chọn tham gia lease theo pool. + - Thoát với mã khác không khi bất kỳ kịch bản nào thất bại. Dùng `--allow-failures` khi bạn muốn có artifact mà không có mã thoát thất bại. - - Yêu cầu hai bot riêng biệt trong cùng nhóm riêng tư, với bot SUT công khai username Telegram. - - Để quan sát bot-với-bot ổn định, bật Bot-to-Bot Communication Mode trong `@BotFather` cho cả hai bot và bảo đảm bot driver có thể quan sát lưu lượng bot trong nhóm. - - Ghi báo cáo QA Telegram, tóm tắt, và artifact observed-messages dưới `.artifacts/qa-e2e/...`. Các scenario trả lời bao gồm RTT từ yêu cầu gửi của driver đến phản hồi SUT được quan sát. + - Yêu cầu hai bot riêng biệt trong cùng một nhóm riêng tư, trong đó bot SUT để lộ tên người dùng Telegram. + - Để quan sát bot-với-bot ổn định, bật Bot-to-Bot Communication Mode trong `@BotFather` cho cả hai bot và đảm bảo bot driver có thể quan sát lưu lượng bot trong nhóm. + - Ghi báo cáo QA Telegram, bản tóm tắt, và artifact tin nhắn đã quan sát dưới `.artifacts/qa-e2e/...`. Các kịch bản trả lời bao gồm RTT từ yêu cầu gửi của driver đến phản hồi SUT đã quan sát. -Các lane vận chuyển trực tiếp dùng chung một hợp đồng tiêu chuẩn để các vận chuyển mới không lệch hướng; ma trận coverage theo từng lane nằm trong [tổng quan QA → Coverage vận chuyển trực tiếp](/vi/concepts/qa-e2e-automation#live-transport-coverage). `qa-channel` là bộ tổng hợp synthetic rộng và không thuộc ma trận đó. +Các lane truyền tải trực tiếp chia sẻ một hợp đồng chuẩn để các truyền tải mới không lệch hướng; ma trận phạm vi theo lane nằm trong [tổng quan QA → Phạm vi truyền tải trực tiếp](/vi/concepts/qa-e2e-automation#live-transport-coverage). `qa-channel` là bộ tổng hợp mô phỏng rộng và không thuộc ma trận đó. ### Thông tin xác thực Telegram dùng chung qua Convex (v1) Khi bật `--credential-source convex` (hoặc `OPENCLAW_QA_CREDENTIAL_SOURCE=convex`) cho -`openclaw qa telegram`, QA lab lấy một lease độc quyền từ pool dựa trên Convex, gửi heartbeats -cho lease đó trong khi lane đang chạy, và giải phóng lease khi tắt. +`openclaw qa telegram`, QA lab lấy một lease độc quyền từ pool được Convex hỗ trợ, Heartbeat +lease đó trong khi lane đang chạy, và giải phóng lease khi tắt. Scaffold dự án Convex tham chiếu: @@ -300,12 +308,12 @@ Scaffold dự án Convex tham chiếu: Biến môi trường bắt buộc: - `OPENCLAW_QA_CONVEX_SITE_URL` (ví dụ `https://your-deployment.convex.site`) -- Một secret cho vai trò được chọn: +- Một secret cho vai trò đã chọn: - `OPENCLAW_QA_CONVEX_SECRET_MAINTAINER` cho `maintainer` - `OPENCLAW_QA_CONVEX_SECRET_CI` cho `ci` - Chọn vai trò thông tin xác thực: - CLI: `--credential-role maintainer|ci` - - Mặc định env: `OPENCLAW_QA_CREDENTIAL_ROLE` (mặc định là `ci` trong CI, nếu không là `maintainer`) + - Mặc định env: `OPENCLAW_QA_CREDENTIAL_ROLE` (mặc định là `ci` trong CI, nếu không thì là `maintainer`) Biến môi trường tùy chọn: @@ -314,15 +322,15 @@ Biến môi trường tùy chọn: - `OPENCLAW_QA_CREDENTIAL_ACQUIRE_TIMEOUT_MS` (mặc định `90000`) - `OPENCLAW_QA_CREDENTIAL_HTTP_TIMEOUT_MS` (mặc định `15000`) - `OPENCLAW_QA_CONVEX_ENDPOINT_PREFIX` (mặc định `/qa-credentials/v1`) -- `OPENCLAW_QA_CREDENTIAL_OWNER_ID` (trace id tùy chọn) -- `OPENCLAW_QA_ALLOW_INSECURE_HTTP=1` cho phép URL Convex `http://` loopback chỉ dành cho phát triển cục bộ. +- `OPENCLAW_QA_CREDENTIAL_OWNER_ID` (ID truy vết tùy chọn) +- `OPENCLAW_QA_ALLOW_INSECURE_HTTP=1` cho phép URL Convex `http://` local loopback cho phát triển chỉ cục bộ. `OPENCLAW_QA_CONVEX_SITE_URL` nên dùng `https://` trong vận hành bình thường. -Các lệnh admin của maintainer (thêm/xóa/liệt kê pool) yêu cầu cụ thể +Các lệnh quản trị của maintainer (thêm/xóa/liệt kê pool) yêu cầu riêng `OPENCLAW_QA_CONVEX_SECRET_MAINTAINER`. -CLI helper cho maintainer: +Trình trợ giúp CLI cho maintainer: ```bash pnpm openclaw qa credentials doctor @@ -333,7 +341,8 @@ pnpm openclaw qa credentials remove --credential-id Dùng `doctor` trước các lần chạy trực tiếp để kiểm tra URL site Convex, secret broker, tiền tố endpoint, timeout HTTP, và khả năng truy cập admin/list mà không in -giá trị secret. Dùng `--json` cho đầu ra máy đọc được trong script và tiện ích CI. +giá trị secret. Dùng `--json` cho đầu ra máy đọc được trong script và tiện ích +CI. Hợp đồng endpoint mặc định (`OPENCLAW_QA_CONVEX_SITE_URL` + `/qa-credentials/v1`): @@ -353,431 +362,454 @@ Hợp đồng endpoint mặc định (`OPENCLAW_QA_CONVEX_SITE_URL` + `/qa-crede - `POST /admin/remove` (chỉ secret maintainer) - Yêu cầu: `{ credentialId, actorId }` - Thành công: `{ status: "ok", changed, credential }` - - Bộ chặn lease đang hoạt động: `{ status: "error", code: "LEASE_ACTIVE", ... }` + - Guard lease đang hoạt động: `{ status: "error", code: "LEASE_ACTIVE", ... }` - `POST /admin/list` (chỉ secret maintainer) - Yêu cầu: `{ kind?, status?, includePayload?, limit? }` - Thành công: `{ status: "ok", credentials, count }` -Dạng payload cho kind Telegram: +Hình dạng payload cho loại Telegram: - `{ groupId: string, driverToken: string, sutToken: string }` -- `groupId` phải là chuỗi id chat Telegram dạng số. -- `admin/add` xác thực dạng này cho `kind: "telegram"` và từ chối payload sai định dạng. +- `groupId` phải là chuỗi ID trò chuyện Telegram dạng số. +- `admin/add` xác thực hình dạng này cho `kind: "telegram"` và từ chối payload sai định dạng. ### Thêm một kênh vào QA -Kiến trúc và tên scenario-helper cho adapter kênh mới nằm trong [tổng quan QA → Thêm một kênh](/vi/concepts/qa-e2e-automation#adding-a-channel). Mức tối thiểu: triển khai transport runner trên seam host `qa-lab` dùng chung, khai báo `qaRunners` trong manifest Plugin, mount dưới dạng `openclaw qa `, và viết scenario dưới `qa/scenarios/`. +Kiến trúc và tên trình trợ giúp kịch bản cho các adapter kênh mới nằm trong [tổng quan QA → Thêm một kênh](/vi/concepts/qa-e2e-automation#adding-a-channel). Mức tối thiểu: triển khai runner truyền tải trên seam host `qa-lab` dùng chung, khai báo `qaRunners` trong manifest Plugin, mount dưới dạng `openclaw qa `, và viết kịch bản trong `qa/scenarios/`. -## Bộ kiểm thử (chạy ở đâu) +## Bộ kiểm thử (chạy gì ở đâu) -Hãy xem các bộ này như “mức độ thực tế tăng dần” (đồng thời độ bất ổn/chi phí cũng tăng): +Hãy xem các bộ này như “mức độ thực tế tăng dần” (và độ không ổn định/chi phí cũng tăng dần): ### Unit / tích hợp (mặc định) - Lệnh: `pnpm test` -- Cấu hình: các lần chạy không nhắm mục tiêu dùng bộ shard `vitest.full-*.config.ts` và có thể mở rộng shard nhiều dự án thành cấu hình theo từng dự án để lập lịch song song -- Tệp: inventory core/unit dưới `src/**/*.test.ts`, `packages/**/*.test.ts`, và `test/**/*.test.ts`; kiểm thử unit UI chạy trong shard chuyên dụng `unit-ui` +- Cấu hình: các lần chạy không nhắm mục tiêu dùng tập shard `vitest.full-*.config.ts` và có thể mở rộng shard nhiều dự án thành cấu hình theo từng dự án để lập lịch song song +- Tệp: inventory core/unit trong `src/**/*.test.ts`, `packages/**/*.test.ts`, và `test/**/*.test.ts`; kiểm thử unit UI chạy trong shard `unit-ui` chuyên dụng - Phạm vi: - - Kiểm thử unit thuần túy - - Kiểm thử tích hợp trong tiến trình (xác thực gateway, định tuyến, tooling, phân tích cú pháp, cấu hình) - - Hồi quy tất định cho các lỗi đã biết + - Kiểm thử unit thuần + - Kiểm thử tích hợp trong tiến trình (xác thực Gateway, định tuyến, tooling, phân tích cú pháp, cấu hình) + - Hồi quy xác định cho các lỗi đã biết - Kỳ vọng: - Chạy trong CI - - Không yêu cầu khóa thật + - Không cần khóa thật - Nên nhanh và ổn định - - Các kiểm thử resolver và loader bề mặt công khai phải chứng minh hành vi fallback rộng của `api.js` và - `runtime-api.js` bằng các fixture Plugin nhỏ được tạo ra, không phải - API nguồn Plugin được đóng gói kèm thật. Việc tải API Plugin thật thuộc về - các bộ contract/tích hợp do Plugin sở hữu. + - Kiểm thử resolver và loader bề mặt công khai phải chứng minh hành vi fallback rộng của `api.js` và + `runtime-api.js` bằng các fixture Plugin nhỏ được tạo, không phải + API nguồn Plugin đi kèm thật. Tải API Plugin thật thuộc về + các bộ hợp đồng/tích hợp do Plugin sở hữu. - + - - `pnpm test` không nhắm mục tiêu chạy mười hai cấu hình phân mảnh nhỏ hơn (`core-unit-fast`, `core-unit-src`, `core-unit-security`, `core-unit-ui`, `core-unit-support`, `core-support-boundary`, `core-contracts`, `core-bundled`, `core-runtime`, `agentic`, `auto-reply`, `extensions`) thay vì một tiến trình dự án gốc native khổng lồ. Điều này giảm RSS đỉnh trên các máy đang tải nặng và tránh việc auto-reply/extension làm đói tài nguyên của các bộ kiểm thử không liên quan. + - `pnpm test` không nhắm mục tiêu chạy mười hai cấu hình phân mảnh nhỏ hơn (`core-unit-fast`, `core-unit-src`, `core-unit-security`, `core-unit-ui`, `core-unit-support`, `core-support-boundary`, `core-contracts`, `core-bundled`, `core-runtime`, `agentic`, `auto-reply`, `extensions`) thay vì một tiến trình dự án gốc native khổng lồ. Điều này giảm RSS đỉnh trên các máy đang tải nặng và tránh để công việc auto-reply/extension làm nghẽn các bộ kiểm thử không liên quan. - `pnpm test --watch` vẫn dùng đồ thị dự án gốc native `vitest.config.ts`, vì vòng lặp watch nhiều phân mảnh không thực tế. - - `pnpm test`, `pnpm test:watch`, và `pnpm test:perf:imports` định tuyến các mục tiêu tệp/thư mục rõ ràng qua các lane theo phạm vi trước, nên `pnpm test extensions/discord/src/monitor/message-handler.preflight.test.ts` tránh phải trả chi phí khởi động đầy đủ của dự án gốc. - - `pnpm test:changed` mặc định mở rộng các đường dẫn git đã thay đổi thành các lane theo phạm vi chi phí thấp: chỉnh sửa trực tiếp tệp kiểm thử, các tệp `*.test.ts` cùng cấp, ánh xạ mã nguồn rõ ràng, và các phụ thuộc đồ thị import cục bộ. Các chỉnh sửa config/setup/package không chạy rộng các kiểm thử trừ khi bạn dùng rõ ràng `OPENCLAW_TEST_CHANGED_BROAD=1 pnpm test:changed`. - - `pnpm check:changed` là cổng kiểm tra cục bộ thông minh thông thường cho công việc phạm vi hẹp. Nó phân loại diff thành core, kiểm thử core, extensions, kiểm thử extension, apps, docs, siêu dữ liệu phát hành, công cụ Docker live, và tooling, rồi chạy các lệnh typecheck, lint, và guard tương ứng. Nó không chạy kiểm thử Vitest; hãy gọi `pnpm test:changed` hoặc `pnpm test ` rõ ràng để có bằng chứng kiểm thử. Các lần tăng phiên bản chỉ gồm siêu dữ liệu phát hành chạy kiểm tra phiên bản/config/phụ thuộc gốc có mục tiêu, với một guard từ chối thay đổi package bên ngoài trường phiên bản cấp cao nhất. - - Các chỉnh sửa harness Docker ACP live chạy kiểm tra tập trung: cú pháp shell cho các script xác thực Docker live và một lần chạy thử không thực thi của bộ lập lịch Docker live. Thay đổi `package.json` chỉ được đưa vào khi diff giới hạn ở `scripts["test:docker:live-*"]`; các chỉnh sửa về dependency, export, version, và bề mặt package khác vẫn dùng các guard rộng hơn. - - Các kiểm thử đơn vị nhẹ import từ agents, commands, plugins, helper auto-reply, `plugin-sdk`, và các vùng tiện ích thuần tương tự định tuyến qua lane `unit-fast`, lane này bỏ qua `test/setup-openclaw-runtime.ts`; các tệp có trạng thái/nặng về runtime vẫn ở các lane hiện có. - - Một số tệp mã nguồn helper `plugin-sdk` và `commands` được chọn cũng ánh xạ các lần chạy changed-mode tới các kiểm thử cùng cấp rõ ràng trong những lane nhẹ đó, nên chỉnh sửa helper tránh chạy lại toàn bộ bộ kiểm thử nặng cho thư mục đó. - - `auto-reply` có các bucket chuyên dụng cho helper core cấp cao nhất, kiểm thử tích hợp `reply.*` cấp cao nhất, và cây con `src/auto-reply/reply/**`. CI tiếp tục tách cây con reply thành các phân mảnh agent-runner, dispatch, và commands/state-routing để một bucket nặng import không chiếm toàn bộ phần đuôi Node. - - CI PR/main thông thường cố ý bỏ qua lượt quét hàng loạt extension và phân mảnh `agentic-plugins` chỉ dành cho phát hành. Full Release Validation điều phối workflow con `Plugin Prerelease` riêng cho các bộ kiểm thử nặng về plugin/extension đó trên các ứng viên phát hành. + - `pnpm test`, `pnpm test:watch`, và `pnpm test:perf:imports` định tuyến các mục tiêu tệp/thư mục tường minh qua các lane có phạm vi trước, nên `pnpm test extensions/discord/src/monitor/message-handler.preflight.test.ts` tránh phải trả toàn bộ chi phí khởi động dự án gốc. + - `pnpm test:changed` mặc định mở rộng các đường dẫn git đã thay đổi thành các lane có phạm vi chi phí thấp: chỉnh sửa kiểm thử trực tiếp, các tệp `*.test.ts` ngang hàng, ánh xạ nguồn tường minh, và các phụ thuộc đồ thị import cục bộ. Chỉnh sửa config/setup/package không chạy kiểm thử diện rộng trừ khi bạn dùng tường minh `OPENCLAW_TEST_CHANGED_BROAD=1 pnpm test:changed`. + - `pnpm check:changed` là cổng kiểm tra cục bộ thông minh bình thường cho công việc hẹp. Nó phân loại diff thành core, kiểm thử core, extensions, kiểm thử extension, apps, tài liệu, metadata phát hành, công cụ Docker live, và tooling, rồi chạy các lệnh typecheck, lint, và guard tương ứng. Nó không chạy kiểm thử Vitest; gọi `pnpm test:changed` hoặc `pnpm test ` tường minh để có bằng chứng kiểm thử. Các bump phiên bản chỉ metadata phát hành chạy các kiểm tra phiên bản/config/phụ thuộc gốc có mục tiêu, với một guard từ chối thay đổi package ngoài trường phiên bản cấp cao nhất. + - Các chỉnh sửa harness Docker ACP live chạy các kiểm tra tập trung: cú pháp shell cho các script xác thực Docker live và một dry-run bộ lập lịch Docker live. Thay đổi `package.json` chỉ được bao gồm khi diff giới hạn ở `scripts["test:docker:live-*"]`; các chỉnh sửa dependency, export, version, và bề mặt package khác vẫn dùng các guard rộng hơn. + - Các kiểm thử đơn vị nhẹ về import từ agents, commands, plugins, helper auto-reply, `plugin-sdk`, và các vùng tiện ích thuần tương tự được định tuyến qua lane `unit-fast`, lane này bỏ qua `test/setup-openclaw-runtime.ts`; các tệp có trạng thái/nặng về runtime vẫn ở các lane hiện có. + - Một số tệp nguồn helper `plugin-sdk` và `commands` được chọn cũng ánh xạ các lần chạy chế độ changed đến các kiểm thử ngang hàng tường minh trong các lane nhẹ đó, nên chỉnh sửa helper tránh chạy lại toàn bộ bộ kiểm thử nặng cho thư mục đó. + - `auto-reply` có các bucket riêng cho helper core cấp cao nhất, kiểm thử tích hợp `reply.*` cấp cao nhất, và cây con `src/auto-reply/reply/**`. CI tiếp tục chia cây con reply thành các phân mảnh agent-runner, dispatch, và commands/state-routing để một bucket nặng về import không sở hữu toàn bộ phần đuôi Node. + - CI PR/main bình thường cố ý bỏ qua sweep hàng loạt extension và phân mảnh chỉ phát hành `agentic-plugins`. Full Release Validation dispatch workflow con `Plugin Prerelease` riêng cho các bộ kiểm thử nặng về Plugin/extension đó trên các release candidate. - + - - Khi bạn thay đổi đầu vào khám phá công cụ tin nhắn hoặc ngữ cảnh runtime compaction, hãy giữ cả hai cấp độ phạm vi kiểm thử. - - Thêm các hồi quy helper tập trung cho các ranh giới định tuyến và chuẩn hóa thuần. - - Giữ cho các bộ kiểm thử tích hợp runner nhúng hoạt động tốt: + - Khi bạn thay đổi input khám phá message-tool hoặc ngữ cảnh runtime + Compaction, hãy giữ cả hai mức độ phủ. + - Thêm các hồi quy helper tập trung cho các ranh giới định tuyến và chuẩn hóa + thuần. + - Giữ các bộ tích hợp embedded runner khỏe mạnh: `src/agents/pi-embedded-runner/compact.hooks.test.ts`, `src/agents/pi-embedded-runner/run.overflow-compaction.test.ts`, và `src/agents/pi-embedded-runner/run.overflow-compaction.loop.test.ts`. - - Các bộ này xác minh rằng id theo phạm vi và hành vi compaction vẫn đi qua các đường dẫn `run.ts` / `compact.ts` thật; kiểm thử chỉ ở helper không phải là phần thay thế đủ cho các đường dẫn tích hợp đó. + - Các bộ đó xác minh rằng id có phạm vi và hành vi Compaction vẫn chảy + qua các đường dẫn `run.ts` / `compact.ts` thật; kiểm thử chỉ helper + không phải là thay thế đủ cho các đường dẫn tích hợp đó. - + - - Config Vitest cơ sở mặc định dùng `threads`. - - Config Vitest dùng chung cố định `isolate: false` và dùng runner không cô lập trên các dự án gốc, e2e, và config live. - - Lane UI gốc giữ thiết lập `jsdom` và optimizer của nó, nhưng cũng chạy trên runner không cô lập dùng chung. - - Mỗi phân mảnh `pnpm test` kế thừa cùng mặc định `threads` + `isolate: false` từ config Vitest dùng chung. - - `scripts/run-vitest.mjs` mặc định thêm `--no-maglev` cho các tiến trình Node con của Vitest để giảm churn biên dịch V8 trong các lần chạy cục bộ lớn. Đặt `OPENCLAW_VITEST_ENABLE_MAGLEV=1` để so sánh với hành vi V8 mặc định. + - Config Vitest cơ sở mặc định là `threads`. + - Config Vitest dùng chung cố định `isolate: false` và dùng runner + không cô lập trên các dự án gốc, config e2e, và live. + - Lane UI gốc giữ setup `jsdom` và optimizer của nó, nhưng cũng chạy trên + runner không cô lập dùng chung. + - Mỗi phân mảnh `pnpm test` kế thừa cùng mặc định `threads` + `isolate: false` + từ config Vitest dùng chung. + - `scripts/run-vitest.mjs` mặc định thêm `--no-maglev` cho các tiến trình + Node con của Vitest để giảm churn biên dịch V8 trong các lần chạy cục bộ lớn. + Đặt `OPENCLAW_VITEST_ENABLE_MAGLEV=1` để so sánh với hành vi V8 gốc. - - `pnpm changed:lanes` hiển thị diff kích hoạt các lane kiến trúc nào. - - Hook pre-commit chỉ định dạng. Nó stage lại các tệp đã định dạng và không chạy lint, typecheck, hoặc kiểm thử. - - Chạy `pnpm check:changed` rõ ràng trước khi bàn giao hoặc push khi bạn cần cổng kiểm tra cục bộ thông minh. - - `pnpm test:changed` mặc định định tuyến qua các lane theo phạm vi chi phí thấp. Chỉ dùng `OPENCLAW_TEST_CHANGED_BROAD=1 pnpm test:changed` khi agent quyết định rằng chỉnh sửa harness, config, package, hoặc contract thật sự cần phạm vi kiểm thử Vitest rộng hơn. - - `pnpm test:max` và `pnpm test:changed:max` giữ cùng hành vi định tuyến, chỉ với giới hạn worker cao hơn. - - Tự động mở rộng worker cục bộ được cố ý giữ thận trọng và lùi lại khi load average của máy chủ đã cao, nên nhiều lần chạy Vitest đồng thời mặc định gây ít tác động hơn. - - Config Vitest cơ sở đánh dấu các tệp dự án/config là `forceRerunTriggers` để các lần chạy lại changed-mode vẫn đúng khi wiring kiểm thử thay đổi. - - Config giữ `OPENCLAW_VITEST_FS_MODULE_CACHE` bật trên các máy chủ được hỗ trợ; đặt `OPENCLAW_VITEST_FS_MODULE_CACHE_PATH=/abs/path` nếu bạn muốn một vị trí cache rõ ràng cho profiling trực tiếp. + - `pnpm changed:lanes` hiển thị các lane kiến trúc mà một diff kích hoạt. + - Hook pre-commit chỉ định dạng. Nó stage lại các tệp đã định dạng và + không chạy lint, typecheck, hoặc kiểm thử. + - Chạy `pnpm check:changed` tường minh trước khi bàn giao hoặc push khi bạn + cần cổng kiểm tra cục bộ thông minh. + - `pnpm test:changed` mặc định định tuyến qua các lane có phạm vi chi phí thấp. Chỉ dùng + `OPENCLAW_TEST_CHANGED_BROAD=1 pnpm test:changed` khi agent + quyết định một chỉnh sửa harness, config, package, hoặc contract thật sự cần + độ phủ Vitest rộng hơn. + - `pnpm test:max` và `pnpm test:changed:max` giữ cùng hành vi định tuyến, + chỉ với giới hạn worker cao hơn. + - Tự động co giãn worker cục bộ cố ý thận trọng và giảm tải + khi load average của host đã cao, nên nhiều lần chạy Vitest đồng thời + mặc định gây ít thiệt hại hơn. + - Config Vitest cơ sở đánh dấu các dự án/tệp config là + `forceRerunTriggers` để các lần chạy lại chế độ changed vẫn đúng khi + dây nối kiểm thử thay đổi. + - Config giữ `OPENCLAW_VITEST_FS_MODULE_CACHE` bật trên các host được hỗ trợ; + đặt `OPENCLAW_VITEST_FS_MODULE_CACHE_PATH=/abs/path` nếu bạn muốn + một vị trí cache tường minh cho profiling trực tiếp. - - `pnpm test:perf:imports` bật báo cáo thời lượng import của Vitest cùng với - đầu ra phân tích import. - - `pnpm test:perf:imports:changed` giới hạn cùng chế độ xem profiling đó vào + - `pnpm test:perf:imports` bật báo cáo thời lượng import của Vitest cùng + output phân rã import. + - `pnpm test:perf:imports:changed` đặt phạm vi cùng góc nhìn profiling cho các tệp đã thay đổi kể từ `origin/main`. - - Dữ liệu thời gian shard được ghi vào `.artifacts/vitest-shard-timings.json`. - Các lượt chạy toàn bộ config dùng đường dẫn config làm khóa; các shard CI - theo include-pattern nối thêm tên shard để các shard đã lọc có thể được theo dõi - riêng. - - Khi một bài kiểm thử nóng vẫn dành phần lớn thời gian cho các import lúc khởi động, - hãy đặt các dependency nặng phía sau một seam `*.runtime.ts` cục bộ hẹp và - mock trực tiếp seam đó thay vì deep-import các helper runtime chỉ + - Dữ liệu thời gian phân mảnh được ghi vào `.artifacts/vitest-shard-timings.json`. + Các lần chạy toàn config dùng đường dẫn config làm khóa; các phân mảnh CI + theo include-pattern nối thêm tên phân mảnh để có thể theo dõi riêng + các phân mảnh đã lọc. + - Khi một kiểm thử nóng vẫn dành phần lớn thời gian cho import khởi động, + giữ các phụ thuộc nặng phía sau một seam `*.runtime.ts` cục bộ hẹp và + mock seam đó trực tiếp thay vì deep-import các helper runtime chỉ để truyền chúng qua `vi.mock(...)`. - `pnpm test:perf:changed:bench -- --ref ` so sánh - `test:changed` đã định tuyến với đường dẫn root-project gốc cho diff đã commit đó - và in thời gian thực chạy cùng RSS tối đa trên macOS. - - `pnpm test:perf:changed:bench -- --worktree` benchmark cây hiện tại - đang bẩn bằng cách định tuyến danh sách tệp đã thay đổi qua + `test:changed` đã định tuyến với đường dẫn dự án gốc native cho diff + đã commit đó và in thời gian thực cùng RSS tối đa trên macOS. + - `pnpm test:perf:changed:bench -- --worktree` benchmark cây làm việc bẩn + hiện tại bằng cách định tuyến danh sách tệp đã thay đổi qua `scripts/test-projects.mjs` và config Vitest gốc. - - `pnpm test:perf:profile:main` ghi một hồ sơ CPU main-thread cho - chi phí khởi động và transform của Vitest/Vite. - - `pnpm test:perf:profile:runner` ghi hồ sơ CPU+heap của runner cho - bộ kiểm thử unit khi tính song song theo tệp bị tắt. + - `pnpm test:perf:profile:main` ghi một CPU profile luồng chính cho + overhead khởi động và transform của Vitest/Vite. + - `pnpm test:perf:profile:runner` ghi CPU+heap profile runner cho + bộ unit khi tắt song song theo tệp. -### Độ ổn định (gateway) +### Độ ổn định (Gateway) - Lệnh: `pnpm test:stability:gateway` -- Config: `vitest.gateway.config.ts`, bị ép dùng một worker +- Config: `vitest.gateway.config.ts`, bị buộc dùng một worker - Phạm vi: - - Khởi động một Gateway loopback thật với chẩn đoán được bật mặc định - - Đẩy churn thông điệp gateway, bộ nhớ và payload lớn tổng hợp qua đường dẫn sự kiện chẩn đoán + - Khởi động một Gateway loopback thật với chẩn đoán được bật theo mặc định + - Đẩy churn thông điệp gateway, bộ nhớ, và payload lớn tổng hợp qua đường dẫn sự kiện chẩn đoán - Truy vấn `diagnostics.stability` qua Gateway WS RPC - - Bao phủ các helper lưu bền bundle độ ổn định chẩn đoán - - Xác nhận recorder vẫn bị giới hạn, các mẫu RSS tổng hợp nằm dưới ngân sách áp lực, và độ sâu hàng đợi theo phiên rút về 0 + - Bao phủ các helper lưu giữ bundle ổn định chẩn đoán + - Khẳng định recorder vẫn bị giới hạn, các mẫu RSS tổng hợp nằm dưới ngân sách áp lực, và độ sâu hàng đợi theo phiên rút về lại zero - Kỳ vọng: - - An toàn cho CI và không cần khóa - - Lane hẹp để theo dõi hồi quy độ ổn định, không thay thế cho toàn bộ bộ kiểm thử Gateway + - An toàn cho CI và không cần key + - Lane hẹp cho theo dõi hồi quy độ ổn định, không phải thay thế cho toàn bộ bộ kiểm thử Gateway -### E2E (kiểm thử nhanh gateway) +### E2E (gateway smoke) - Lệnh: `pnpm test:e2e` - Config: `vitest.e2e.config.ts` -- Tệp: `src/**/*.e2e.test.ts`, `test/**/*.e2e.test.ts`, và các bài kiểm thử E2E của Plugin đóng gói trong `extensions/` +- Tệp: `src/**/*.e2e.test.ts`, `test/**/*.e2e.test.ts`, và kiểm thử E2E của Plugin đi kèm dưới `extensions/` - Mặc định runtime: - Dùng Vitest `threads` với `isolate: false`, khớp với phần còn lại của repo. - Dùng worker thích ứng (CI: tối đa 2, cục bộ: mặc định 1). - - Chạy ở chế độ im lặng theo mặc định để giảm chi phí I/O console. -- Ghi đè hữu ích: - - `OPENCLAW_E2E_WORKERS=` để ép số lượng worker (giới hạn ở 16). - - `OPENCLAW_E2E_VERBOSE=1` để bật lại đầu ra console chi tiết. + - Mặc định chạy ở chế độ silent để giảm overhead I/O console. +- Override hữu ích: + - `OPENCLAW_E2E_WORKERS=` để buộc số worker (giới hạn ở 16). + - `OPENCLAW_E2E_VERBOSE=1` để bật lại output console chi tiết. - Phạm vi: - - Hành vi gateway end-to-end nhiều instance - - Các bề mặt WebSocket/HTTP, ghép cặp Node và mạng nặng hơn + - Hành vi Gateway end-to-end nhiều instance + - Bề mặt WebSocket/HTTP, ghép cặp node, và networking nặng hơn - Kỳ vọng: - Chạy trong CI (khi được bật trong pipeline) - - Không yêu cầu khóa thật - - Nhiều phần chuyển động hơn kiểm thử unit (có thể chậm hơn) + - Không cần key thật + - Nhiều thành phần chuyển động hơn kiểm thử đơn vị (có thể chậm hơn) -### E2E: kiểm thử nhanh backend OpenShell +### E2E: OpenShell backend smoke - Lệnh: `pnpm test:e2e:openshell` - Tệp: `extensions/openshell/src/backend.e2e.test.ts` - Phạm vi: - - Khởi động một gateway OpenShell biệt lập trên host qua Docker + - Khởi động một Gateway OpenShell cô lập trên host qua Docker - Tạo sandbox từ một Dockerfile cục bộ tạm thời - - Chạy backend OpenShell của OpenClaw qua `sandbox ssh-config` thật + SSH exec - - Xác minh hành vi hệ thống tệp remote-canonical qua cầu nối fs của sandbox + - Kiểm tra backend OpenShell của OpenClaw qua `sandbox ssh-config` thật + SSH exec + - Xác minh hành vi hệ thống tệp chuẩn từ xa qua cầu nối sandbox fs - Kỳ vọng: - - Chỉ chạy khi chọn tham gia; không thuộc lượt chạy `pnpm test:e2e` mặc định - - Cần CLI `openshell` cục bộ cùng một Docker daemon hoạt động - - Dùng `HOME` / `XDG_CONFIG_HOME` biệt lập, rồi hủy gateway kiểm thử và sandbox -- Ghi đè hữu ích: - - `OPENCLAW_E2E_OPENSHELL=1` để bật bài kiểm thử khi chạy thủ công bộ e2e rộng hơn + - Chỉ opt-in; không thuộc lần chạy `pnpm test:e2e` mặc định + - Cần CLI `openshell` cục bộ cùng Docker daemon hoạt động + - Dùng `HOME` / `XDG_CONFIG_HOME` cô lập, rồi hủy Gateway và sandbox kiểm thử +- Override hữu ích: + - `OPENCLAW_E2E_OPENSHELL=1` để bật kiểm thử khi chạy thủ công bộ e2e rộng hơn - `OPENCLAW_E2E_OPENSHELL_COMMAND=/path/to/openshell` để trỏ tới binary CLI hoặc script wrapper không mặc định -### Live (nhà cung cấp thật + mô hình thật) +### Live (provider thật + model thật) - Lệnh: `pnpm test:live` - Config: `vitest.live.config.ts` -- Tệp: `src/**/*.live.test.ts`, `test/**/*.live.test.ts`, và các bài kiểm thử live của Plugin đóng gói trong `extensions/` +- Tệp: `src/**/*.live.test.ts`, `test/**/*.live.test.ts`, và kiểm thử live của Plugin đi kèm dưới `extensions/` - Mặc định: **được bật** bởi `pnpm test:live` (đặt `OPENCLAW_LIVE_TEST=1`) - Phạm vi: - - “Nhà cung cấp/mô hình này có thực sự hoạt động _hôm nay_ với thông tin xác thực thật không?” - - Bắt các thay đổi định dạng của nhà cung cấp, khác biệt khi gọi tool, vấn đề xác thực và hành vi giới hạn tốc độ + - “Provider/model này có thật sự hoạt động _hôm nay_ với thông tin xác thực thật không?” + - Bắt các thay đổi định dạng provider, điểm khác biệt tool-calling, vấn đề xác thực, và hành vi rate limit - Kỳ vọng: - - Theo thiết kế không ổn định cho CI (mạng thật, chính sách nhà cung cấp thật, quota, sự cố dịch vụ) - - Tốn tiền / dùng giới hạn tốc độ - - Ưu tiên chạy các tập con đã thu hẹp thay vì “mọi thứ” -- Các lượt chạy live source `~/.profile` để lấy các khóa API còn thiếu. -- Theo mặc định, các lượt chạy live vẫn cô lập `HOME` và sao chép tài liệu config/auth vào một home kiểm thử tạm thời để fixture unit không thể sửa đổi `~/.openclaw` thật của bạn. + - Không ổn định cho CI theo thiết kế (mạng thật, chính sách provider thật, quota, sự cố) + - Tốn tiền / dùng rate limit + - Ưu tiên chạy các tập con thu hẹp thay vì “mọi thứ” +- Các lần chạy live source `~/.profile` để lấy các API key còn thiếu. +- Theo mặc định, các lần chạy live vẫn cô lập `HOME` và sao chép material config/auth vào home kiểm thử tạm thời để fixture unit không thể sửa đổi `~/.openclaw` thật của bạn. - Chỉ đặt `OPENCLAW_LIVE_USE_REAL_HOME=1` khi bạn cố ý cần kiểm thử live dùng thư mục home thật của mình. -- `pnpm test:live` hiện mặc định ở chế độ yên tĩnh hơn: nó giữ đầu ra tiến trình `[live] ...`, nhưng ẩn thông báo `~/.profile` bổ sung và tắt log khởi động gateway/tiếng ồn Bonjour. Đặt `OPENCLAW_LIVE_TEST_QUIET=0` nếu bạn muốn lấy lại toàn bộ log khởi động. -- Xoay vòng khóa API (theo từng nhà cung cấp): đặt `*_API_KEYS` với định dạng dấu phẩy/dấu chấm phẩy hoặc `*_API_KEY_1`, `*_API_KEY_2` (ví dụ `OPENAI_API_KEYS`, `ANTHROPIC_API_KEYS`, `GEMINI_API_KEYS`) hoặc ghi đè theo từng live qua `OPENCLAW_LIVE_*_KEY`; kiểm thử sẽ thử lại khi gặp phản hồi giới hạn tốc độ. -- Đầu ra tiến trình/Heartbeat: - - Các bộ live hiện phát dòng tiến trình tới stderr để các lệnh gọi nhà cung cấp kéo dài vẫn thấy đang hoạt động ngay cả khi capture console của Vitest đang yên tĩnh. - - `vitest.live.config.ts` tắt chặn console của Vitest để các dòng tiến trình nhà cung cấp/gateway stream ngay trong các lượt chạy live. - - Tinh chỉnh Heartbeat mô hình trực tiếp bằng `OPENCLAW_LIVE_HEARTBEAT_MS`. +- `pnpm test:live` hiện mặc định dùng chế độ yên tĩnh hơn: nó giữ output tiến độ `[live] ...`, nhưng ẩn thông báo `~/.profile` bổ sung và tắt tiếng log bootstrap Gateway/Bonjour chatter. Đặt `OPENCLAW_LIVE_TEST_QUIET=0` nếu bạn muốn có lại toàn bộ log khởi động. +- Xoay vòng API key (theo provider): đặt `*_API_KEYS` với định dạng dấu phẩy/chấm phẩy hoặc `*_API_KEY_1`, `*_API_KEY_2` (ví dụ `OPENAI_API_KEYS`, `ANTHROPIC_API_KEYS`, `GEMINI_API_KEYS`) hoặc override theo live qua `OPENCLAW_LIVE_*_KEY`; kiểm thử retry khi có phản hồi rate limit. +- Output tiến độ/Heartbeat: + - Các bộ live giờ phát dòng tiến độ ra stderr để các lệnh gọi provider dài hiển thị là vẫn hoạt động ngay cả khi Vitest console capture yên tĩnh. + - `vitest.live.config.ts` tắt chặn console của Vitest để các dòng tiến độ provider/gateway stream ngay trong các lần chạy live. + - Tinh chỉnh Heartbeat model trực tiếp bằng `OPENCLAW_LIVE_HEARTBEAT_MS`. - Tinh chỉnh Heartbeat gateway/probe bằng `OPENCLAW_LIVE_GATEWAY_HEARTBEAT_MS`. -## Tôi nên chạy bộ kiểm thử nào? +## Tôi nên chạy bộ nào? Dùng bảng quyết định này: - Chỉnh sửa logic/kiểm thử: chạy `pnpm test` (và `pnpm test:coverage` nếu bạn đã thay đổi nhiều) -- Chạm tới mạng Gateway / giao thức WS / ghép đôi: thêm `pnpm test:e2e` -- Gỡ lỗi “bot của tôi bị ngừng hoạt động” / lỗi theo nhà cung cấp / gọi công cụ: chạy `pnpm test:live` đã thu hẹp phạm vi +- Đụng đến mạng Gateway / giao thức WS / ghép cặp: thêm `pnpm test:e2e` +- Gỡ lỗi “bot của tôi bị sập” / lỗi theo từng nhà cung cấp / gọi công cụ: chạy `pnpm test:live` đã thu hẹp phạm vi ## Kiểm thử trực tiếp (có truy cập mạng) -Đối với ma trận mô hình trực tiếp, kiểm thử khói backend CLI, kiểm thử khói ACP, bộ kiểm thử app-server -Codex, và tất cả kiểm thử trực tiếp cho nhà cung cấp phương tiện (Deepgram, BytePlus, ComfyUI, hình ảnh, -nhạc, video, bộ kiểm thử phương tiện) — cùng với xử lý thông tin xác thực cho các lần chạy trực tiếp — xem -[Kiểm thử — bộ kiểm thử trực tiếp](/vi/help/testing-live). +Với ma trận mô hình trực tiếp, các bài smoke backend CLI, smoke ACP, harness máy chủ ứng dụng Codex, và tất cả kiểm thử trực tiếp của nhà cung cấp media (Deepgram, BytePlus, ComfyUI, hình ảnh, nhạc, video, media harness) — cùng với xử lý thông tin xác thực cho các lần chạy trực tiếp — xem [Kiểm thử — bộ kiểm thử trực tiếp](/vi/help/testing-live). ## Trình chạy Docker (kiểm tra tùy chọn "hoạt động trên Linux") Các trình chạy Docker này được chia thành hai nhóm: -- Trình chạy mô hình trực tiếp: `test:docker:live-models` và `test:docker:live-gateway` chỉ chạy tệp trực tiếp theo khóa hồ sơ tương ứng bên trong ảnh Docker của repo (`src/agents/models.profiles.live.test.ts` và `src/gateway/gateway-models.profiles.live.test.ts`), gắn thư mục cấu hình cục bộ và workspace của bạn (và nạp `~/.profile` nếu được gắn). Các điểm vào cục bộ tương ứng là `test:live:models-profiles` và `test:live:gateway-profiles`. -- Trình chạy trực tiếp Docker mặc định dùng giới hạn kiểm thử khói nhỏ hơn để một lượt quét Docker đầy đủ vẫn thực tế: +- Trình chạy mô hình trực tiếp: `test:docker:live-models` và `test:docker:live-gateway` chỉ chạy tệp trực tiếp profile-key tương ứng bên trong ảnh Docker của repo (`src/agents/models.profiles.live.test.ts` và `src/gateway/gateway-models.profiles.live.test.ts`), mount thư mục cấu hình cục bộ và workspace của bạn (và source `~/.profile` nếu được mount). Các điểm vào cục bộ tương ứng là `test:live:models-profiles` và `test:live:gateway-profiles`. +- Các trình chạy trực tiếp Docker mặc định dùng giới hạn smoke nhỏ hơn để một lượt quét Docker đầy đủ vẫn thực tế: `test:docker:live-models` mặc định là `OPENCLAW_LIVE_MAX_MODELS=12`, và `test:docker:live-gateway` mặc định là `OPENCLAW_LIVE_GATEWAY_SMOKE=1`, `OPENCLAW_LIVE_GATEWAY_MAX_MODELS=8`, `OPENCLAW_LIVE_GATEWAY_STEP_TIMEOUT_MS=45000`, và `OPENCLAW_LIVE_GATEWAY_MODEL_TIMEOUT_MS=90000`. Ghi đè các biến môi trường đó khi bạn - rõ ràng muốn lần quét toàn diện lớn hơn. -- `test:docker:all` xây dựng ảnh Docker trực tiếp một lần thông qua `test:docker:live-build`, đóng gói OpenClaw một lần dưới dạng tarball npm qua `scripts/package-openclaw-for-docker.mjs`, rồi xây dựng/tái sử dụng hai ảnh `scripts/e2e/Dockerfile`. Ảnh cơ bản chỉ là trình chạy Node/Git cho các lane cài đặt/cập nhật/phụ thuộc Plugin; các lane đó gắn tarball đã dựng sẵn. Ảnh chức năng cài đặt cùng tarball đó vào `/app` cho các lane chức năng ứng dụng đã dựng. Định nghĩa lane Docker nằm trong `scripts/lib/docker-e2e-scenarios.mjs`; logic lập kế hoạch nằm trong `scripts/lib/docker-e2e-plan.mjs`; `scripts/test-docker-all.mjs` thực thi kế hoạch đã chọn. Bộ tổng hợp dùng bộ lập lịch cục bộ có trọng số: `OPENCLAW_DOCKER_ALL_PARALLELISM` kiểm soát các slot tiến trình, còn giới hạn tài nguyên ngăn các lane trực tiếp nặng, cài đặt npm và nhiều dịch vụ cùng khởi động một lúc. Nếu một lane đơn lẻ nặng hơn các giới hạn đang hoạt động, bộ lập lịch vẫn có thể khởi động lane đó khi pool trống và sau đó giữ nó chạy một mình cho đến khi có lại dung lượng. Mặc định là 10 slot, `OPENCLAW_DOCKER_ALL_LIVE_LIMIT=9`, `OPENCLAW_DOCKER_ALL_NPM_LIMIT=10`, và `OPENCLAW_DOCKER_ALL_SERVICE_LIMIT=7`; chỉ tinh chỉnh `OPENCLAW_DOCKER_ALL_WEIGHT_LIMIT` hoặc `OPENCLAW_DOCKER_ALL_DOCKER_LIMIT` khi máy chủ Docker có thêm dư địa. Trình chạy mặc định thực hiện kiểm tra trước Docker, xóa các container OpenClaw E2E cũ, in trạng thái mỗi 30 giây, lưu thời gian lane thành công trong `.artifacts/docker-tests/lane-timings.json`, và dùng các thời gian đó để khởi động các lane dài hơn trước trong các lần chạy sau. Dùng `OPENCLAW_DOCKER_ALL_DRY_RUN=1` để in manifest lane có trọng số mà không xây dựng hoặc chạy Docker, hoặc `node scripts/test-docker-all.mjs --plan-json` để in kế hoạch CI cho các lane đã chọn, nhu cầu gói/ảnh, và thông tin xác thực. -- `Package Acceptance` là cổng gói gốc GitHub cho câu hỏi "tarball có thể cài đặt này có hoạt động như một sản phẩm không?" Nó phân giải một gói ứng viên từ `source=npm`, `source=ref`, `source=url`, hoặc `source=artifact`, tải lên dưới tên `package-under-test`, rồi chạy các lane Docker E2E tái sử dụng với đúng tarball đó thay vì đóng gói lại ref đã chọn. `workflow_ref` chọn workflow/tập lệnh bộ kiểm thử đáng tin cậy, còn `package_ref` chọn commit/nhánh/thẻ nguồn để đóng gói khi `source=ref`; điều này cho phép logic chấp nhận hiện tại xác thực các commit đáng tin cậy cũ hơn. Hồ sơ được sắp theo độ bao phủ: `smoke` là cài đặt/kênh/tác nhân nhanh cộng với Gateway/cấu hình, `package` là hợp đồng gói/cập nhật/Plugin và là thay thế gốc mặc định cho phần lớn phạm vi gói/cập nhật của Parallels, `product` thêm các kênh MCP, dọn dẹp cron/tác nhân con, tìm kiếm web OpenAI, và OpenWebUI, còn `full` chạy các phần Docker theo đường phát hành với OpenWebUI. Xác thực phát hành chạy delta gói tùy chỉnh (`bundled-channel-deps-compat plugins-offline`) cộng với QA gói Telegram vì các phần Docker theo đường phát hành đã bao phủ các lane gói/cập nhật/Plugin trùng lặp. Các lệnh chạy lại Docker GitHub nhắm mục tiêu được tạo từ artifact sẽ bao gồm artifact gói trước đó và đầu vào ảnh đã chuẩn bị khi có, để các lane lỗi có thể tránh xây dựng lại gói và ảnh. -- Kiểm tra build và phát hành chạy `scripts/check-cli-bootstrap-imports.mjs` sau tsdown. Bộ bảo vệ duyệt đồ thị dựng tĩnh từ `dist/entry.js` và `dist/cli/run-main.js` và báo lỗi nếu khởi động trước điều phối nhập các phụ thuộc gói như Commander, giao diện nhắc, undici, hoặc ghi log trước khi điều phối lệnh; nó cũng giữ phần chạy Gateway được đóng gói trong ngân sách và từ chối import tĩnh các đường dẫn Gateway lạnh đã biết. Kiểm thử khói CLI đã đóng gói cũng bao phủ trợ giúp gốc, trợ giúp onboard, trợ giúp doctor, trạng thái, lược đồ cấu hình, và lệnh liệt kê mô hình. -- Tương thích kế thừa Package Acceptance được giới hạn ở `2026.4.25` (bao gồm `2026.4.25-beta.*`). Đến hết mốc đó, bộ kiểm thử chỉ dung thứ các khoảng trống metadata của gói đã phát hành: mục kiểm kê QA riêng tư bị bỏ qua, thiếu `gateway install --wrapper`, thiếu tệp patch trong fixture git sinh từ tarball, thiếu `update.channel` được lưu bền, vị trí bản ghi cài đặt Plugin kế thừa, thiếu lưu bền bản ghi cài đặt marketplace, và di trú metadata cấu hình trong `plugins update`. Với các gói sau `2026.4.25`, các đường dẫn đó là lỗi nghiêm ngặt. -- Trình chạy kiểm thử khói container: `test:docker:openwebui`, `test:docker:onboard`, `test:docker:npm-onboard-channel-agent`, `test:docker:update-channel-switch`, `test:docker:session-runtime-context`, `test:docker:agents-delete-shared-workspace`, `test:docker:gateway-network`, `test:docker:browser-cdp-snapshot`, `test:docker:mcp-channels`, `test:docker:pi-bundle-mcp-tools`, `test:docker:cron-mcp-cleanup`, `test:docker:plugins`, `test:docker:plugin-update`, và `test:docker:config-reload` khởi động một hoặc nhiều container thật và xác minh các đường tích hợp cấp cao hơn. + thật sự muốn lượt quét toàn diện lớn hơn. +- `test:docker:all` xây dựng ảnh Docker trực tiếp một lần qua `test:docker:live-build`, đóng gói OpenClaw một lần thành tarball npm thông qua `scripts/package-openclaw-for-docker.mjs`, rồi xây dựng/tái sử dụng hai ảnh `scripts/e2e/Dockerfile`. Ảnh cơ bản chỉ là trình chạy Node/Git cho các lane cài đặt/cập nhật/phụ thuộc Plugin; các lane đó mount tarball đã dựng sẵn. Ảnh chức năng cài cùng tarball đó vào `/app` cho các lane chức năng ứng dụng đã dựng. Định nghĩa lane Docker nằm trong `scripts/lib/docker-e2e-scenarios.mjs`; logic lập kế hoạch nằm trong `scripts/lib/docker-e2e-plan.mjs`; `scripts/test-docker-all.mjs` thực thi kế hoạch đã chọn. Bộ tổng hợp dùng bộ lập lịch cục bộ có trọng số: `OPENCLAW_DOCKER_ALL_PARALLELISM` kiểm soát số slot tiến trình, còn các giới hạn tài nguyên giữ cho các lane nặng về trực tiếp, cài npm và đa dịch vụ không khởi động cùng lúc. Nếu một lane đơn lẻ nặng hơn các giới hạn đang hoạt động, bộ lập lịch vẫn có thể khởi động lane đó khi pool trống rồi giữ nó chạy một mình cho đến khi lại có dung lượng. Mặc định là 10 slot, `OPENCLAW_DOCKER_ALL_LIVE_LIMIT=9`, `OPENCLAW_DOCKER_ALL_NPM_LIMIT=10`, và `OPENCLAW_DOCKER_ALL_SERVICE_LIMIT=7`; chỉ tinh chỉnh `OPENCLAW_DOCKER_ALL_WEIGHT_LIMIT` hoặc `OPENCLAW_DOCKER_ALL_DOCKER_LIMIT` khi host Docker còn nhiều dư địa hơn. Trình chạy thực hiện preflight Docker theo mặc định, xóa các container E2E OpenClaw cũ, in trạng thái mỗi 30 giây, lưu thời lượng các lane thành công trong `.artifacts/docker-tests/lane-timings.json`, và dùng các thời lượng đó để khởi động các lane dài hơn trước trong các lần chạy sau. Dùng `OPENCLAW_DOCKER_ALL_DRY_RUN=1` để in manifest lane có trọng số mà không xây dựng hoặc chạy Docker, hoặc `node scripts/test-docker-all.mjs --plan-json` để in kế hoạch CI cho các lane đã chọn, nhu cầu package/ảnh và thông tin xác thực. +- `Package Acceptance` là cổng package gốc GitHub cho câu hỏi "tarball có thể cài đặt này có hoạt động như một sản phẩm không?" Nó phân giải một package ứng viên từ `source=npm`, `source=ref`, `source=url`, hoặc `source=artifact`, tải nó lên dưới dạng `package-under-test`, rồi chạy các lane Docker E2E tái sử dụng với đúng tarball đó thay vì đóng gói lại ref đã chọn. `workflow_ref` chọn các script workflow/harness đáng tin cậy, còn `package_ref` chọn commit/branch/tag nguồn để đóng gói khi `source=ref`; điều này cho phép logic acceptance hiện tại xác thực các commit đáng tin cậy cũ hơn. Các profile được sắp xếp theo độ bao phủ: `smoke` là cài đặt/kênh/agent nhanh cộng với Gateway/cấu hình, `package` là hợp đồng package/cập nhật/Plugin cộng với fixture upgrade-survivor không cần khóa và thay thế native mặc định cho hầu hết phạm vi package/cập nhật Parallels, `product` thêm các kênh MCP, dọn dẹp cron/subagent, tìm kiếm web OpenAI và OpenWebUI, còn `full` chạy các khối Docker theo đường dẫn phát hành với OpenWebUI. Xác thực phát hành chạy một delta package tùy chỉnh (`bundled-channel-deps-compat plugins-offline`) cộng với QA package Telegram vì các khối Docker theo đường dẫn phát hành đã bao phủ các lane package/cập nhật/Plugin chồng lấp. Các lệnh chạy lại Docker GitHub có mục tiêu được tạo từ artifact bao gồm artifact package trước đó và đầu vào ảnh đã chuẩn bị khi có, để các lane lỗi có thể tránh xây dựng lại package và ảnh. +- Kiểm tra build và phát hành chạy `scripts/check-cli-bootstrap-imports.mjs` sau tsdown. Guard duyệt đồ thị build tĩnh từ `dist/entry.js` và `dist/cli/run-main.js` rồi thất bại nếu quá trình khởi động trước dispatch import các phụ thuộc package như Commander, giao diện nhắc lệnh, undici hoặc logging trước khi dispatch lệnh; nó cũng giữ chunk chạy Gateway đã bundle trong ngân sách và từ chối import tĩnh các đường dẫn Gateway nguội đã biết. Smoke CLI đã đóng gói cũng bao phủ trợ giúp gốc, trợ giúp onboard, trợ giúp doctor, trạng thái, schema cấu hình và một lệnh liệt kê mô hình. +- Tương thích cũ của Package Acceptance được giới hạn ở `2026.4.25` (bao gồm `2026.4.25-beta.*`). Tới ngưỡng đó, harness chỉ dung thứ các thiếu sót metadata package đã phát hành: các mục kho QA riêng tư bị lược bỏ, thiếu `gateway install --wrapper`, thiếu tệp patch trong fixture git sinh từ tarball, thiếu `update.channel` đã lưu, vị trí bản ghi cài đặt Plugin cũ, thiếu lưu bản ghi cài đặt marketplace, và di trú metadata cấu hình trong `plugins update`. Với các package sau `2026.4.25`, các đường dẫn đó là lỗi nghiêm ngặt. +- Trình chạy smoke container: `test:docker:openwebui`, `test:docker:onboard`, `test:docker:npm-onboard-channel-agent`, `test:docker:update-channel-switch`, `test:docker:upgrade-survivor`, `test:docker:session-runtime-context`, `test:docker:agents-delete-shared-workspace`, `test:docker:gateway-network`, `test:docker:browser-cdp-snapshot`, `test:docker:mcp-channels`, `test:docker:pi-bundle-mcp-tools`, `test:docker:cron-mcp-cleanup`, `test:docker:plugins`, `test:docker:plugin-update`, và `test:docker:config-reload` khởi động một hoặc nhiều container thật và xác minh các đường dẫn tích hợp cấp cao hơn. -Các trình chạy Docker mô hình trực tiếp cũng chỉ bind-mount các home xác thực CLI cần thiết (hoặc tất cả loại được hỗ trợ khi lần chạy không bị thu hẹp), rồi sao chép chúng vào home của container trước khi chạy để OAuth CLI bên ngoài có thể làm mới token mà không làm thay đổi kho xác thực của máy chủ: +Các trình chạy Docker mô hình trực tiếp cũng chỉ bind-mount các home xác thực CLI cần thiết (hoặc tất cả home được hỗ trợ khi lần chạy không bị thu hẹp), rồi sao chép chúng vào home của container trước khi chạy để OAuth của CLI bên ngoài có thể làm mới token mà không làm thay đổi kho xác thực của host: -- Mô hình trực tiếp: `pnpm test:docker:live-models` (script: `scripts/test-live-models-docker.sh`) -- Kiểm thử khói bind ACP: `pnpm test:docker:live-acp-bind` (script: `scripts/test-live-acp-bind-docker.sh`; mặc định bao gồm Claude, Codex và Gemini, với phạm vi Droid/OpenCode nghiêm ngặt qua `pnpm test:docker:live-acp-bind:droid` và `pnpm test:docker:live-acp-bind:opencode`) -- Kiểm thử khói backend CLI: `pnpm test:docker:live-cli-backend` (script: `scripts/test-live-cli-backend-docker.sh`) -- Kiểm thử khói harness app-server Codex: `pnpm test:docker:live-codex-harness` (script: `scripts/test-live-codex-harness-docker.sh`) -- Gateway + agent dev: `pnpm test:docker:live-gateway` (script: `scripts/test-live-gateway-models-docker.sh`) -- Kiểm thử khói khả năng quan sát: `pnpm qa:otel:smoke` là một lane kiểm tra nguồn QA riêng tư. Nó cố ý không thuộc các lane phát hành Docker của gói vì npm tarball bỏ qua QA Lab. -- Kiểm thử khói trực tiếp Open WebUI: `pnpm test:docker:openwebui` (script: `scripts/e2e/openwebui-docker.sh`) -- Trình hướng dẫn onboarding (TTY, scaffolding đầy đủ): `pnpm test:docker:onboard` (script: `scripts/e2e/onboard-docker.sh`) -- Kiểm thử khói onboarding/channel/agent bằng npm tarball: `pnpm test:docker:npm-onboard-channel-agent` cài đặt OpenClaw tarball đã đóng gói toàn cục trong Docker, cấu hình OpenAI qua onboarding tham chiếu env cộng với Telegram theo mặc định, xác minh doctor đã sửa các phụ thuộc runtime của Plugin đã kích hoạt, và chạy một lượt agent OpenAI được mock. Tái sử dụng tarball đã build sẵn bằng `OPENCLAW_CURRENT_PACKAGE_TGZ=/path/to/openclaw-*.tgz`, bỏ qua rebuild trên host bằng `OPENCLAW_NPM_ONBOARD_HOST_BUILD=0`, hoặc đổi channel bằng `OPENCLAW_NPM_ONBOARD_CHANNEL=discord`. -- Kiểm thử khói chuyển channel cập nhật: `pnpm test:docker:update-channel-switch` cài đặt OpenClaw tarball đã đóng gói toàn cục trong Docker, chuyển từ gói `stable` sang git `dev`, xác minh channel đã lưu và Plugin hoạt động sau cập nhật, rồi chuyển lại về gói `stable` và kiểm tra trạng thái cập nhật. -- Kiểm thử khói ngữ cảnh runtime phiên: `pnpm test:docker:session-runtime-context` xác minh việc lưu transcript ngữ cảnh runtime ẩn cùng với sửa chữa doctor cho các nhánh ghi lại prompt bị trùng lặp chịu ảnh hưởng. -- Kiểm thử khói cài đặt toàn cục Bun: `bash scripts/e2e/bun-global-install-smoke.sh` đóng gói cây hiện tại, cài bằng `bun install -g` trong home cô lập, và xác minh `openclaw infer image providers --json` trả về các provider hình ảnh đi kèm thay vì bị treo. Tái sử dụng tarball đã build sẵn bằng `OPENCLAW_BUN_GLOBAL_SMOKE_PACKAGE_TGZ=/path/to/openclaw-*.tgz`, bỏ qua build trên host bằng `OPENCLAW_BUN_GLOBAL_SMOKE_HOST_BUILD=0`, hoặc sao chép `dist/` từ image Docker đã build bằng `OPENCLAW_BUN_GLOBAL_SMOKE_DIST_IMAGE=openclaw-dockerfile-smoke:local`. -- Kiểm thử khói Docker của trình cài đặt: `bash scripts/test-install-sh-docker.sh` dùng chung một cache npm cho các container root, update và direct-npm. Kiểm thử khói update mặc định dùng npm `latest` làm baseline ổn định trước khi nâng cấp lên tarball ứng viên. Ghi đè bằng `OPENCLAW_INSTALL_SMOKE_UPDATE_BASELINE=2026.4.22` cục bộ, hoặc bằng input `update_baseline_version` của workflow Install Smoke trên GitHub. Các kiểm tra trình cài đặt không phải root giữ cache npm cô lập để các mục cache do root sở hữu không che khuất hành vi cài đặt cục bộ của người dùng. Đặt `OPENCLAW_INSTALL_SMOKE_NPM_CACHE_DIR=/path/to/cache` để tái sử dụng cache root/update/direct-npm giữa các lần chạy lại cục bộ. -- CI Install Smoke bỏ qua bản cập nhật toàn cục direct-npm trùng lặp bằng `OPENCLAW_INSTALL_SMOKE_SKIP_NPM_GLOBAL=1`; chạy script cục bộ không có env đó khi cần phạm vi kiểm tra `npm install -g` trực tiếp. -- Kiểm thử khói CLI xóa workspace dùng chung của agents: `pnpm test:docker:agents-delete-shared-workspace` (script: `scripts/e2e/agents-delete-shared-workspace-docker.sh`) mặc định build image Dockerfile gốc, seed hai agent với một workspace trong home container cô lập, chạy `agents delete --json`, và xác minh JSON hợp lệ cùng hành vi giữ lại workspace. Tái sử dụng image install-smoke bằng `OPENCLAW_AGENTS_DELETE_SHARED_WORKSPACE_E2E_IMAGE=openclaw-dockerfile-smoke:local OPENCLAW_AGENTS_DELETE_SHARED_WORKSPACE_E2E_SKIP_BUILD=1`. -- Mạng Gateway (hai container, xác thực WS + health): `pnpm test:docker:gateway-network` (script: `scripts/e2e/gateway-network-docker.sh`) -- Kiểm thử khói snapshot CDP trình duyệt: `pnpm test:docker:browser-cdp-snapshot` (script: `scripts/e2e/browser-cdp-snapshot-docker.sh`) build image E2E nguồn cộng với một lớp Chromium, khởi động Chromium với CDP thô, chạy `browser doctor --deep`, và xác minh snapshot vai trò CDP bao phủ URL liên kết, phần tử có thể nhấp được thăng cấp từ con trỏ, tham chiếu iframe và metadata frame. -- Hồi quy reasoning tối thiểu của OpenAI Responses web_search: `pnpm test:docker:openai-web-search-minimal` (script: `scripts/e2e/openai-web-search-minimal-docker.sh`) chạy một máy chủ OpenAI được mock qua Gateway, xác minh `web_search` nâng `reasoning.effort` từ `minimal` lên `low`, sau đó ép schema provider từ chối và kiểm tra chi tiết thô xuất hiện trong log Gateway. -- Cầu nối channel MCP (Gateway đã seed + cầu nối stdio + kiểm thử khói raw notification-frame của Claude): `pnpm test:docker:mcp-channels` (script: `scripts/e2e/mcp-channels-docker.sh`) -- Công cụ MCP gói Pi (máy chủ MCP stdio thật + kiểm thử khói cho phép/từ chối profile Pi nhúng): `pnpm test:docker:pi-bundle-mcp-tools` (script: `scripts/e2e/pi-bundle-mcp-tools-docker.sh`) -- Dọn dẹp MCP Cron/subagent (Gateway thật + teardown tiến trình con MCP stdio sau các lần chạy cron cô lập và subagent một lần): `pnpm test:docker:cron-mcp-cleanup` (script: `scripts/e2e/cron-mcp-cleanup-docker.sh`) -- Plugin (kiểm thử khói cài đặt, cài/gỡ gói kitchen-sink của ClawHub, cập nhật marketplace và bật/kiểm tra gói Claude): `pnpm test:docker:plugins` (script: `scripts/e2e/plugins-docker.sh`) - Đặt `OPENCLAW_PLUGINS_E2E_CLAWHUB=0` để bỏ qua khối ClawHub, hoặc ghi đè cặp package/runtime kitchen-sink mặc định bằng `OPENCLAW_PLUGINS_E2E_CLAWHUB_SPEC` và `OPENCLAW_PLUGINS_E2E_CLAWHUB_ID`. Khi không có `OPENCLAW_CLAWHUB_URL`/`CLAWHUB_URL`, bài kiểm thử dùng máy chủ fixture ClawHub cục bộ khép kín. -- Kiểm thử khói cập nhật Plugin không thay đổi: `pnpm test:docker:plugin-update` (script: `scripts/e2e/plugin-update-unchanged-docker.sh`) -- Kiểm thử khói metadata tải lại cấu hình: `pnpm test:docker:config-reload` (script: `scripts/e2e/config-reload-source-docker.sh`) -- Phụ thuộc runtime của Plugin đi kèm: `pnpm test:docker:bundled-channel-deps` mặc định build một image runner Docker nhỏ, build và đóng gói OpenClaw một lần trên host, rồi mount tarball đó vào từng kịch bản cài đặt Linux. Tái sử dụng image bằng `OPENCLAW_SKIP_DOCKER_BUILD=1`, bỏ qua rebuild trên host sau một bản build cục bộ mới bằng `OPENCLAW_BUNDLED_CHANNEL_HOST_BUILD=0`, hoặc trỏ tới tarball hiện có bằng `OPENCLAW_CURRENT_PACKAGE_TGZ=/path/to/openclaw-*.tgz`. Tổ hợp Docker đầy đủ và các chunk bundled-channel theo đường phát hành pre-pack tarball này một lần, rồi chia nhỏ kiểm tra channel đi kèm thành các lane độc lập, bao gồm các lane cập nhật riêng cho Telegram, Discord, Slack, Feishu, memory-lancedb và ACPX. Các chunk phát hành tách kiểm thử khói channel, mục tiêu cập nhật và hợp đồng setup/runtime thành `bundled-channels-core`, `bundled-channels-update-a`, `bundled-channels-update-b` và `bundled-channels-contracts`; chunk tổng hợp `bundled-channels` vẫn có sẵn để chạy lại thủ công. Workflow phát hành cũng tách các chunk trình cài đặt provider và chunk cài/gỡ Plugin đi kèm; các chunk cũ `package-update`, `plugins-runtime` và `plugins-integrations` vẫn là bí danh tổng hợp để chạy lại thủ công. Dùng `OPENCLAW_BUNDLED_CHANNELS=telegram,slack` để thu hẹp ma trận channel khi chạy trực tiếp lane đi kèm, hoặc `OPENCLAW_BUNDLED_CHANNEL_UPDATE_TARGETS=telegram,acpx` để thu hẹp kịch bản cập nhật. Các lần chạy Docker theo kịch bản mặc định dùng `OPENCLAW_BUNDLED_CHANNEL_DOCKER_RUN_TIMEOUT=900s`; kịch bản cập nhật nhiều mục tiêu mặc định dùng `OPENCLAW_BUNDLED_CHANNEL_UPDATE_DOCKER_RUN_TIMEOUT=2400s`. Lane này cũng xác minh rằng `channels..enabled=false` và `plugins.entries..enabled=false` chặn việc doctor sửa chữa phụ thuộc runtime. -- Thu hẹp phụ thuộc runtime của Plugin đi kèm khi lặp bằng cách tắt các kịch bản không liên quan, ví dụ: +- Mô hình trực tiếp: `pnpm test:docker:live-models` (tập lệnh: `scripts/test-live-models-docker.sh`) +- Kiểm thử khói liên kết ACP: `pnpm test:docker:live-acp-bind` (tập lệnh: `scripts/test-live-acp-bind-docker.sh`; mặc định bao phủ Claude, Codex và Gemini, với phạm vi bao phủ Droid/OpenCode nghiêm ngặt qua `pnpm test:docker:live-acp-bind:droid` và `pnpm test:docker:live-acp-bind:opencode`) +- Kiểm thử khói backend CLI: `pnpm test:docker:live-cli-backend` (tập lệnh: `scripts/test-live-cli-backend-docker.sh`) +- Kiểm thử khói harness app-server Codex: `pnpm test:docker:live-codex-harness` (tập lệnh: `scripts/test-live-codex-harness-docker.sh`) +- Gateway + tác tử dev: `pnpm test:docker:live-gateway` (tập lệnh: `scripts/test-live-gateway-models-docker.sh`) +- Kiểm thử khói khả năng quan sát: `pnpm qa:otel:smoke` là một lane kiểm tra nguồn QA riêng tư. Nó cố ý không thuộc các lane phát hành Docker của gói vì tarball npm bỏ qua QA Lab. +- Kiểm thử khói trực tiếp Open WebUI: `pnpm test:docker:openwebui` (tập lệnh: `scripts/e2e/openwebui-docker.sh`) +- Trình hướng dẫn onboarding (TTY, scaffold đầy đủ): `pnpm test:docker:onboard` (tập lệnh: `scripts/e2e/onboard-docker.sh`) +- Kiểm thử khói tarball npm cho onboarding/kênh/tác tử: `pnpm test:docker:npm-onboard-channel-agent` cài đặt tarball OpenClaw đã đóng gói ở phạm vi toàn cục trong Docker, cấu hình OpenAI qua onboarding tham chiếu env cùng với Telegram theo mặc định, xác minh doctor đã sửa các phụ thuộc runtime của Plugin đã kích hoạt, và chạy một lượt tác tử OpenAI được mô phỏng. Tái sử dụng tarball đã build sẵn bằng `OPENCLAW_CURRENT_PACKAGE_TGZ=/path/to/openclaw-*.tgz`, bỏ qua rebuild trên host bằng `OPENCLAW_NPM_ONBOARD_HOST_BUILD=0`, hoặc đổi kênh bằng `OPENCLAW_NPM_ONBOARD_CHANNEL=discord`. +- Kiểm thử khói chuyển kênh cập nhật: `pnpm test:docker:update-channel-switch` cài đặt tarball OpenClaw đã đóng gói ở phạm vi toàn cục trong Docker, chuyển từ gói `stable` sang git `dev`, xác minh kênh đã lưu và Plugin sau cập nhật hoạt động, sau đó chuyển lại về gói `stable` và kiểm tra trạng thái cập nhật. +- Kiểm thử khói khả năng sống sót sau nâng cấp: `pnpm test:docker:upgrade-survivor` cài đặt tarball OpenClaw đã đóng gói đè lên một fixture người dùng cũ không sạch với các tác tử, cấu hình kênh, allowlist Plugin, trạng thái phụ thuộc runtime Plugin cũ, và các tệp workspace/session hiện có. Nó chạy cập nhật gói cùng doctor không tương tác mà không cần khóa nhà cung cấp hoặc kênh trực tiếp, sau đó khởi động một Gateway loopback và kiểm tra việc bảo toàn cấu hình/trạng thái cùng ngân sách khởi động/trạng thái. +- Kiểm thử khói ngữ cảnh runtime phiên: `pnpm test:docker:session-runtime-context` xác minh tính bền vững transcript ngữ cảnh runtime ẩn cùng với sửa chữa doctor cho các nhánh ghi lại prompt bị trùng lặp bị ảnh hưởng. +- Kiểm thử khói cài đặt toàn cục Bun: `bash scripts/e2e/bun-global-install-smoke.sh` đóng gói cây hiện tại, cài đặt bằng `bun install -g` trong một home cô lập, và xác minh `openclaw infer image providers --json` trả về các nhà cung cấp hình ảnh đóng gói kèm thay vì treo. Tái sử dụng tarball đã build sẵn bằng `OPENCLAW_BUN_GLOBAL_SMOKE_PACKAGE_TGZ=/path/to/openclaw-*.tgz`, bỏ qua build trên host bằng `OPENCLAW_BUN_GLOBAL_SMOKE_HOST_BUILD=0`, hoặc sao chép `dist/` từ một image Docker đã build bằng `OPENCLAW_BUN_GLOBAL_SMOKE_DIST_IMAGE=openclaw-dockerfile-smoke:local`. +- Kiểm thử khói Docker của trình cài đặt: `bash scripts/test-install-sh-docker.sh` chia sẻ một cache npm giữa các container root, update và direct-npm của nó. Kiểm thử khói cập nhật mặc định dùng npm `latest` làm baseline ổn định trước khi nâng cấp lên tarball ứng viên. Ghi đè cục bộ bằng `OPENCLAW_INSTALL_SMOKE_UPDATE_BASELINE=2026.4.22`, hoặc bằng input `update_baseline_version` của workflow Install Smoke trên GitHub. Các kiểm tra trình cài đặt không phải root giữ một cache npm cô lập để các mục cache do root sở hữu không che lấp hành vi cài đặt cục bộ của người dùng. Đặt `OPENCLAW_INSTALL_SMOKE_NPM_CACHE_DIR=/path/to/cache` để tái sử dụng cache root/update/direct-npm giữa các lần chạy lại cục bộ. +- Install Smoke CI bỏ qua cập nhật toàn cục direct-npm trùng lặp bằng `OPENCLAW_INSTALL_SMOKE_SKIP_NPM_GLOBAL=1`; chạy tập lệnh cục bộ mà không có env đó khi cần phạm vi bao phủ `npm install -g` trực tiếp. +- Kiểm thử khói CLI xóa workspace dùng chung của tác tử: `pnpm test:docker:agents-delete-shared-workspace` (tập lệnh: `scripts/e2e/agents-delete-shared-workspace-docker.sh`) mặc định build image Dockerfile gốc, seed hai tác tử với một workspace trong home container cô lập, chạy `agents delete --json`, và xác minh JSON hợp lệ cùng hành vi giữ lại workspace. Tái sử dụng image install-smoke bằng `OPENCLAW_AGENTS_DELETE_SHARED_WORKSPACE_E2E_IMAGE=openclaw-dockerfile-smoke:local OPENCLAW_AGENTS_DELETE_SHARED_WORKSPACE_E2E_SKIP_BUILD=1`. +- Mạng Gateway (hai container, xác thực WS + health): `pnpm test:docker:gateway-network` (tập lệnh: `scripts/e2e/gateway-network-docker.sh`) +- Kiểm thử khói ảnh chụp nhanh CDP của trình duyệt: `pnpm test:docker:browser-cdp-snapshot` (tập lệnh: `scripts/e2e/browser-cdp-snapshot-docker.sh`) build image E2E nguồn cùng một lớp Chromium, khởi động Chromium với CDP thô, chạy `browser doctor --deep`, và xác minh ảnh chụp nhanh vai trò CDP bao phủ URL liên kết, các phần tử có thể nhấp được nâng cấp từ con trỏ, tham chiếu iframe và metadata frame. +- Hồi quy reasoning tối thiểu OpenAI Responses web_search: `pnpm test:docker:openai-web-search-minimal` (tập lệnh: `scripts/e2e/openai-web-search-minimal-docker.sh`) chạy một máy chủ OpenAI được mô phỏng qua Gateway, xác minh `web_search` nâng `reasoning.effort` từ `minimal` lên `low`, sau đó buộc schema nhà cung cấp từ chối và kiểm tra chi tiết thô xuất hiện trong log Gateway. +- Cầu nối kênh MCP (Gateway đã seed + cầu nối stdio + kiểm thử khói frame thông báo Claude thô): `pnpm test:docker:mcp-channels` (tập lệnh: `scripts/e2e/mcp-channels-docker.sh`) +- Công cụ MCP gói Pi (máy chủ MCP stdio thật + kiểm thử khói cho phép/từ chối hồ sơ Pi nhúng): `pnpm test:docker:pi-bundle-mcp-tools` (tập lệnh: `scripts/e2e/pi-bundle-mcp-tools-docker.sh`) +- Dọn dẹp MCP Cron/subagent (Gateway thật + tháo dỡ tiến trình con MCP stdio sau các lần chạy cron cô lập và subagent một lần): `pnpm test:docker:cron-mcp-cleanup` (tập lệnh: `scripts/e2e/cron-mcp-cleanup-docker.sh`) +- Plugin (kiểm thử khói cài đặt, cài đặt/gỡ cài đặt ClawHub kitchen-sink, cập nhật marketplace, và bật/kiểm tra gói Claude): `pnpm test:docker:plugins` (tập lệnh: `scripts/e2e/plugins-docker.sh`) + Đặt `OPENCLAW_PLUGINS_E2E_CLAWHUB=0` để bỏ qua khối ClawHub, hoặc ghi đè cặp package/runtime kitchen-sink mặc định bằng `OPENCLAW_PLUGINS_E2E_CLAWHUB_SPEC` và `OPENCLAW_PLUGINS_E2E_CLAWHUB_ID`. Khi không có `OPENCLAW_CLAWHUB_URL`/`CLAWHUB_URL`, kiểm thử sử dụng một máy chủ fixture ClawHub cục bộ hermetic. +- Kiểm thử khói cập nhật Plugin không đổi: `pnpm test:docker:plugin-update` (tập lệnh: `scripts/e2e/plugin-update-unchanged-docker.sh`) +- Kiểm thử khói metadata tải lại cấu hình: `pnpm test:docker:config-reload` (tập lệnh: `scripts/e2e/config-reload-source-docker.sh`) +- Phụ thuộc runtime của Plugin đóng gói kèm: `pnpm test:docker:bundled-channel-deps` mặc định build một image runner Docker nhỏ, build và đóng gói OpenClaw một lần trên host, rồi mount tarball đó vào từng kịch bản cài đặt Linux. Tái sử dụng image bằng `OPENCLAW_SKIP_DOCKER_BUILD=1`, bỏ qua rebuild trên host sau một build cục bộ mới bằng `OPENCLAW_BUNDLED_CHANNEL_HOST_BUILD=0`, hoặc trỏ tới một tarball hiện có bằng `OPENCLAW_CURRENT_PACKAGE_TGZ=/path/to/openclaw-*.tgz`. Các chunk Docker aggregate đầy đủ và bundled-channel theo đường phát hành pre-pack tarball này một lần, rồi chia nhỏ kiểm tra kênh đóng gói kèm thành các lane độc lập, bao gồm các lane cập nhật riêng cho Telegram, Discord, Slack, Feishu, memory-lancedb và ACPX. Các chunk phát hành tách kiểm thử khói kênh, mục tiêu cập nhật, và hợp đồng setup/runtime thành `bundled-channels-core`, `bundled-channels-update-a`, `bundled-channels-update-b` và `bundled-channels-contracts`; chunk aggregate `bundled-channels` vẫn có sẵn cho các lần chạy lại thủ công. Workflow phát hành cũng tách các chunk trình cài đặt nhà cung cấp và các chunk cài đặt/gỡ cài đặt Plugin đóng gói kèm; các chunk cũ `package-update`, `plugins-runtime` và `plugins-integrations` vẫn là alias aggregate cho các lần chạy lại thủ công. Dùng `OPENCLAW_BUNDLED_CHANNELS=telegram,slack` để thu hẹp ma trận kênh khi chạy trực tiếp lane đóng gói kèm, hoặc `OPENCLAW_BUNDLED_CHANNEL_UPDATE_TARGETS=telegram,acpx` để thu hẹp kịch bản cập nhật. Các lần chạy Docker theo từng kịch bản mặc định là `OPENCLAW_BUNDLED_CHANNEL_DOCKER_RUN_TIMEOUT=900s`; kịch bản cập nhật nhiều mục tiêu mặc định là `OPENCLAW_BUNDLED_CHANNEL_UPDATE_DOCKER_RUN_TIMEOUT=2400s`. Lane cũng xác minh rằng `channels..enabled=false` và `plugins.entries..enabled=false` sẽ chặn sửa chữa doctor/phụ thuộc runtime. +- Thu hẹp phụ thuộc runtime của Plugin đóng gói kèm trong khi lặp bằng cách tắt các kịch bản không liên quan, ví dụ: `OPENCLAW_BUNDLED_CHANNEL_SCENARIOS=0 OPENCLAW_BUNDLED_CHANNEL_UPDATE_SCENARIO=0 OPENCLAW_BUNDLED_CHANNEL_ROOT_OWNED_SCENARIO=0 OPENCLAW_BUNDLED_CHANNEL_SETUP_ENTRY_SCENARIO=0 pnpm test:docker:bundled-channel-deps`. -Để prebuild và tái sử dụng image chức năng dùng chung theo cách thủ công: +Để build sẵn và tái sử dụng image chức năng dùng chung theo cách thủ công: ```bash OPENCLAW_DOCKER_E2E_IMAGE=openclaw-docker-e2e-functional:local pnpm test:docker:e2e-build OPENCLAW_DOCKER_E2E_IMAGE=openclaw-docker-e2e-functional:local OPENCLAW_SKIP_DOCKER_BUILD=1 pnpm test:docker:mcp-channels ``` -Các ghi đè image theo suite như `OPENCLAW_GATEWAY_NETWORK_E2E_IMAGE` vẫn được ưu tiên khi được đặt. Khi `OPENCLAW_SKIP_DOCKER_BUILD=1` trỏ tới một image dùng chung từ xa, các script sẽ pull image đó nếu nó chưa có cục bộ. Các bài kiểm thử Docker QR và trình cài đặt giữ Dockerfile riêng vì chúng xác thực hành vi package/cài đặt thay vì runtime ứng dụng đã build dùng chung. +Các override image theo suite như `OPENCLAW_GATEWAY_NETWORK_E2E_IMAGE` vẫn được ưu tiên khi được đặt. Khi `OPENCLAW_SKIP_DOCKER_BUILD=1` trỏ tới một image dùng chung từ xa, các tập lệnh sẽ pull nó nếu nó chưa có cục bộ. Các kiểm thử Docker cho QR và trình cài đặt giữ Dockerfile riêng vì chúng xác thực hành vi gói/cài đặt thay vì runtime ứng dụng đã build dùng chung. -Các runner Docker live-model cũng bind-mount checkout hiện tại ở chế độ chỉ đọc và -stage nó vào một workdir tạm thời bên trong container. Điều này giữ cho image -runtime gọn nhẹ trong khi vẫn chạy Vitest trên đúng nguồn/cấu hình cục bộ của bạn. -Bước staging bỏ qua các cache chỉ dùng cục bộ lớn và output build ứng dụng như -`.pnpm-store`, `.worktrees`, `__openclaw_vitest__`, và các thư mục output `.build` -hoặc Gradle cục bộ của ứng dụng để các lần chạy live Docker không mất nhiều phút sao chép -artifact đặc thù của máy. +Các trình chạy Docker mô hình live cũng bind-mount checkout hiện tại ở chế độ chỉ đọc và +stage nó vào một workdir tạm thời bên trong container. Điều này giữ cho image runtime +gọn nhẹ trong khi vẫn chạy Vitest trên đúng source/config cục bộ của bạn. +Bước staging bỏ qua các cache lớn chỉ dùng cục bộ và output build ứng dụng như +`.pnpm-store`, `.worktrees`, `__openclaw_vitest__`, và các thư mục output `.build` cục bộ của ứng dụng hoặc +Gradle để các lần chạy Docker live không mất nhiều phút sao chép +artifact riêng của máy. Chúng cũng đặt `OPENCLAW_SKIP_CHANNELS=1` để các probe live của Gateway không khởi động -worker channel Telegram/Discord/v.v. thật bên trong container. -`test:docker:live-models` vẫn chạy `pnpm test:live`, vì vậy hãy truyền qua -`OPENCLAW_LIVE_GATEWAY_*` cả khi bạn cần thu hẹp hoặc loại trừ phạm vi live của Gateway +worker kênh Telegram/Discord/v.v. thật bên trong container. +`test:docker:live-models` vẫn chạy `pnpm test:live`, vì vậy hãy truyền tiếp +`OPENCLAW_LIVE_GATEWAY_*` khi bạn cần thu hẹp hoặc loại trừ phạm vi live của Gateway khỏi lane Docker đó. -`test:docker:openwebui` là một kiểm thử khói tương thích cấp cao hơn: nó khởi động một -container gateway OpenClaw với các endpoint HTTP tương thích OpenAI được bật, -khởi động một container Open WebUI đã pin trỏ tới gateway đó, đăng nhập qua -Open WebUI, xác minh `/api/models` hiển thị `openclaw/default`, rồi gửi một +`test:docker:openwebui` là một smoke tương thích cấp cao hơn: nó khởi động một +container Gateway OpenClaw với các endpoint HTTP tương thích OpenAI được bật, +khởi động một container Open WebUI đã ghim phiên bản trỏ tới Gateway đó, đăng nhập qua +Open WebUI, xác minh `/api/models` công bố `openclaw/default`, rồi gửi một yêu cầu chat thật qua proxy `/api/chat/completions` của Open WebUI. -Lần chạy đầu tiên có thể chậm hơn đáng kể vì Docker có thể cần pull image -Open WebUI và Open WebUI có thể cần hoàn tất thiết lập cold-start riêng. -Lane này kỳ vọng có khóa mô hình live dùng được, và `OPENCLAW_PROFILE_FILE` -(`~/.profile` theo mặc định) là cách chính để cung cấp khóa đó trong các lần chạy Docker hóa. -Các lần chạy thành công in một payload JSON nhỏ như `{ "ok": true, "model": +Lần chạy đầu tiên có thể chậm hơn rõ rệt vì Docker có thể cần kéo image +Open WebUI và Open WebUI có thể cần hoàn tất thiết lập cold-start của chính nó. +Lane này cần một khóa mô hình live dùng được, và `OPENCLAW_PROFILE_FILE` +(mặc định là `~/.profile`) là cách chính để cung cấp khóa đó trong các lần chạy Docker hóa. +Các lần chạy thành công in ra một payload JSON nhỏ như `{ "ok": true, "model": "openclaw/default", ... }`. -`test:docker:mcp-channels` cố ý có tính xác định và không cần tài khoản -Telegram, Discord hoặc iMessage thật. Nó boot một container Gateway đã seed, -khởi động container thứ hai sinh ra `openclaw mcp serve`, rồi xác minh -khám phá hội thoại đã định tuyến, đọc transcript, metadata tệp đính kèm, -hành vi hàng đợi sự kiện live, định tuyến gửi outbound, và thông báo channel kiểu Claude + -quyền qua cầu nối MCP stdio thật. Kiểm tra thông báo -kiểm tra trực tiếp các frame MCP stdio thô để kiểm thử khói xác thực những gì +`test:docker:mcp-channels` được thiết kế có tính xác định và không cần tài khoản +Telegram, Discord hoặc iMessage thật. Nó khởi động một container Gateway đã seed, +khởi động một container thứ hai sinh ra `openclaw mcp serve`, rồi xác minh +việc khám phá cuộc hội thoại được định tuyến, đọc transcript, metadata attachment, +hành vi hàng đợi sự kiện live, định tuyến gửi outbound, và thông báo kênh + +quyền kiểu Claude qua cầu nối stdio MCP thật. Kiểm tra thông báo +kiểm tra trực tiếp các frame stdio MCP thô để smoke xác thực những gì cầu nối thật sự phát ra, không chỉ những gì một SDK client cụ thể tình cờ hiển thị. `test:docker:pi-bundle-mcp-tools` có tính xác định và không cần khóa mô hình live. -Nó build image Docker của repo, khởi động một máy chủ probe MCP stdio thật -bên trong container, hiện thực hóa máy chủ đó qua runtime MCP gói Pi nhúng, -thực thi công cụ, rồi xác minh `coding` và `messaging` giữ -công cụ `bundle-mcp` trong khi `minimal` và `tools.deny: ["bundle-mcp"]` lọc chúng. +Nó build image Docker của repo, khởi động một server probe stdio MCP thật +bên trong container, hiện thực hóa server đó qua runtime MCP của bundle Pi nhúng, +thực thi tool, rồi xác minh `coding` và `messaging` giữ lại +tool `bundle-mcp` trong khi `minimal` và `tools.deny: ["bundle-mcp"]` lọc chúng. `test:docker:cron-mcp-cleanup` có tính xác định và không cần khóa mô hình live. -Nó khởi động một Gateway đã seed với máy chủ probe MCP stdio thật, chạy một -lượt cron cô lập và một lượt con một lần `/subagents spawn`, rồi xác minh -tiến trình con MCP thoát sau mỗi lần chạy. +Nó khởi động một Gateway đã seed với một server probe stdio MCP thật, chạy một +lượt cron cô lập và một lượt con một lần qua `/subagents spawn`, rồi xác minh +process con MCP thoát sau mỗi lần chạy. -Kiểm thử khói thread ngôn ngữ thường ACP thủ công (không phải CI): +Smoke thread ACP ngôn ngữ tự nhiên thủ công (không phải CI): - `bun scripts/dev/discord-acp-plain-language-smoke.ts --channel ...` -- Giữ script này cho các quy trình hồi quy/gỡ lỗi. Có thể cần lại script này để xác thực định tuyến luồng ACP, vì vậy đừng xóa nó. +- Giữ script này cho các workflow hồi quy/debug. Nó có thể lại cần thiết cho việc xác thực định tuyến thread ACP, vì vậy đừng xóa nó. -Biến môi trường hữu ích: +Các biến môi trường hữu ích: - `OPENCLAW_CONFIG_DIR=...` (mặc định: `~/.openclaw`) được mount vào `/home/node/.openclaw` - `OPENCLAW_WORKSPACE_DIR=...` (mặc định: `~/.openclaw/workspace`) được mount vào `/home/node/.openclaw/workspace` -- `OPENCLAW_PROFILE_FILE=...` (mặc định: `~/.profile`) được mount vào `/home/node/.profile` và được source trước khi chạy kiểm thử -- `OPENCLAW_DOCKER_PROFILE_ENV_ONLY=1` để chỉ xác minh các biến môi trường được source từ `OPENCLAW_PROFILE_FILE`, dùng các thư mục cấu hình/không gian làm việc tạm thời và không mount xác thực CLI bên ngoài -- `OPENCLAW_DOCKER_CLI_TOOLS_DIR=...` (mặc định: `~/.cache/openclaw/docker-cli-tools`) được mount vào `/home/node/.npm-global` cho các bản cài CLI được lưu bộ nhớ đệm bên trong Docker -- Các thư mục/tệp xác thực CLI bên ngoài trong `$HOME` được mount chỉ đọc dưới `/host-auth...`, rồi được sao chép vào `/home/node/...` trước khi kiểm thử bắt đầu +- `OPENCLAW_PROFILE_FILE=...` (mặc định: `~/.profile`) được mount vào `/home/node/.profile` và được source trước khi chạy test +- `OPENCLAW_DOCKER_PROFILE_ENV_ONLY=1` để chỉ xác minh các biến môi trường được source từ `OPENCLAW_PROFILE_FILE`, dùng các thư mục config/workspace tạm thời và không mount xác thực CLI bên ngoài +- `OPENCLAW_DOCKER_CLI_TOOLS_DIR=...` (mặc định: `~/.cache/openclaw/docker-cli-tools`) được mount vào `/home/node/.npm-global` cho các bản cài CLI được cache bên trong Docker +- Các thư mục/tệp xác thực CLI bên ngoài dưới `$HOME` được mount chỉ đọc dưới `/host-auth...`, rồi được sao chép vào `/home/node/...` trước khi test bắt đầu - Thư mục mặc định: `.minimax` - Tệp mặc định: `~/.codex/auth.json`, `~/.codex/config.toml`, `.claude.json`, `~/.claude/.credentials.json`, `~/.claude/settings.json`, `~/.claude/settings.local.json` - - Các lần chạy nhà cung cấp được thu hẹp chỉ mount những thư mục/tệp cần thiết suy ra từ `OPENCLAW_LIVE_PROVIDERS` / `OPENCLAW_LIVE_GATEWAY_PROVIDERS` - - Ghi đè thủ công bằng `OPENCLAW_DOCKER_AUTH_DIRS=all`, `OPENCLAW_DOCKER_AUTH_DIRS=none`, hoặc một danh sách phân tách bằng dấu phẩy như `OPENCLAW_DOCKER_AUTH_DIRS=.claude,.codex` + - Các lần chạy provider đã thu hẹp chỉ mount các thư mục/tệp cần thiết được suy ra từ `OPENCLAW_LIVE_PROVIDERS` / `OPENCLAW_LIVE_GATEWAY_PROVIDERS` + - Ghi đè thủ công bằng `OPENCLAW_DOCKER_AUTH_DIRS=all`, `OPENCLAW_DOCKER_AUTH_DIRS=none`, hoặc danh sách phân tách bằng dấu phẩy như `OPENCLAW_DOCKER_AUTH_DIRS=.claude,.codex` - `OPENCLAW_LIVE_GATEWAY_MODELS=...` / `OPENCLAW_LIVE_MODELS=...` để thu hẹp lần chạy -- `OPENCLAW_LIVE_GATEWAY_PROVIDERS=...` / `OPENCLAW_LIVE_PROVIDERS=...` để lọc các nhà cung cấp trong container -- `OPENCLAW_SKIP_DOCKER_BUILD=1` để dùng lại ảnh `openclaw:local-live` hiện có cho các lần chạy lại không cần dựng lại -- `OPENCLAW_LIVE_REQUIRE_PROFILE_KEYS=1` để đảm bảo thông tin xác thực đến từ kho hồ sơ (không phải môi trường) -- `OPENCLAW_OPENWEBUI_MODEL=...` để chọn mô hình được Gateway cung cấp cho smoke Open WebUI -- `OPENCLAW_OPENWEBUI_PROMPT=...` để ghi đè prompt kiểm tra nonce được smoke Open WebUI sử dụng -- `OPENWEBUI_IMAGE=...` để ghi đè thẻ ảnh Open WebUI đã ghim +- `OPENCLAW_LIVE_GATEWAY_PROVIDERS=...` / `OPENCLAW_LIVE_PROVIDERS=...` để lọc provider trong container +- `OPENCLAW_SKIP_DOCKER_BUILD=1` để tái sử dụng image `openclaw:local-live` hiện có cho các lần chạy lại không cần rebuild +- `OPENCLAW_LIVE_REQUIRE_PROFILE_KEYS=1` để bảo đảm credentials đến từ profile store (không phải env) +- `OPENCLAW_OPENWEBUI_MODEL=...` để chọn mô hình được Gateway công bố cho smoke Open WebUI +- `OPENCLAW_OPENWEBUI_PROMPT=...` để ghi đè prompt kiểm tra nonce được dùng bởi smoke Open WebUI +- `OPENWEBUI_IMAGE=...` để ghi đè tag image Open WebUI đã ghim -## Kiểm tra hợp lệ tài liệu +## Kiểm tra hợp lý tài liệu -Chạy kiểm tra tài liệu sau khi chỉnh sửa tài liệu: `pnpm check:docs`. -Chạy xác thực anchor Mintlify đầy đủ khi bạn cũng cần kiểm tra tiêu đề trong trang: `pnpm docs:check-links:anchors`. +Chạy kiểm tra tài liệu sau khi sửa tài liệu: `pnpm check:docs`. +Chạy xác thực anchor Mintlify đầy đủ khi bạn cũng cần kiểm tra heading trong trang: `pnpm docs:check-links:anchors`. -## Hồi quy ngoại tuyến (an toàn cho CI) +## Hồi quy offline (an toàn cho CI) -Đây là các hồi quy “pipeline thật” không có nhà cung cấp thật: +Đây là các hồi quy “pipeline thật” không có provider thật: -- Gọi công cụ Gateway (OpenAI giả lập, Gateway thật + vòng lặp tác tử thật): `src/gateway/gateway.test.ts` (trường hợp: "runs a mock OpenAI tool call end-to-end via gateway agent loop") -- Trình hướng dẫn Gateway (WS `wizard.start`/`wizard.next`, ghi cấu hình + bắt buộc xác thực): `src/gateway/gateway.test.ts` (trường hợp: "runs wizard over ws and writes auth token config") +- Gọi tool của Gateway (OpenAI giả lập, Gateway thật + vòng lặp agent thật): `src/gateway/gateway.test.ts` (case: "runs a mock OpenAI tool call end-to-end via gateway agent loop") +- Wizard Gateway (WS `wizard.start`/`wizard.next`, ghi config + bắt buộc auth): `src/gateway/gateway.test.ts` (case: "runs wizard over ws and writes auth token config") -## Đánh giá độ tin cậy của tác tử (Skills) +## Eval độ tin cậy agent (Skills) -Chúng ta đã có một vài kiểm thử an toàn cho CI hoạt động như “đánh giá độ tin cậy của tác tử”: +Chúng ta đã có một vài test an toàn cho CI hoạt động như “eval độ tin cậy agent”: -- Gọi công cụ giả lập qua Gateway thật + vòng lặp tác tử (`src/gateway/gateway.test.ts`). -- Các luồng trình hướng dẫn đầu cuối xác thực việc nối phiên và hiệu lực cấu hình (`src/gateway/gateway.test.ts`). +- Gọi tool giả lập qua Gateway thật + vòng lặp agent (`src/gateway/gateway.test.ts`). +- Luồng wizard end-to-end xác thực wiring session và hiệu ứng config (`src/gateway/gateway.test.ts`). -Những phần vẫn còn thiếu cho Skills (xem [Skills](/vi/tools/skills)): +Những gì vẫn còn thiếu cho Skills (xem [Skills](/vi/tools/skills)): -- **Ra quyết định:** khi Skills được liệt kê trong prompt, tác tử có chọn đúng Skills (hoặc tránh những Skills không liên quan) không? -- **Tuân thủ:** tác tử có đọc `SKILL.md` trước khi sử dụng và làm theo các bước/tham số bắt buộc không? -- **Hợp đồng quy trình:** các kịch bản nhiều lượt xác nhận thứ tự công cụ, việc mang theo lịch sử phiên và ranh giới sandbox. +- **Ra quyết định:** khi skills được liệt kê trong prompt, agent có chọn đúng skill (hoặc tránh skill không liên quan) không? +- **Tuân thủ:** agent có đọc `SKILL.md` trước khi dùng và làm theo các bước/args bắt buộc không? +- **Hợp đồng workflow:** các kịch bản nhiều lượt assert thứ tự tool, truyền tiếp lịch sử session, và ranh giới sandbox. -Các đánh giá trong tương lai trước hết nên giữ tính xác định: +Các eval tương lai trước hết nên giữ tính xác định: -- Một trình chạy kịch bản dùng nhà cung cấp giả lập để xác nhận các lời gọi công cụ + thứ tự, việc đọc tệp Skills và nối phiên. -- Một bộ nhỏ các kịch bản tập trung vào Skills (sử dụng so với tránh, gating, chèn prompt). -- Đánh giá live tùy chọn (opt-in, được kiểm soát bằng biến môi trường) chỉ sau khi bộ an toàn cho CI đã sẵn sàng. +- Một trình chạy kịch bản dùng provider giả lập để assert các lệnh gọi tool + thứ tự, việc đọc tệp skill, và wiring session. +- Một bộ nhỏ các kịch bản tập trung vào skill (dùng so với tránh, gating, prompt injection). +- Eval live tùy chọn (opt-in, có env gate) chỉ sau khi bộ an toàn cho CI đã có sẵn. -## Kiểm thử hợp đồng (hình dạng Plugin và kênh) +## Test hợp đồng (hình dạng Plugin và kênh) -Kiểm thử hợp đồng xác minh rằng mọi Plugin và kênh đã đăng ký đều tuân thủ hợp đồng giao diện của nó. Chúng lặp qua tất cả Plugin được phát hiện và chạy một bộ xác nhận về hình dạng và hành vi. Lane đơn vị `pnpm test` mặc định cố ý bỏ qua các tệp smoke và đường nối dùng chung này; hãy chạy rõ ràng các lệnh hợp đồng khi bạn chạm vào bề mặt kênh hoặc nhà cung cấp dùng chung. +Test hợp đồng xác minh rằng mọi Plugin và kênh đã đăng ký đều tuân thủ +hợp đồng interface của nó. Chúng lặp qua tất cả Plugin được khám phá và chạy một bộ +assertion về hình dạng và hành vi. Lane unit `pnpm test` mặc định cố ý +bỏ qua các tệp smoke và đường nối chung này; hãy chạy rõ ràng các lệnh hợp đồng +khi bạn chạm vào bề mặt kênh hoặc provider chung. ### Lệnh - Tất cả hợp đồng: `pnpm test:contracts` - Chỉ hợp đồng kênh: `pnpm test:contracts:channels` -- Chỉ hợp đồng nhà cung cấp: `pnpm test:contracts:plugins` +- Chỉ hợp đồng provider: `pnpm test:contracts:plugins` ### Hợp đồng kênh Nằm trong `src/channels/plugins/contracts/*.contract.test.ts`: -- **plugin** - Hình dạng Plugin cơ bản (id, tên, khả năng) -- **setup** - Hợp đồng trình hướng dẫn thiết lập -- **session-binding** - Hành vi ràng buộc phiên +- **plugin** - Hình dạng Plugin cơ bản (id, tên, capability) +- **setup** - Hợp đồng setup wizard +- **session-binding** - Hành vi binding session - **outbound-payload** - Cấu trúc payload tin nhắn -- **inbound** - Xử lý tin nhắn đến -- **actions** - Trình xử lý hành động kênh -- **threading** - Xử lý ID luồng -- **directory** - API thư mục/danh sách thành viên +- **inbound** - Xử lý tin nhắn inbound +- **actions** - Handler action của kênh +- **threading** - Xử lý ID thread +- **directory** - API directory/roster - **group-policy** - Thực thi chính sách nhóm -### Hợp đồng trạng thái nhà cung cấp +### Hợp đồng trạng thái provider Nằm trong `src/plugins/contracts/*.contract.test.ts`. -- **status** - Kiểm tra trạng thái kênh +- **status** - Probe trạng thái kênh - **registry** - Hình dạng registry Plugin -### Hợp đồng nhà cung cấp +### Hợp đồng provider Nằm trong `src/plugins/contracts/*.contract.test.ts`: -- **auth** - Hợp đồng luồng xác thực -- **auth-choice** - Lựa chọn/chọn xác thực -- **catalog** - API danh mục mô hình -- **discovery** - Phát hiện Plugin +- **auth** - Hợp đồng luồng auth +- **auth-choice** - Lựa chọn/chọn auth +- **catalog** - API catalog mô hình +- **discovery** - Khám phá Plugin - **loader** - Tải Plugin -- **runtime** - Runtime nhà cung cấp -- **shape** - Hình dạng/giao diện Plugin -- **wizard** - Trình hướng dẫn thiết lập +- **runtime** - Runtime provider +- **shape** - Hình dạng/interface Plugin +- **wizard** - Setup wizard ### Khi nào chạy - Sau khi thay đổi export hoặc subpath của plugin-sdk -- Sau khi thêm hoặc sửa đổi một kênh hoặc Plugin nhà cung cấp -- Sau khi refactor đăng ký hoặc phát hiện Plugin +- Sau khi thêm hoặc sửa một kênh hoặc provider Plugin +- Sau khi refactor đăng ký hoặc khám phá Plugin -Kiểm thử hợp đồng chạy trong CI và không yêu cầu khóa API thật. +Test hợp đồng chạy trong CI và không cần khóa API thật. ## Thêm hồi quy (hướng dẫn) -Khi bạn sửa một vấn đề nhà cung cấp/mô hình được phát hiện trong live: +Khi bạn sửa một vấn đề provider/mô hình được phát hiện trong live: -- Thêm hồi quy an toàn cho CI nếu có thể (nhà cung cấp mock/stub, hoặc ghi lại phép biến đổi hình dạng yêu cầu chính xác) -- Nếu vốn dĩ chỉ live mới kiểm thử được (giới hạn tốc độ, chính sách xác thực), giữ kiểm thử live thật hẹp và opt-in qua biến môi trường -- Ưu tiên nhắm vào lớp nhỏ nhất bắt được lỗi: - - lỗi chuyển đổi/phát lại yêu cầu nhà cung cấp → kiểm thử mô hình trực tiếp - - lỗi pipeline phiên/lịch sử/công cụ Gateway → smoke live Gateway hoặc kiểm thử mock Gateway an toàn cho CI -- Lan can SecretRef traversal: - - `src/secrets/exec-secret-ref-id-parity.test.ts` suy ra một mục tiêu mẫu cho mỗi lớp SecretRef từ metadata registry (`listSecretTargetRegistryEntries()`), rồi xác nhận các exec id có đoạn traversal bị từ chối. - - Nếu bạn thêm một họ mục tiêu SecretRef `includeInPlan` mới trong `src/secrets/target-registry-data.ts`, hãy cập nhật `classifyTargetClass` trong kiểm thử đó. Kiểm thử cố ý thất bại với các id mục tiêu chưa được phân loại để các lớp mới không thể bị bỏ qua âm thầm. +- Thêm hồi quy an toàn cho CI nếu có thể (provider mock/stub, hoặc ghi lại đúng phép biến đổi hình dạng request) +- Nếu vấn đề vốn chỉ xảy ra trong live (rate limit, chính sách auth), hãy giữ test live hẹp và opt-in qua biến môi trường +- Ưu tiên nhắm vào tầng nhỏ nhất bắt được lỗi: + - lỗi chuyển đổi/replay request của provider → test models trực tiếp + - lỗi pipeline session/history/tool của Gateway → smoke live Gateway hoặc test mock Gateway an toàn cho CI +- Guardrail duyệt SecretRef: + - `src/secrets/exec-secret-ref-id-parity.test.ts` suy ra một target được lấy mẫu cho mỗi lớp SecretRef từ metadata registry (`listSecretTargetRegistryEntries()`), rồi assert các exec id dạng traversal-segment bị từ chối. + - Nếu bạn thêm một họ target SecretRef `includeInPlan` mới trong `src/secrets/target-registry-data.ts`, hãy cập nhật `classifyTargetClass` trong test đó. Test cố ý fail với target id chưa được phân loại để các lớp mới không thể bị bỏ qua âm thầm. ## Liên quan diff --git a/docs/vi/reference/test.md b/docs/vi/reference/test.md index 5537f1f0e..519002eee 100644 --- a/docs/vi/reference/test.md +++ b/docs/vi/reference/test.md @@ -1,56 +1,57 @@ --- read_when: - Chạy hoặc sửa các bài kiểm thử -summary: Cách chạy kiểm thử cục bộ (vitest) và khi nào dùng các chế độ force/coverage +summary: Cách chạy kiểm thử cục bộ (vitest) và khi nào nên dùng chế độ force/coverage title: Kiểm thử x-i18n: - generated_at: "2026-04-29T23:13:19Z" + generated_at: "2026-04-30T18:38:33Z" model: gpt-5.5 provider: openai - source_hash: 9328d6f0383b5067fa8bb5d0f1bf22a3b9048a267908bf85167842ddc3d12e42 + source_hash: 131f2bad3b2806d28394213cec38d632d106ddbf8ff04d06345ab8046fb8bcf2 source_path: reference/test.md workflow: 16 --- -- Bộ công cụ kiểm thử đầy đủ (bộ kiểm thử, kiểm thử trực tiếp, Docker): [Kiểm thử](/vi/help/testing) +- Bộ công cụ kiểm thử đầy đủ (bộ kiểm thử, trực tiếp, Docker): [Kiểm thử](/vi/help/testing) -- `pnpm test:force`: Dừng mọi tiến trình Gateway còn sót lại đang giữ cổng điều khiển mặc định, sau đó chạy toàn bộ bộ Vitest với một cổng Gateway biệt lập để các kiểm thử máy chủ không va chạm với một phiên bản đang chạy. Dùng lệnh này khi một lần chạy Gateway trước đó khiến cổng 18789 bị chiếm. -- `pnpm test:coverage`: Chạy bộ đơn vị với coverage V8 (thông qua `vitest.unit.config.ts`). Đây là gate coverage đơn vị theo tệp đã tải, không phải coverage toàn bộ tệp trong toàn repo. Ngưỡng là 70% cho dòng/hàm/câu lệnh và 55% cho nhánh. Vì `coverage.all` là false, gate này đo các tệp được bộ coverage đơn vị tải thay vì xem mọi tệp nguồn thuộc lane đã tách là chưa được coverage. +- `pnpm test:force`: Diệt mọi tiến trình Gateway còn sót lại đang giữ cổng điều khiển mặc định, sau đó chạy toàn bộ bộ Vitest với một cổng Gateway cô lập để các kiểm thử máy chủ không xung đột với một phiên bản đang chạy. Dùng lệnh này khi một lần chạy Gateway trước đó để lại cổng 18789 bị chiếm dụng. +- `pnpm test:coverage`: Chạy bộ kiểm thử đơn vị với coverage V8 (thông qua `vitest.unit.config.ts`). Đây là cổng coverage đơn vị theo tệp đã được tải, không phải coverage toàn bộ repo cho mọi tệp. Ngưỡng là 70% dòng/hàm/câu lệnh và 55% nhánh. Vì `coverage.all` là false, cổng này đo các tệp được bộ coverage đơn vị tải thay vì coi mọi tệp nguồn theo làn tách là chưa được cover. - `pnpm test:coverage:changed`: Chỉ chạy coverage đơn vị cho các tệp đã thay đổi kể từ `origin/main`. -- `pnpm test:changed`: lần chạy kiểm thử thay đổi thông minh, chi phí thấp. Nó chạy các mục tiêu chính xác từ chỉnh sửa kiểm thử trực tiếp, các tệp `*.test.ts` cùng cấp, ánh xạ nguồn tường minh và đồ thị import cục bộ. Các thay đổi rộng/config/package bị bỏ qua trừ khi chúng ánh xạ đến các kiểm thử chính xác. -- `OPENCLAW_TEST_CHANGED_BROAD=1 pnpm test:changed`: lần chạy kiểm thử thay đổi rộng tường minh. Dùng khi một chỉnh sửa về test harness/config/package nên rơi về hành vi kiểm thử thay đổi rộng hơn của Vitest. -- `pnpm changed:lanes`: hiển thị các lane kiến trúc được kích hoạt bởi diff so với `origin/main`. -- `pnpm check:changed`: chạy gate kiểm tra thay đổi thông minh cho diff so với `origin/main`. Nó chạy typecheck, lint và các lệnh guard cho các lane kiến trúc bị ảnh hưởng, nhưng không chạy kiểm thử Vitest. Dùng `pnpm test:changed` hoặc `pnpm test ` tường minh để có bằng chứng kiểm thử. -- `pnpm test`: định tuyến các mục tiêu tệp/thư mục tường minh qua các lane Vitest có phạm vi. Các lần chạy không chỉ định mục tiêu dùng các nhóm shard cố định và mở rộng thành các cấu hình lá để thực thi song song cục bộ; nhóm plugin luôn mở rộng thành các cấu hình shard theo từng plugin thay vì một tiến trình root-project khổng lồ. -- Các lần chạy test wrapper kết thúc bằng một tóm tắt ngắn dạng `[test] passed|failed|skipped ... in ...`. Dòng thời lượng riêng của Vitest vẫn là chi tiết theo từng shard. -- Trạng thái kiểm thử OpenClaw dùng chung: dùng `src/test-utils/openclaw-test-state.ts` từ Vitest khi một kiểm thử cần `HOME`, `OPENCLAW_STATE_DIR`, `OPENCLAW_CONFIG_PATH`, fixture cấu hình, workspace, thư mục agent hoặc kho auth-profile biệt lập. -- Trình trợ giúp E2E tiến trình: dùng `test/helpers/openclaw-test-instance.ts` khi một kiểm thử E2E cấp tiến trình Vitest cần Gateway đang chạy, env CLI, thu thập log và dọn dẹp ở một nơi. -- Trình trợ giúp E2E Docker/Bash: các lane source `scripts/lib/docker-e2e-image.sh` có thể truyền `docker_e2e_test_state_shell_b64