Enforce readiness tiers and reconcile blocked workplans

Assistant: codex
Assistant-Model: gpt-6-astra
Assistant-Session: 01a0e75a-fc5c-7913-9dba-9846210c766d
This commit is contained in:
tegwick 2026-09-28 11:40:57 +02:00
parent 370e1f84c7
commit 36445ae679
14 changed files with 652 additions and 39 deletions

View file

@ -28,7 +28,7 @@
set -euo pipefail
export BAO_ADDR="${BAO_ADDR:-https://bao.coulomb.social}"
export BAO_ADDR="${BAO_ADDR:-http://127.0.0.1:18200}"
GRANT_FILE="${GRANT_FILE:-$HOME/.claude-bao-token}"
GRANT_POLICY="${GRANT_POLICY:-ops-mason-build}"
GRANT_TTL="${GRANT_TTL:-45m}"

View file

@ -24,31 +24,42 @@ REQUIRED = ("description", "owner", "used_by", "rotation", "on_loss")
DEFAULT_ROOTS = ("operators", "platform/workloads")
def bao(*args: str) -> dict | list | None:
class InventoryError(RuntimeError):
"""Inventory could not be completed; never report this as an empty store."""
def bao(*args: str) -> dict | list:
env = dict(os.environ)
env.setdefault("BAO_ADDR", "https://bao.coulomb.social")
env.setdefault("BAO_ADDR", "http://127.0.0.1:18200")
grant = os.path.expanduser("~/.claude-bao-token")
if "BAO_TOKEN" not in env and os.path.exists(grant):
with open(grant) as f:
env["BAO_TOKEN"] = f.read().strip()
if not env.get("BAO_TOKEN"):
raise InventoryError("No scoped BAO_TOKEN or ops-mason grant; inventory was not run.")
# The Vault/OpenBao CLI rejects flags placed after a positional argument,
# so -format=json goes immediately before the path, not at the end.
argv = ["bao", *args[:-1], "-format=json", args[-1]]
p = subprocess.run(argv, capture_output=True, text=True, timeout=30, env=env)
try:
p = subprocess.run(argv, capture_output=True, text=True, timeout=30, env=env)
except (OSError, subprocess.TimeoutExpired) as exc:
raise InventoryError("OpenBao metadata command unavailable or timed out") from exc
if p.returncode != 0:
return None
raise InventoryError(f"OpenBao metadata request failed for {args[-1]}; inventory incomplete")
try:
return json.loads(p.stdout)
except json.JSONDecodeError:
return None
except json.JSONDecodeError as exc:
raise InventoryError("Invalid OpenBao metadata response; inventory incomplete") from exc
def walk(prefix: str) -> list[str]:
keys = bao("kv", "list", prefix)
if not isinstance(keys, list):
return []
raise InventoryError(f"Invalid metadata listing for {prefix}")
out: list[str] = []
for k in keys:
if not isinstance(k, str) or not k.rstrip("/") or "/" in k.rstrip("/") or k.rstrip("/") in {".", ".."}:
raise InventoryError(f"Invalid child in metadata listing for {prefix}")
child = f"{prefix.rstrip('/')}/{k.rstrip('/')}"
out.extend(walk(child) if k.endswith("/") else [child])
return out
@ -62,9 +73,13 @@ def main() -> int:
for root in roots:
for path in walk(root):
total += 1
meta = bao("kv", "metadata", "get", path) or {}
d = meta.get("data", {}) if isinstance(meta, dict) else {}
meta = bao("kv", "metadata", "get", path)
if not isinstance(meta, dict) or not isinstance(meta.get("data"), dict):
raise InventoryError(f"Invalid metadata response for {path}")
d = meta["data"]
cm = d.get("custom_metadata") or {}
if not isinstance(cm, dict):
raise InventoryError(f"Invalid custom metadata for {path}")
missing = [k for k in REQUIRED if not cm.get(k)]
if missing:
incomplete += 1
@ -90,4 +105,8 @@ def main() -> int:
if __name__ == "__main__":
raise SystemExit(main())
try:
raise SystemExit(main())
except InventoryError as exc:
print(f"ERROR: {exc}", file=sys.stderr)
raise SystemExit(2)