Skip to content

roots.revision() takes index.lock in the shared Mech checkouts #123

Description

@realmarcin

Found in the adversarial review of #120.

revision() writes to each Mech repo's .git/index, so the pipeline is no longer read-only against the checkouts

Where: scripts/fleet/roots.py:107

Plain git status refreshes the index opportunistically: it takes index.lock and rewrites .git/index when stat data is stale. Before this PR the pipeline only read the Mech checkouts. Now every census or stats run takes locks in them, twice per Mech. The live checkouts are shared with a nightly fast-forward and with claw agent worktrees (ProteinTraitsMech has three linked worktrees). A concurrent git merge --ff-only or git add that hits the lock window fails with 'Unable to create .../index.lock: File exists'. The window is large for TaxonMech's 626k-entry index.

Failure scenario. Someone runs mech_stats.py against the default MECHS_ROOT during the ~23:13 scheduled fast-forward, or while a claw agent commits in ProteinTraitsMech. revision()'s status holds index.lock while it writes the refreshed index, and the other process's git command aborts.

Evidence. Scratch probe in a CommunityMech clone: touch one record, then GIT_OPTIONAL_LOCKS=0 git status leaves .git/index mtime at 1790307521. Calling roots.revision('CommunityMech') changes it to 1790307541. git worktree list on the live ProteinTraitsMech shows three linked worktrees, including one under culturebotai-claw/workspace/.

Verifier (partly, low). roots.revision() (scripts/fleet/roots.py:107) runs git status --porcelain without --no-optional-locks. On every call it takes .git/index.lock in the checkout under MECHS_ROOT for the whole status scan (about 5 s for TaxonMech), and it rewrites .git/index when stat data is stale. prefix_census.py and mech_stats.py each call it once per Mech. The pipeline does write into the default MECHS_ROOT when run as _fleet/README.md describes: those are the live shared checkouts, and on main the pipeline ran no git there. During that window, any concurrent index-writing git command in the same main worktree (a manual or agent git merge --ff-only, pull, checkout or add there) aborts with "Unable to create .../index.lock: File exists". Commits in linked worktrees, such as the claw worktrees of ProteinTraitsMech, use separate index files and are not affected. No scheduled nightly fast-forward exists on this machine; the fast-forwards in the reflog are ad hoc. The update-xmech-page skill's procedure points MECHS_ROOT at scratch sparse clones, so it only locks throwaway clones. Fix: git --no-optional-locks status --porcelain, or pass env GIT_OPTIONAL_LOCKS=0 to the subprocess. With that, contention dropped to 0 in my test.

Suggested fix. Use git --no-optional-locks status ... (or pass env GIT_OPTIONAL_LOCKS=0 to the subprocess).

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions