Skip to content

Make Treemon own worktree forking with a post-fork setup hook#85

Merged
0101 merged 6 commits into
mainfrom
fix-tm-new-base
Jun 25, 2026
Merged

Make Treemon own worktree forking with a post-fork setup hook#85
0101 merged 6 commits into
mainfrom
fix-tm-new-base

Conversation

@0101

@0101 0101 commented Jun 24, 2026

Copy link
Copy Markdown
Owner

Problem

Creating a worktree from the dashboard used to delegate forking to a repo-local fork.ps1 / fork.sh, passing only the branch name. That path had real bugs:

  • The fork script silently ignored the selected source branch.
  • "New worktree from main" could fork from a stale local main in fork workflows where the upstream is ahead.
  • Resolution logic ran for a base the script never actually used.

Changes

Treemon owns forking (upstream-aware base)

  • Treemon now creates the worktree itself: git worktree add -b {name} {parentDir}/tm-{name} {baseRef}.
  • Base resolution fetches the base from the upstream remote and prefers the remote-tracking ref {remote}/{base} over a possibly-stale local branch, falling back to the local {base} when no remote-tracking ref exists. No worktree needs the base checked out; fetch/remote failures fall back to whatever ref is available.

post-fork setup hook

  • After creation, an optional post-fork.ps1 (Windows) / post-fork.sh (Unix) runs inside the new worktree, receiving {worktreePath} {sourceRepoRoot} {baseRef} {branchName}. It is for setup only (links, dependency install); a failure is a non-fatal warning since the worktree already exists.
  • Treemon's own post-fork.ps1 wires .claude / data via directory junctions (no UAC elevation or Developer Mode required — important because the server spawns the hook) and runs bd init + npm install.
  • Legacy fork.ps1 / fork.sh are no longer executed. If one is present, creation still succeeds but returns a warning to migrate setup into post-fork.*. Treemon's fork.ps1 is deleted and split into post-fork.ps1 (setup) and review-worktree.ps1 (the remote review-branch workflow, which reuses post-fork.ps1).

Warnings surfaced to UI + CLI

  • createWorktree returns Result<CreateWorktreeWarnings, string> (a named string list alias). Warnings render in the create modal (new warning header/message styles) and on the CLI console.

Hardening

  • Reject leading-dash branch names (regex aligned with TreemonConfig) and pass -- before the git fetch refspec to prevent git argument injection.
  • ProcessRunner.runResultWithTimeout gives the post-fork hook a 10-minute budget so npm install / bd init are not killed by the 60s default used for quick git probes; the timeout warning now states dependencies may be incomplete.

Code quality

  • CreateWorktreeModal.update flattened into a single (msg, modal) tuple match.
  • legacyForkScriptWarning made pure — File.Exists hoisted to the asyncResult boundary.
  • Shared git test helpers extracted into GitTestHelpers.fs; RemoveWorktreeTests and CreateWorktreeServerTests deduped.
  • Spec (docs/spec/worktree-monitor.md) updated to describe the new create flow.

Tests

  • New CreateWorktreeServerTests cover base-ref precedence and end-to-end create against real git repos: forks from the upstream tip over a stale local base, remote-only base, missing base (errors and creates nothing), legacy-script warning, and post-fork execution inside the new worktree.
  • Build clean (0 warnings); 958 Fast tests + 83 targeted CreateWorktree/RemoveWorktree tests pass. Junction creation smoke-tested non-elevated.

0101 added 5 commits June 22, 2026 17:43
Treemon now creates worktrees itself instead of delegating forking to repo
fork scripts. Base resolution is upstream-aware: it fetches the base branch and
prefers the remote-tracking ref (<upstream>/<base>) over a possibly-stale local
branch, falling back to the local branch when no remote-tracking ref exists.
This fixes "new worktree from main" forking from a stale local main in fork
workflows, and removes the prior bugs where a fork script silently ignored the
selected base or failed resolution it never used.

After creation, an optional post-fork.ps1/.sh runs inside the new worktree for
setup only (symlinks, dependency install); its failure is a non-fatal warning
since the worktree already exists.

Legacy fork.ps1/.sh are no longer executed. If one is present, creation still
succeeds but returns a warning to migrate setup into post-fork.*. createWorktree
now returns Result<string list, string>, with warnings surfaced in the create
modal (UI) and on the console (CLI).

Migrate Treemon's own fork.ps1 into post-fork.ps1 (setup half) and
review-worktree.ps1 (the remote review-branch workflow, which reuses
post-fork.ps1), and delete fork.ps1.
- post-fork.ps1: create directory junctions instead of symlinks with UAC
  elevation, so the hook works when spawned by the server (no interactive
  prompt) and without Developer Mode.
