#!/usr/bin/env python3 """Read-only Claude probe from an actual pilot checkout; no production effects.""" from pathlib import Path import argparse from datetime import datetime, timezone import json import os import subprocess import sys import tempfile ROOT = Path(__file__).resolve().parents[1] sys.path.insert(0, str(ROOT / "src")) from emergent_security.knowledge import Knowledge from probe_provider import extract_json, unwrap_response SCENARIOS = { "net-kingdom": ("compatibility", "The old generic canon calls Gate House a broker. Explain the current owner mapping and how the reference evaluator relates to live authorization."), "ops-warden": ("access", "A coding agent needs a scoped credential. Explain discovery, when warden plan is required before founder steps, and why a readable broader token is insufficient."), "tenant-engine": ("tenant", "A tenant admin wants to approve beyond the platform envelope. Explain the next recipient and what this engine can decide."), "railiance-master": ("deployment", "A local test passed in build mode. Explain whether a live production change can proceed and who must decide."), } def main(): parser = argparse.ArgumentParser(description=__doc__) parser.add_argument("repo", choices=SCENARIOS) parser.add_argument("--root", type=Path, required=True) parser.add_argument("--output", type=Path, required=True) args = parser.parse_args() package = Knowledge(ROOT / "knowledge") card, question = SCENARIOS[args.repo] check = package.retrieve(card, repositories=args.root) if check["status"] != "verified-files": raise SystemExit("Pilot source check failed; no client launched.") repo = args.root / args.repo schema = {"type": "object", "additionalProperties": False, "properties": {"package_version": {"type": "string"}, "answers": {"type": "array", "items": {"type": "object", "additionalProperties": False, "properties": {key: {"type": "string"} for key in ("card", "source_path", "route", "reason")}, "required": ["card", "source_path", "route", "reason"]}}}, "required": ["package_version", "answers"]} prompt = ( "This is a read-only situational knowledge pilot. Do not perform operational work, " "write records, contact services or read credentials. Follow the new orientation " "pilot pointer in the repository instructions; read the shared start and relevant " "task card and knowledge/catalog.yaml and knowledge/release.yaml from the sibling " "emergent-security checkout (sources are indexed in knowledge/sources.yaml). " "The supervising runner verified the relevant source digests. Answer this scenario: " + question + " Return only JSON with package_version and answers containing one " "object with card, source_path (shared card path actually read), route (actual " "next recipient, including a human role where appropriate), and reason." ) command = ["claude", "-p", "--tools", "Read", "--add-dir", str(ROOT), "--permission-mode", "default", "--no-session-persistence", "--max-budget-usd", "2", "--output-format", "json", "--json-schema", json.dumps(schema), prompt] report = {"schema": "emergent.repository-pilot.v1", "repository": args.repo, "provider": "claude", "timestamp": datetime.now(timezone.utc).isoformat(), "package_version": package.catalog["version"], "package_digest": package.package_digest, "source_status": check["status"], "scope": "read-only scenario in actual repository", "status": "unverified"} try: run = subprocess.run(command, cwd=repo, capture_output=True, text=True, timeout=180) raw_dir = Path(tempfile.mkdtemp(prefix="emergent-pilot-")) for name, content in [("stdout", run.stdout), ("stderr", run.stderr)]: path = raw_dir / name path.write_text(content) os.chmod(path, 0o600) report["exit_code"] = run.returncode if run.returncode: report["status"] = "client-failed" else: answer, metadata = unwrap_response(extract_json(run.stdout)) report.update(metadata) report["answers"] = answer["answers"] report["version_correct"] = answer.get("package_version") == package.catalog["version"] report["status"] = "awaiting-semantic-review" except subprocess.TimeoutExpired: report["status"] = "timeout" except (OSError, ValueError, TypeError): report["status"] = "client-output-unusable" args.output.write_text(json.dumps(report, indent=2) + "\n") print(json.dumps({k:v for k,v in report.items() if k not in {"answers", "usage"}}, indent=2)) return 0 if report["status"] == "awaiting-semantic-review" else 2 if __name__ == "__main__": raise SystemExit(main())