Fix Dispatch Flag Suggestion for Local Checkouts

Claude Code·Opus 5.5·gtrrz-victor·14h ago·32min·1 Checkpoint·3 file changes·+33/-4·14K tokens

The change is sound and close to approvable. I found one real (but small) bug and a few minor issues. The affected tests pass locally (dispatch, search, and the wizard tests in cli). The trail shows CI green and the agent-findings gate passing; the only open gate is approvals.

What the PR does

Dispatch used to reject any non-GitHub origin. It now reads the origin through gitremote.ParseURL and keeps the forge the remote names, producing gh/… or et/…. Cloud mode sends that slug as-is. Local mode labels GitHub repos with their bare name as before and native repos with et/…, with no github.com link. Wizard discovery now includes native checkouts. The old GitHub-only parser in search is removed. Both callers move to the new helper, so nothing still uses the old one.

Findings

1. Local mode tells the user to pass --repos, which --local rejects (cmd/entire/cli/dispatch/mode_local.go:482, :485, :491) resolveOriginRepoSlug is shared by cloud mode and local mode (enumerateRepoCandidates), and all three of its errors now say "pass --repos". But options.go:28 refuses that combination: --repos cannot be used with --local. So someone running entire dispatch --local in a GitLab checkout is pointed to a flag that is then refused. The old messages didn't suggest the flag, so this is new in the PR. Fix: drop the hint from the shared helper and add it in runServer when it wraps the error, or make the message depend on the mode. OriginRepoSlug's own message ("expected gh/<owner>/<repo> or et/<project>/<repo>") reads fine in both modes.

2. Lost test coverage for paths with extra segments (origin_slug_test.go) The deleted TestParseGitHubRemote_RejectsExtraPathSegments covered the strings.Contains(info.Repo, "/") branch. Nothing replaces it, so that branch in OriginRepoSlug is now untested. Suggested table rows:

  • https://github.com/acme/thing/extra.git
  • entire://cell/et/proj/repo/extra

The ssh://git@github.com/… form also lost its only test.

3. Nit: the origin slug isn't checked against the --repos grammar OriginRepoSlug builds forge/owner/repo by hand. The round-trip test checks only two remotes against normalizeRepoSlug. A native project or repo name that repoNamePattern rejects (for example a leading _) would be sent by default but refused if typed explicitly. That is exactly what the round-trip test says must not happen. Running the result through SplitRepoSlug would make that rule hold for every input.

4. Nit: stale comment (repo_url.go:14-16) It still says "the origin remote is GitHub by construction". The code still behaves correctly, because only gh slugs reach it bare, but the reasoning in the comment is no longer true.

5. The known follow-up is now more visible The PR lists "authenticated repo list labels every row gh/" as out of scope. Now that disk discovery returns et/…, a native repo could appear as both et/x/y (from disk) and gh/x/y (from the server list) in the picker, if the server listing includes native repos. I didn't verify whether it does. It's fine to defer, but it's worth a tracked issue.

Verdict: approve once #1 is fixed. #2 is a quick addition, and #3–#5 are optional. I haven't posted anything on the trail; I can add these as trail comments or request changes if you want.

uhm,quick question. Why was it failing because of the forge? is it fetching remote changes?

14h ago·8.7s

No, it doesn't fetch anything. The failure happened locally, before any network call, while parsing the origin URL string.

Before this PR, dispatch's code that works out which repo you're in called search.ParseGitHubRemote(originURL), which accepted only remotes whose canonical host was github.com:

  • https://github.com/acme/thing → host github.com → accepted
  • entire://cell/gh/acme/thing (a GitHub mirror) → the gh token maps back to github.com → accepted
  • entire://aws-us-east-2.entire.io/et/entirehq/entire-api (native) → et has no upstream host, so CanonicalHost() falls back to the cell host aws-us-east-2.entire.io → not github.com → error: "dispatch currently supports GitHub origin remotes only"

That parsed name is only used to identify the repo:

  • Cloud mode: it becomes the repos value in the request to the Entire server, so the server knows which repo to summarize. A native checkout errored before the request was built. That's why --repos et/… already worked: passing it skips the origin lookup.
  • Local mode: it's just the label for the repo group. The checkpoints come from the local checkpoint store either way, so rejecting a native checkout there was purely the name lookup being too strict.

So "forge" here only means "which forge does the origin URL say this repo lives on." The PR stops assuming that's GitHub and keeps whatever forge the URL names (gh or et).

is dispatch doing any git op?

14h ago·14.6s

Yes, but only read-only, local git operations. Dispatch never fetches, pushes, or writes refs.

Cloud mode (the default) does one git-related thing: it opens the repo with go-git and reads the origin URL from the git config, which is what this PR changes. The summary itself is generated on the Entire server, which already has the checkpoints.

Local mode (--local) reads more:

  • git rev-parse --show-toplevel to find the repo root (mode_local.go:167).
  • git log <range> --grep Entire-Checkpoint: to find checkpoint IDs reachable from the current branch (mode_local.go:369).
  • git log --all --grep Entire-Checkpoint: to get commit subjects for those checkpoints (mode_local.go:543).
  • git symbolic-ref refs/remotes/origin/HEAD, rev-parse --verify and merge-base --is-ancestor to work out the default branch and the commit range (mode_local.go:440-461).
  • A read of the checkpoint store, checkpoint.Open with ReadRemotes. That reads the local metadata branch and then the remote-tracking refs already on disk. It passes no fetchers, and the code comment at mode_local.go:293 says it never touches the network. A checkpoint that hasn't been fetched yet falls back to its commit subject.

The wizard also runs git rev-parse --show-toplevel on candidate directories (dispatch_wizard.go:537).

So local mode's output is only as fresh as your last git fetch. If teammates' checkpoints haven't been fetched, you get the commit-subject fallback instead of the full session summary.

Side note: those exec.CommandContext(ctx, "git", …) calls predate this PR and run without the execx helpers. Dispatch runs as a user command rather than inside a hook, so the repo-override rule in CLAUDE.md doesn't strictly apply.

This trail has been merged, can you create a new branch to fix the finding 1?

14h ago·2m

I fixed finding 1 on a new branch, dispatch-local-repos-hint, cut from the latest origin/main. Nothing is committed or pushed yet.

The change:

  • dispatch/mode_local.go: resolveOriginRepoSlug no longer mentions --repos in any of its three errors. That function is shared by both modes, and local mode refuses --repos. A short comment explains why.
  • dispatch/mode_cloud.go: the cloud path adds the hint when it gets the error: … (or pass --repos gh/<owner>/<repo> or et/<project>/<repo> to name the repo). Cloud users see the same advice as before.
  • dispatch/mode_local_test.go: a new test, TestLocalMode_UnknownOriginHostDoesNotSuggestRepos, runs local mode in a checkout whose origin is on gitlab.com. It checks that the error names the host and does not mention --repos. I confirmed it fails on main (the error there says "pass --repos to name the repo") and passes with the fix.

Verification: mise run fmt changed nothing, mise run lint reports 0 issues, and the dispatch and cli package tests pass. The existing cloud test that requires the --repos hint still passes. I haven't run the full mise run check; CLAUDE.md requires it before committing, so I'll run it then.

Local mode's error still ends with "expected gh/<owner>/<repo> or et/<project>/<repo>", which comes from OriginRepoSlug. It describes what a valid origin looks like and doesn't name a flag, so I left it alone.

Should I run mise run check, commit, and open a PR?

commit, push and create PR

13h ago·5m

The agent review is still running. I'll poll in the background until the findings gate finishes: