Skip to content

v0.21.2.0 fix(remote): self-heal unregistered remote projects after Add Project#55

Merged
avinashjoshi merged 3 commits into
mainfrom
fix-remote-project-host-registration
May 27, 2026
Merged

v0.21.2.0 fix(remote): self-heal unregistered remote projects after Add Project#55
avinashjoshi merged 3 commits into
mainfrom
fix-remote-project-host-registration

Conversation

@avinashjoshi

Copy link
Copy Markdown
Owner

Summary

Closes the trap where adding a remote project from the TUI looked successful but attaching to its (main) row errored with project not registered for that host — and the suggested recovery command used a flag the CLI doesn't accept.

Wire protocol

  • canopy ls --json emits a new per-row project_root field (absolute path on the host). Additive; pre-v0.21.2 laptops parse and ignore.

Self-heal

  • refreshRemoteCmd now calls autoRegisterRemoteOrphans on every tick. For each (host, project) pair the remote sent a project_root for and the laptop's hosts.json doesn't have, validate the path against the same safety contract as the v0.20 result-file channel and reg.AddProject it. Idempotent. No-op when the remote is too old to send the field.

Surface failures, don't swallow them

  • registerRemoteAddProject returns the reason it couldn't auto-register instead of dropping it into ~/.canopy/log/canopy.log. The success toast renders ⚠ <reason> with the literal manual-recovery command and stretches from 3 s to 8 s so the user can copy it.

Correct the broken hint

  • update_attach.go:211 was suggesting canopy project add --host tower <path>, but canopy project add accepts --on, not --host. Fixed flag and arg order.

Test Coverage

Six regression tests in internal/ui/remote_project_recovery_test.go:

  • TestAttachRemoteRow_NotRegisteredErrorWording — asserts --on and correct arg order
  • TestShowAddProjectToast_WarningRendersInToast — toast carries warning + extended expiry
  • TestAutoRegisterRemoteOrphans_RegistersUnknownProject — happy path + dedup + on-disk persistence
  • TestAutoRegisterRemoteOrphans_SkipsEmptyProjectRoot — older-remote graceful degradation
  • TestAutoRegisterRemoteOrphans_RejectsInvalidPath — relative paths and control chars rejected
  • TestAutoRegisterRemoteOrphans_SkipsFailedHost — errored hosts don't poison the registry

All paths in the diff have direct test coverage. go test ./... and go test -tags=e2e ./... both pass.

Caveat

The self-heal needs the remote canopy to also be on v0.21.2+ (so it emits project_root). For users whose remote is still pre-v0.21.2, the corrected attach error message gives them a copy-pasteable manual recovery command.

Test plan

  • go test ./... passes
  • go test -tags=e2e ./... passes
  • go build ./... clean
  • Manual: add a project on a v0.21.2 tower → row attaches without manual register
  • Manual: add a project on a pre-v0.21.2 remote → toast shows the warning + manual command

🤖 Generated with Claude Code

avinashjoshi and others added 3 commits May 26, 2026 17:27
Adds a per-row project_root field (absolute path of the project on the
host) to LsJSONWorkspace and the matching laptop-side RemoteWorkspace
parser. Additive — older laptops ignore the field, older remotes leave
it empty. No behavior change yet; consumed in the next commit.
…project warnings

Three compounding pieces of the "I added a project on tower from the
TUI, the toast said success, but Enter on its (main) row errors with
project not registered for that host" trap, fixed end to end.

- refreshRemoteCmd calls a new autoRegisterRemoteOrphans helper on
  every tick. For each (host, project) pair the remote reported a
  project_root for and the laptop's hosts.json doesn't have, validate
  the path and reg.AddProject it. Skips errored hosts, dedups across
  workspaces of the same project, no-ops when project_root is empty
  (older remotes). Same path-safety contract as the v0.20 result-file
  channel.

- registerRemoteAddProject now returns the reason it couldn't
  auto-register instead of swallowing it into a log warning. The
  success toast carries a "⚠ <reason>" follow-up with the literal
  manual-recovery command, and the toast window stretches from 3s to
  8s when a warning is present so the user can read and copy it.

- update_attach.go's "project not registered for that host" hint was
  pointing at canopy project add --host, but the CLI only accepts
  --on. Fixed the flag and put the project name in the right argv
  slot.

Six regression tests cover all three branches (attach error wording,
toast with/without warning, orphan registration happy path, no-op for
empty project_root, path validation rejection, errored-host skip).
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
@avinashjoshi avinashjoshi merged commit 73b0860 into main May 27, 2026
2 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.

1 participant