feat: implement configurable tool container home directory

- Add ToolType.home_directory column with default /home/user
- Add Alembic migration to add column, set existing rows, and rewrite
  /workspace to /home/user/{{WORKSPACE_NAME}} in legacy templates
- Add merge migration fc8f1a20cbf6 to resolve Alembic multiple heads
- Update manifest compiler to honor manifest.home_directory for HOME,
  WORKDIR, /workspace symlink, and default repo mount target
- Update legacy dockerfile/compose instance generation to use
  tool_type.home_directory
- Thread resolved home_dir through config profile and git mount expansion
- Generate entrypoint permission fixer to chown home/mounts at startup
- Update base.dockerfile with sudo/passwordless sudo for permission fixer
- Add unit tests for manifest compiler, instance service, and migrations
- Add placeholder integration test for container lifecycle
- Update openspec/tasks/home-path-expansion.md task checkboxes
- Update project maps for modified files

Quality gates: py_compile, ruff, mypy, pytest tests/unit (205 passed),
pytest tests/integration (110 passed, 35 skipped). Alembic round-trip
and container lifecycle integration tests require Docker/PostgreSQL.
This commit is contained in:
Developer
2026-06-14 13:09:41 +00:00
parent b4203a4a09
commit ddd92e3dd4
51 changed files with 846 additions and 121 deletions
+1 -1
View File
@@ -2,7 +2,7 @@
dir: openspec/tasks
## role
Technical specification and task tracking directory for planned engineering improvements across the project's container runtime, workspace management, and developer tooling systems.
Contains technical specification documents tracking planned features and architectural improvements for the project.
## parent
index: openspec/.pi-map.index.md
map: openspec/.pi-map.md
+4 -4
View File
@@ -4,17 +4,17 @@ dir: openspec/tasks
index: openspec/tasks/.pi-map.index.md
## role
Technical specification and task tracking directory for planned engineering improvements across the project's container runtime, workspace management, and developer tooling systems.
Contains technical specification documents tracking planned features and architectural improvements for the project.
## files
- config-profile-multi-repo-mounts.md | Technical specification for refactoring git mount configuration to support multiple repository mappings per mount instead of single source/target pairs | dep: git, docker compose, react/typescript, pytest, npm, fastapi
- home-path-expansion.md | Defines a technical implementation plan for adding configurable home/workspace directory support to tool containers in an API service. | dep: SQLAlchemy/Alembic, Docker, Docker Compose, Jinja2 templating, pytest, npm/frontend tooling
- home-path-expansion.md | Design and implementation plan for adding configurable home/workspace directory support to tool containers in an API application. | dep: SQLAlchemy/Alembic, Docker, Docker Compose, pytest, PostgreSQL, Node.js/npm
- mount-specificity-ordering.md | Tracks completion status of a project task for implementing mount specificity ordering in Docker volume handling | dep: docker.py, pytest, tsc
- terminal-responsiveness.md | A technical specification document outlining 7 pending tasks to improve web terminal performance through asyncio-native I/O, binary WebSocket frames, WebGL rendering, flow control, and comprehensive benchmarking. | dep: asyncio, WebSocket, xterm-addon-webgl, docker, pytest
- tool-definition-manifest.md | A project task specification document defining a multi-PR system for implementing a Tool Definition Manifest System with backend manifest compilation, frontend workshop UI, and legacy migration support. | dep: SQLAlchemy, Alembic, Docker, Docker Compose, FastAPI/REST API, React/TypeScript frontend
## arch
Markdown-based living documentation pattern using standalone specification files that each capture a discrete technical initiative with implementation plans, completion tracking, and cross-referencing between backend API changes, frontend UI work, and infrastructure migrations.
Markdown-based task tracking system using standalone specification documents that each define discrete feature work across backend, frontend, and infrastructure concerns.
## tags
mount, docker, pytest, tool, manifest, technical, specification, support
mount, docker, pytest, tool, manifest, specification, support, docker compose
## symbols
-
## workflows
+42 -33
View File
@@ -10,17 +10,17 @@ This task extends the earlier `home-path-expansion` work into a full configurabl
**File**: `apps/api/src/models/tool/tool_type.py`
- Add `home_directory: Mapped[str]` column.
- Non-nullable with server default `"/home/user"`.
- [x] Add `home_directory: Mapped[str]` column.
- [x] Non-nullable with server default `"/home/user"`.
### T1.2: Alembic migration for legacy tool types
**File**: `apps/api/alembic/versions/<new>_add_tool_type_home_directory.py`
- Add the column.
- Set existing rows to `/home/user`.
- Rewrite `compose_template` and `dockerfile_template` to replace `/workspace` with `/home/user/{{WORKSPACE_NAME}}` where applicable.
- Provide downgrade that reverses rewrites and drops the column.
- [x] Add the column.
- [x] Set existing rows to `/home/user`.
- [x] Rewrite `compose_template` and `dockerfile_template` to replace `/workspace` with `/home/user/{{WORKSPACE_NAME}}` where applicable.
- [x] Provide downgrade that reverses rewrites and drops the column.
## T2: Manifest compiler
@@ -28,22 +28,22 @@ This task extends the earlier `home-path-expansion` work into a full configurabl
**File**: `apps/api/src/services/build/manifest_compiler.py`
- Update `get_manifest_home_dir()` to return `manifest.home_directory` if present, else derive from `user.name`, else `/root`.
- [x] Update `get_manifest_home_dir()` to return `manifest.home_directory` if present, else derive from `user.name`, else `/root`.
### T2.2: Dockerfile generation
**File**: `apps/api/src/services/build/manifest_compiler.py`
- Set `ENV HOME={home_directory}` and `ENV USER={user.name}`.
- Set `WORKDIR {home_directory}` unless overridden by `runtime.working_dir`.
- Create `/workspace` symlink pointing to `{home_directory}/{{WORKSPACE_NAME}}` placeholder or create it at runtime.
- [x] Set `ENV HOME={home_directory}` and `ENV USER={user.name}`.
- [x] Set `WORKDIR {home_directory}` unless overridden by `runtime.working_dir`.
- [x] Create `/workspace` symlink pointing to `{home_directory}/{{WORKSPACE_NAME}}` placeholder or create it at runtime.
### T2.3: Compose generation
**File**: `apps/api/src/services/build/manifest_compiler.py`
- Use `{home_directory}/{repo_name}` as default repo mount target when the manifest has no explicit repo mount.
- Keep `~`/`$HOME` expansion base equal to `home_directory`.
- [x] Use `{home_directory}/{repo_name}` as default repo mount target when the manifest has no explicit repo mount.
- [x] Keep `~`/`$HOME` expansion base equal to `home_directory`.
## T3: Legacy instance generation
@@ -51,16 +51,16 @@ This task extends the earlier `home-path-expansion` work into a full configurabl
**File**: `apps/api/src/services/tool/instance_service.py`
- Use `tool_type.home_directory` (default `/home/user`).
- Mount `{repo_path}:{home_directory}/{repo_name}`.
- Ensure `/workspace` symlink exists.
- [x] Use `tool_type.home_directory` (default `/home/user`).
- [x] Mount `{repo_path}:{home_directory}/{repo_name}`.
- [x] Ensure `/workspace` symlink exists.
### T3.2: Compose-based tools
**File**: `apps/api/src/services/docker/compose.py`, `apps/api/src/services/tool/instance_service.py`
- Add `WORKSPACE_NAME` and `HOME_DIRECTORY` to template variables.
- Validate migrated templates render correctly.
- [x] Add `WORKSPACE_NAME` and `HOME_DIRECTORY` to template variables.
- [x] Validate migrated templates render correctly.
## T4: Config-profile and git mount expansion
@@ -68,14 +68,14 @@ This task extends the earlier `home-path-expansion` work into a full configurabl
**File**: `apps/api/src/services/tool/instance_service.py`
- Compute `home_dir` from ToolType/manifest in `start_tool_instance()`.
- Pass to `apply_resolved_profile()` and `resolve_git_mounts()`.
- [x] Compute `home_dir` from ToolType/manifest in `start_tool_instance()`.
- [x] Pass to `apply_resolved_profile()` and `resolve_git_mounts()`.
### T4.2: Verify `~`/`$HOME` expansion
**File**: `apps/api/src/services/config/config_profile_resolver.py`
- Ensure `expand_container_path()` is called with the resolved `home_dir`.
- [x] Ensure `expand_container_path()` is called with the resolved `home_dir`.
## T5: Entrypoint permission fixer
@@ -83,15 +83,15 @@ This task extends the earlier `home-path-expansion` work into a full configurabl
**File**: `apps/api/src/services/build/manifest_compiler.py`
- Generate a startup script that chowns `{home_directory}` and mounted paths to the container user.
- Create `/workspace` symlink at runtime if needed.
- Avoid recursive chown of large repo subtrees.
- [x] Generate a startup script that chowns `{home_directory}` and mounted paths to the container user.
- [x] Create `/workspace` symlink at runtime if needed.
- [x] Avoid recursive chown of large repo subtrees.
### T5.2: Base image support
**File**: `tool-images/base.dockerfile` (optional)
- Ensure `sudo` is available and the runtime user can elevate if the fixer runs inside the base image.
- [x] Ensure `sudo` is available and the runtime user can elevate if the fixer runs inside the base image.
## T6: Tests
@@ -104,21 +104,21 @@ This task extends the earlier `home-path-expansion` work into a full configurabl
- `apps/api/tests/unit/test_alembic_migrations.py`
Cover:
- `expand_container_path` edge cases.
- `get_manifest_home_dir` precedence.
- `compile_dockerfile`/`compile_compose` behavior.
- Legacy instance mount target.
- Alembic migration round-trip.
- [x] `expand_container_path` edge cases.
- [x] `get_manifest_home_dir` precedence.
- [x] `compile_dockerfile`/`compile_compose` behavior.
- [x] Legacy instance mount target.
- [x] Alembic migration round-trip (round-trip against Postgres skipped in this environment).
### T6.2: Integration tests
**File**: `apps/api/tests/integration/test_tool_instance_lifecycle.py`
Cover:
- Container starts with `HOME=/home/user` and repo at `/home/user/{repo_name}`.
- `/workspace` symlink works.
- Config-profile and git mounts under `~` are writable.
- Explicit manifest repo mount target is preserved.
- [ ] Container starts with `HOME=/home/user` and repo at `/home/user/{repo_name}`.
- [ ] `/workspace` symlink works.
- [ ] Config-profile and git mounts under `~` are writable.
- [ ] Explicit manifest repo mount target is preserved.
## T7: Verification
@@ -130,6 +130,9 @@ pytest tests/unit/test_home_path_expansion.py tests/unit/test_manifest_compiler.
pytest tests/integration/test_tool_instance_lifecycle.py -xvs
```
- [x] Unit tests passed (32 passed).
- [ ] Integration tests require Docker/Postgres.
### T7.2: Alembic round-trip
```bash
@@ -139,12 +142,18 @@ alembic downgrade -1
alembic upgrade head
```
- [ ] Alembic round-trip requires PostgreSQL.
- [x] Single head confirmed (`fc8f1a20cbf6`).
- [x] Migration imports verified.
### T7.3: Frontend typecheck
```bash
cd apps/web && npm run typecheck
```
- [x] No frontend changes made.
## Estimation
| Task | Effort | Files |