Skip to content

feat: detect missing project paths + remap (port of upstream #35) - #20

Merged
JeanBaptisteRenard merged 4 commits into
mainfrom
feat/missing-project-remap
May 30, 2026
Merged

feat: detect missing project paths + remap (port of upstream #35)#20
JeanBaptisteRenard merged 4 commits into
mainfrom
feat/missing-project-remap

Conversation

@JeanBaptisteRenard

Copy link
Copy Markdown
Collaborator

Summary

Port of doctly/switchboard#35 by @HaydnG, adapted to our heavily-diverged fork.

When users move their project directories, sessions become orphaned — they appear in the sidebar with no indication that anything is wrong. This PR makes that failure mode visible and fixable:

  • Detection: session-cache.js flags missing: !fs.existsSync(projectPath) on each project row at cache-build time, and sorts missing projects to the bottom.
  • Visual feedback (sidebar.js + style.css): missing groups get amber warning icon, dimmed opacity (0.55, 0.8 on hover), auto-collapse, and a "Change path" upload button always visible on the header.
  • Session lock-out: session items under a .project-group.missing get .disabled class + tooltip directing users to "Change path".
  • XSS fix: project name rendering now uses escapeHtml() (upstream fix, included).
  • remap-project IPC (main.js + preload.js): opens a folder-picker, rewrites cwd in every .jsonl in the folder atomically (tmp + rename), then calls refreshFolder() + notifyRendererProjectsChanged().

Fork-divergence adaptations

The upstream diff touched the same files but our fork diverged substantially:

Upstream assumption Fork reality Adaptation
Folder key = oldPath.replace(/[/_]/g, '-') Folder key = encodeProjectPath(oldPath) (Claude CLI's actual encoding) Used encodeProjectPath() in the IPC handler
projectMap keyed on folder projectMap keyed on projectPath; two locations create entries Added missing flag to both projectMap.set() calls
Single remove-project insertion point Fork has delete-worktree IPC below Inserted after remove-project, before delete-worktree
Plain header innerHTML (no subagents) Worktree groups, subagent carets, heatmap Injected only the missing icon + remap button; left all fork-specific DOM untouched

Note on showSession sub-fix

The 4th part of upstream #35 (showSession() on openTerminal error) was already ported separately in PR #19 (fix/openterminal-error-visible → commit 0d8f4f2) and is the first commit on this branch. It is NOT re-applied here.

Tests

7 new tests in test/remap-project.test.js (node:test, no jsdom needed for pure I/O logic):

  • Rewrites cwd in a single JSONL file
  • Rewrites cwd across multiple JSONL files atomically
  • Preserves lines without cwd field verbatim
  • Preserves empty lines in JSONL files
  • Atomic write: .tmp file is created and then removed by rename
  • Lines with invalid JSON are passed through unchanged
  • Non-.jsonl files in the folder are ignored

All 7 new tests pass. Pre-existing test suite: 47/53 pass (13 dom-sidebar failures are pre-existing — morphdom not installed in the isolated worktree environment, unrelated to this PR).

Lint: 0 errors (220 pre-existing warnings, unchanged).

- CRITICAL-1: replace flat readdirSync with enumerateSessionFiles so
  subagent transcripts under <uuid>/subagents/*.jsonl and the legacy
  <uuid>/*.jsonl layout are also rewritten
- CRITICAL-2: add active-sessions guard — refuse remap if any non-exited
  PTY session has projectPath matching the folder (avoids concurrent-writer
  data loss); also re-check fs.existsSync(oldPath) at handler entry so a
  path that came back does not get clobbered
- Extract rewriteJsonlAtomic helper that cleans up orphan .tmp files on
  error (try/catch around writeFileSync + renameSync)
- Switch statSync → lstatSync on newPath to make symlink intent explicit
- Tests: add subagent layout (preferred + legacy), orphan .tmp cleanup,
  and active-sessions guard tests (4 new tests, total 51 passing / 64)
@JeanBaptisteRenard
JeanBaptisteRenard merged commit effeaeb into main May 30, 2026
7 checks passed
@JeanBaptisteRenard
JeanBaptisteRenard deleted the feat/missing-project-remap branch May 30, 2026 01:47
JeanBaptisteRenard added a commit that referenced this pull request Aug 14, 2026
* docs: refresh README + project docs post-migration

Credit doctly/switchboard upstream and highlight what the fork adds
(new About-this-fork section). Fix stale devsuitup migration leftovers
(download links, repo refs in .ai/). Correct the cp-is-safe claim that
contradicted the 2026-06-04 appimagelauncherd incident. Add the missing
user docs for schedules + triggers (docs/automation.md), document the
chain field in the trigger-watcher context, extend the fork-features
list past PR #20, refresh the release gotchas (ruleset approval, draft
publish step) and the project-structure tree.

* docs: fix review findings (PR ranges, stale counts, §2 heading, fork note)

* docs: fix perf-campaign PR range — feature PRs, not release-bump PRs

* docs: remove Skaleet-internal references (review feedback)

* docs(ai): distill portable agent practices into the repo (post-import removal)
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.

1 participant