76df8b7ab6
Add owner-safe lesson catalog, fixture-backed capability statuses, CLI, and unit tests without live OAuth or connect scripts.
115 lines
3.1 KiB
Python
115 lines
3.1 KiB
Python
#!/usr/bin/env python3
|
|
"""Build a capability report from setup fixtures.
|
|
|
|
Usage:
|
|
python build_capability_report.py [--fixtures PATH] [--salon NAME] [--format text|json]
|
|
|
|
All data is labeled as fixture/offline — never silent fake live data.
|
|
"""
|
|
|
|
from __future__ import annotations
|
|
|
|
import argparse
|
|
import json
|
|
import pathlib
|
|
import sys
|
|
|
|
# Ensure the _lib package is importable regardless of cwd.
|
|
_REPO_ROOT = pathlib.Path(__file__).resolve().parents[3]
|
|
sys.path.insert(0, str(_REPO_ROOT / "skills" / "_lib"))
|
|
|
|
from lumina_skills.providers.setup.fixture_provider import (
|
|
load_capability_fixture,
|
|
load_fixture_metadata,
|
|
)
|
|
from lumina_skills.setup.capability_report import format_capability_report_text
|
|
from lumina_skills.setup.lesson_catalog import (
|
|
format_all_lessons_text,
|
|
format_lesson_text,
|
|
get_lesson,
|
|
get_all_lessons,
|
|
)
|
|
|
|
# Default fixture: Claire Bennett demo capability matrix.
|
|
_DEFAULT_FIXTURE = _REPO_ROOT / "data" / "fixtures" / "setup" / "capability_matrix.json"
|
|
|
|
|
|
def main() -> int:
|
|
parser = argparse.ArgumentParser(
|
|
description="Build a capability report from setup fixture data.",
|
|
)
|
|
parser.add_argument(
|
|
"--fixtures",
|
|
type=pathlib.Path,
|
|
default=_DEFAULT_FIXTURE,
|
|
help="Path to capability fixture JSON file.",
|
|
)
|
|
parser.add_argument(
|
|
"--salon",
|
|
type=str,
|
|
default=None,
|
|
help="Override salon name.",
|
|
)
|
|
parser.add_argument(
|
|
"--format",
|
|
choices=["text", "json"],
|
|
default="text",
|
|
help="Output format (default: text).",
|
|
)
|
|
parser.add_argument(
|
|
"--lesson",
|
|
type=int,
|
|
default=None,
|
|
help="Show a specific setup lesson (1-7) instead of the capability report.",
|
|
)
|
|
parser.add_argument(
|
|
"--all-lessons",
|
|
action="store_true",
|
|
help="Show all setup lessons instead of the capability report.",
|
|
)
|
|
args = parser.parse_args()
|
|
|
|
# Lesson mode.
|
|
if args.lesson is not None:
|
|
lesson = get_lesson(args.lesson)
|
|
if lesson is None:
|
|
print(f"Error: No lesson found for step {args.lesson}", file=sys.stderr)
|
|
return 1
|
|
print(format_lesson_text(lesson))
|
|
return 0
|
|
|
|
if args.all_lessons:
|
|
print(format_all_lessons_text())
|
|
return 0
|
|
|
|
# Capability report mode.
|
|
try:
|
|
report = load_capability_fixture(args.fixtures)
|
|
except FileNotFoundError as exc:
|
|
print(f"Error: {exc}", file=sys.stderr)
|
|
return 1
|
|
except (json.JSONDecodeError, KeyError, ValueError) as exc:
|
|
print(f"Error parsing fixture: {exc}", file=sys.stderr)
|
|
return 1
|
|
|
|
# Override salon name if requested.
|
|
if args.salon:
|
|
from lumina_skills.setup.capability_report import build_capability_report
|
|
report = build_capability_report(
|
|
capabilities=report.capabilities,
|
|
salon_name=args.salon,
|
|
is_fixture=report.is_fixture,
|
|
)
|
|
|
|
# Output.
|
|
if args.format == "json":
|
|
print(json.dumps(report.to_dict(), indent=2))
|
|
else:
|
|
print(format_capability_report_text(report))
|
|
|
|
return 0
|
|
|
|
|
|
if __name__ == "__main__":
|
|
raise SystemExit(main())
|