Skip to content

Cold launch fetches exactly the requested ref; delete the workspace-clone fetch #150

Closed

Description

@blooop

Question

Per the #144 decision, the foreground cold path makes exactly one narrow network call and no broad one. Depends on the updater-sweep build ticket (the sweep must exist before the foreground stops sweeping).

  • ensure_repo (repo_manager.py:204-236) stops fetching: remove the _should_fetch/fetch_repo branch and the auto_fetch parameter (production never passes False; tests that did get the behavior for free). It becomes the pure locked clone-if-missing primitive.
  • ensure_branch (workspace_clone.py:172-206): replace lazy_fetch (:190) with an unconditional targeted fetch of the requested ref into the bare repo (git fetch origin +refs/heads/<branch>:refs/heads/<branch>); on ref-missing-on-remote, one targeted fetch of the default branch before ensure_branch_exists bases on it. Model the outcome as the three-way result from Move the interval git fetch off the foreground launch path and out of the repo lock #144 (updated / ref-missing / network-failed → proceed-fresh / create-from-default / warn-and-use-cache-or-error), not a bool. Do not write last_fetched here.
  • Delete _prepare_workspace step 4 (workspace_clone.py:298-310) — its output is unused (plain git checkout <branch> at :338).
  • Do not restructure lock cycles — Collapse the duplicated ensure_repo passes and repo-lock cycles on the cold path #143 owns that seam.

Failing tests first: (1) the lock-aware fetch pin from #144 — no +refs/heads/* fetch in the foreground, only the targeted refspec ever under the repo lock (flock LOCK_NB probe in the fake subprocess.run); (2) re-registration path runs zero fetch in the workspace clone; (3) staleness contract integration: remote gains a commit after the cache cloned → new workspace HEAD == remote tip; ref only on remote → succeeds; ref nowhere → existing error.

Files: devlaunch/worktree/repo_manager.py, devlaunch/worktree/workspace_clone.py, test/test_worktree_repo_manager.py (existing auto_fetch tests), test/integration/test_repo_manager_real.py.

Activity

  1. self-assigned this
    on Aug 14, 2026
  2. blooop commented on Aug 14, 2026

    @blooop
    OwnerAuthor

    breadcrumb: claimed and building on branch off up-to-date main (the #149 updater sweep is merged, so the foreground can stop sweeping). Restating the slice: the cold launch makes exactly one narrow network call — a targeted fetch of the requested ref — and no broad one; ensure_repo becomes the pure clone-if-missing primitive; the workspace-clone fetch is deleted.

    Seams I will test at, per the #144 resolution:

    1. The subprocess.run boundary, with a lock-held probe (open the repo lock path in a second file description and try a non-blocking flock). Pins: no broad all-refs fetch anywhere in the foreground, and any fetch recorded while the repo lock is held carries only the single targeted refspec.
    2. The same boundary for the re-registration path (clone already on disk): zero fetch in the workspace clone.
    3. A real-git integration seam over a local file-URL remote for the staleness contract: remote gains a commit after the cache cloned it → new workspace starts at the remote tip; ref only on the remote → succeeds; ref nowhere → the existing error verbatim.

    The targeted-fetch outcome will be a three-way result (updated / ref-missing-on-remote / network-failed), not a bool, and it will not write last_fetched — that bookkeeping stayed with the sweep. Not touching lock cycles; #143 owns that seam.

  3. blooop commented on Aug 14, 2026

    @blooop
    OwnerAuthor

    breadcrumb: built and opened PR #185.

    The slice: the cold launch now makes exactly one narrow network call — a targeted fetch of the requested branch — and no broad one. ensure_repo is the pure clone-if-missing primitive (the auto_fetch knob went with the fetch it gated), and the workspace-clone fetch is deleted, since the checkout beside it never read a remote-tracking ref.

    The targeted-fetch outcome is the three-way sum the resolution asked for, following the Unsaved idiom already in workspace_state.py (frozen dataclasses, a Union alias, and an unhandled_* arm-checker for the py310-compatible exhaustiveness check). Keeping "the remote says the ref is not there" apart from "the remote did not answer" turned out to be load-bearing in two places: only the former licenses cutting the branch from the default branch, and only the latter means fall back to the cache. It does not write last_fetched.

    Two things worth recording for whoever reviews or builds on this:

    • The lock-held probe works as the resolution predicted — opening the lock path in a second file description and attempting a non-blocking flock conflicts with the production code's own lock inside one process, so the test measures the real lock rather than bookkeeping a test could get wrong.
    • One unproven name reaches the new fetch: the default branch is read back from metadata, not proven by a WorkspaceId like the requested branch is. Rejecting it raises ValueError, which the launch path does not guard for around ensure_branch, so a hand-edited record would have surfaced as a traceback. It is caught at that one call and logged, leaving the failure to git as before.

    A test from #149 had explicitly deferred its own subject here (it pinned the foreground broad fetch as untimed, noting #150 would decide its future); it is rewritten, since that fetch is gone.

    Each pin was checked by reintroducing the regression rather than only by passing against the fix: the deleted fetches put back fail 5 of the 6 lock/fetch pins, and stubbing the targeted fetch to a no-op fails the three freshness assertions in the integration contract. Lock cycles untouched — #143 owns that seam, and per the resolution it now inherits a launch path whose only under-lock network call is bounded by one branch.

  4. blooop commented on Aug 14, 2026

    @blooop
    OwnerAuthor

    Review of #185 (fresh context, two-axis): Request changes — 2 blocking (locale-dependent RefMissingOnRemote detection collapses the three-way outcome; unreachable assertion in the "ref nowhere" pin). #185 (review)

  5. blooop commented on Aug 14, 2026

    @blooop
    OwnerAuthor

    breadcrumb: review fix pass on PR #185 pushed. Both blocking findings closed: git is now addressed in the C locale where its stderr is classified, so the three-way fetch outcome holds under any host locale; and the ref-nowhere pin asserts each of its two failure sites separately, with the staleness-contract docstring corrected to name the branch creation as where an empty cache is discovered. Also warned the previously-silent default-branch fetch failure. The dead auto_fetch config knob was left for its own ticket.

  6. blooop commented on Aug 14, 2026

    @blooop
    OwnerAuthor

    wf-review re-review verdict: Approve — both prior blocking findings verified fixed at HEAD, no new blockers from the fix pass. #185

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

Metadata

Metadata

Assignees

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions