Harden M8 preflight foundation
This commit is contained in:
@@ -351,6 +351,48 @@ def _cmd_registry_update(args):
|
||||
return 0
|
||||
|
||||
|
||||
def _print_preflight_sections(report: dict, prefix: str = "") -> None:
|
||||
"""Render the common portions of a structured preflight report."""
|
||||
labels = (
|
||||
("errors", "ERROR"),
|
||||
("warnings", "WARN"),
|
||||
("suggestions", "HINT"),
|
||||
)
|
||||
for key, marker in labels:
|
||||
values = report.get(key) or []
|
||||
if values:
|
||||
print(f"{prefix}{key.title()} ({len(values)}):")
|
||||
for value in values:
|
||||
print(f" {marker}: {value}")
|
||||
|
||||
|
||||
def _print_registry_suggestions(suggestions: dict) -> None:
|
||||
"""Render registry-specific category, similarity, and scrutiny evidence."""
|
||||
category = suggestions.get("category") or {}
|
||||
if category.get("suggested"):
|
||||
print(
|
||||
f"Suggested category: {category['suggested']} "
|
||||
f"({category.get('confidence', 0):.0%} confidence)"
|
||||
)
|
||||
|
||||
similar = suggestions.get("similar_tools") or []
|
||||
if similar:
|
||||
print(f"Similar registry tools ({len(similar)}):")
|
||||
for item in similar:
|
||||
print(
|
||||
f" - {item.get('name', 'unknown')} "
|
||||
f"({item.get('similarity', 0):.0%} similar)"
|
||||
)
|
||||
|
||||
scrutiny = suggestions.get("scrutiny") or {}
|
||||
findings = scrutiny.get("findings") or []
|
||||
if findings:
|
||||
print(f"Scrutiny findings ({len(findings)}):")
|
||||
for finding in findings:
|
||||
marker = str(finding.get("result", "info")).upper()
|
||||
print(f" {marker}: {finding.get('message', '')}")
|
||||
|
||||
|
||||
def _cmd_registry_publish(args):
|
||||
"""Publish a tool to the registry."""
|
||||
from ..registry_client import RegistryError, get_client
|
||||
@@ -404,6 +446,9 @@ def _cmd_registry_publish(args):
|
||||
# Validate
|
||||
try:
|
||||
data = yaml.safe_load(config_yaml)
|
||||
if not isinstance(data, dict):
|
||||
print("Error: config.yaml must contain a YAML mapping", file=sys.stderr)
|
||||
return 1
|
||||
name = data.get("name", "")
|
||||
version = data.get("version", "")
|
||||
if not name or not version:
|
||||
@@ -424,36 +469,41 @@ def _cmd_registry_publish(args):
|
||||
print(f" README: {len(readme)} bytes")
|
||||
print()
|
||||
|
||||
from ..preflight import analyze_tool
|
||||
from ..tool import Tool
|
||||
try:
|
||||
local_report = analyze_tool(Tool.from_dict(data))
|
||||
except (KeyError, TypeError, ValueError) as exc:
|
||||
print(f"Local preflight error: {exc}", file=sys.stderr)
|
||||
return 1
|
||||
|
||||
_print_preflight_sections(local_report.to_dict(), prefix="Local ")
|
||||
if not local_report.ok:
|
||||
return 1
|
||||
|
||||
# Attempt registry preflight if token is configured
|
||||
config = load_config()
|
||||
if config.registry.token:
|
||||
try:
|
||||
client = get_client()
|
||||
result = client.publish_tool(
|
||||
config_yaml, readme=readme, defaults=defaults,
|
||||
dry_run=True,
|
||||
)
|
||||
except Exception as e:
|
||||
print(f"Registry preflight error: {e}", file=sys.stderr)
|
||||
return 1
|
||||
errors = result.get("errors") or []
|
||||
warnings = result.get("warnings") or []
|
||||
suggestions = result.get("suggestions") or []
|
||||
if errors:
|
||||
print(f"Preflight errors ({len(errors)}):")
|
||||
for err in errors:
|
||||
print(f" ERROR: {err}")
|
||||
if warnings:
|
||||
print(f"Preflight warnings ({len(warnings)}):")
|
||||
for warn in warnings:
|
||||
print(f" WARN: {warn}")
|
||||
if suggestions:
|
||||
print(f"Suggestions ({len(suggestions)}):")
|
||||
for sug in suggestions:
|
||||
print(f" HINT: {sug}")
|
||||
if not errors and not warnings and not suggestions:
|
||||
print("Registry preflight passed.")
|
||||
return 0 if not errors else 1
|
||||
if not config.registry.token:
|
||||
print("No registry token configured — local preflight only.")
|
||||
return 0
|
||||
|
||||
try:
|
||||
client = get_client()
|
||||
result = client.publish_tool(
|
||||
config_yaml, readme=readme, defaults=defaults,
|
||||
dry_run=True,
|
||||
)
|
||||
except RegistryError as exc:
|
||||
print(f"Registry preflight failed: {exc}", file=sys.stderr)
|
||||
return 1
|
||||
|
||||
remote_report = result.get("preflight") or {}
|
||||
_print_preflight_sections(remote_report, prefix="Registry ")
|
||||
_print_registry_suggestions(result.get("suggestions") or {})
|
||||
if not remote_report.get("errors"):
|
||||
print("Registry preflight passed.")
|
||||
return 0
|
||||
return 1
|
||||
|
||||
# Check for token
|
||||
config = load_config()
|
||||
|
||||
Reference in New Issue
Block a user