feat(cli): expand --uv-compile to all node management commands with conflict attribution

Add --uv-compile flag to reinstall, update, fix, restore-snapshot,
restore-dependencies, and install-deps commands. Each skips per-node
pip installs and runs batch uv pip compile after all operations.

Change CollectedDeps.sources type to dict[str, list[tuple[str, str]]]
to store (pack_path, pkg_spec) per requester. On resolution failure,
_run_unified_resolve() cross-references conflict packages with sources
using word-boundary regex and displays which node packs requested each
conflicting package.

Update EN/KO user docs and DESIGN/PRD developer docs to cover the
expanded commands and conflict attribution output. Strengthen unit
tests for sources tuple format and compile failure attribution.
Bump version to 4.1b3.
This commit is contained in:
Dr.Lt.Data
2026-03-10 23:43:44 +09:00
parent f042d73b72
commit e0f8e653c7
8 changed files with 473 additions and 32 deletions
@@ -56,7 +56,8 @@ class CollectedDeps:
"""Aggregated dependency collection result."""
requirements: list[PackageRequirement] = field(default_factory=list)
skipped: list[tuple[str, str]] = field(default_factory=list)
sources: dict[str, list[str]] = field(default_factory=dict)
sources: dict[str, list[tuple[str, str]]] = field(default_factory=dict)
"""pkg_name → [(pack_path, pkg_spec), ...] — tracks which node packs request each package."""
extra_index_urls: list[str] = field(default_factory=list)
@@ -275,7 +276,7 @@ class UnifiedDepResolver:
"""Collect dependencies from all node packs."""
requirements: list[PackageRequirement] = []
skipped: list[tuple[str, str]] = []
sources: dict[str, list[str]] = defaultdict(list)
sources: defaultdict[str, list[tuple[str, str]]] = defaultdict(list)
extra_index_urls: list[str] = []
# Snapshot installed packages once to avoid repeated subprocess calls.
@@ -362,7 +363,7 @@ class UnifiedDepResolver:
requirements.append(
PackageRequirement(name=pkg_name, spec=pkg_spec, source=pack_path)
)
sources[pkg_name].append(pack_path)
sources[pkg_name].append((pack_path, pkg_spec))
# Commit staged index URLs only after all validation passed.
if pending_urls: