84 lines
3.9 KiB
Python
84 lines
3.9 KiB
Python
"""Registration and dependency contract for newly route-backed HUX families."""
|
|
|
|
from __future__ import annotations
|
|
|
|
import sys
|
|
from pathlib import Path
|
|
|
|
ROOT = Path(__file__).resolve().parents[2]
|
|
FOUNDATION = ROOT / "dockerfiles" / "hermes-hux-foundation"
|
|
if str(FOUNDATION) not in sys.path:
|
|
sys.path.insert(0, str(FOUNDATION))
|
|
|
|
from hux import contracts, flags, server
|
|
|
|
ALL_ON = ",".join(card["flag"] for card in contracts.load_flags()["cards"])
|
|
EXPECTED_FAMILIES = ("modes", "multimodal", "suggestions", "releases")
|
|
EXPECTED_ROUTES = {
|
|
"HUX-06": {
|
|
"/hux/v1/modes",
|
|
"/hux/v1/projects/{project_id}/conversations/{id}/mode",
|
|
},
|
|
"HUX-07": {
|
|
"/hux/v1/projects/{project_id}/conversations/{id}/multimodal/items",
|
|
"/hux/v1/projects/{project_id}/conversations/{id}/multimodal/items/{item_id}",
|
|
"/hux/v1/projects/{project_id}/conversations/{id}/multimodal/items/{item_id}/transcript-corrections",
|
|
"/hux/v1/projects/{project_id}/conversations/{id}/capture-intents",
|
|
},
|
|
"HUX-09": {
|
|
"/hux/v1/projects/{project_id}/conversations/{id}/suggestions/evaluate",
|
|
"/hux/v1/projects/{project_id}/conversations/{id}/suggestions/{suggestion_id}/decisions",
|
|
"/hux/v1/projects/{project_id}/conversations/{id}/suggestions/states",
|
|
},
|
|
"HUX-12": {
|
|
"/hux/v1/projects/{project_id}/conversations/{id}/releases",
|
|
"/hux/v1/projects/{project_id}/conversations/{id}/releases/{release_id}",
|
|
"/hux/v1/projects/{project_id}/conversations/{id}/releases/{release_id}/transitions",
|
|
},
|
|
}
|
|
|
|
|
|
def test_server_registers_each_family_and_exact_card_routes(tmp_path):
|
|
assert all(name in server.FAMILIES for name in EXPECTED_FAMILIES)
|
|
router = server.build_router(tmp_path, {"HUX_FLAGS": ALL_ON, "HUX_ROUTER_KEY": "rk"})
|
|
pairs = [(route.method, route.template) for route in router.routes]
|
|
assert len(pairs) == len(set(pairs)), "method/template registration must be unique"
|
|
registered = {route.template for route in router.routes}
|
|
for card, expected in EXPECTED_ROUTES.items():
|
|
assert set(flags.CARD_ROUTES[card]) == expected
|
|
assert expected <= registered
|
|
assert router.flags.enabled(card)
|
|
|
|
|
|
def test_release_followthrough_requires_foundation_but_not_activity():
|
|
registry = contracts.load_flags()
|
|
release = next(card for card in registry["cards"] if card["card"] == "HUX-12")
|
|
assert release["depends_on"] == ["HUX-11"]
|
|
assert release["contracts"] == ["release.schema.json", "release-ledger.schema.json"]
|
|
assert not flags.Flags({"HUX_FLAGS": "hux.release_followthrough"}).enabled("HUX-12")
|
|
enabled = flags.Flags({"HUX_FLAGS": "hux.foundation,hux.release_followthrough"})
|
|
assert enabled.enabled("HUX-12")
|
|
|
|
|
|
def test_contract_loader_and_worker_allowlist_are_complete():
|
|
schemas = contracts.load_all()
|
|
assert {"multimodal.schema.json", "release-ledger.schema.json"} <= schemas.keys()
|
|
multimodal = next(card for card in contracts.load_flags()["cards"] if card["card"] == "HUX-07")
|
|
assert multimodal["contracts"][-1] == "multimodal.schema.json"
|
|
worker_expected = {
|
|
("GET", "/hux/v1/modes"),
|
|
("GET", "/hux/v1/projects/{project_id}/conversations/{id}/mode"),
|
|
("POST", "/hux/v1/projects/{project_id}/conversations/{id}/multimodal/items"),
|
|
("POST", "/hux/v1/projects/{project_id}/conversations/{id}/releases"),
|
|
("GET", "/hux/v1/projects/{project_id}/conversations/{id}/releases"),
|
|
("GET", "/hux/v1/projects/{project_id}/conversations/{id}/releases/{release_id}"),
|
|
("POST", "/hux/v1/projects/{project_id}/conversations/{id}/releases/{release_id}/transitions"),
|
|
}
|
|
assert worker_expected <= flags.WORKER_ROUTES
|
|
assert ("PUT", "/hux/v1/projects/{project_id}/conversations/{id}/mode") not in flags.WORKER_ROUTES
|
|
assert not any("suggestions" in path for _, path in flags.WORKER_ROUTES)
|
|
|
|
|
|
def test_registration_test_stays_bounded():
|
|
assert len(Path(__file__).read_text().splitlines()) <= 500
|