feat: add live config profile refresh

- Standardize built-in tool users for shared writable profile mounts
- Mount canonical non-Git profile sources across compatible instances
- Report restart-required outcomes and guard active profile deletion
- Surface restart feedback in config profile editing

Quality gates: frontend build passed; backend py_compile and LSP passed.
Skipped: backend pytest/Ruff unavailable; Docker/manual checks not approved.
This commit is contained in:
Developer
2026-07-21 11:12:41 +00:00
parent f9f9372ee7
commit add7c1b500
19 changed files with 546 additions and 160 deletions
@@ -532,6 +532,54 @@ class TestApplyResolvedProfile:
assert Path(volumes[0]["source"]).name == "workspace_x_y"
assert (Path(volumes[0]["source"]) / "z.json").exists()
def test_top_level_files_use_profile_scoped_direct_bind_mounts(self, tmp_path) -> None:
"""Top-level files are shared safely without mounting over a workspace."""
profile_id = uuid.uuid4()
resolved = ResolvedProfile(
profile_id=profile_id,
profile_name="test",
files={".tool/config.toml": "setting = true"},
)
instance_root = tmp_path / "instances"
_, files, volumes, _ = apply_resolved_profile(
str(instance_root / "instance-a"),
resolved,
working_dir="/workspace/project",
)
canonical_file = (
instance_root / "config-profiles" / str(profile_id) / "files" / ".tool" / "config.toml"
)
assert files == {}
assert volumes == [
{
"source": str(canonical_file),
"target": "/workspace/project/.tool/config.toml",
"type": "bind",
"readonly": False,
}
]
assert canonical_file.read_text() == "setting = true"
def test_instances_share_profile_scoped_mount_sources(self, tmp_path) -> None:
"""Different instance paths resolve a profile to one canonical source."""
profile_id = uuid.uuid4()
resolved = ResolvedProfile(
profile_id=profile_id,
profile_name="test",
mounts={"/app": ResolvedMount(target="/app", mode="rw", files={"config.ini": "x"})},
)
instance_root = tmp_path / "instances"
_, _, first_volumes, _ = apply_resolved_profile(str(instance_root / "instance-a"), resolved)
_, _, second_volumes, _ = apply_resolved_profile(str(instance_root / "instance-b"), resolved)
assert first_volumes[0]["source"] == second_volumes[0]["source"]
assert first_volumes[0]["source"] == str(
instance_root / "config-profiles" / str(profile_id) / "mounts" / "app"
)
def test_empty_mount_produces_no_volumes(self, tmp_path) -> None:
"""A mount with no files should not produce any volume entries."""
resolved = ResolvedProfile(
@@ -579,7 +627,7 @@ class TestApplyResolvedProfile:
assert len(volumes) == 1
assert volumes[0]["target"] == "/etc/app"
assert volumes[0].get("readonly") is True
assert volumes[0].get("readonly")
def test_writable_mount_does_not_set_readonly_flag(self, tmp_path) -> None:
"""A mount with mode 'rw' should not set readonly on the volume entry."""
@@ -598,7 +646,7 @@ class TestApplyResolvedProfile:
assert len(volumes) == 1
assert volumes[0]["target"] == "/app"
assert volumes[0].get("readonly") is False
assert not volumes[0].get("readonly")
class TestCheckIncludeCycle: