Harness Academy
Tài liệu gốc 22 21 phútTiếng Việt + English
docs/adr/0012-isolated-workspace.mdXem bản gốc
Ngôn ngữ bài đọc
Bản dịch tiếng Việt

Bản dịch đầy đủ theo đúng cấu trúc tài liệu; code, liên kết và định danh kỹ thuật được giữ nguyên.

0012. Không gian làm việc biệt lập - một SandboxExecutor + phần phụ trợ mỏng, sắp xếp các công cụ thông qua đường nối, sao chép tại gốc

Trạng thái: Đã chấp nhận Ngày: 2026-07-03 Đã sửa đổi: 2026-07-04 — đã thêm §10: một SANDBOX_GIT_TOKEN, hai cơ chế tiêm — modal tiêm trực tiếp nó vào sandbox env; docker cung cấp nó cho Proxy thông tin xác thực (tự động tương tác khi token được đặt) để nhân viên không bị tín dụng. Một núm xoay cho phép mô hình đẩy một nhánh/mở PR từ bên trong hộp cát; sự phân chia docker-vs-modal chỉ là cách token được đưa vào, không phải cái nào token hoặc nơi nó được định cấu hình. Đã sửa đổi: 2026-07-13 — §10 được thay thế bởi ADR-0016: không có cơ chế tiêm hai dài hơn. Proxy thông tin xác thực bị xóa và docker chấp nhận phương thức trực tiếp tiêm, vậy SANDBOX_GIT_TOKEN đạt đến môi trường Công nhân như GITHUB_TOKEN trong cả hai phần phụ trợ — và một quá trình đóng hộp cát có thể đọc được nó. §§1–9 (toàn bộ thiết kế Không gian làm việc biệt lập, bao gồm cả bàn tay) không thay đổi. Văn bản §10 bên dưới không được chỉnh sửa để ghi lại những gì đã được quyết định vào ngày 2026-07-04.

Thay thế một phần, ADR-0011: §2 (Docker hình dạng vỏ cố định), §3 (hình dạng trống rỗng / không có cây cục bộ theo phương thức) và hai hình dạng trên mỗi chế độ bash mô tả. Nó giữ lại ADR-0011 §1 ( CommandExecutor đường may + SANDBOX_MODE bảo vệ khởi động), §5 (an toàn phát lại cho bash hộp cát), §6 (Proxy xác thực docker headless) và §7 (thang cô lập-phụ trợ).

Bối cảnh

ADR-0011 đã được vận chuyển SANDBOX_MODE=docker|modal dưới dạng phần chia phụ gia: các công cụ tệp máy chủ được giữ lại hoạt động trên cây repo thực trong khi chỉ bash chạy trong một .decode/sandbox/ gãi. hai phần phụ trợ phân kỳ rõ ràng — Docker đã tạo ra một vỏ liên tục xuyên qua điểm đánh dấu+$? giao thức với một hết thời gian chờ giết và khởi động lại; Modal đã chạy fresh-exec trong một bản ghi từ xa trống không có cây cục bộ - mỗi cái cần của riêng mình bash mô tả. Điều này hoạt động nhưng không bị cô lập (các công cụ tệp của agent vẫn chạm vào repo thực) cũng như không đồng nhất (hai hình dạng, hai mô tả, hai bộ vỏ cạnh).

Mục tiêu bây giờ là Không gian làm việc biệt lập theo kiểu codex/opencode: ở chế độ hộp cát, agent hoạt động trên một git clone của repository do người dùng cung cấp tại /workspace, với toàn bộ phạm vi công cụ (tệp + shell) được chứa ở đó, trong khi các hiện vật khai thác của chính bộ decode vẫn được giữ nguyên. none chế độ phải giữ nguyên byte.

Hai lực thiết kế đã được con người giải quyết trong quá trình chải lông:

  1. Công cụ tệp trung thực. Thiết kế đầu tiên giữ các công cụ tệp trên máy chủ .decode/sandbox/ gương được giữ lại được hội tụ với điều khiển từ xa bằng đồng bộ hóa mtime-delta. Điều này đã bị từ chối: một mtime delta không thể tuyên truyền điều khiển từ xa rm, vậy read/glob cuối cùng sẽ nói dối về Không gian làm việc. Thay vào đó, tập tin các công cụ hoạt động trực tiếp trên hệ thống tệp hộp cát thông qua đường nối phụ trợ — harness pi ExecutionEnv mẫu "hoán đổi tập hợp" (hoán đổi phần phụ trợ I/O của công cụ tệp trên mỗi môi trường thực thi).
  2. Vận chuyển tối thiểu. Với hoạt động tệp trực tiếp, không có đồng bộ hóa cho mỗi cuộc gọi; các byte duy nhất vượt qua là MỘT lần tải lên bootstrap khi tạo và (Chỉ phương thức) MỘT lần quét xuất cuối phiên.

