Files
yao-meta-skill/scripts/yao_cli_telemetry.py
T
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

96 lines
3.2 KiB
Python

#!/usr/bin/env python3
"""Metadata-only CLI telemetry helpers for yao.py."""
import argparse
import os
import sys
from pathlib import Path
from typing import Any
from render_adoption_drift_report import append_event, normalize_event, skill_defaults, utc_now
SCRIPT_INTERFACE = "internal-module"
SCRIPT_INTERFACE_REASON = "Imported by yao.py to record opt-in metadata-only CLI run telemetry."
ENABLE_ENV = "YAO_CLI_TELEMETRY"
EVENTS_ENV = "YAO_CLI_TELEMETRY_EVENTS"
TRUTHY = {"1", "true", "yes", "on"}
FALSY = {"0", "false", "no", "off"}
def add_telemetry_args(parser: argparse.ArgumentParser) -> None:
parser.add_argument(
"--record-cli-telemetry",
action="store_true",
help="Record metadata-only yao.py command telemetry to reports/telemetry_events.jsonl.",
)
parser.add_argument(
"--no-cli-telemetry",
action="store_true",
help="Disable yao.py command telemetry even when YAO_CLI_TELEMETRY is enabled.",
)
parser.add_argument(
"--telemetry-events-jsonl",
help="Override the local metadata-only telemetry JSONL path.",
)
def telemetry_enabled(args: argparse.Namespace, environ: dict[str, str] | None = None) -> bool:
environ = environ or os.environ
if getattr(args, "no_cli_telemetry", False):
return False
if getattr(args, "record_cli_telemetry", False):
return True
raw = environ.get(ENABLE_ENV, "").strip().lower()
if raw in TRUTHY:
return True
if raw in FALSY:
return False
return False
def telemetry_path(root: Path, args: argparse.Namespace, environ: dict[str, str] | None = None) -> Path:
environ = environ or os.environ
configured = getattr(args, "telemetry_events_jsonl", None) or environ.get(EVENTS_ENV)
if configured:
return Path(configured).expanduser().resolve()
return root / "reports" / "telemetry_events.jsonl"
def normalize_command_name(value: Any) -> str:
raw = str(value or "unknown")
lowered = raw.strip().lower()
safe = "".join(char for char in lowered if char.isalnum() or char in {"-", "_"})
return safe[:64] or "unknown"
def cli_event(root: Path, args: argparse.Namespace, returncode: int) -> dict[str, str]:
defaults = skill_defaults(root)
ok = returncode == 0
return {
"event": "script_run",
"skill": defaults["skill"],
"version": defaults["version"],
"activation_type": "manual",
"outcome": "accepted" if ok else "failed",
"failure_type": "none" if ok else "script_error",
"timestamp": utc_now(),
"source": "yao_cli",
"command": normalize_command_name(getattr(args, "command", "unknown")),
}
def maybe_record_cli_event(root: Path, args: argparse.Namespace, returncode: int) -> None:
if not telemetry_enabled(args):
return
path = telemetry_path(root, args)
event, failures = normalize_event(cli_event(root, args, returncode), skill_defaults(root), "yao-cli")
if failures or event is None:
sys.stderr.write(f"Telemetry skipped: {'; '.join(failures)}\n")
return
try:
append_event(path, event)
except OSError as exc:
sys.stderr.write(f"Telemetry skipped: {exc}\n")