#!/usr/bin/env python3 """Run tenant onboarding task specs through the harness (deterministic adapter). Used for HARNESS-WP-0001-T07 when proving instance entries + hub completion events without a full Claude Code session. Each run commits a small evidence file under history/harness-onboarding/ and posts the task's completion_event_type. """ from __future__ import annotations import argparse import json import subprocess import sys from pathlib import Path # Allow running from repo root without install. _ROOT = Path(__file__).resolve().parents[1] if str(_ROOT) not in sys.path: sys.path.insert(0, str(_ROOT)) from rein_aharness.runner import run_task from rein_aharness.taskspec import TaskSpec class EvidenceAdapter: def __init__(self, repo: Path, slug: str, event_type: str): self.repo = repo self.slug = slug self.event_type = event_type self.prompts: list[str] = [] def execute_prompt(self, prompt, config): self.prompts.append(prompt) out_dir = self.repo / "history" / "harness-onboarding" out_dir.mkdir(parents=True, exist_ok=True) path = out_dir / f"{self.slug}.md" path.write_text( f"# Harness onboarding run — {self.slug}\n\n" f"- completion_event_type: `{self.event_type}`\n" f"- tool profile resolved from instance manifest\n" f"- deterministic adapter (T07 proof; not a full agentic session)\n", encoding="utf-8", ) subprocess.run(["git", "add", str(path.relative_to(self.repo))], cwd=self.repo, check=True) subprocess.run( [ "git", "-c", "user.email=rein-aharness@local", "-c", "user.name=rein-aharness", "commit", "-qm", f"harness onboard: {self.slug}", ], cwd=self.repo, check=True, ) from llm_connect.models import LLMResponse return LLMResponse( content=f"onboard {self.slug} ok", model="onboard-adapter", usage={}, finish_reason="stop", ) def main(argv: list[str] | None = None) -> int: parser = argparse.ArgumentParser(description=__doc__) parser.add_argument( "--task-file", action="append", required=True, help="Task JSON path (repeatable)", ) parser.add_argument("--no-hub", action="store_true") args = parser.parse_args(argv) results = [] for task_path in args.task_file: spec = TaskSpec.from_file(task_path) slug = Path(task_path).stem adapter = EvidenceAdapter(spec.target_repo, slug, spec.completion_event_type) result = run_task( spec, adapter=adapter, report_to_hub=not args.no_hub, write_metrics=True, ) results.append( { "task_file": task_path, "ok": result.ok, "committed": result.committed, "tool_profile": result.tool_profile, "event": spec.completion_event_type, "reason": result.reason, "head_after": result.head_after, } ) print(json.dumps(results[-1], indent=2)) if not result.ok: return 1 print(json.dumps({"all_ok": True, "runs": len(results)}, indent=2)) return 0 if __name__ == "__main__": raise SystemExit(main())