#!/usr/bin/env python3 """P3-B 파일럿 e2e — DES-DIRECTOR→DES-PROD→DES-PLATFORM handoff 체인(standalone check). 실제 authored Contract v2(디스크) 3종을 **임시 레지스트리**에 trusted CLI 4단 게이트로 활성화하고 (사람 signoff 는 주입으로 시뮬레이션 — 실제 활성화는 사용자 real signoff 필요), active 상태에서 (1) validate_method_execution / validate_report 의 step-results Hard Fail (2) spawn/transition handoff Hard Fail(both-active 엣지) 이 실제로 발동하는지 end-to-end 로 검증한다. **프로덕션 레지스트리(org-os/..)는 건드리지 않는다.** """ import hashlib import importlib.util import os import sys import tempfile import yaml ROOT = os.environ.get("CLAUDE_PROJECT_DIR", os.getcwd()) HOOKS = os.path.join(ROOT, ".claude", "hooks") passed = failed = 0 def check(name, ok): global passed, failed if ok: passed += 1 print(f" ✅ {name}") else: failed += 1 print(f" ❌ {name}") def _load(mod, path): spec = importlib.util.spec_from_file_location(mod, os.path.join(HOOKS, path)) m = importlib.util.module_from_spec(spec) if HOOKS not in sys.path: sys.path.insert(0, HOOKS) spec.loader.exec_module(m) return m mc = _load("method_contracts", "method_contracts.py") amc = _load("activate_method_contract", "activate_method_contract.py") vr = _load("validate_report", "validate_report.py") CHAIN = [("DES-DIRECTOR", "converge-directions"), ("DES-PROD", "post-direction"), ("DES-PLATFORM", "tokenize")] _rm = mc.load_role_methods() _yes = lambda w, s: True # noqa: E731 — 사람 signoff 존재 시뮬레이션 _no = lambda e: False # noqa: E731 _ok = lambda e: True # noqa: E731 print("== 파일럿: 실제 계약 3종을 임시 레지스트리에 활성화(4단 게이트) ==") with tempfile.TemporaryDirectory() as td: reg = os.path.join(td, "activations.yaml") hashes = {} for role, mid in CHAIN: prof = mc.resolve_method_profile(role, mid) h = mc.canonical_contract_hash(prof) hashes[(role, mid)] = h rep = os.path.join(td, f"{role}.golden.report.yaml") open(rep, "w").write(f"bottom-line: golden {role}/{mid}\n") rh = hashlib.sha256(open(rep, "rb").read()).hexdigest() ok, errs = amc.verify(role, mid, h, rep, rh, "wf-pilot", has_signoff=_yes) check(f"{role}/{mid} 4-gate verify 통과(real hash+golden+signoff)", ok) # wrong hash → 거부(리뷰본과 다른 계약 활성화 차단) okb, _ = amc.verify(role, mid, "0" * 64, rep, rh, "wf-pilot", has_signoff=_yes) check(f"{role}/{mid} 잘못된 hash → 거부", not okb) amc.apply_activation(role, mid, { "status": "active", "contract-sha256": h, "validation-report": rep, "validation-report-sha256": rh, "acceptance-workflow": "wf-pilot", "acceptance-stage": amc.signoff_stage(role, mid, h), }, registry_path=reg) ACTIVE = yaml.safe_load(open(reg))["method-contract-activations"]["roles"] check("3 계약 모두 active 기록", all(ACTIVE[r]["methods"][m]["status"] == "active" for r, m in CHAIN)) print("== active: validate_method_execution step-results Hard Fail(실제 계약) ==") dd_h = hashes[("DES-DIRECTOR", "converge-directions")] # (1) method-execution 누락 → Hard Fail errs = mc.validate_method_execution({"role-id": "DES-DIRECTOR", "tier": "standard"}, activations=ACTIVE) check("method-execution 누락 → Hard Fail", errs != []) # (2) 정상 실행(모든 step completed+artifact / 대안 3) → 통과 _steps = ["rehydrate-originals", "compare-tradeoffs", "converge-one", "preserve-dissent"] me_ok = {"role-id": "DES-DIRECTOR", "method-id": "converge-directions", "contract-sha256": dd_h, "step-results": [{"step-id": s, "status": "completed", "artifact-refs": [{"report-id": "r", "sha256": "a" * 64}]} for s in _steps], "decisions": [{"decision-id": "d1", "selected-option-id": "a", "alternatives": [{"option-id": "a"}, {"option-id": "b"}, {"option-id": "c"}]}]} check("정상 method-execution → 통과", mc.validate_method_execution({"role-id": "DES-DIRECTOR", "tier": "standard", "method-execution": me_ok}, activations=ACTIVE) == []) # (3) converge-one artifact-ref 누락 → Hard Fail(자기신고 금지) me_bad = {"role-id": "DES-DIRECTOR", "method-id": "converge-directions", "contract-sha256": dd_h, "step-results": [{"step-id": s, "status": "completed", "artifact-refs": ([] if s == "converge-one" else [{"report-id": "r", "sha256": "a" * 64}])} for s in _steps], "decisions": me_ok["decisions"]} check("converge-one artifact-ref 누락 → Hard Fail", any("converge-one" in e for e in mc.validate_method_execution( {"role-id": "DES-DIRECTOR", "tier": "standard", "method-execution": me_bad}, activations=ACTIVE))) # (4) 대안 부족(<3) → Hard Fail me_alt = {**me_ok, "decisions": [{"decision-id": "d1", "selected-option-id": "a", "alternatives": [{"option-id": "a"}]}]} check("대안 부족(