#!/usr/bin/env python3 """Start or inspect the structurally no-send Hermes/leoclean staging runtime.""" from __future__ import annotations import argparse import asyncio import hashlib import importlib import json import os import platform import shlex import signal import stat import subprocess import sys import tempfile from pathlib import Path from typing import Any READINESS_SCHEMA = "livingip.leocleanNoSendServiceReadiness.v1" class NoSendContractError(RuntimeError): """The runtime does not satisfy its no-send contract.""" def _require(condition: bool, message: str) -> None: if not condition: raise NoSendContractError(message) class _SealedToolMap(dict[str, Any]): """Read-only registry map after the reviewed tools are installed.""" @staticmethod def _deny(*_args: Any, **_kwargs: Any) -> None: raise NoSendContractError("Hermes tool registry is sealed by the no-send runtime") __setitem__ = _deny __delitem__ = _deny clear = _deny pop = _deny popitem = _deny setdefault = _deny update = _deny def _load_json(path: Path) -> dict[str, Any]: try: value = json.loads(path.read_text(encoding="utf-8")) except (OSError, json.JSONDecodeError) as exc: raise NoSendContractError(f"cannot load {path.name}: {type(exc).__name__}") from exc _require(isinstance(value, dict), f"{path.name} must be a JSON object") return value def _sha256(path: Path) -> str: digest = hashlib.sha256() with path.open("rb") as handle: for chunk in iter(lambda: handle.read(1024 * 1024), b""): digest.update(chunk) return digest.hexdigest() def _runtime_root() -> Path: return Path(__file__).resolve().parent def _validate_contract(value: dict[str, Any]) -> None: _require( set(value) == { "schema", "runtime_mode", "transport_authority", "service_mode", "handler_platform", "plugins", "toolset", "profile", "environment", "database", "claim_ceiling", }, "no-send runtime contract fields are not exact", ) _require( value.get("schema") == "livingip.leocleanNoSendRuntimeContract.v1", "no-send runtime contract schema is invalid", ) _require(value.get("runtime_mode") == "gcp_staging_no_send", "runtime mode is not no-send staging") _require(value.get("transport_authority") == "absent", "transport authority is not absent") _require(value.get("service_mode") == "gateway_without_platform_adapters", "service mode is not no-send") _require(value.get("handler_platform") == "api_server", "handler platform is not the reviewed surface") _require( value.get("plugins") == { "allowed": [ { "name": "leo-db-context", "source": "user", "tools": [], "hooks": ["post_llm_call", "pre_llm_call"], } ] }, "plugin contract is not exact", ) toolset = value.get("toolset") or {} _require( toolset.get("allowed_tools") == ["skills_list", "skill_view", "terminal"], "allowed tool contract is not exact", ) _require( set(toolset.get("forbidden_tools") or []) == {"cronjob", "delegate_task", "memory", "process", "send_message", "skill_manage"}, "forbidden tool contract is not exact", ) _require( set(toolset.get("terminal_commands") or []) == { "context", "decision-matrix-status", "edges", "evidence", "list-proposals", "propose-core-change", "propose-edge", "search", "search-proposals", "show", "show-proposal", "status", }, "terminal command contract is not exact", ) profile = value.get("profile") or {} _require( set(profile.get("template_entries") or []) == {"bin", "config.yaml", "plugins", "skills"}, "profile template contract is not exact", ) _require( set(profile.get("required_runtime_entries") or []) == {"SOUL.md", "identity-lock.json", "identity-manifest.json"}, "runtime identity contract is not exact", ) _require( set(profile.get("forbidden_entries") or []) == {".env", "BOOT.md", "auth.json", "gateway.json", "hooks", "processes.json", "secrets"}, "forbidden profile contract is not exact", ) learning_policy = profile.get("learning_policy") or {} _require( set(learning_policy) == { "automatic_memory_review_interval", "automatic_skill_review_interval", "memory_enabled", "user_profile_enabled", } and learning_policy.get("memory_enabled") is False and learning_policy.get("user_profile_enabled") is False and type(learning_policy.get("automatic_memory_review_interval")) is int and learning_policy.get("automatic_memory_review_interval") == 0 and type(learning_policy.get("automatic_skill_review_interval")) is int and learning_policy.get("automatic_skill_review_interval") == 0, "learning policy contract is not exact", ) routing_policy = profile.get("routing_policy") or {} _require( set(routing_policy) == {"cheap_model", "smart_model_routing"} and routing_policy.get("cheap_model") == "absent" and routing_policy.get("smart_model_routing") is False, "routing policy contract is not exact", ) environment = value.get("environment") or {} _require( environment.get("allowed_provider_credentials") == ["OPENROUTER_API_KEY"], "provider credential contract is not exact", ) _require( set(environment.get("allowed_runtime_variables") or []) == {"HERMES_HOME", "PYTHONDONTWRITEBYTECODE", "PYTHONNOUSERSITE", "PYTHONSAFEPATH"}, "runtime environment allowlist is not exact", ) required_forbidden_exact = { "ALL_PROXY", "BASH_ENV", "BOT_TOKEN", "ENV", "GATEWAY_ALLOW_ALL_USERS", "GATEWAY_ALLOWED_USERS", "GOOGLE_APPLICATION_CREDENTIALS", "HERMES_ENABLE_PROJECT_PLUGINS", "HERMES_SESSION_PLATFORM", "HTTP_PROXY", "HTTPS_PROXY", "LD_PRELOAD", "PYTHONHOME", "PYTHONPATH", "TELEGRAM_BOT_TOKEN", } _require( set(environment.get("forbidden_exact") or []) == required_forbidden_exact, "forbidden environment contract is not exact", ) _require( set(environment.get("forbidden_prefixes") or []) == { "CLOUDSDK_", "DINGTALK_", "DISCORD_", "EMAIL_", "FEISHU_", "HERMES_", "LD_", "MATRIX_", "MATTERMOST_", "SIGNAL_", "SLACK_", "SMS_", "TELEGRAM_", "TWILIO_", "WEBCOM_", "WEBHOOK_", "WHATSAPP_", }, "transport environment prefix contract is not exact", ) _require( set(environment.get("forbidden_suffixes") or []) == {"_PASSWORD", "_SECRET", "_TOKEN", "_API_KEY"}, "secret-shaped environment contract is not exact", ) database = value.get("database") or {} _require( database == { "automatic_context_modes": ["claim_evidence_challenge", "review_only_candidate"], "canonical_database": "teleo_canonical", "runtime_role": "leoclean_kb_runtime", "proposal_function": "kb_stage.stage_leoclean_proposal(text,text,text,text,jsonb)", "direct_canonical_writes": "denied", "direct_stage_table_writes": "denied", "proposal_staging": "function_only", "unsupported_context_policy": "fail_closed", }, "database authority contract is not exact", ) _require(isinstance(value.get("claim_ceiling"), str) and bool(value["claim_ceiling"]), "claim ceiling is missing") def _contract() -> dict[str, Any]: value = _load_json(_runtime_root() / "runtime-contract.json") _require( value.get("schema") == "livingip.leocleanNoSendRuntimeContract.v1", "unsupported no-send runtime contract", ) _validate_contract(value) return value def _validate_environment(contract: dict[str, Any]) -> None: policy = contract["environment"] allowed_provider = set(policy["allowed_provider_credentials"]) allowed_runtime = set(policy["allowed_runtime_variables"]) forbidden_exact = set(policy["forbidden_exact"]) forbidden_prefixes = tuple(policy["forbidden_prefixes"]) forbidden_suffixes = tuple(policy["forbidden_suffixes"]) violations: list[str] = [] for name, value in os.environ.items(): if not value: continue if name in allowed_provider or name in allowed_runtime: continue if name in forbidden_exact or name.startswith(forbidden_prefixes) or name.endswith(forbidden_suffixes): violations.append(name) _require(not violations, f"forbidden transport environment is present: {sorted(violations)}") def _validate_profile(profile: Path, contract: dict[str, Any], *, template: bool) -> None: _require(profile.is_dir() and not profile.is_symlink(), "profile root is missing or unsafe") forbidden = set(contract["profile"]["forbidden_entries"]) actual = {path.name for path in profile.iterdir()} present_forbidden = sorted(actual & forbidden) _require(not present_forbidden, f"forbidden profile entries are present: {present_forbidden}") _require(not any(path.is_symlink() for path in profile.rglob("*")), "profile contains a symlink") immutable_entries = set(contract["profile"]["template_entries"]) expected_template = _runtime_root() / "profile-template" _require(expected_template.is_dir(), "bound profile template is missing") for entry in sorted(immutable_entries): expected = expected_template / entry observed = profile / entry _require(expected.exists() and observed.exists(), f"immutable profile entry is missing: {entry}") _require(expected.is_dir() == observed.is_dir(), f"immutable profile entry type drifted: {entry}") if expected.is_file(): _require(_sha256(expected) == _sha256(observed), f"immutable profile file drifted: {entry}") _require( stat.S_IMODE(expected.stat().st_mode) == stat.S_IMODE(observed.stat().st_mode), f"immutable profile file mode drifted: {entry}", ) continue expected_files = { path.relative_to(expected).as_posix(): ( _sha256(path), stat.S_IMODE(path.stat().st_mode), ) for path in expected.rglob("*") if path.is_file() } observed_files = { path.relative_to(observed).as_posix(): ( _sha256(path), stat.S_IMODE(path.stat().st_mode), ) for path in observed.rglob("*") if path.is_file() } _require(observed_files == expected_files, f"immutable profile tree drifted: {entry}") if template: _require(actual == immutable_entries, "profile template entry set is not exact") else: required_identity = set(contract["profile"]["required_runtime_entries"]) state_policy = contract["profile"]["allowed_runtime_state"] state_directories = set(state_policy["directories"]) state_files = set(state_policy["files"]) allowed = immutable_entries | required_identity | state_directories | state_files _require(required_identity <= actual, "compiled runtime profile is incomplete") _require(actual <= allowed, f"compiled runtime profile has unapproved entries: {sorted(actual - allowed)}") for name in sorted(required_identity): entry = profile / name _require( entry.is_file() and entry.stat().st_size <= 1024 * 1024, f"runtime identity entry is invalid: {name}" ) for name in sorted(actual & state_directories): _require((profile / name).is_dir(), f"runtime state entry must be a directory: {name}") for name in sorted(actual & state_files): _require((profile / name).is_file(), f"runtime state entry must be a file: {name}") def _load_profile_config(profile: Path, contract: dict[str, Any]) -> dict[str, Any]: try: import yaml value = yaml.safe_load((profile / "config.yaml").read_text(encoding="utf-8")) or {} except (OSError, TypeError, ValueError) as exc: raise NoSendContractError(f"cannot load config.yaml: {type(exc).__name__}") from exc _require(isinstance(value, dict), "config.yaml must be a mapping") expected_top_level = { "agent", "display", "known_plugin_toolsets", "mcp_servers", "memory", "model", "platform_toolsets", "skills", "smart_model_routing", } _require(set(value) == expected_top_level, "config.yaml top-level fields are not exact") _require(value.get("mcp_servers") == {}, "MCP servers are forbidden in no-send staging") memory = value.get("memory") or {} _require( set(memory) == {"enabled", "memory_enabled", "nudge_interval", "user_profile_enabled"} and memory.get("enabled") is False and memory.get("memory_enabled") is False and memory.get("user_profile_enabled") is False and type(memory.get("nudge_interval")) is int and memory.get("nudge_interval") == 0, "persistent memory and automatic memory review must be disabled", ) skills = value.get("skills") or {} _require( set(skills) == {"creation_nudge_interval"} and type(skills.get("creation_nudge_interval")) is int and skills.get("creation_nudge_interval") == 0, "automatic skill review must be disabled", ) _require(value.get("smart_model_routing") is False, "smart-model routing must be disabled") expected_toolset = contract["toolset"]["name"] _require( value.get("platform_toolsets") == {"api_server": [expected_toolset]}, "handler toolset binding is not exact", ) _require( value.get("known_plugin_toolsets") == {"api_server": []}, "plugin toolset allowlist is not exact", ) encoded = json.dumps(value, sort_keys=True).lower() for marker in ( "telegram", "discord", "whatsapp", "slack", "signal", "mattermost", "matrix", "dingtalk", "feishu", "wecom", "webhook", "bot_token", "send_message", ): _require(marker not in encoded, f"transport marker is forbidden in config.yaml: {marker}") return value def _load_effective_policy(contract: dict[str, Any]) -> dict[str, Any]: """Prove what the pinned Hermes loader will give the actual agent runtime.""" try: from agent.smart_model_routing import choose_cheap_model_route from hermes_cli.config import load_config effective = load_config() except Exception as exc: raise NoSendContractError(f"cannot load effective Hermes config: {type(exc).__name__}") from exc _require(isinstance(effective, dict), "effective Hermes config must be a mapping") learning_policy = contract["profile"]["learning_policy"] memory = effective.get("memory") or {} skills = effective.get("skills") or {} _require(isinstance(memory, dict) and isinstance(skills, dict), "effective learning policy is invalid") _require(memory.get("memory_enabled") is False, "effective Hermes memory policy is not disabled") _require(memory.get("user_profile_enabled") is False, "effective Hermes user profile is not disabled") memory_interval = memory.get("nudge_interval") _require( type(memory_interval) is int and memory_interval == learning_policy["automatic_memory_review_interval"], "effective Hermes memory-review interval is not disabled", ) skill_interval = skills.get("creation_nudge_interval") _require( type(skill_interval) is int and skill_interval == learning_policy["automatic_skill_review_interval"], "effective Hermes skill-review policy is not disabled", ) _require(effective.get("smart_model_routing") is False, "effective Hermes smart routing is not disabled") _require( choose_cheap_model_route("what time is it?", effective.get("smart_model_routing")) is None, "effective Hermes config selected a cheap-model route", ) return { "memory_enabled": memory.get("memory_enabled"), "user_profile_enabled": memory.get("user_profile_enabled"), "memory_nudge_interval": memory.get("nudge_interval"), "skill_creation_nudge_interval": skills.get("creation_nudge_interval"), "smart_model_routing": False, "cheap_model_route": None, } def _restricted_terminal_handler( profile: Path, allowed_commands: set[str], tool_args: dict[str, Any], **_kwargs: Any, ) -> str: if not isinstance(tool_args, dict): return json.dumps({"output": "", "exit_code": 126, "error": "terminal arguments must be an object"}) unexpected = sorted(set(tool_args) - {"command", "timeout"}) if unexpected: return json.dumps({"output": "", "exit_code": 126, "error": "terminal arguments contain unsupported fields"}) command = tool_args.get("command") if not isinstance(command, str) or not command.strip(): return json.dumps({"output": "", "exit_code": 126, "error": "terminal command is required"}) if "\x00" in command or "\n" in command or "\r" in command: return json.dumps( {"output": "", "exit_code": 126, "error": "terminal command contains a forbidden control character"} ) try: argv = shlex.split(command, posix=True) except ValueError as exc: return json.dumps({"output": "", "exit_code": 126, "error": f"invalid terminal command: {exc}"}) wrapper = (profile / "bin" / "teleo-kb").resolve() if not argv or argv[0] not in {"teleo-kb", str(wrapper)}: return json.dumps({"output": "", "exit_code": 126, "error": "only the reviewed teleo-kb wrapper is allowed"}) if len(argv) < 2 or argv[1] not in allowed_commands: return json.dumps({"output": "", "exit_code": 126, "error": "teleo-kb command is outside the allowlist"}) forbidden_tokens = {";", "&&", "||", "|", ">", ">>", "<", "<<", "&"} forbidden_overrides = { "--canonical-db", "--credential-mode", "--db", "--host", "--password-secret", "--port", "--project", "--user", } if any(token in forbidden_tokens for token in argv[2:]): return json.dumps({"output": "", "exit_code": 126, "error": "terminal command contains a shell control token"}) if any( token in forbidden_overrides or any(token.startswith(f"{option}=") for option in forbidden_overrides) for token in argv[2:] ): return json.dumps({"output": "", "exit_code": 126, "error": "terminal command contains an identity override"}) try: timeout = int(tool_args.get("timeout") or 60) except (TypeError, ValueError): return json.dumps({"output": "", "exit_code": 126, "error": "terminal timeout must be an integer"}) timeout = min(max(timeout, 1), 120) child_environment = { "HOME": str(profile / "state"), "HERMES_HOME": str(profile), "LANG": "C", "LC_ALL": "C", "PATH": "/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin", } try: result = subprocess.run( [str(wrapper), *argv[1:]], cwd=profile, env=child_environment, text=True, capture_output=True, check=False, timeout=timeout, ) except subprocess.TimeoutExpired: return json.dumps({"output": "", "exit_code": 124, "error": "teleo-kb command timed out"}) return json.dumps( { "output": result.stdout[:65536], "exit_code": result.returncode, "error": (result.stderr[:65536] or None), "truncated": len(result.stdout) > 65536 or len(result.stderr) > 65536, } ) def _restricted_terminal_schema(commands: list[str]) -> dict[str, Any]: return { "name": "terminal", "description": "Run one reviewed teleo-kb knowledge command without a shell.", "parameters": { "type": "object", "properties": { "command": { "type": "string", "description": f"teleo-kb followed by one of: {', '.join(commands)}", }, "timeout": { "type": "integer", "minimum": 1, "maximum": 120, }, }, "required": ["command"], "additionalProperties": False, }, } def _plugin_inventory(contract: dict[str, Any]) -> list[dict[str, Any]]: from hermes_cli.plugins import get_plugin_manager manager = get_plugin_manager() observed: list[dict[str, Any]] = [] for name, loaded in sorted(manager._plugins.items()): observed.append( { "name": name, "source": loaded.manifest.source, "tools": sorted(loaded.tools_registered), "hooks": sorted(loaded.hooks_registered), "enabled": loaded.enabled, "error": loaded.error, } ) expected = [ { **item, "tools": sorted(item["tools"]), "hooks": sorted(item["hooks"]), "enabled": True, "error": None, } for item in contract["plugins"]["allowed"] ] _require(observed == expected, "effective Hermes plugin inventory is not exact") return observed def _assert_tool_registry(profile: Path, contract: dict[str, Any]) -> dict[str, Any]: from tools.registry import registry allowed_tools = sorted(contract["toolset"]["allowed_tools"]) _require(sorted(registry._tools) == allowed_tools, "effective Hermes tool registry is not exact") _require(isinstance(registry._tools, _SealedToolMap), "Hermes tool registry is not sealed") terminal_entry = registry._tools.get("terminal") _require(terminal_entry is not None, "restricted terminal is not registered") expected_marker = f"livingip-nosend-terminal:{profile.resolve()}" _require( getattr(terminal_entry.handler, "_livingip_no_send_handler", None) == expected_marker, "restricted terminal handler identity drifted", ) _require( terminal_entry.schema == _restricted_terminal_schema(contract["toolset"]["terminal_commands"]), "restricted terminal schema drifted", ) for forbidden in contract["toolset"]["forbidden_tools"]: _require(forbidden not in registry._tools, f"forbidden Hermes tool remains registered: {forbidden}") dispatched = json.loads(registry.dispatch(forbidden, {})) _require( dispatched == {"error": f"Unknown tool: {forbidden}"}, f"forbidden tool dispatch is not denied: {forbidden}" ) return { "toolset": contract["toolset"]["name"], "tools": sorted(registry._tools), "send_message_present": "send_message" in registry._tools, "registry_sealed": True, "terminal_handler": "livingip.restricted_teleo_kb.v1", "terminal_restricted_to": "profile/bin/teleo-kb", "plugins": _plugin_inventory(contract), } def _prepare_tool_surface(profile: Path, config: dict[str, Any], contract: dict[str, Any]) -> dict[str, Any]: import toolsets from hermes_cli import tools_config from tools.registry import registry importlib.import_module("tools.skills_tool") importlib.import_module("tools.terminal_tool") importlib.import_module("tools.process_registry") toolset_name = contract["toolset"]["name"] allowed_tools = list(contract["toolset"]["allowed_tools"]) toolsets.TOOLSETS[toolset_name] = { "description": "LivingIP no-send Cloud SQL knowledge tools", "tools": allowed_tools, "includes": [], } resolved = tools_config._get_platform_tools(config, contract["handler_platform"]) _require(resolved == {toolset_name}, "effective Hermes toolset is not exact") missing = sorted(name for name in allowed_tools if name not in registry._tools) _require(not missing, f"required Hermes tools are not registered: {missing}") _plugin_inventory(contract) retained = {name: registry._tools[name] for name in allowed_tools} terminal_entry = retained["terminal"] def restricted_terminal(args: dict[str, Any], **kwargs: Any) -> str: return _restricted_terminal_handler( profile, set(contract["toolset"]["terminal_commands"]), args, **kwargs, ) restricted_terminal._livingip_no_send_handler = f"livingip-nosend-terminal:{profile.resolve()}" # type: ignore[attr-defined] terminal_entry.handler = restricted_terminal terminal_entry.schema = _restricted_terminal_schema(contract["toolset"]["terminal_commands"]) terminal_entry.check_fn = None terminal_entry.requires_env = [] terminal_entry.toolset = toolset_name for name, entry in retained.items(): entry.toolset = toolset_name if name != "terminal": entry.check_fn = None entry.requires_env = [] registry._tools = _SealedToolMap(retained) registry._toolset_checks = {} return _assert_tool_registry(profile, contract) def _prepare( profile: Path, *, template: bool, ) -> tuple[dict[str, Any], dict[str, Any], dict[str, Any], dict[str, Any]]: contract = _contract() _validate_environment(contract) _validate_profile(profile, contract, template=template) os.environ["HERMES_HOME"] = str(profile) hermes_source = _runtime_root() / "hermes-agent" _require(hermes_source.is_dir(), "bound Hermes source tree is missing") if str(hermes_source) not in sys.path: sys.path.insert(0, str(hermes_source)) config = _load_profile_config(profile, contract) effective_policy = _load_effective_policy(contract) tool_surface = _prepare_tool_surface(profile, config, contract) return contract, config, tool_surface, effective_policy async def _exercise_runner(runner: Any, profile: Path, contract: dict[str, Any]) -> dict[str, Any]: started = await runner.start() _require(started, "Hermes no-send gateway did not start") post_start = _assert_tool_registry(profile, contract) hooks = [ {"name": item.get("name"), "path": item.get("path"), "events": sorted(item.get("events") or [])} for item in runner.hooks.loaded_hooks ] _require( hooks == [{"name": "boot-md", "path": "(builtin)", "events": ["gateway:startup"]}], "effective gateway hook inventory is not exact", ) importlib.import_module("model_tools") post_discovery = _assert_tool_registry(profile, contract) await runner.stop() _require(not runner.adapters, "gateway retained a transport adapter after stop") return { "started": True, "stopped": True, "post_start_registry": post_start, "post_discovery_registry": post_discovery, "gateway_hooks": hooks, } def probe(profile: Path, *, template: bool) -> dict[str, Any]: contract, config, tool_surface, effective_policy = _prepare(profile, template=template) from gateway.config import GatewayConfig from gateway.run import GatewayRunner gateway_config = GatewayConfig.from_dict({"platforms": {}}) runner = GatewayRunner(gateway_config) adapters = getattr(runner, "adapters", None) _require(isinstance(adapters, dict), "GatewayRunner adapters are not inspectable") _require(not adapters, "GatewayRunner unexpectedly has a transport adapter") _require(getattr(runner, "_smart_model_routing", None) == {}, "GatewayRunner retained smart-model routing") _require(not gateway_config.get_connected_platforms(), "a messaging platform is connected") _assert_tool_registry(profile, contract) lifecycle = asyncio.run(_exercise_runner(runner, profile, contract)) return { "schema": "livingip.leocleanNoSendRuntimeProbe.v1", "status": "pass", "runtime_mode": contract["runtime_mode"], "config_sha256": _sha256(profile / "config.yaml"), "gateway_runner": f"{runner.__class__.__module__}.{runner.__class__.__name__}", "gateway_adapter_count": len(adapters), "connected_platforms": [], "tool_surface": tool_surface, "effective_policy": effective_policy, "lifecycle": lifecycle, "provider_credential_names_present": sorted( name for name in contract["environment"]["allowed_provider_credentials"] if os.getenv(name) ), "claim_ceiling": contract["claim_ceiling"], "model": config["model"]["default"], "python_version": platform.python_version(), } def _write_readiness( profile: Path, readiness_file: Path, contract: dict[str, Any], runner: Any, tool_surface: dict[str, Any], ) -> None: state = profile / "state" _require(state.is_dir() and not state.is_symlink(), "service state directory is missing or unsafe") expected_parent = state.resolve(strict=True) _require( readiness_file.parent.resolve(strict=True) == expected_parent, "readiness file must be inside profile state" ) _require(readiness_file.name == "readiness.json", "readiness file name is not exact") _require(not readiness_file.is_symlink(), "readiness file cannot be a symlink") identity_hashes = {} for name in ("SOUL.md", "identity-lock.json", "identity-manifest.json"): path = profile / name _require(path.is_file() and not path.is_symlink(), f"runtime identity entry is unsafe: {name}") identity_hashes[name] = _sha256(path) payload = { "schema": READINESS_SCHEMA, "status": "ready", "process_id": os.getpid(), "runtime_mode": contract["runtime_mode"], "config_sha256": _sha256(profile / "config.yaml"), "gateway_adapter_count": len(runner.adapters), "connected_platforms": [], "tool_surface": tool_surface, "identity_sha256": identity_hashes, } encoded = (json.dumps(payload, separators=(",", ":"), sort_keys=True) + "\n").encode("utf-8") descriptor = None temporary = None try: descriptor, temporary = tempfile.mkstemp(prefix=".readiness.", dir=expected_parent) os.fchmod(descriptor, 0o600) with os.fdopen(descriptor, "wb", closefd=True) as handle: descriptor = None handle.write(encoded) handle.flush() os.fsync(handle.fileno()) os.replace(temporary, readiness_file) temporary = None finally: if descriptor is not None: os.close(descriptor) if temporary is not None: Path(temporary).unlink(missing_ok=True) async def _run_service(profile: Path, readiness_file: Path | None = None) -> bool: contract, _config, _surface, _effective_policy = _prepare(profile, template=False) from gateway.config import GatewayConfig from gateway.run import GatewayRunner config = GatewayConfig.from_dict({"platforms": {}}) runner = GatewayRunner(config) _require(not runner.adapters, "service cannot start with a transport adapter") _require(getattr(runner, "_smart_model_routing", None) == {}, "service retained smart-model routing") _assert_tool_registry(profile, contract) importlib.import_module("model_tools") tool_surface = _assert_tool_registry(profile, contract) loop = asyncio.get_running_loop() stop_tasks: set[asyncio.Task[Any]] = set() def stop() -> None: task = asyncio.create_task(runner.stop()) stop_tasks.add(task) task.add_done_callback(stop_tasks.discard) for sig in (signal.SIGINT, signal.SIGTERM): try: loop.add_signal_handler(sig, stop) except NotImplementedError: pass started = await runner.start() _require(started, "Hermes no-send gateway did not start") tool_surface = _assert_tool_registry(profile, contract) if readiness_file is not None: _write_readiness(profile, readiness_file, contract, runner, tool_surface) try: await runner.wait_for_shutdown() return True finally: if readiness_file is not None: readiness_file.unlink(missing_ok=True) def main() -> int: parser = argparse.ArgumentParser(description=__doc__) subparsers = parser.add_subparsers(dest="command", required=True) for name in ("probe", "service"): child = subparsers.add_parser(name) child.add_argument("--profile", required=True, type=Path) if name == "probe": child.add_argument("--template", action="store_true") else: child.add_argument("--readiness-file", type=Path) args = parser.parse_args() try: if args.command == "probe": print(json.dumps(probe(args.profile.resolve(), template=args.template), sort_keys=True)) return 0 readiness_file = args.readiness_file.absolute() if args.readiness_file else None return 0 if asyncio.run(_run_service(args.profile.resolve(), readiness_file)) else 1 except NoSendContractError as exc: print(json.dumps({"status": "fail", "error": str(exc)}, sort_keys=True), file=sys.stderr) return 65 if __name__ == "__main__": raise SystemExit(main())