WARDEN-WP-0029: implement plan front door, org posture, desk, freshness
All checks were successful
CI Smoke / host-smoke (push) Successful in 1s
CI Smoke / container-smoke (push) Successful in 2s

Ship posture-aware access planning: organization_posture=build (axis C),
catalog freshness warnings, warden plan verdicts, localhost founder desk,
and playbook/agent guidance that retire /tmp file-drop patterns.

Compose route catalog + handoff rather than a second routing layer.
This commit is contained in:
tegwick 2026-07-18 16:59:37 +02:00
parent 5c6b71b83b
commit 5149946a4c
18 changed files with 1690 additions and 102 deletions

View file

@ -5,12 +5,19 @@ subsystem. It loads the machine-readable routing catalog and answers "who owns
this need and where is the authoritative doc". The one lane ops-warden executes
(SSH certificate issuance) is the only entry that carries authored steps.
"""
from warden.routing.catalog import Catalog, CatalogError, find_catalog_path, load_catalog
from warden.routing.catalog import (
Catalog,
CatalogError,
CatalogFreshness,
find_catalog_path,
load_catalog,
)
from warden.routing.models import RouteEntry
__all__ = [
"Catalog",
"CatalogError",
"CatalogFreshness",
"RouteEntry",
"find_catalog_path",
"load_catalog",

View file

@ -13,10 +13,11 @@ never restates another subsystem's procedure.
"""
from __future__ import annotations
import hashlib
import os
import re
from dataclasses import dataclass
from datetime import date
from dataclasses import dataclass, field
from datetime import date, datetime, timezone
from pathlib import Path
from typing import List, Optional
@ -112,6 +113,45 @@ def find_catalog_path(start: Optional[Path] = None) -> Path:
)
@dataclass
class CatalogFreshness:
"""Install vs source freshness for the routing catalog (WARDEN-WP-0029 T05).
Surfaces the path that was loaded, whether it is the wheel-bundled fallback
(the stale-CLI failure mode), a content hash, and entry review age. Never
carries secret material.
"""
path: str
source: str # "override" | "repo" | "bundled"
content_hash: str
mtime_iso: str
package_version: str
entry_count: int
active_count: int
newest_reviewed: Optional[str]
oldest_reviewed: Optional[str]
stale_entry_count: int
using_bundled: bool
warnings: List[str] = field(default_factory=list)
def to_dict(self) -> dict:
return {
"path": self.path,
"source": self.source,
"content_hash": self.content_hash,
"mtime_iso": self.mtime_iso,
"package_version": self.package_version,
"entry_count": self.entry_count,
"active_count": self.active_count,
"newest_reviewed": self.newest_reviewed,
"oldest_reviewed": self.oldest_reviewed,
"stale_entry_count": self.stale_entry_count,
"using_bundled": self.using_bundled,
"warnings": list(self.warnings),
}
@dataclass
class Catalog:
path: Path
@ -161,6 +201,85 @@ class Catalog:
if is_review_stale(e.reviewed, threshold_days=threshold_days, today=today)
]
def freshness(
self,
*,
stale_threshold_days: int = DEFAULT_STALE_DAYS,
today: Optional[date] = None,
) -> CatalogFreshness:
"""Describe which catalog was loaded and how fresh it is (WP-0029 T05)."""
path = self.path.resolve()
text = path.read_text(encoding="utf-8") if path.exists() else ""
digest = hashlib.sha256(text.encode("utf-8")).hexdigest()[:12]
mtime_iso = ""
if path.exists():
mtime_iso = datetime.fromtimestamp(
path.stat().st_mtime, tz=timezone.utc
).isoformat()
source = _classify_catalog_source(path)
using_bundled = source == "bundled"
reviewed_dates = [e.reviewed for e in self.entries if e.reviewed]
newest = max(reviewed_dates) if reviewed_dates else None
oldest = min(reviewed_dates) if reviewed_dates else None
stale_count = len(self.stale(include_draft=True, threshold_days=stale_threshold_days, today=today))
package_version = _package_version()
warnings: List[str] = []
if using_bundled:
warnings.append(
"using wheel-bundled catalog fallback — reinstall from checkout "
"(`uv tool install -e .` or `pip install -e .`) if lanes look missing"
)
if stale_count:
warnings.append(
f"{stale_count} catalog entr{'y' if stale_count == 1 else 'ies'} "
f"past {stale_threshold_days}d review cadence"
)
return CatalogFreshness(
path=str(path),
source=source,
content_hash=digest,
mtime_iso=mtime_iso,
package_version=package_version,
entry_count=len(self.entries),
active_count=len(self.listed(include_draft=False)),
newest_reviewed=newest,
oldest_reviewed=oldest,
stale_entry_count=stale_count,
using_bundled=using_bundled,
warnings=warnings,
)
def _package_version() -> str:
try:
from importlib.metadata import version
return version("ops-warden")
except Exception: # noqa: BLE001
try:
from warden import __version__
return str(__version__)
except Exception: # noqa: BLE001
return "unknown"
def _classify_catalog_source(path: Path) -> str:
"""Classify catalog load path for freshness warnings."""
if os.environ.get("WARDEN_ROUTING_CATALOG"):
return "override"
resolved = str(path.resolve())
if "/_registry/" in resolved or resolved.endswith("/warden/_registry/routing/catalog.yaml"):
return "bundled"
# hatch force-include places registry at warden/_registry
parts = path.resolve().parts
if "_registry" in parts:
return "bundled"
return "repo"
def _assert_no_secret_material(
entry_id: str, field_name: str, value: str, *, prose: bool = False