Assistant: codex Assistant-Model: gpt-6-astra Assistant-Session: 01a06e82-3e08-7042-a79d-438ac6eed8db
279 lines
9 KiB
Python
279 lines
9 KiB
Python
from __future__ import annotations
|
|
|
|
import argparse
|
|
import json
|
|
import sys
|
|
from collections.abc import Callable
|
|
from pathlib import Path
|
|
from typing import Any
|
|
|
|
from .api import serve
|
|
from .service import (
|
|
CanonServiceError,
|
|
alignment_template,
|
|
artifact_graph,
|
|
generate_agent_briefs,
|
|
generate_indexes,
|
|
generate_tree,
|
|
inspect_canon,
|
|
list_artifacts,
|
|
list_models,
|
|
list_standards,
|
|
list_views,
|
|
profile_graph,
|
|
profile_inspect,
|
|
profile_validate,
|
|
read_view,
|
|
review_capability_record,
|
|
review_kit,
|
|
validate_canon,
|
|
write_validation_report,
|
|
)
|
|
|
|
|
|
Command = Callable[[argparse.Namespace], dict[str, Any]]
|
|
|
|
|
|
def build_parser() -> argparse.ArgumentParser:
|
|
parser = argparse.ArgumentParser(prog="info-tech-canon")
|
|
parser.add_argument(
|
|
"--root",
|
|
default="",
|
|
help="Infospace root. Defaults to ./infospace from the repository root.",
|
|
)
|
|
sub = parser.add_subparsers(dest="command", required=True)
|
|
|
|
inspect = sub.add_parser("inspect", help="Inspect the canon infospace")
|
|
inspect.set_defaults(handler=_inspect)
|
|
|
|
artifacts = sub.add_parser("artifacts", help="List canon artifacts")
|
|
artifacts.add_argument("--kind", default="")
|
|
artifacts.set_defaults(handler=_artifacts)
|
|
|
|
models = sub.add_parser("models", help="List canon model artifacts")
|
|
models.set_defaults(handler=_models)
|
|
|
|
standards = sub.add_parser("standards", help="List canon standard artifacts")
|
|
standards.set_defaults(handler=_standards)
|
|
|
|
review_kit_cmd = sub.add_parser(
|
|
"review-kit",
|
|
help="Read the consumer repository alignment review kit",
|
|
)
|
|
review_kit_cmd.set_defaults(handler=_review_kit)
|
|
|
|
alignment_template_cmd = sub.add_parser(
|
|
"alignment-template",
|
|
help="Read the consumer alignment workplan template",
|
|
)
|
|
alignment_template_cmd.set_defaults(handler=_alignment_template)
|
|
|
|
validate = sub.add_parser("validate", help="Validate the canon infospace")
|
|
validate.add_argument(
|
|
"--write",
|
|
default="",
|
|
help="Write the JSON validation payload to this path.",
|
|
)
|
|
validate.set_defaults(handler=_validate)
|
|
|
|
index = sub.add_parser("index", help="Refresh generated indexes and views")
|
|
index.set_defaults(handler=_index)
|
|
|
|
tree = sub.add_parser("tree", help="Refresh the generated infospace tree")
|
|
tree.set_defaults(handler=_tree)
|
|
|
|
agent_briefs = sub.add_parser("agent-briefs", help="Refresh generated agent briefs")
|
|
agent_briefs.set_defaults(handler=_agent_briefs)
|
|
|
|
views = sub.add_parser("views", help="List or read generated views")
|
|
views.add_argument("name", nargs="?", default="")
|
|
views.set_defaults(handler=_views)
|
|
|
|
graph = sub.add_parser("graph", help="Export the canon artifact graph")
|
|
graph.add_argument("--format", choices=["json", "mermaid"], default="json")
|
|
graph.set_defaults(handler=_graph)
|
|
|
|
profile = sub.add_parser("profile", help="Inspect canon profiles")
|
|
profile_sub = profile.add_subparsers(dest="profile_command", required=True)
|
|
profile_inspect_cmd = profile_sub.add_parser("inspect", help="Inspect a profile")
|
|
profile_inspect_cmd.add_argument("profile")
|
|
profile_inspect_cmd.set_defaults(handler=_profile_inspect)
|
|
profile_validate_cmd = profile_sub.add_parser("validate", help="Validate a profile")
|
|
profile_validate_cmd.add_argument("profile")
|
|
profile_validate_cmd.set_defaults(handler=_profile_validate)
|
|
profile_graph_cmd = profile_sub.add_parser("graph", help="Export a profile graph")
|
|
profile_graph_cmd.add_argument("profile")
|
|
profile_graph_cmd.add_argument("--format", choices=["json", "mermaid"], default="json")
|
|
profile_graph_cmd.set_defaults(handler=_profile_graph)
|
|
|
|
capability_review = sub.add_parser(
|
|
"capability-review",
|
|
help="Review a consumer capability record against the live catalog",
|
|
)
|
|
capability_review.add_argument("record")
|
|
capability_review.set_defaults(handler=_capability_review)
|
|
|
|
emission = sub.add_parser("emission-review", help="Validate a source-owned YAML/JSON cadence declaration")
|
|
emission.add_argument("record")
|
|
emission.set_defaults(handler=_emission_review)
|
|
coverage = sub.add_parser("validation-coverage", help="List implemented checks and explicit limits")
|
|
coverage.set_defaults(handler=_coverage)
|
|
freshness = sub.add_parser("check-generated", help="Check projections without changing source files")
|
|
freshness.set_defaults(handler=_check_generated)
|
|
inventory = sub.add_parser("scope-inventory", help="Derive scope counts from the artifact registry")
|
|
inventory.set_defaults(handler=_scope_inventory)
|
|
bundle = sub.add_parser("export-emission-contract", help="Export a content-addressed contract tar")
|
|
bundle.add_argument("destination")
|
|
bundle.set_defaults(handler=_export_emission)
|
|
benchmark = sub.add_parser("benchmark-reads", help="Measure ten uncached inspect calls")
|
|
benchmark.set_defaults(handler=_benchmark_reads)
|
|
|
|
api = sub.add_parser("api", help="Run the read-only local API")
|
|
api.add_argument("--host", default="127.0.0.1")
|
|
api.add_argument("--port", type=int, default=8765)
|
|
api.set_defaults(handler=_api)
|
|
|
|
return parser
|
|
|
|
|
|
def main(argv: list[str] | None = None) -> int:
|
|
parser = build_parser()
|
|
args = parser.parse_args(argv)
|
|
handler: Command = args.handler
|
|
try:
|
|
result = handler(args)
|
|
except CanonServiceError as exc:
|
|
_print_json(exc.to_dict())
|
|
return 2
|
|
except Exception as exc:
|
|
_print_json(
|
|
{
|
|
"ok": False,
|
|
"error": {
|
|
"code": "unhandled_error",
|
|
"message": str(exc),
|
|
"details": {},
|
|
},
|
|
}
|
|
)
|
|
return 1
|
|
if result:
|
|
_print_json(result)
|
|
return 0 if result.get("ok", False) else 1
|
|
|
|
|
|
def _root(args: argparse.Namespace) -> Path | None:
|
|
return Path(args.root) if args.root else None
|
|
|
|
|
|
def _inspect(args: argparse.Namespace) -> dict[str, Any]:
|
|
return inspect_canon(_root(args))
|
|
|
|
|
|
def _artifacts(args: argparse.Namespace) -> dict[str, Any]:
|
|
return list_artifacts(_root(args), kind=args.kind or None)
|
|
|
|
|
|
def _models(args: argparse.Namespace) -> dict[str, Any]:
|
|
return list_models(_root(args))
|
|
|
|
|
|
def _standards(args: argparse.Namespace) -> dict[str, Any]:
|
|
return list_standards(_root(args))
|
|
|
|
|
|
def _review_kit(args: argparse.Namespace) -> dict[str, Any]:
|
|
return review_kit(_root(args))
|
|
|
|
|
|
def _alignment_template(args: argparse.Namespace) -> dict[str, Any]:
|
|
return alignment_template(_root(args))
|
|
|
|
|
|
def _validate(args: argparse.Namespace) -> dict[str, Any]:
|
|
if args.write:
|
|
return write_validation_report(args.write, _root(args))
|
|
return validate_canon(_root(args))
|
|
|
|
|
|
def _index(args: argparse.Namespace) -> dict[str, Any]:
|
|
return generate_indexes(_root(args))
|
|
|
|
|
|
def _tree(args: argparse.Namespace) -> dict[str, Any]:
|
|
return generate_tree(_root(args))
|
|
|
|
|
|
def _agent_briefs(args: argparse.Namespace) -> dict[str, Any]:
|
|
return generate_agent_briefs(_root(args))
|
|
|
|
|
|
def _views(args: argparse.Namespace) -> dict[str, Any]:
|
|
if args.name:
|
|
return read_view(args.name, _root(args))
|
|
return list_views(_root(args))
|
|
|
|
|
|
def _graph(args: argparse.Namespace) -> dict[str, Any]:
|
|
return artifact_graph(_root(args), output_format=args.format)
|
|
|
|
|
|
def _capability_review(args: argparse.Namespace) -> dict[str, Any]:
|
|
return review_capability_record(args.record, _root(args))
|
|
|
|
|
|
def _emission_review(args):
|
|
from .contracts import review_emission
|
|
return review_emission(args.record, _root(args))
|
|
|
|
|
|
def _coverage(args):
|
|
from .contracts import coverage
|
|
from .service import load_context
|
|
return coverage(load_context(_root(args)))
|
|
|
|
|
|
def _check_generated(args):
|
|
from .maintenance import check_generated
|
|
from .service import load_context
|
|
return check_generated(load_context(_root(args)))
|
|
|
|
|
|
def _scope_inventory(args):
|
|
from .maintenance import scope_inventory
|
|
from .service import load_context
|
|
return dict(scope_inventory(load_context(_root(args))), ok=True)
|
|
|
|
|
|
def _export_emission(args):
|
|
from .maintenance import export_emission_bundle
|
|
from .paths import infospace_root
|
|
return export_emission_bundle(infospace_root(_root(args)), Path(args.destination))
|
|
|
|
|
|
def _benchmark_reads(args):
|
|
from .maintenance import benchmark_reads
|
|
from .paths import infospace_root
|
|
return benchmark_reads(infospace_root(_root(args)))
|
|
|
|
|
|
def _profile_inspect(args: argparse.Namespace) -> dict[str, Any]:
|
|
return profile_inspect(args.profile, _root(args))
|
|
|
|
|
|
def _profile_validate(args: argparse.Namespace) -> dict[str, Any]:
|
|
return profile_validate(args.profile, _root(args))
|
|
|
|
|
|
def _profile_graph(args: argparse.Namespace) -> dict[str, Any]:
|
|
return profile_graph(args.profile, _root(args), output_format=args.format)
|
|
|
|
|
|
def _api(args: argparse.Namespace) -> dict[str, Any]:
|
|
serve(host=args.host, port=args.port, root=_root(args))
|
|
return {}
|
|
|
|
|
|
def _print_json(data: dict[str, Any]) -> None:
|
|
json.dump(data, sys.stdout, indent=2, sort_keys=True)
|
|
sys.stdout.write("\n")
|