Skip to content

Commit 18ff384

Browse files
committed
feat: add codex runtime validation modes
1 parent 8b746f3 commit 18ff384

1 file changed

Lines changed: 89 additions & 5 deletions

File tree

scripts/validate_runtime.sh

Lines changed: 89 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -6,12 +6,17 @@ cd "$ROOT"
66

77
STRICT_RUNTIME=0
88
CODEX_HOME_DIR=""
9+
MODE="auto"
910

1011
usage() {
1112
cat <<'EOF'
12-
Usage: scripts/validate_runtime.sh [--codex-home PATH] [--strict-runtime]
13+
Usage: scripts/validate_runtime.sh [--codex-home PATH] [--strict-runtime] [--mode auto|static|installed|live]
1314
14-
Runs installed-runtime validation against a temporary CODEX_HOME by default.
15+
Modes:
16+
auto Static materialization plus best-effort installed-runtime probes (default).
17+
static No codex binary and no network; materialize and parse generated TOML only.
18+
installed Require a local codex binary; no package-registry freshness checks.
19+
live Require a local codex binary and run network-backed freshness checks.
1520
EOF
1621
}
1722

@@ -24,6 +29,18 @@ while [ "$#" -gt 0 ]; do
2429
--strict|--strict-runtime)
2530
STRICT_RUNTIME=1
2631
;;
32+
--mode)
33+
shift
34+
MODE=${1:?--mode requires auto, static, installed, or live}
35+
case "$MODE" in
36+
auto|static|installed|live) ;;
37+
*)
38+
printf 'Invalid --mode: %s\n' "$MODE" >&2
39+
usage >&2
40+
exit 2
41+
;;
42+
esac
43+
;;
2744
-h|--help)
2845
usage
2946
exit 0
@@ -57,12 +74,75 @@ fi
5774

5875
scripts/install_system_codex.sh --dry-run --codex-home "$CODEX_HOME_DIR" "${strict_args[@]}"
5976
scripts/install_system_codex.sh --apply --codex-home "$CODEX_HOME_DIR" "${strict_args[@]}"
77+
78+
python3 - "$CODEX_HOME_DIR" <<'PY'
79+
from __future__ import annotations
80+
81+
import re
82+
import sys
83+
import tomllib
84+
from pathlib import Path
85+
86+
home = Path(sys.argv[1])
87+
config = home / "config.toml"
88+
yolo = home / "rldyour-yolo.config.toml"
89+
safe = home / "rldyour-safe.config.toml"
90+
required = [config, yolo, safe]
91+
92+
93+
def fail(message: str) -> None:
94+
print(f"static materialization check failed: {message}", file=sys.stderr)
95+
raise SystemExit(1)
96+
97+
98+
def load(path: Path) -> dict:
99+
if not path.exists():
100+
fail(f"missing generated file {path}")
101+
text = path.read_text(encoding="utf-8")
102+
if "default_permissions" in text:
103+
fail(f"{path.name} contains active default_permissions while legacy sandbox is selected")
104+
if re.search(r"^\s*\[profiles\.", text, re.M):
105+
fail(f"{path.name} contains legacy [profiles.*] table")
106+
if re.search(r"^\s*profile\s*=", text, re.M):
107+
fail(f"{path.name} contains legacy profile selector")
108+
if "plugin_hooks" in text:
109+
fail(f"{path.name} contains removed plugin_hooks feature flag")
110+
with path.open("rb") as fh:
111+
return tomllib.load(fh)
112+
113+
114+
base, yolo_cfg, safe_cfg = [load(path) for path in required]
115+
features = base.get("features") or {}
116+
if features.get("hooks") is not True:
117+
fail("config.toml must enable features.hooks")
118+
if features.get("multi_agent") is not True:
119+
fail("config.toml must enable features.multi_agent")
120+
if "plugin_hooks" in features:
121+
fail("config.toml must not enable removed features.plugin_hooks")
122+
if not base.get("mcp_servers"):
123+
fail("config.toml must materialize [mcp_servers.*] entries")
124+
if yolo_cfg.get("approval_policy") != "never":
125+
fail("rldyour-yolo.config.toml must set approval_policy = \"never\"")
126+
if yolo_cfg.get("sandbox_mode") != "danger-full-access":
127+
fail("rldyour-yolo.config.toml must set sandbox_mode = \"danger-full-access\"")
128+
if safe_cfg.get("approval_policy") != "on-request":
129+
fail("rldyour-safe.config.toml must set approval_policy = \"on-request\"")
130+
if safe_cfg.get("sandbox_mode") != "workspace-write":
131+
fail("rldyour-safe.config.toml must set sandbox_mode = \"workspace-write\"")
132+
print("ok: static Codex runtime materialization")
133+
PY
134+
135+
if [ "$MODE" = "static" ]; then
136+
printf 'Static runtime validation passed with CODEX_HOME=%s.\n' "$CODEX_HOME_DIR"
137+
exit 0
138+
fi
139+
60140
scripts/doctor_system_codex.sh --quick --codex-home "$CODEX_HOME_DIR" "${strict_args[@]}"
61141
if command -v codex >/dev/null 2>&1; then
62142
CODEX_HOME="$CODEX_HOME_DIR" scripts/validate_execpolicy_rules.sh "$CODEX_HOME_DIR/rules"
63143
CODEX_HOME="$CODEX_HOME_DIR" python3 scripts/smoke_codex_hook_listing.py --codex-home "$CODEX_HOME_DIR"
64-
elif [ "$STRICT_RUNTIME" -eq 1 ]; then
65-
printf 'codex command not found; strict runtime execpolicy validation cannot run.\n' >&2
144+
elif [ "$STRICT_RUNTIME" -eq 1 ] || [ "$MODE" = "installed" ] || [ "$MODE" = "live" ]; then
145+
printf 'codex command not found; installed runtime validation cannot run.\n' >&2
66146
exit 1
67147
else
68148
printf 'skip execpolicy rules validation: codex command not found\n'
@@ -71,4 +151,8 @@ scripts/smoke_hooks.sh --codex-home "$CODEX_HOME_DIR"
71151
scripts/smoke_fullrepo_sync.sh
72152
scripts/smoke_fullrepo_bootstrap_init.sh
73153

74-
printf 'Runtime validation passed with CODEX_HOME=%s.\n' "$CODEX_HOME_DIR"
154+
if [ "$MODE" = "live" ]; then
155+
python3 scripts/check_mcp_runtime_versions.py
156+
fi
157+
158+
printf 'Runtime validation passed in %s mode with CODEX_HOME=%s.\n' "$MODE" "$CODEX_HOME_DIR"

0 commit comments

Comments
 (0)