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:
parent
370e1f84c7
commit
36445ae679
14 changed files with 652 additions and 39 deletions
|
|
@ -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}"
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue