Files
multica/.github
Bohan Jiang 734ad51c93 MUL-5774 fix(daemon): isolate Git metadata for Windows Codex checkouts (#6565)
* fix(daemon): isolate Git metadata for Windows Codex checkouts

Codex's sandbox resolves a linked worktree's gitdir to the shared .repos
cache and keeps it read-only even when the task workdir is an explicit
writable root, so `git add` / `git commit` fail from inside a
`multica repo checkout`. Linux was fixed by moving those tasks to a
task-local clone (#2925); Windows native sandbox still took the linked
worktree path and hits the same wall (#6449).

- repoCheckoutModeFor now returns isolated for Windows Codex as well as
  Linux Codex. The MULTICA_REPO_CHECKOUT_MODE -> CLI -> daemon ->
  WorktreeParams.IsolatedGitMetadata chain already carries the mode, so
  no new API surface is needed.
- The isolated clone passes --no-hardlinks on Windows. NTFS hard links
  only exist within one volume and every link shares one underlying file
  and security descriptor, so linking would both break a cross-drive
  cache/workdir pair and let the sandbox re-permission the daemon-owned
  cache's objects. Objects are copied there instead.

The shared cache stays read-only; this does not widen ACLs, add a
writable root, or lean on safe.directory.

Co-authored-by: multica-agent <github@multica.ai>

* fix(daemon): correct Codex sandbox facts and prove Windows checkout in CI

Review follow-up on the Windows isolated-checkout fix.

The source map claimed both Linux and Windows sandboxes keep a linked
worktree's external gitdir read-only. That is not what the daemon does:
execenv's codexSandboxPolicyFor defaults BOTH platforms to
danger-full-access, so only a user who opted into windows.sandbox
actually trips the read-only gitdir. Linux keeping the isolated checkout
is a retained layout, not a live workaround. Agents read this file to
decide whether their checkout can be committed to, so it must not
contradict the sandbox policy. Corrected the source map, the stale
"(Linux Codex)" comment in partial_clone_test.go, and the
repoCheckoutModeFor doc — which now also records why the layout is a
per-platform choice rather than a per-policy one.

builtin_skills_test.go gains "Linux and Windows Codex" and "task-local
Git metadata" anchors; the previous assertions covered only generic repo
wording and would not have caught this platform contract regressing.
Verified the anchor fails when the SKILL.md sentence is reverted.

Windows evidence: cache_windows_test.go asserts on a real Windows host
that the gitdir resolves inside the task checkout, that branch/add/commit
succeed, that the shared cache base ref is unchanged, and that objects
are private copies rather than NTFS hard links — plus a cross-volume
checkout, which is what a hard link cannot express at all. Wired into the
existing windows-execenv CI job, which exists for exactly this class of
"only a real Windows host proves it" regression. The shared no-hardlink
assertion is now one helper used by both the cross-platform and Windows
tests.

This does not replace a manual smoke under a real Codex elevated sandbox
identity; CI cannot assume that identity.

Co-authored-by: multica-agent <github@multica.ai>

* ci: scope the Windows repo-checkout step to the windows-tagged tests

The step used a prefix match, which also selected the package's
cross-platform isolated-checkout test. That test cannot run on Windows:
repocache derives a cache directory name from the full source repo path,
so a t.TempDir() path already embedding a long test name doubles and
exceeds MAX_PATH, and git fails with "Filename too long". It belongs to
the ubuntu backend job, which runs the whole package.

Both windows-tagged tests already passed in the failing run, including
the cross-volume one, which used the runner's real C:/D: pair rather
than skipping. Anchoring the selector to their exact names turns the job
green without weakening any assertion.

Co-authored-by: multica-agent <github@multica.ai>

---------

Co-authored-by: J <j@multica.ai>
Co-authored-by: multica-agent <github@multica.ai>
2026-08-07 16:53:40 +08:00
..