29a12bb102
- 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
72 lines
2.1 KiB
Markdown
72 lines
2.1 KiB
Markdown
# 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:
|
|
```json
|
|
{"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:
|
|
```json
|
|
{"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:
|
|
```json
|
|
{"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
|