Skip to content

tracked modules should leave clone on tracking branch, not detached #29

Description

@baby-joel

Context

modules init for tracked modules (manifest entries with a <track> column, added in #26) currently does:

git fetch -q origin "$track"
git checkout -q FETCH_HEAD

This intentionally leaves the clone in detached HEAD at the freshly-fetched tracking ref. The consequence: any consumer that wants to edit and push from the clone has to do a follow-up "make it editable" dance themselves (typically in a welcome task or similar).

That dance has a subtle footgun. Reproduced today in baby-joel/home's welcome task:

  1. modules init detaches at origin/main tip — good.
  2. Welcome sees detached HEAD and runs git checkout main to put the clone on a real branch.
  3. The local main branch ref is stale — it points at the previous session's tip, not the freshly-fetched one.
  4. Net effect: git checkout main regresses HEAD by N commits. The drift detector then warns "N commits available — run modules init to pull", even though modules init literally just ran.

The fix on the consumer side is one line — git checkout -B main origin/main — but the failure mode is invisible by default (you only notice if you happen to compare HEAD before and after, or if you have a drift warning that contradicts the just-pulled state). Anyone copying the welcome pattern is at risk.

Proposal

When a manifest entry has a <track> ref, modules init should leave the clone on a real branch tracking the remote, not detached at FETCH_HEAD.

Concretely, replace:

git fetch -q origin "$track"
git checkout -q FETCH_HEAD

with something like:

git fetch -q origin "$track"
git checkout -B "$track" "origin/$track" -q
# (optionally: git branch --set-upstream-to "origin/$track" "$track")

Semantics:

  • Reproducibility unchanged: tracked clones still end up at exactly origin/<track> tip.
  • Editability becomes the default for tracked modules: the clone is push-ready out of the box; consumers don't need a follow-up dance.
  • Untracked (purely pinned) modules still detach at the pin — no behavior change.

This matches the spirit of the original tracking design (#19): "freshness layer for gitignored local clones." If the clone is meant to be the editable view of a tracked repo (which is the emerging pattern for home repos using den/fold via modules), making it editable is the obvious default.

Why this is the right layer

Right now every home that wants to edit through modules/ has to reimplement the same checkout dance, and any subtle bug in that dance (like the one above) propagates. Today only baby-joel/home does the dance — but per recent house decisions we're migrating all agent homes to treat modules/{den,fold} as the canonical editable clone (replacing the old ~/agents/<name>/{den,fold} workspace clones). That means every home is about to need the dance, which means the dance should not exist.

Consumers that explicitly want detached state (e.g. CI provisioners that don't push) lose nothing: they were already on the tip; being on a real branch ref doesn't impose any operation, and they can still git checkout --detach HEAD if they want.

Verification approach

  • BATS coverage: extend the init tests in test/init.bats to assert that after modules init on a tracked module, git symbolic-ref HEAD returns refs/heads/<track> and HEAD matches origin/<track>.
  • Regression test: stale local <track> branch (pointing at an older SHA) — after modules init, local <track> should be advanced to origin/<track> (this is exactly the scenario that regresses today on the consumer side).

Out of scope

  • Whether to --set-upstream automatically — separable; safe default but worth its own line of discussion.
  • Whether untracked modules should also stop detaching — no, pin reproducibility relies on detach.

Happy to PR this if the direction lands.

Related

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