Files
yao-meta-skill/scripts/import_telemetry_events.py
YAO 31ce04c655 Split meta skill CLI and review gates
Merge the beta-ready Yao Meta Skill architecture, report, evidence gate, and release-boundary updates.\n\nRelease boundary: beta/public testing is allowed; formal world-class, fully reviewed, or superiority claims remain blocked until the pending evidence gates are accepted.
2026-06-17 18:43:02 +08:00

140 lines
5.1 KiB
Python

#!/usr/bin/env python3
import argparse
import json
from pathlib import Path
from typing import Any
from render_adoption_drift_report import display_path, normalize_event, render_report, skill_defaults
def load_candidate_events(
input_jsonl: Path,
defaults: dict[str, str],
default_source: str,
default_command: str,
) -> tuple[list[dict[str, str]], list[str]]:
events: list[dict[str, str]] = []
failures: list[str] = []
for index, line in enumerate(input_jsonl.read_text(encoding="utf-8").splitlines(), start=1):
if not line.strip():
continue
try:
raw = json.loads(line)
except json.JSONDecodeError as exc:
failures.append(f"line {index}: invalid JSONL event: {exc.msg}")
continue
if not isinstance(raw, dict):
failures.append(f"line {index}: telemetry event must be a JSON object")
continue
raw.setdefault("source", default_source)
raw.setdefault("command", default_command)
event, event_failures = normalize_event(raw, defaults, f"line {index}")
failures.extend(event_failures)
if event:
events.append(event)
return events, failures
def append_events(events_jsonl: Path, events: list[dict[str, str]]) -> None:
events_jsonl.parent.mkdir(parents=True, exist_ok=True)
with events_jsonl.open("a", encoding="utf-8") as handle:
for event in events:
handle.write(json.dumps(event, ensure_ascii=False, sort_keys=True) + "\n")
def import_events(
skill_dir: Path,
input_jsonl: Path,
events_jsonl: Path | None = None,
output_json: Path | None = None,
output_md: Path | None = None,
generated_at: str | None = None,
default_source: str = "external",
default_command: str = "external-client",
dry_run: bool = False,
) -> dict[str, Any]:
skill_dir = skill_dir.resolve()
input_jsonl = input_jsonl.resolve()
reports_dir = skill_dir / "reports"
events_jsonl = (events_jsonl or reports_dir / "telemetry_events.jsonl").resolve()
output_json = (output_json or reports_dir / "adoption_drift_report.json").resolve()
output_md = (output_md or reports_dir / "adoption_drift_report.md").resolve()
failures: list[str] = []
if not input_jsonl.exists():
failures.append(f"Input telemetry JSONL does not exist: {display_path(input_jsonl)}")
candidate_events: list[dict[str, str]] = []
else:
candidate_events, load_failures = load_candidate_events(
input_jsonl,
skill_defaults(skill_dir),
default_source,
default_command,
)
failures.extend(load_failures)
adoption_report: dict[str, Any] | None = None
if not failures and not dry_run:
append_events(events_jsonl, candidate_events)
adoption_report = render_report(
skill_dir,
events_jsonl=events_jsonl,
output_json=output_json,
output_md=output_md,
generated_at=generated_at,
)
return {
"ok": not failures,
"schema_version": "1.0",
"skill_dir": display_path(skill_dir),
"input_jsonl": display_path(input_jsonl),
"events_jsonl": display_path(events_jsonl),
"dry_run": dry_run,
"imported_count": 0 if failures or dry_run else len(candidate_events),
"candidate_count": len(candidate_events),
"failures": failures,
"imported_preview": candidate_events[:5],
"artifacts": {
"events_jsonl": display_path(events_jsonl),
"adoption_drift_json": display_path(output_json),
"adoption_drift_md": display_path(output_md),
},
"adoption_drift": {
"summary": adoption_report.get("summary", {}) if adoption_report else {},
"artifacts": adoption_report.get("artifacts", {}) if adoption_report else {},
},
}
def main() -> None:
parser = argparse.ArgumentParser(description="Import external metadata-only telemetry into a local skill event stream.")
parser.add_argument("skill_dir", nargs="?", default=".")
parser.add_argument("--input-jsonl", required=True)
parser.add_argument("--events-jsonl")
parser.add_argument("--output-json")
parser.add_argument("--output-md")
parser.add_argument("--generated-at")
parser.add_argument("--source", choices=["external", "manual", "unknown", "yao_cli"], default="external")
parser.add_argument("--command", default="external-client")
parser.add_argument("--dry-run", action="store_true")
args = parser.parse_args()
report = import_events(
Path(args.skill_dir),
Path(args.input_jsonl),
events_jsonl=Path(args.events_jsonl) if args.events_jsonl else None,
output_json=Path(args.output_json) if args.output_json else None,
output_md=Path(args.output_md) if args.output_md else None,
generated_at=args.generated_at,
default_source=args.source,
default_command=args.command,
dry_run=args.dry_run,
)
print(json.dumps(report, ensure_ascii=False, indent=2))
if not report["ok"]:
raise SystemExit(2)
if __name__ == "__main__":
main()