Rename Castle -> Wild PC across the repo

Repo-side rename only (Phases 1-3 of the migration plan); the live box
(~/.castle, systemd units, /data/castle, domains) is a separate cutover.

- Slug `castle` -> `wildpc`: CLI command, module names (wildpc_core/cli/api),
  dist names, entry point `wildpc = wildpc_cli.main:main`.
- Identifiers: CastleConfig/NATSClient/DirError/MDNS -> Wildpc*.
- Env/constants: CASTLE_* -> WILDPC_*; ~/.castle -> ~/.wildpc, castle.yaml ->
  wildpc.yaml, /data/castle -> /data/wildpc.
- Systemd UNIT_PREFIX castle- -> wildpc-; own programs castle-api/gateway/etc.
- Display prose "Castle" -> "Wild PC" in docs, agent-guide files, README, frontend.
- Package dirs and bootstrap yaml renamed via git mv; lockfiles regenerated;
  redundant nested uv.lock files dropped (workspace root lock is authoritative).

Tests: core 273, cli 47, wildpc-api 120 all pass. Frontend type-checks + builds.
Fixed a stale test fixture (secret_env_path kind arg) broken pre-rename.
This commit is contained in:
2026-07-18 22:55:08 -07:00
parent 25d7a522cc
commit 05b28cb584
190 changed files with 2428 additions and 3337 deletions

View File

@@ -0,0 +1,94 @@
"""Tests for nodes endpoints."""
from pathlib import Path
from fastapi.testclient import TestClient
from wildpc_core.registry import Deployment, NodeConfig, NodeRegistry
from wildpc_api.mesh import MeshStateManager
class TestNodesList:
"""GET /nodes endpoint tests."""
def test_returns_local_node(self, client: TestClient) -> None:
"""Always returns the local node."""
response = client.get("/nodes")
assert response.status_code == 200
data = response.json()
assert len(data) >= 1
local = data[0]
assert local["hostname"] == "test-node"
assert local["is_local"] is True
assert local["online"] is True
def test_local_node_counts(self, client: TestClient) -> None:
"""Local node has correct deployment counts."""
response = client.get("/nodes")
data = response.json()
local = data[0]
assert local["deployed_count"] == 2 # test-svc + test-tool
assert local["service_count"] == 1 # only test-svc is a service
def test_includes_remote_nodes(
self, client: TestClient, registry_path: Path
) -> None:
"""Remote nodes from mesh state are included."""
import wildpc_api.mesh as mesh_mod
original = mesh_mod.mesh_state
try:
mgr = MeshStateManager()
remote_reg = NodeRegistry(
node=NodeConfig(hostname="devbox", gateway_port=9000),
deployed={
"remote-svc": Deployment(
manager="systemd",
launcher="python",
run_cmd=["svc"],
port=9050,
kind="service",
),
},
)
mgr.update_node("devbox", remote_reg)
mesh_mod.mesh_state = mgr
# Also patch the reference in the nodes module
import wildpc_api.nodes as nodes_mod
nodes_mod.mesh_state = mgr
response = client.get("/nodes")
data = response.json()
hostnames = [n["hostname"] for n in data]
assert "devbox" in hostnames
devbox = next(n for n in data if n["hostname"] == "devbox")
assert devbox["is_local"] is False
assert devbox["deployed_count"] == 1
finally:
mesh_mod.mesh_state = original
import wildpc_api.nodes as nodes_mod2
nodes_mod2.mesh_state = original
class TestNodeDetail:
"""GET /nodes/{hostname} endpoint tests."""
def test_local_node_detail(self, client: TestClient) -> None:
"""Returns local node detail with deployed components."""
response = client.get("/nodes/test-node")
assert response.status_code == 200
data = response.json()
assert data["hostname"] == "test-node"
assert data["is_local"] is True
assert len(data["deployed"]) == 2 # test-svc + test-tool
svc = next(d for d in data["deployed"] if d["id"] == "test-svc")
assert svc["node"] == "test-node"
def test_unknown_node_returns_404(self, client: TestClient) -> None:
"""Returns 404 for unknown hostname."""
response = client.get("/nodes/nonexistent")
assert response.status_code == 404