Các sự kiện được xác nhận trong khi xác định phạm vi (chuỗi công cụ đã cài đặt): modal 1.5.1 vạch trần Sandbox.filesystem (SandboxFilesystem) với read_bytes / write_bytes / copy_from_local (máy chủ→điều khiển từ xa) / copy_to_local (từ xa→máy chủ) / list_files / make_directory / remove / stat - được xác minh qua modal.sandbox_fs; ContainerProcess.stdin là một thứ có thể ghi được StreamWriter (tar-over-exec cũng là khả thi cho bootstrap). Docker CLI, cấu trúc liên kết Proxy thông tin xác thực và tính an toàn khi phát lại {"cache": False} config không thay đổi so với ADR-0011. ADR này được chuẩn bị thành các nhiệm vụ 078–085 (tính năng isolated-workspace).

Quyết định

  1. Thay thế, không thêm. Trong chế độ hộp cát, Không gian làm việc bị cô lập là hoạt động — phần tách M8 (công cụ lưu trữ tệp trên repo thực + bash trong một vết xước) sẽ ngừng hoạt động ở trạng thái hướng tới người dùng. none vẫn giống hệt byte (máy chủ LocalExecutor; công cụ tập tin đường dẫn trực tiếp; deps.cwd == khởi chạy cwd).

  2. Một SandboxExecutor + hai phần phụ trợ mỏng. Hai người thực thi hợp nhất thành MỘT SandboxExecutor (tạo → thực thi bash -lc <cmd> mỗi cuộc gọi → hủy; fresh-exec trong cả hai) trên một SandboxBackend Giao thức mang exec + file ops + vòng đời. Docker's Persist-Shell + marker/$? giao thức + máy shell-reset/kill-and-restart bị xóa; thời gian chờ của docker bây giờ sẽ giết chết một cái docker execvà container vẫn tồn tại (phản ánh quy tắc exec-dies-sandbox-survives của Modal). Tính bền vững của hệ thống tập tin vẫn ở cả hai (một vùng chứa/một hộp cát mỗi phiên).

  3. Không gian làm việc = sao chép tại thư mục gốc. /workspace (hộp cát) ≡ máy chủ .decode/sandbox/ (settings.sandbox_workspace_dir) ≡ a git clone của repo người dùng cung cấp thông qua --repo <url-or-local-path> / SANDBOX_REPO (bản sao phía máy chủ tại HEAD đã cam kết của nguồn, sử dụng tín dụng git xung quanh; --local để có bản sao cục bộ nhanh). Không có repo → Không gian làm việc trống. --repo với SANDBOX_MODE=none → một dòng stderr thân thiện, lối ra khác không. Kết quả được trả về thông qua việc xây dựng Trở lại tay (§8), không đẩy thủ công.

    Sửa đổi (2026-07). Việc hạ cấp thành trống trên một bản sao không thành công vẫn là chính sách của REPL và chỉ REPL's: nó giả sử một người đọc cảnh báo và phản ứng. Cuộc chạy headless không có chuyện đó con người, do đó, sự thất bại của quá trình nhân bản hiện là gây tử vong (runtime/flow.py::_prepare_headless_tool_scope). Điều gì đã buộc điều này: một URL trình duyệt (…/tree/main) đã qua dưới dạng --repo để ba agent được trả lương chạy tới hoàn thành bên trong Không gian làm việc trống và Người giao lại sau đó đã từ chối gửi bất kỳ không gian làm việc nào trong số đó ("không phải là git repo có nguồn gốc"). Sự xuống cấp trong im lặng chỉ là một mặc định hợp lý khi có ai đó đang xem; nếu không, nó sẽ chuyển lỗi đánh máy trong một giây thành N lần chạy lãng phí.

  4. Công cụ tệp hoạt động trên hệ thống tệp hộp cát thông qua đường nối ("hoán đổi bộ"). SandboxBackend Giao thức phát triển read_bytes / write_bytes / make_directory / list_dir / stat / remove; logic phía máy chủ được chia sẻ (ngăn chặn, tìm kiếm/thay thế của chỉnh sửa, cắt ngắn, kết xuất) vẫn ở trên đường nối và chỉ vận chuyển byte là cho mỗi phần phụ trợ. Docker hoạt động của tệp là pathlib đơn giản trên Workspace được gắn liên kết (mount làm cho thư mục máy chủ be hộp cát fs - zero hệ thống ống nước từ xa, luôn trung thực). **Các hoạt động của tệp Modal là SandboxFilesystem API (trực tiếp chống lại điều khiển từ xa - không có gương). glob/grep chạy dưới dạng lệnh từ xa (find/grep) thông qua exec cho cả hai phần phụ trợ (không bao giờ tải xuống cây để tìm kiếm), với tính chẵn lẻ đầu ra cho máy chủ triển khai. Ngăn chặn được phân lớp: phía trên đường nối, toán học về đường dẫn bất khả tri phụ trợ (_resolve_logical, một nếp gấp gốc logic - không phải máy chủ Path.resolve, vì đường dẫn Modal không phải là máy chủ đường dẫn) từ chối .. / lối thoát tuyệt đối cho cả hai chương trình phụ trợ; và bởi vì docker mount được chia sẻ với máy chủ, phần phụ trợ docker ngoài ra giải quyết các liên kết tượng trưng về mặt vật lý bên dưới đường nối và tăng lên WorkspaceEscape (một OSError lớp tệp hiển thị dưới dạng từ chối), do đó, một liên kết tượng trưng được đặt trong Không gian làm việc bởi bash không thể theo dõi quá trình gắn kết vào máy chủ - chỉ riêng chuỗi toán học không thể nhìn thấy một liên kết tượng trưng. Modal không cần lớp như vậy (tệp chỉ hoạt động từ xa trên hộp cát dùng một lần - không có fs máy chủ để trốn vào). none chế độ giữ các công cụ đường dẫn trực tiếp ngày nay, giống hệt byte.

  5. Việc vận chuyển là tối thiểu (đồng bộ hóa mtime đã ngừng hoạt động). Docker: liên kết gắn kết là phương tiện vận chuyển duy nhất (luôn hoạt động - không khởi động, không xuất). Modal: MỘT tải lên bootstrap của repo nhân bản + kỹ năng gieo mầm tại sandbox tạo (copy_from_local / tar-over-exec) và ONE cuối phiên càn quét xuất khẩu /workspace → chủ nhà .decode/sandbox/ (copy_to_local) nên không gian làm việc cuối cùng là Host-visible để chuyển giao git. Giữa phiên /ship có thể kích hoạt tính năng xuất độc lập ( hộp cát vẫn tồn tại). Không có điểm đánh dấu, không có vùng đồng bằng cho mỗi cuộc gọi, không có máy móc giới hạn kích thước.

  6. Trang chủ khai thác so với phạm vi công cụ. Cwd ra mắt là Trang chủ khai thác — .decode/sessions, .decode/MEMORY.md, nhật ký, .decode/skills, và .decode/settings.json tập tin quyền luôn neo ở đó. Chỉ phạm vi công cụ của agent (deps.cwd) di chuyển vào Không gian làm việc. AgentDeps phát triển harness_home; danh mục kỹ năng/người điều phối và bộ nhớ được đọc harness_home, trong khi công cụ tìm kiếm/tập tin + bash đọc deps.cwd. extract_on_exit, việc tạo nhật ký phiên và tải/lưu giữ tệp quyền được xâu chuỗi với harness_home một cách rõ ràng. TRONG none chế độ hai đều bình đẳng.

  7. Quy tắc đặt công cụ: chỉ tính toán tùy ý vượt qua ranh giới. Khai thác có cấu trúc các hoạt động vẫn ở phía máy chủ, với hiệu ứng của chúng nằm trong Không gian làm việc nếu có liên quan:

    (Các) công cụVị tríPhạm vi
    read / write / editlogic máy chủ, vận chuyển byte qua đường nối phụ trợKhông gian làm việc (deps.cwd)
    glob / greplogic máy chủ; việc tìm kiếm thực hiện trong hộp cát (exec tìm/grep)Không gian làm việc
    bashbên trong hộp cátKhông gian làm việc
    enter_plan_mode / exit_plan_mode / sleep / todo_write / skill / ask_userchủ nhàtiêm trạng thái / bối cảnh khai thác thuần túy; Nhiệm vụ + tạo phẩm phiên/bộ nhớ tại Harness Home
    web_fetchchủ, vẫn bị kiểm soát ngay cả ở chế độ hộp cátđến mạng chủ
    lsp + Công cụ làm giàu chẩn đoán sau chỉnh sửamáy chủ (ty), chỉ vào đường dẫn Workspacenone+docker: các tập tin Workspace trực tiếp; modal: nỗ lực tốt nhất-vô hiệu hóa + ghi chú thân thiện (ADR-0007-nhất quán)
    agent/agent phụ (M10, tương lai)vòng lặp máy chủ; các công cụ của nó kế thừa các đường nối phiên (đường nối trình thực thi cấp mô-đun + tương tự deps.cwd) - nó bash đưa vào phiên hộp cát CÙNG, các công cụ tệp của nó trong cùng một Không gian làm việcKhông gian làm việc miễn phí (không có máy móc mới)
    Nhà máy MCP (M15, tương lai)quyết định vị trí trên mỗi máy chủ (công việc trong tương lai)—
  8. Trở lại Git — khai thác vận chuyển Không gian làm việc dưới dạng Nhánh phiên, phía máy chủ. Kết quả của phiên hộp cát được đảm bảo tồn tại: khai thác (a) thu thập git Workspace cục bộ tiểu bang tại .decode/sandbox (docker: mount trực tiếp; modal: bị người thực thi quét xuống export() đầu tiên — /ship kích hoạt xuất khẩu giữa phiên); (b) đảm bảo chúng vào một cơ chế xác định decode/<session-id-short> Chi nhánh phiên — mô hình không được tin cậy để cam kết, do đó nhánh được trỏ vào trạng thái cuối cùng và bất kỳ cây công việc bẩn nào đều được tự động cam kết (của chính mô hình các nhánh/cam kết được giữ nguyên, không bao giờ viết lại); và (c) gửi chúng với git Push Origin decode/<session-id> using the user's ambient host credentials — --repo <URL> hạ cánh nhánh trên điều khiển từ xa, --repo <local path> trong repository nguồn cục bộ, không có thông tin xác thực. ** Mỗi lệnh git chạy phía máy chủ đối với Không gian làm việc cục bộ — không có thông tin xác thực nào được đưa vào hộp cát**, giống hệt bất biến bí mật không bao giờ có trong hộp cát mà Proxy thông tin xác thực (§9) duy trì. Nó bị bỏ qua vì Không gian làm việc no-repo / non-git / không thay đổi-vs-clone-HEAD. Độ bền theo lớp: Phiên cục bộ Nhánh luôn tồn tại ngay cả khi việc đẩy không thành công (một dòng thân thiện đặt tên cho nó và .decode/sandbox/ vị trí). Được kích hoạt cả hai tự động (Lối ra REPL — nỗ lực tối đa/không gây tử vong cùng với việc phân tích bộ nhớ/LSP/bộ thực thi; headless decode run --repo hoàn thành) và một cách rõ ràng (chỉ nhàn rỗi /ship Lệnh TUI, dành riêng như /compact//clear, in ấn nhánh + kết quả đẩy; một dòng thân thiện "không có không gian làm việc hộp cát" trong none chế độ).

    Bản sửa đổi (2026-07, lần chạy từ xa đầu tiên). "Phía máy chủ" nghĩa là quy trình sở hữu Không gian làm việc, cái trên ngăn xếp từ xa không phải là máy đã gõ decode run. Một bản sao chạy headless, hoạt động và quét lại Không gian làm việc của nó bên trong vùng chứa luồng Kitaru; vận chuyển từ do đó việc gửi cli đã đẩy chiếc máy tính xách tay đó không liên quan .decode/sandbox trong khi cuộc chạy là thực tế công việc đã chết với container. Hai bản sửa lỗi, cả hai đều tồn tại trong mã:

    • Tay quay headless chạy trong dòng (runtime/flow.py::_ship_headless_workspace), trong finally, sau người thực thi gặt hái - gặt là thứ quét qua hộp cát phương thức hệ thống tập tin vào Không gian làm việc đang được chuyển đi. Ngăn xếp cục bộ không bị ảnh hưởng (luồng chạy đang trong quá trình, cùng một cwd). REPL / /ship các đường dẫn không thay đổi.
    • Quá trình đẩy không có thông tin xác thực xung quanh trong vùng chứa luồng, do đó, nó xác thực bằng SANDBOX_GIT_TOKEN khi một cài đặt được thiết lập — trong quy trình khai thác, thông qua cùng một thông tin xác thực người trợ giúp mà Công nhân nhận được. Không thay đổi: không có thông tin xác thực nào được đưa vào hộp cát (ADR-0016 §4). Và dòng không bao giờ mất kết quả không còn hứa hẹn chi nhánh địa phương là "an toàn": trong một lần chạy từ xa nhánh tồn tại chính xác như thời gian tồn tại của container.
  9. Giữ lại từ ADR-0011, không thay đổi. CommandExecutor đường may + SANDBOX_MODE khởi động bảo vệ (§1); sự an toàn khi chơi lại {"cache": False} điểm kiểm tra bash khi sandbox_mode != "none" (§5); Proxy thông tin xác thực của docker không có giao diện — hiện được kết nối với docker bộ điều hợp phụ trợ, install_executor đường may còn nguyên vẹn (§6); và bảng bậc thang phụ trợ cách ly (§7). REPL tương tác không có kitaru và none đường dẫn không nhập mô-đun hộp cát.

  10. Thông tin đăng nhập của công cụ Sandbox — một SANDBOX_GIT_TOKEN, được chèn khác nhau cho mỗi chương trình phụ trợ. Ngoài ra sự hỗ trợ từ phía máy chủ (§8), một mô hình có thể muốn thực hiện cuộc gọi được xác thực của riêng mình từ bên trong Không gian làm việc — git push chi nhánh của nó, gh pr create — để kết quả đi từ xa → từ xa mà không có xuất/gửi "đồng bộ" phía máy chủ. Cài đặt đơn, SANDBOX_GIT_TOKEN, cung cấp điều đó thông tin xác thực cho cả hai chương trình phụ trợ; chỉ có cơ chế tiêm là khác, bởi vì chỉ docker mới có thể đồng định vị một proxy:

    • docker → Proxy thông tin xác thực (không có tín dụng). Sidecar mitmproxy headless được giữ lại (§9 / §6) đưa thông tin xác thực sau khi yêu cầu rời khỏi nhân viên, trên mạng docker mỗi lần chạy — công nhân giữ token no. Khi nào SANDBOX_GIT_TOKEN được đặt không trống proxy tự động tương tác (không tách biệt SANDBOX_CREDENTIAL_PROXY_ENABLED cờ cần thiết) và github_token_rules xây dựng hai quy tắc tiêu đề phía máy chủ từ một token đó - Bearer for api.github.com, Cơ bản x-access-token:<PAT> cho github.com git Transport (git-over-HTTPS của GitHub không chấp nhận Bearer). git là được cài đặt vào trình chạy có dây proxy khi tạo (apt của nó thoát ra thông qua chuyển tiếp của proxy với máy nhân bản Debian, CA đã được tin cậy) để quy tắc Cơ bản có một máy khách - một mô hình git push từ bên trong hộp cát xác thực từ đầu đến cuối trong khi nhân viên không có token. (Cổng đang mở giá trị đã giải quyết, phản ánh phương thức if token:: rõ ràng SANDBOX_GIT_TOKEN= quyết định không giá trị và để proxy xuống — nó không bao giờ tham gia và đưa vào các tiêu đề rác trống.) SANDBOX_CREDENTIAL_PROXY_ENABLED cờ + DEFAULT_PROXY_RULES (Bí mật Kitaru) vẫn là tướng quân đường dẫn cho các máy chủ khác. Đây là con đường cứng rắn; nó tốn một thùng chứa mitmproxy và CA-trust bước.
    • modal → tiêm trực tiếp (SANDBOX_GIT_TOKEN). Modal không có mạng cùng vị trí để chạy proxy bật, do đó, token tương tự được đưa vào hộp cát: SANDBOX_GIT_TOKEN cưỡi một modal.Secret vào sandbox env như GITHUB_TOKENvà một git người trợ giúp thông tin xác thực đã nướng sẽ đọc $GITHUB_TOKEN tại thời điểm đẩy (vì vậy token sẽ sử dụng Bí mật, không bao giờ là lớp hình ảnh được lưu trong bộ nhớ đệm). GITHUB_TOKEN phục vụ cả hai git push và gh cùng một lúc - không có base64, không sắp xếp quy tắc, không có token giả. Đơn giản hơn nhưng token có có thể đọc được bên trong hộp cát. nguồn được thống nhất (một cài đặt); cơ chế sự bất đối xứng được chọn có mục đích: docker chia sẻ hạt nhân máy chủ, do đó việc giữ bí mật cho nhân viên (tiêm sau khi xuất ra) sẽ kiếm được sự phức tạp; modal là một hộp từ xa, phù du, do đó, token có phạm vi bên trong nó có một vụ nổ giới hạn bán kính và mua sự đơn giản thực sự — được giảm nhẹ bằng cách yêu cầu PAT chi tiết, có phạm vi repo (Nội dung
    • Yêu cầu kéo), không phải là token cổ điển rộng rãi. SANDBOX_GIT_TOKEN trống — bỏ đặt (mặc định) hoặc an rõ ràng SANDBOX_GIT_TOKEN= — không tiêm gì vào cả hai chương trình phụ trợ và tắt proxy docker trừ khi cờ chọn tham gia, do đó, bất biến nghiêm ngặt "không có bí mật trong hộp cát" được giữ cho đến khi người vận hành chọn tham gia; sự hỗ trợ từ phía máy chủ (§8) vẫn là cách không cần thông tin xác thực để gửi kết quả.

    Sửa đổi (2026-07-13 — gh tàu ở cả hai hộp cát; docker cần token mồi nhử). §10 được đặt tên gh pr create như một trường hợp thúc đẩy nhưng chỉ từng cài đặt git. Một cuộc chạy thực sự đã chứng minh khoảng cách: mô hình đẩy nhánh của nó rồi chết gh: command not found — lực đẩy đã hạ cánh rồi, nên lần lượt đã hoàn thành một nửa, đó là hình dạng thất bại tồi tệ nhất có thể xảy ra. gh hiện đã được cài đặt cùng với git trong cả hai phần phụ trợ (nó không có trong mọt sách Debian, vì vậy cả hai đều lấy repository apt của GitHub): docker cài đặt nó mỗi phiên trong _git_setup_command(); modal sẽ biến nó thành một lớp hình ảnh được lưu trong bộ nhớ cache.

    Đường dẫn docker cần một điều mà ADR này không lường trước được — và §10 ở trên đã gợi ý về điều đó khi nó ghi nhận phương thức cần "không có token giả". gh từ chối đưa ra bất kỳ yêu cầu nào khi nó không tìm thấy token nào trong env của nó: nó bị lỗi cục bộ với gh auth login, không bao giờ gửi yêu cầu HTTP proxy tồn tại để xác thực. Do đó, một công nhân không có thẻ không thể lái xe gh, dù thế nào đi chăng nữa sửa các Quy tắc proxy. Vì vậy, người được ủy quyền đưa cho công nhân một mồi nhử GH_TOKEN (proxy._GH_PLACEHOLDER_TOKEN): gh tiến hành, gửi Authorization: token <decoy>, và phần bổ sung ghi đè tiêu đề đó bằng thông tin xác thực thực sau khi yêu cầu đã rời khỏi nhân viên (mitmproxy's headers[name] = value thay thế thay vì nối thêm). Tính bất biến không bị ảnh hưởng - mồi nhử là một chuỗi trơ không xác thực gì cả và thông tin xác thực thực sự vẫn chỉ tồn tại trong vùng chứa proxy. Chi phí có thể quan sát được: docker exec <worker> env | grep -i token bây giờ in mồi nhử thay vì không có gì, vì vậy "công nhân không giữ token" được xác minh bằng cách kiểm tra xem nó chứa gì không phải là bí mật, đúng hơn là nó chẳng có gì cả.

    phương thức không cần mồi nhử: gh đọc thực tế GITHUB_TOKEN cái modal.Secret đã tiêm rồi.

    Sửa đổi (2026-07-13 — DEFAULT_PROXY_RULES tên Settings các lĩnh vực, không phải bí mật của Kitaru). Trong đó §10 nói SANDBOX_CREDENTIAL_PROXY_ENABLED cờ + DEFAULT_PROXY_RULES (Bí mật của Kitaru) vẫn là đường dẫn chung cho các vật chủ khác, một nửa bí mật Kitaru được thay thế (ADR-0015 §6): mẫu tiêu đề của quy tắc đặt tên cho Settings trường ({{ acme_api_token }}) và giải quyết từ cấu hình ngậm nước — ở điều khiển từ xa DECODE_ENV giá trị đến thông qua Nhóm môi trường. Cờ, danh sách quy tắc và vai trò đường dẫn chung không thay đổi; chỉ có đường nối độ phân giải được di chuyển. SANDBOX_GIT_TOKEN / github_token_rules() (cái này chủ đề của phần) không bị ảnh hưởng — chúng xây dựng các giá trị tiêu đề theo nghĩa đen, vì base64 cơ bản biến đổi là một phép tính mà không mẫu nào có thể diễn đạt được.

Sơ đồ

flowchart TB
    subgraph home["HARNESS HOME = launch cwd (always anchors artifacts)"]
        art[".decode/sessions · .decode/MEMORY.md · logs<br/>.decode/skills · .decode/settings.json"]
    end

    subgraph none["SANDBOX_MODE=none (DEFAULT — byte-identical)"]
        nfiles["read/write/edit/glob/grep — direct pathlib"]
        nbash["bash — LocalExecutor (host subprocess)"]
    end

    subgraph sandbox["SANDBOX_MODE=docker|modal — ISOLATED WORKSPACE"]
        tools["file/search tools + bash<br/>deps.cwd = WORKSPACE (logical root)<br/>shared logic host-side: containment · edit · truncate · render"]
        exec{{"SandboxExecutor (one) — create · exec bash -lc · export · destroy<br/>SandboxBackend Protocol: exec + file ops"}}
        tools --> exec
        docker["DockerBackend<br/>exec = docker exec (fresh) · file ops = pathlib on the MOUNT<br/>-v .decode/sandbox:/workspace (live, always truthful)"]
        modal["ModalBackend<br/>exec = sb.exec (fresh) · file ops = SandboxFilesystem (direct)<br/>glob/grep = remote find/grep · 1 bootstrap upload + 1 export sweep"]
        exec --> docker
        exec --> modal
        ws["WORKSPACE = /workspace ≡ .decode/sandbox<br/>= git clone of --repo (or empty)"]
        docker -->|bind mount| ws
        modal -->|copy_from_local / copy_to_local| ws
    end

    subgraph proxy["CREDENTIAL PROXY (retained, headless+docker) — worker holds NO secret"]
        mitm["mitmproxy addon container — injects header after the request leaves the worker"]
    end
    docker -. proxy path .-> mitm

    subgraph gtok["SANDBOX_GIT_TOKEN (opt-in, §10) — ONE token, injected per-backend"]
        tok["docker: sources the proxy (auto-engages) → Bearer/Basic header after egress, worker token-free<br/>modal: modal.Secret → GITHUB_TOKEN env + git credential helper (readable in-sandbox by design)"]
    end
    tok -. docker: feeds .-> mitm
    modal -. modal: direct inject .-> tok

    git(["Hand-back: decode/&lt;session-id&gt; branch<br/>secured + pushed host-side — no cred in the sandbox"])
    ws --> git

    classDef homec fill:#4527a0,stroke:#311b92,color:#ffffff;
    classDef nonec fill:#1565c0,stroke:#0d47a1,color:#ffffff;
    classDef toolc fill:#00838f,stroke:#005662,color:#ffffff;
    classDef seamc fill:#37474f,stroke:#102027,color:#ffffff;
    classDef exec fill:#2e7d32,stroke:#1b5e20,color:#ffffff;
    classDef wsc fill:#ef6c00,stroke:#e65100,color:#ffffff;
    classDef sec fill:#c62828,stroke:#8e0000,color:#ffffff;
    classDef ext fill:#6a1b9a,stroke:#38006b,color:#ffffff;
    class art homec;
    class nfiles,nbash nonec;
    class tools toolc;
    class exec seamc;
    class docker,modal exec;
    class ws wsc;
    class mitm sec;
    class tok mcredc;
    class git ext;
    classDef mcredc fill:#ad1457,stroke:#880e4f,color:#ffffff;

hậu quả

  • Một đường may, một hình dạng, một mô tả. Hai người thực thi + hai bash mô tả thu gọn thành một SandboxExecutor + một đoạn sandbox thống nhất; quy tắc thực thi mới giống hệt nhau trên các chương trình phụ trợ. Các trường hợp cạnh shell cố định (đồng bộ hóa điểm đánh dấu, đặt lại shell, chia nhỏ không có vòng lặp) đều bị xóa mã.
  • Công cụ tệp không bao giờ nói dối. Hoạt động của tệp trực tiếp (docker mount / modal SandboxFilesystem) có nghĩa là read / glob luôn phản ánh Không gian làm việc thực sự - bao gồm cả việc xóa - mà mirror+mtime-sync bị từ chối không thể đảm bảo. Giá là một chuyến khứ hồi từ xa cho mỗi hoạt động trên Modal (có thể chấp nhận được; lớp công cụ là tuần tự).
  • Vận chuyển tối thiểu. Chỉ tải lên bootstrap (cả hai) và xuất cuối phiên (Modal) vượt qua dây; docker cưỡi thú cưỡi của nó miễn phí.
  • Sự cô lập là thực tế và thống nhất — toàn bộ phạm vi công cụ của agent là Không gian làm việc; harness hiện vật riêng ở tại Harness Home; git là sự hỗ trợ thông qua cơ chế đẩy phía máy chủ nhỏ (cam kết → chi nhánh → git push), với thông tin xác thực vẫn nằm trong quá trình lưu trữ — không bao giờ nằm trong Worker, bất biến giống như Proxy thông tin xác thực.
  • Kết quả tồn tại theo từng lớp — việc chuyển giao luôn để lại dấu vết cục bộ decode/<id> chi nhánh (công việc bẩn thỉu được giữ lại, cam kết mô hình được giữ nguyên) và đẩy nó đến --repo nguồn khi tín dụng cho phép; một cú đẩy thất bại là một dòng đặt tên chi nhánh thân thiện, không bao giờ bị mất phiên. Tự động thoát + rõ ràng /ship.
  • Các subagent M10 kế thừa điều này miễn phí — chúng chạy trên vòng lặp máy chủ nhưng các công cụ của chúng nhận đường nối thực thi cấp mô-đun + deps.cwd, vì vậy họ bash và nộp hồ sơ cho các hoạt động trong cùng một phiên Không gian làm việc không có hệ thống dây điện bổ sung.
  • Giữ lại các đảm bảo — trình bảo vệ khởi động, an toàn phát lại, Proxy thông tin xác thực (công nhân giữ không có bí mật), thang cách ly, REPL không có kitaru và byte giống hệt none con đường.
  • Một token, hai tư thế (§10). Một đơn SANDBOX_GIT_TOKEN cung cấp thông tin xác thực trong hộp cát cho một công cụ đã được xác thực gọi từ bên trong sandbox trên cả hai chương trình phụ trợ — docker cung cấp nó cho Proxy thông tin xác thực (tự động tham gia, nhân viên không có token), phương thức giao dịch độ cứng để đơn giản bằng cách tiêm nó vào sandbox env. Nguồn thống nhất; chỉ có cơ chế khác nhau. Mặc định (trống) không tiêm gì và dựa vào sự hỗ trợ của phía chủ nhà nên "không có bí mật trong hộp cát" vẫn giữ ở mọi nơi cho đến khi nhà điều hành chọn tham gia. Chi phí trung thực: token modal đã chọn tham gia có thể được đọc bởi một agent được đưa vào nhanh chóng, chỉ bị giới hạn bởi phạm vi của PAT — lý do khiến đường dẫn docker vẫn dựa trên proxy.
  • Trần trung thực (ponytail:):
    • LSP phương thức là nỗ lực tốt nhất — ty chạy phía máy chủ và không thể truy cập fs từ xa. Nâng cấp đường dẫn: chạy ty bên trong hộp cát trên stdio đường ống (hoãn lại).
    • Mất phương thức trong chuyến bay khi hồi sinh — hộp cát hết hạn tối đa được tạo lại + khởi động lại từ máy chủ .decode/sandbox trạng thái; các thay đổi trong hộp cát kể từ lần xuất cuối cùng có thể bị mất (tệp ghi chú nói như vậy) - vẫn tốt hơn so với thiết lập lại toàn bộ cũ.
    • Địa phương --repo chỉ nhân bản HEAD — bụi cây làm việc không được cam kết của nguồn cục bộ không được sao chép.

Công việc tương lai

  • Tự động cho phép các công cụ hộp cát — cổng vẫn giữ nguyên byte giống với none chế độ tính năng này (con người- giải quyết); việc xử lý "trong hộp cát" là phê duyệt tự động bị trì hoãn (được thực hiện từ ADR-0011).
  • Khóa lối ra cứng — hợp tác http_proxy/CA vẫn giữ nguyên mức trần; nội bộ từ chối mặc định mạng là đường dẫn nâng cấp (được mang từ ADR-0011).
  • Đầu ra thống nhất cho lưu lượng truy cập web của agent — định tuyến web_fetch (và công cụ gửi đi phía máy chủ khác cuộc gọi) thông qua hộp cát / Proxy thông tin xác thực cho một câu chuyện đầu ra — được xem xét, hoãn lại.
  • ty bên trong hộp cát — bản nâng cấp LSP Modal (và docker chặt chẽ hơn) qua đường ống stdio.
  • Vị trí MCP trên mỗi máy chủ (M15) — các máy chủ MCP hướng tới không gian làm việc bên trong ranh giới, bên ngoài-SaaS phía máy chủ; quyết định khi nào nhà máy MCP hạ cánh.
  • git-aware /Manifest Transport — nếu tar bootstrap/export cần mở rộng quy mô, a vận chuyển địa chỉ nội dung hoặc git-diff thay thế bản sao toàn bộ cây.
  • Tạo PR tự động (gh pr create) — xoay nút đẩy decode/<id> Phiên Chi nhánh thành một kéo yêu cầu - được chuyển sang M14 (bước đánh giá PR trên đám mây).
Mục lục nguồn