core: drop pre-migration read-compat now both nodes are current-format

Both machines (civil, primer) are on the current on-disk layout, so the
read-compat for older formats is dead weight. Remove it:

- config loader: only deployments/<kind>/<name>.yaml (drop flat deployments/*.yaml
  and the services/+jobs/ split); drop the run.runner→manager normalizer.
- registry loader: require composite <kind>/<name> keys + manager/kind (registry.yaml
  is regenerated every apply, so it's always current).
- manifest: drop the proxy/public→reach legacy input and the component→program alias
  (the derived proxy/public read accessors stay). reach field defaults already match.
- config_editor: parse incoming specs directly (frontend sends the current shape).
- save_config: drop the flat-file migration cleanup.

Bootstrap seeds move to bootstrap/deployments/<kind>/ and install.sh seeds that
per-kind tree directly. The legacy→current translation for terse test fixtures
moves into each test conftest (out of production). All suites green (362).
This commit is contained in:
2026-07-07 09:16:03 -07:00
parent 0226538229
commit 5beebfd739
17 changed files with 247 additions and 206 deletions

View File

@@ -167,34 +167,12 @@ def load_registry(path: Path | None = None) -> NodeRegistry:
deployed: dict[str, Deployment] = {}
for key, comp_data in data.get("deployed", {}).items():
# Key is the composite "<kind>/<name>" (new) or a bare name (legacy).
key_kind, name = key.split("/", 1) if "/" in key else (None, key)
# New shape carries manager/launcher/kind; legacy carries runner/behavior.
manager = comp_data.get("manager")
launcher = comp_data.get("launcher")
if manager is None:
runner = comp_data.get("runner", "command")
manager = {"static": "caddy", "path": "path", "remote": "none"}.get(
runner, "systemd"
)
if manager == "systemd":
launcher = runner
kind = comp_data.get("kind") or key_kind
if kind is None:
behavior = comp_data.get("behavior")
if comp_data.get("schedule"):
kind = "job"
elif manager == "caddy" or behavior == "frontend":
kind = "static"
elif manager == "path" or behavior == "tool":
kind = "tool"
elif manager == "none":
kind = "reference"
else:
kind = "service"
# Key is the composite "<kind>/<name>"; manager/kind are always present
# (save_registry writes them). registry.yaml is regenerated every apply.
kind, name = key.split("/", 1)
deployed[NodeRegistry.key(kind, name)] = Deployment(
manager=manager,
launcher=launcher,
manager=comp_data["manager"],
launcher=comp_data.get("launcher"),
run_cmd=comp_data.get("run_cmd", []),
stop_cmd=comp_data.get("stop_cmd", []),
env=comp_data.get("env", {}),