Skip to content

Clone the bare repo and mirrors without hardlinks - #127

Merged
moodmosaic merged 1 commit into
protocol-security:masterfrom
orsissimo:fix/bare-no-hardlinks
Nov 3, 2026
Merged

moodmosaic merged 1 commit into
protocol-security:masterfrom
orsissimo:fix/bare-no-hardlinks

Conversation

@orsissimo

@orsissimo orsissimo commented Nov 2, 2026 •

Copy link
Copy Markdown
Contributor

Summary

Changes

  • launch.sh: add --no-hardlinks --dissociate to both bare clones so they copy objects, including those borrowed through alternates. Add comments explaining why copying is needed before chmod -R a+rwX.
  • tests/test_launch.sh: add section 35b using the live create_bare_repo, begin_engagement and mirror_submodules functions with private runtime paths. Use a git clone --shared source with packs, a loose object made after gc, and a submodule with packs. Check agent-work, the mirror's commit, unshared packs and loose object with unchanged modes, and no objects/info/alternates in the bare repo. Check that the borrowed commit remains readable after moving the lender repo away and that every bare clone copies objects.
  • USAGE.md: remove both upstream.git and mirrors from the private runtime directory through an alpine container. Remove the runtime directory and state file only after that succeeds, so files written by a different container UID cannot leave a partial cleanup. Docker and the alpine image are required.
  • CHANGELOG.md: document the fix and remediation under Unreleased. Note that the bare repo and mirrors need their own space where earlier clones shared objects through hardlinks or alternates.

Self-review checklist

  • This PR addresses a single concern (why?). If it covers multiple independent changes, I've split them into separate PRs.

Test plan

Validation after rebase onto cd7d006 (2026-11-03):

  • Unit suite on macOS: 14 files, 1710 tests, 0 failures.
  • Docker runtime signal tests: 16 passed, 0 failed on the preceding base (608c5c5). The second rebase only resolved the changelog; the PR code patch is unchanged (git range-diff).
  • ShellCheck with the CI flags and git diff --check pass.
  • API and OAuth integration phases skipped: ANTHROPIC_API_KEY and CLAUDE_CODE_OAUTH_TOKEN are not set in this session.

Earlier validation, before this rebase:

  • bash tests/test_launch.sh: 245 passed. With master's launch.sh, nine checks in section 35b fail.
  • ./tests/test.sh --unit: macOS Bash 3.2.57, 1399 tests; Ubuntu 24.04 Bash 5.2, 1411 tests as UID 501 and as UID 1000. Each run covered 13 files with 0 failures in the last two full rounds. In the first round one assertion unrelated to this change failed once under load: a grep -q behind a pipe under pipefail, which master's tests have too.
  • ./tests/test.sh --runtime: 16 passed on macOS with OrbStack and on Ubuntu as UID 501 and UID 1000.
  • ShellCheck on all tracked shell files: same notices as master, info level only.
  • ./tests/test.sh --oauth: passed with a real agent on macOS and Ubuntu as UID 501 and UID 1000. The checkout's pack kept one link and its mode.
  • Live run with two real agents on a target with a submodule, on macOS and Ubuntu as UID 501: start, mid-run harvest, stop, post-process (which harvests the agents' work), costs.sh and progress.sh. Ran interactive sessions on the existing bare repo and a fresh bare repo after Cleanup, each followed by harvest. Ran git fsck on the checkout, submodule, bare repo and mirror. After every step, the checkout had no world-writable or multiply linked object file, and no object file changed mode.
  • Remediation on a damaged checkout, on macOS and Ubuntu as UID 501 and UID 1000: a session with master's launch.sh left 10 world-writable, hardlinked object files. The Cleanup block from USAGE.md and the commands from the CHANGELOG entry, run as written, removed the bare repo, mirrors and containers and restored the modes. git fsck passed. A new session and harvest worked with no shared or world-writable object file.
  • Space measured with df on a repository with a 900 MB .git: on macOS, the bare clone went from about 24 MB and 0.07 s to about 885 MB and under 1 s. On Ubuntu with the temporary directory on a separate tmpfs, the old clone already copied, so nothing changed.
  • ./tests/test.sh --all: not run; phase 2 requires an API key.

@moodmosaic

Copy link
Copy Markdown
Member

Thank you, @orsissimo! Can you rebase this?

@orsissimo
orsissimo force-pushed the fix/bare-no-hardlinks branch from a5039b3 to 4dbb314 Compare November 3, 2026 16:14
@orsissimo
orsissimo force-pushed the fix/bare-no-hardlinks branch from 4dbb314 to 27e67f3 Compare November 3, 2026 16:18
@moodmosaic
moodmosaic merged commit ad6237d into protocol-security:master Nov 3, 2026
4 of 5 checks passed
moodmosaic added a commit that referenced this pull request Nov 3, 2026
PR #127 moved the bare repo from /tmp/${PROJECT}-upstream.git into the
private runtime directory (swarm_runtime_dir/upstream.git). runtime_pi.sh
still used the legacy path, so the error and codex containers mounted a
nonexistent upstream and the zero-exit error test failed.

Point BARE at the runtime dir via swarm_runtime_dir, and clean up the whole
runtime directory on teardown.

Model: deepseek-v4-flash (m5m-ds4)
Tools: Pi 1.4.0
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants