Widen the early issue-fetch gate for worktree mode #323
Labels
No labels
batch
bug
chore
documentation
enhancement
pi-loop
ready
resume
No milestone
No project
No assignees
1 participant
Notifications
Due date
Dependencies
No dependencies set
Reference
david/pi-loop#323
Loading…
Reference in a new issue
No description provided.
Delete branch "%!s()"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Summary
Make any run that will create a worktree — a bare repo, or a normal clone with
worktree.enabled: true— fetch the issue early so the worktree folder can be named with the issue summary. Reuses the existing early-fetch seam; no second fetch path is added.Background
src/cli/services/runCli.tscontains the privateresolveWorkDirForIssue({ originalCwd, runGit, issueRef, config, originHost, resolveWorkDirFn?, fetchIssueFn?, stdout, stderr }). Current flow:resolveWorkDirFnis injected (tests), it is called directly with a placeholder summary and{ cwd, fetchedContext: undefined }is returned.isInsideWorktreefast path → returnoriginalCwd, no fetch.isBareRepository;if (!isBare)→ returnoriginalCwd, no early fetch (this is the gate to widen).fetchIssueFn ?? fetchIssue(which dispatches on the provider), wrap any failure inGitWorktreeError(failed to fetch issue <key>: <message>), then callresolveWorkDirwith the fetched summary; return{ cwd, fetchedContext }.The caller
runSingleIssueModecatchesGitWorktreeError→ stderr + exit 1, noerror.json, and whenfetchedContextis set it logsissue context fetched early (bare repo worktree mode)(viasetupLogger.info) and the pipeline skips the issue-fetch stage.Why the early fetch exists (ADR-022 §8): the worktree folder name is
buildBranchFolderName(issueKey, summary, provider)(e.g.issue-42-add-login-page) for both repo kinds, and the name needs the issue summary, which only the issue API provides. So any run that will create a worktree must fetch the issue first.Behavior change to implement and test: for a normal clone with worktree mode enabled, an issue-API error now aborts the run before any stage, wrapped as
GitWorktreeError(stderr, exit 1, noerror.json). Today a normal clone reaches the issue-fetch stage, which has a bounded-retry policy. This is a deliberate, documented change (called out in the CHANGELOG by a later docs step in this series).Batch mode reality check: as of this writing,
runBatch/runScanMode(src/batch/services/) process each issue in the launchcwdviamakeBatchGitSeamand never callresolveWorkDirForIssue— batch mode has no per-issue worktree resolution. The plan this step derives from assumed batch would inherit the behavior for free; verify rather than assume (see step 6).Depends on: #320 (config schema), #321 (parse-time
dirvalidation), #322 (worktree routing) — the value this step threads is parsed and validated by the first two, and consumed by the third.Implementation Details
Files:
src/cli/services/runCli.ts,src/cli/services/runCli.test.ts.Derive the effective worktree dir from the parsed config-file result (
ConfigFileResult, loaded at startup inrunClias theconfigFilevariable; note--help/--list-modelsskip loading, so it can beundefined):(enabled — absent or explicit
true— passesdirthrough; disabled passesundefined; absent section passesundefined.) Thread aworktreeDir: string | undefinedfield throughrunSingleIssueMode's input and intoresolveWorkDirForIssue(mirror howenvis passed).Add
worktreeDirtoresolveWorkDirForIssue's input, to theresolveWorkDirFncallable type, and pass it through to theresolveWorkDircall.Widen the gate — replace
with:
Keep the existing
GitWorktreeErrorwrapping and thefetchedContextreturn untouched, so the issue-fetch stage is skipped exactly as it is for bare repos.Change the log line
'issue context fetched early (bare repo worktree mode)'→'issue context fetched early (worktree mode)'.Batch mode: confirm what
runBatch/runScanModedo per issue. If they still route per-issue work through the launchcwd(not throughresolveWorkDirForIssue), add a regression test asserting the batch path is unaffected by worktree config (runs in the launch repo, no early fetch) and say so in the PR description — do not claim inheritance. If the batch path has since changed to route per-issue worktree resolution throughresolveWorkDirForIssue, confirm it inherits the widened gate and test that instead.Update the injectable
resolveWorkDirFn/fetchIssueFntype declarations (both the top-level CLI deps and therunSingleIssueModeinput) and the test doubles inrunCli.test.ts.Acceptance Criteria
fetchedContext.worktree.enabled: true(with a validdir): early fetch happens,fetchedContextis returned, the worktree cwd is used.enabled: false: no early fetch, no behavior change.GitWorktreeError(stderr message, exit 1, noerror.json) — asserted.--helpand--list-modelsbypass config loading, so a brokenworktree.dirnever blocks them.npm run lintandnpm testpass.Test Plan
Extend
runCli.test.ts(existingresolveWorkDirFn/fetchIssueFndoubles): the three repo-kind/gate cases above, theGitWorktreeErrorsurfacing case, and the batch-mode assertion. Runnpm test.pi-loop opened and merged a pull request for this issue: #329