Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,9 @@ anchor: function lanes
created: 2026-10-19T16:56:39Z
norm: '1'
sig: a117f6b009a0a5ab
body_hash: 73bf0673747cc608
raw_hash: deaa38044cf0d425
body_hash: 608b9efe149e4af0
raw_hash: eaf0bb12be123591
vouched: 2026-10-19T18:03:00Z
lines: 67-112
---

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
---
id: 01M5AN9A1YPT5XAP3TS3ACX5BT
anchor: function lanes
created: 2026-10-19T18:02:53Z
norm: '1'
sig: a117f6b009a0a5ab
body_hash: 608b9efe149e4af0
raw_hash: eaf0bb12be123591
lines: 67-120
---

lane clones ignored files like node_modules into worktrees whose branch may not ignore them, so only tracked changes may block a move
2 changes: 1 addition & 1 deletion apps/app/src/move-channel.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ const OUTCOMES = {
hosted:
"The channel becomes a hosted channel there, with this host as its workspace. It keeps its chats, messages, and lanes.",
cloud:
"Its tools then run in a container on the team's compute service, which starts from a fresh clone with the channel's pushed lanes. It keeps its chats and messages, and can't move back yet.",
"Its tools then run in a container on the team's compute service, which starts from a fresh clone with the channel's pushed lanes; untracked files stay on this Mac. It keeps its chats and messages, and can't move back yet.",
};

type Props = {
Expand Down
12 changes: 10 additions & 2 deletions apps/host/src/compute.ts
Original file line number Diff line number Diff line change
Expand Up @@ -92,9 +92,17 @@ async function lanes(root: string, prefix: string): Promise<Lane[]> {
const unready: string[] = [];
const ready: Lane[] = [];
for (const lane of found) {
// lane clones the project's ignored files, such as node_modules, into worktrees whose branch may
// not ignore them, so untracked files can't block a move; they stay on this host.
const changed = lane.branch
? (await output(lane.path, ["diff", "--name-only", "HEAD"])).split("\n").filter(Boolean)
: [];
if (!lane.branch) unready.push(`${lane.name} (no branch)`);
else if (await output(lane.path, ["status", "--porcelain"])) {
unready.push(`${lane.name} (uncommitted changes)`);
else if (changed.length) {
const more = changed.length > 3 ? `, and ${changed.length - 3} more` : "";
unready.push(
`${lane.name} (uncommitted changes to ${changed.slice(0, 3).join(", ")}${more})`,
);
} else if (pushed.get(lane.branch) !== lane.head) unready.push(`${lane.name} (not pushed)`);
else {
const base = (await git(root, ["config", "--get", `lane.${lane.branch}.base`])).stdout.trim();
Expand Down