Skip to content

feat: add configurable worktree project mappings#481

Merged
wesm merged 6 commits into
wesm:mainfrom
mariusvniekerk:middleman/issue-416
May 10, 2026
Merged

feat: add configurable worktree project mappings#481
wesm merged 6 commits into
wesm:mainfrom
mariusvniekerk:middleman/issue-416

Conversation

@mariusvniekerk
Copy link
Copy Markdown
Contributor

@mariusvniekerk mariusvniekerk commented May 8, 2026

Closes #416.

Adds user-configurable rules that map worktree paths back to a canonical
project, so worktree sessions group with the parent repo instead of becoming
a separate project derived from the branch name.

The built-in parser infers a session's project from its cwd, which works for
standard layouts but not custom worktree conventions like
~/code/{project}.worktrees/feat/my-feature/ — those sessions end up under
my-feature rather than {project}. This branch adds a manual override that
lives in SQLite, is scoped to the current machine, and is applied both as new
sessions stream in and to existing sessions on demand.

How it works

  • New worktree_project_mappings table keyed by (machine, path_prefix) with
    an enabled flag. Path prefixes are cleaned and have trailing separators
    stripped so matches are stable regardless of how a user types the prefix.
  • The sync engine loads the active mappings for the host machine on each pass
    and rewrites project for any session whose cwd falls under an enabled
    prefix. The resolver is wired into all ingestion paths: single-session
    writes, incremental sync, bulk resync, and the rebuild-and-swap full
    resync. Excluded, trashed, and skipped session files are left alone so the
    rewriter does not resurrect intentionally removed data.
  • REST API under /api/v1/settings/worktree-mappings (list / create / update /
    delete / apply). The server derives the machine identifier itself instead
    of accepting it from the client, so a mapping created on one machine never
    bleeds into another machine's view of synced sessions.
  • Settings panel in the SPA for adding, editing, toggling, and deleting
    mappings, plus an Apply action that runs the rewrite over already-imported
    sessions and reports how many were matched and updated.

Notes

  • Mappings are explicit and manual — there is no auto-discovery. The intent
    is to let users formalize their personal layout once and have it stick.
  • Mappings only mutate project; the rest of the session record, including
    data carried through the bulk resync's rebuild-and-copy path, is preserved.

Worktree project inference was limited to built-in parser behavior, which left machine-specific worktree layouts with no durable way to collapse feature checkout paths back into canonical projects. This adds explicit machine-scoped mappings stored in SQLite, with sync and resync paths applying them consistently while preserving session archive data.

Mappings are managed manually from settings and only rewrite existing sessions through an explicit apply action or normal sync/resync ingestion. The API derives the machine from the running server so synced sessions do not introduce cross-machine configuration drift.

Validation: go test ./internal/db ./internal/sync ./internal/server -run 'Test(WorktreeProjectMappings|ResolveWorktreeProjectMapping|ApplyWorktreeProjectMappings|ApplyWorktreeProjectMappingsToSession|CopySessionMetadataPreservesWorktreeProjectMappings|SyncEngineAppliesWorktreeProjectMapping|SyncSingleSessionAppliesWorktreeProjectMapping|SyncSingleSessionSkippedClaudeAppliesWorktreeProjectMapping|SyncSingleSessionIncrementalAppliesWorktreeProjectMapping|SyncAllIncrementalAppliesWorktreeProjectMapping|SyncAllSkipped.*Worktree.*Mapping|SyncPathsSkipped.*Worktree.*Mapping|ResyncAllAppliesWorktreeProjectMappingDuringBulkWrites|WorktreeMappingsAPI)' -count=1

Validation: bun run check

Validation: bun run build

🤖 Generated with [OpenAI Codex](https://openai.com/codex)
Co-authored-by: OpenAI Codex <noreply@openai.com>
@roborev-ci
Copy link
Copy Markdown

roborev-ci Bot commented May 8, 2026

roborev: Combined Review (18fcfe4)

No Medium, High, or Critical issues found.

All review agents reported the code is clean.


Synthesized from 3 reviews (agents: codex, gemini | types: default, security)

@roborev-ci
Copy link
Copy Markdown

roborev-ci Bot commented May 8, 2026

roborev: Combined Review (549db0b)

High-level verdict: Changes are not ready to merge due to compile-breaking issues and one behavior regression.

High

  • internal/server/worktree_mappings.go:36
    s.db.(*db.DB) performs a type assertion on s.db, but Server.db is already a concrete *db.DB, so this does not compile.
    Fix: Use localDB := s.db directly, or make the server DB field an interface consistently if runtime DB discrimination is required.

  • frontend/src/lib/api/client.ts:867
    deleteWorktreeMapping references undefined helpers/types: getBase, authHeaders, ApiError, and apiErrorMessage. This breaks TypeScript compilation.
    Fix: Implement deletion using the existing BASE/fetchJSON pattern, or add the missing shared helpers before using them.

Medium

  • internal/sync/engine.go:1938
    Skipped sync paths now call applyWorktreeMappingToSkippedPath, so saving a mapping can rewrite existing archived sessions during normal sync without the explicit Apply action. This contradicts the documented behavior that saves only store the rule and existing sessions are rewritten only by explicit apply/full resync.
    Fix: Remove mapping application from skipped-file paths and keep automatic mapping limited to sessions that are actually parsed/written, plus the explicit apply/resync flows.

Synthesized from 3 reviews (agents: codex, gemini | types: default, security)

@roborev-ci
Copy link
Copy Markdown

roborev-ci Bot commented May 8, 2026

roborev: Combined Review (50e28ed)

No Medium, High, or Critical findings were reported.

The only findings raised were Low severity, so they are omitted per the review rules.


Synthesized from 3 reviews (agents: codex, gemini | types: default, security)

@roborev-ci
Copy link
Copy Markdown

roborev-ci Bot commented May 9, 2026

roborev: Combined Review (be4fa6e)

Summary verdict: one medium-severity issue needs attention before merge.

Medium

  • internal/sync/engine.go:1938 - Skipped, unchanged session files now call applyWorktreeMappingToSkippedPath, so saving a mapping and running normal sync can rewrite existing archived session projects. That conflicts with the feature design that historical rows change only through explicit apply/resync.
    • Fix: Remove mapping application from skip paths. Apply mappings only when a session is actually parsed/written, or through the explicit apply action/full resync.

Synthesized from 3 reviews (agents: codex, gemini | types: default, security)

@roborev-ci
Copy link
Copy Markdown

roborev-ci Bot commented May 10, 2026

roborev: Combined Review (279b657)

No Medium, High, or Critical issues found across the reviews.

All reporting agents that provided findings agreed the code is clean.


Synthesized from 3 reviews (agents: codex, gemini | types: default, security)

@roborev-ci
Copy link
Copy Markdown

roborev-ci Bot commented May 10, 2026

roborev: Combined Review (78c8f27)

Verdict: No medium-or-higher severity issues found.

All review agents either reported no issues or provided no findings, so there are no actionable PR comments to include.


Synthesized from 3 reviews (agents: codex, gemini | types: default, security)

@wesm wesm merged commit c8bb17c into wesm:main May 10, 2026
13 checks 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.

Grouping worktrees into parent project

2 participants