Files
Alex Blank 29a12bb102 feat: expand ~ and $HOME in mount target paths
- Add expand_container_path() helper that resolves ~/ and $HOME/ prefixes
- Add get_manifest_home_dir() to compute /home/{user.name} or /root from manifest
- Set ENV HOME=... and ENV USER=... in generated Dockerfile for runtime compatibility
- Pass home_dir through instance creation and startup pipeline
- Expand mount targets in apply_resolved_profile() for regular profile mounts
- Expand mapping targets in _resolve_git_mount_mappings() for git mounts
- Expand working_directory and volume targets in _modify_compose_file()
- Update _prepare_manifest_instance to return home_dir alongside image tag
- Fetch tool_type early in start_instance to determine home_dir before profile application

Quality gates: pytest 188 passed, frontend typecheck clean

Addresses: home-path-expansion
2026-05-29 00:01:04 +02:00

2.1 KiB

Spec: ~ / $HOME Expansion in Mount Paths

Requirements

Functional

  1. FR-1: ~ in mount target paths MUST be expanded to the container's home directory.
  2. FR-2: $HOME in mount target paths MUST be expanded to the container's home directory.
  3. FR-3: For manifest-based tools with user.name, home MUST be /home/{user.name}.
  4. FR-4: For manifest-based tools without user block, home MUST be /root.
  5. FR-5: For legacy tool types, home MUST be /root.
  6. FR-6: Git mount mapping.target_path MUST support ~ and $HOME.
  7. FR-7: The generated Dockerfile MUST set HOME env var.

Non-Functional

  1. NFR-1: No database schema changes.
  2. NFR-2: No frontend changes.
  3. NFR-3: Existing profiles without ~ MUST continue working.

API Contracts

No API changes. Resolution happens server-side during compose generation.

Scenarios

Scenario 1: pi-agent with ~ mount

Given a Config Profile with:

{"mounts": [{"target": "~/workspace", "mode": "rw", "files": {}}]}

And a pi-agent manifest with user.name = "user"

When the profile is applied

Then the compose file contains /home/user/workspace as the mount target.

Scenario 2: Legacy tool with $HOME mount

Given a Config Profile with:

{"mounts": [{"target": "$HOME/config", "mode": "ro", "files": {}}]}

And a legacy tool type (no manifest)

When the profile is applied

Then the compose file contains /root/config as the mount target.

Scenario 3: Git mount with ~ target

Given a Config Profile with:

{"git_mounts": [{"remote_url": "...", "mappings": [{"source_path": ".", "target_path": "~/repo"}]}]}

And a manifest with user.name = "user"

When the profile is applied

Then the compose file contains /home/user/repo as the mount target.

Test Strategy

  1. Unit test expand_container_path with ~, $HOME, absolute paths, relative paths
  2. Unit test get_manifest_home_dir with user block, without user block
  3. Integration test: profile with ~ mount applied to pi-agent instance
  4. Integration test: profile with $HOME mount applied to legacy instance