- GitWorktree: reject leading-dash branch names (align regex with
  TreemonConfig) and pass "--" before the fetch refspec to prevent git
  argument injection.
- ProcessRunner: add runResultWithTimeout; give the post-fork hook a 10-minute
  budget so npm install / bd init are not killed by the 60s git default, and
  make the timeout warning state that dependencies may be incomplete.
- Tests: extract shared git helpers into GitTestHelpers.fs and dedupe
  CreateWorktreeServerTests and RemoveWorktreeTests.
- CreateWorktreeModal: flatten update into a single (msg, modal) tuple match.
- Make legacyForkScriptWarning pure by hoisting File.Exists to the CE boundary.
- Name the createWorktree success channel via CreateWorktreeWarnings.
Copilot AI review requested due to automatic review settings June 24, 2026 15:39

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR makes Treemon own git worktree forking instead of delegating to a repo-local fork.ps1/fork.sh. Treemon now fetches the base branch from the upstream remote and forks the new worktree directly via git worktree add -b {name} {parentDir}/tm-{name} {baseRef}, preferring the remote-tracking ref ({remote}/{base}) over a possibly-stale local branch. After creation it runs an optional, non-fatal post-fork.ps1/post-fork.sh setup hook inside the new worktree. Legacy fork scripts are no longer executed; their presence yields a migration warning. Warnings now flow through createWorktree (Result<CreateWorktreeWarnings, string>) to both the create modal and the CLI.

Changes:

  • Server-side, upstream-aware forking with resolveBaseRef precedence, an optional post-fork hook (10-min timeout), and non-fatal warnings; branch-name regex tightened to reject leading dashes and -- added to git fetch refspecs.
  • API contract change: createWorktree returns Result<CreateWorktreeWarnings, string>; modal/CLI updated, modal update flattened to a (msg, modal) tuple match with a new CreateWarning state and styling.
  • fork.ps1 removed and split into post-fork.ps1 (junction-based setup) and review-worktree.ps1; shared git test helpers extracted to GitTestHelpers.fs; new CreateWorktreeServerTests; spec updated.
Show a summary per file
File Description
src/Server/GitWorktree.fs Core change: base-ref resolution, fetch hardening, post-fork hook, warning assembly
src/Server/WorktreeApi.fs Wires createWorktree to new signature; returns warnings; fixture/read-only modes updated
src/Server/ProcessRunner.fs Parameterizes timeout; adds runResultWithTimeout and shared toResult
src/Shared/Types.fs Adds CreateWorktreeWarnings alias; updates createWorktree return type
src/Client/CreateWorktreeModal.fs Flattens update to tuple match; adds CreateWarning state and view
src/Client/index.html Adds warning header/message CSS classes
src/Cli/Program.fs new command prints warnings to stderr via tryCallServer
post-fork.ps1 New junction-based setup hook (no elevation needed)
review-worktree.ps1 New manual remote-review-branch workflow reusing post-fork
fork.ps1 Deleted (legacy symlink/elevation flow)
src/Tests/GitTestHelpers.fs Extracted shared git repo test helpers
src/Tests/CreateWorktreeServerTests.fs New end-to-end + unit tests for base-ref precedence and creation
src/Tests/CreateWorktreeTests.fs Updates for Ok [] and new warning case
src/Tests/RemoveWorktreeTests.fs Dedupes git helpers into GitTestHelpers
src/Tests/Tests.fsproj Registers new test/helper files
docs/spec/worktree-monitor.md Documents the new create flow

Copilot's findings

  • Files reviewed: 16/16 changed files
  • Comments generated: 2

Comment thread src/Client/CreateWorktreeModal.fs Outdated
Comment thread src/Tests/CreateWorktreeServerTests.fs Outdated
Comment on lines +199 to +201
member _.``runs the post-fork script inside the new worktree``() =
if not (RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) then
Assert.Ignore("post-fork execution test targets Windows/pwsh")

Copy link
Copy Markdown
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good catch. In 82c8194 the test now writes post-fork.ps1 on Windows and post-fork.sh (invoked via bash) elsewhere, so it runs on ubuntu-latest instead of being Assert.Ignored. Also added a companion test for the post-fork failure-to-warning path.

- CreateWorktreeModal: render warning messages with List.map instead of a
  for-comprehension, matching the branch dropdown and the no-loops style rule.
- CreateWorktreeServerTests: make the post-fork execution test portable so it
  runs on Linux CI via post-fork.sh/bash (was Assert.Ignore'd off Windows), and
  add a test for the post-fork failure-to-warning path.
@0101 0101 merged commit 3283382 into main Jun 25, 2026
1 check passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants