#!/usr/bin/env python3 """Experience-foundation, organization design, and tool-neutral adapter regression.""" import hashlib import json import os import shutil import subprocess import sys import yaml ROOT = os.path.dirname(os.path.dirname(os.path.dirname(os.path.abspath(__file__)))) HOOKS = os.path.join(ROOT, ".claude", "hooks") WS = os.path.join(ROOT, ".claude", "tests", "fixtures", "experience-foundation-ws") os.environ["CLAUDE_PROJECT_DIR"] = ROOT os.environ["ORGOS_WORKSPACE"] = WS sys.path.insert(0, HOOKS) import state_engine as SE # noqa: E402 import lint_design_direction as LDD # noqa: E402 shutil.rmtree(WS, ignore_errors=True) os.makedirs(WS, exist_ok=True) passed = failed = 0 def check(name, condition): global passed, failed if condition: passed += 1 print(f" PASS {name}") else: failed += 1 print(f" FAIL {name}") def sha(path): return hashlib.sha256(open(path, "rb").read()).hexdigest() def report(wf, artifact_id, kind, stage, producer, body, tier="standard"): directory = os.path.join(WS, "completion-records", wf) os.makedirs(directory, exist_ok=True) path = os.path.join(directory, artifact_id + ".report.yaml") document = { "report-type": "workflow-artifact", "artifact-kind": kind, "artifact-version": 1, "tier": tier, "identity": {"artifact-id": artifact_id, "workflow-id": wf, "stage": stage, "producer-role-id": producer}, "report-header": { "bottom-line": f"{kind} fixture", "decision-needed": {"needed": False}, "confidence": {"value": "Med", "derived-from": "evidence"}, "risks": [], "evidence": [{"source-uri": "README.md", "grade": "E3"}], }, "payload": body, } with open(path, "w", encoding="utf-8") as handle: yaml.safe_dump(document, handle, allow_unicode=True, sort_keys=False) return path def open_stage(wf, stage): current = SE.read_ledger(wf).get("stage") event = {"state-event-id": f"fixture-{wf}-{stage}", "event-type": "state-transition", "workflow-id": wf, "from": current, "to": stage, "actor": "OPS-ORCH", "effective-at": SE._now()} return SE._atomic_event_transaction(wf, workflow_event=event)[0] def submit_accept(wf, path, reviewer): return SE.submit_artifact(wf, path, "OPS-ORCH")[0] and SE.review_artifact( wf, path, "accepted", reviewer)[0] print("== parent and typed applicability ==") SE.init_ledger("parent", tier="light") profile = report("parent", "profile", "workload-profile", "intake", "EXEC-CEO", { "surfaces": {"ui": True, "public-api": False, "persistence": False, "infrastructure": False}, "surface-archetype": "interactive-learning", "experience-change": "incremental", "risk": {"security-bearing": False, "data-migration": False, "external-side-effect": False, "risk-level": "Low", "reversibility": "two-way-door", "blast-radius": "single-role", "privacy": False, "regulatory": False, "slo-impact": False}, "required-capabilities": ["product", "design"], "product-feature": True, }, tier="light") check("interactive-learning workload submitted", SE.submit_artifact("parent", profile, "OPS-ORCH")[0]) check("fixture opens parent decide", open_stage("parent", "decide")) packet = report("parent", "decision", "executive-decision-packet", "decide", "EXEC-CEO", { "recommendation": "proceed", "selected-option-id": "a", "evaluation-criteria": ["fit"], "option-evaluations": [{"option-id": "a", "scores": {"fit": 1}, "evidence-refs": ["README.md"]}], "tradeoffs": ["time"], "dissent": [], "kill-criteria": ["no demand"], "revisit-conditions": ["market changes"], "evidence-refs": ["README.md"], }, tier="light") check("product decision accepted", submit_accept("parent", packet, "HUMAN-001")) brief0 = os.path.join(WS, "brief-without-foundation.yaml") with open(brief0, "w", encoding="utf-8") as handle: yaml.safe_dump({"product-goal": "ship", "core-users": ["buyer"], "core-tasks": ["evaluate"], "information-density": "medium", "required-accessibility": "WCAG AA", "brand-constraints": ["legible"], "avoid-cliches": ["generic hero"], "representative-screen-requirement": "core-task", "tech-platform-constraints": ["web"]}, handle) try: SE.init_ledger("direction-too-early", plan="design-direction", parent_workflow="parent", product_decision="decision", direction_input_brief=brief0) early_blocked = False except ValueError: early_blocked = True check("design-direction blocked before foundation", early_blocked) try: SE.init_ledger("foundation-light", plan="experience-foundation", tier="light", parent_workflow="parent", product_decision="decision") light_blocked = False except ValueError: light_blocked = True check("required interactive-learning foundation cannot use light tier", light_blocked) print("== benchmark -> strategy -> IA -> wireframes ==") SE.init_ledger("foundation", plan="experience-foundation", tier="standard", parent_workflow="parent", product_decision="decision") check("foundation parent gate", SE.complete_stage("foundation", "OPS-ORCH", to="experience-benchmark")[0]) check("enter benchmark", SE.enter_stage("foundation", "experience-benchmark", actor="OPS-ORCH")[0]) shots = [] for index in range(10): path = os.path.join(WS, f"shot-{index}.bin") with open(path, "wb") as handle: handle.write(f"capture-{index}".encode()) shots.append(path) refs = [] for index in range(5): refs.append({ "name": f"Reference {index}", "class": "direct" if index < 3 else "adjacent", "source-url": f"https://example.com/{index}", "captured-at": "2026-07-20T00:00:00Z", "screenshots": { "desktop": [{"path": shots[index * 2], "sha256": sha(shots[index * 2])}], "mobile": [{"path": shots[index * 2 + 1], "sha256": sha(shots[index * 2 + 1])}], }, "flows": [{"name": "core", "steps": ["enter", "act"]}], "information-architecture": {"root": ["entry", "detail"]}, "interaction-patterns": ["progressive disclosure"], "content-strategy": {"message": "value before proof"}, "strengths": [{"claim": "clear task", "evidence-refs": [shots[index * 2]]}], "weaknesses": [{"claim": "weak recovery", "evidence-refs": [shots[index * 2 + 1]]}], }) benchmark = report("foundation", "benchmark", "competitive-experience-benchmark", "experience-benchmark", "GTM-CI", { "parent-workflow-id": "parent", "product-decision-id": "decision", "category": "learning product", "target-job": "understand a mechanism", "surface-archetype": "interactive-learning", "references": refs, "synthesis": {"table-stakes": ["clear value"], "adopt": ["proof"], "adapt": ["entry"], "avoid": ["generic hero"], "differentiation-opportunities": ["guided evaluation"], "unresolved-questions": []}, "no-copy-attestation": True, }) check("benchmark accepted", submit_accept("foundation", benchmark, "EXEC-CPO")) check("benchmark gate", SE.complete_stage("foundation", "OPS-ORCH", to="experience-strategy")[0]) check("enter strategy", SE.enter_stage("foundation", "experience-strategy", actor="OPS-ORCH")[0]) strategy = report("foundation", "strategy", "experience-strategy", "experience-strategy", "EXEC-CPO", { "parent-workflow-id": "parent", "product-decision-id": "decision", "benchmark-ref": benchmark, "benchmark-sha256": sha(benchmark), "experience-thesis": "guided confidence", "target-users": ["buyer"], "jobs-to-be-done": ["evaluate"], "value-proposition": "decide with evidence", "differentiation": ["recovery-aware proof"], "message-hierarchy": ["value", "proof", "action"], "success-metrics": ["qualified action"], "decision": "proceed", }) check("strategy accepted", submit_accept("foundation", strategy, "HUMAN-001")) check("strategy alone cannot pass feasibility gate", not SE.complete_stage("foundation", "OPS-ORCH", to="information-architecture")[0]) technical = report("foundation", "technical-feasibility", "experience-technical-feasibility", "experience-strategy", "EXEC-CTO", { "parent-workflow-id": "parent", "product-decision-id": "decision", "strategy-ref": strategy, "strategy-sha256": sha(strategy), "architecture-fit": {"simulation": "deterministic browser model"}, "delivery-sustainability": {"content-unit": "versioned mechanism pack"}, "constraints": ["no production diagnosis claim"], "risks": ["content engine drift"], "mitigations": ["versioned fixtures"], "verdict": "feasible", }) check("technical feasibility accepted", submit_accept("foundation", technical, "HUMAN-001")) check("technical-only cannot replace COO feasibility", not SE.complete_stage("foundation", "OPS-ORCH", to="information-architecture")[0]) operational = report("foundation", "operational-feasibility", "experience-operational-feasibility", "experience-strategy", "EXEC-COO", { "parent-workflow-id": "parent", "product-decision-id": "decision", "strategy-ref": strategy, "strategy-sha256": sha(strategy), "operating-model": {"owner": "learning content operations"}, "content-operations": {"release-unit": "mechanism deep dive"}, "support-and-recovery": {"boundary": "guided simulation support"}, "constraints": ["one validated mechanism at a time"], "risks": ["review queue"], "mitigations": ["candidate release cap"], "verdict": "feasible", }) check("operational feasibility accepted", submit_accept("foundation", operational, "HUMAN-001")) check("strategy gate", SE.complete_stage("foundation", "OPS-ORCH", to="information-architecture")[0]) check("enter IA", SE.enter_stage("foundation", "information-architecture", actor="OPS-ORCH")[0]) blueprint = report("foundation", "blueprint", "experience-blueprint", "information-architecture", "DOC-IA", { "parent-workflow-id": "parent", "product-decision-id": "decision", "benchmark-ref": benchmark, "benchmark-sha256": sha(benchmark), "strategy-ref": strategy, "strategy-sha256": sha(strategy), "experience-thesis": "guided confidence", "target-users": ["buyer"], "jobs-to-be-done": ["evaluate"], "value-proposition": "decide with evidence", "differentiation": ["recovery-aware proof"], "content-model": {"entities": ["claim", "proof"]}, "page-inventory": ["entry", "proof", "action"], "navigation-model": {"primary": ["proof"]}, "message-hierarchy": ["value", "proof", "action"], "task-flows": [{"id": "evaluate", "steps": ["entry", "proof", "action"]}], "state-matrix": {"default": {}, "loading": {}, "empty": {}, "error": {}, "partial": {}, "completed": {}}, "responsive-priorities": ["value", "action", "proof"], "accessibility-intent": {"target": "WCAG AA"}, "success-metrics": ["qualified action"], }) check("blueprint accepted", submit_accept("foundation", blueprint, "EXEC-CPO")) check("blueprint gate", SE.complete_stage("foundation", "OPS-ORCH", to="wireframes")[0]) check("enter wireframes", SE.enter_stage("foundation", "wireframes", actor="OPS-ORCH")[0]) wireframes = report("foundation", "wireframes", "wireframe-set", "wireframes", "DES-PROD", { "parent-workflow-id": "parent", "product-decision-id": "decision", "blueprint-ref": blueprint, "blueprint-sha256": sha(blueprint), "screens": [{"id": "entry", "purpose": "explain value", "primary-action": "evaluate", "content-priority": ["value", "proof"], "desktop": {"regions": 3}, "mobile": {"regions": 2}, "states": ["default", "loading", "error"]}], "validation": {"information-scent": "passed", "task-completion": "passed", "cognitive-load": "passed", "responsive-hierarchy": "passed"}, "art-direction-deferred": True, }) check("wireframes accepted", submit_accept("foundation", wireframes, "EXEC-CPO")) check("parent link registered", SE.register_experience_foundation("parent", "foundation")) check("wireframe terminal gate", SE.complete_stage("foundation", "OPS-ORCH", to="foundation-approved")[0]) check("foundation enters terminal", SE.enter_stage("foundation", "foundation-approved", actor="OPS-ORCH")[0]) check("parent exact foundation valid", SE._has_experience_foundation("parent", SE.read_ledger("parent"))) approval = SE.read_ledger("parent")["experience-foundation-approval"] check("parent link binds technical and operational exact revisions", approval.get("technical-sha256") == sha(technical) and approval.get("operational-sha256") == sha(operational)) print("== direction exact refs and organization design adapters ==") brief = os.path.join(WS, "direction-input-brief.yaml") brief_body = {"product-goal": "ship", "core-users": ["buyer"], "core-tasks": ["evaluate"], "information-density": "medium", "required-accessibility": "WCAG AA", "brand-constraints": ["legible"], "avoid-cliches": ["generic hero"], "representative-screen-requirement": "core-task", "tech-platform-constraints": ["web"]} for approval_key, brief_key in (("benchmark", "competitive-experience-benchmark"), ("blueprint", "experience-blueprint"), ("wireframe", "wireframe-set")): brief_body[f"{brief_key}-ref"] = approval[f"{approval_key}-ref"] brief_body[f"{brief_key}-sha256"] = approval[f"{approval_key}-sha256"] with open(brief, "w", encoding="utf-8") as handle: yaml.safe_dump(brief_body, handle, sort_keys=False) try: SE.init_ledger("direction", plan="design-direction", parent_workflow="parent", product_decision="decision", direction_input_brief=brief) direction_ok = True except ValueError: direction_ok = False check("design-direction accepts exact foundation refs", direction_ok) compiler = subprocess.run([sys.executable, os.path.join(HOOKS, "compile_design_system.py"), "--check"], cwd=ROOT, capture_output=True, text=True) check("organization design adapters are drift-free", compiler.returncode == 0) query = subprocess.run([sys.executable, os.path.join(HOOKS, "design_registry.py"), "--surface", "interactive-learning", "--state", "candidate"], cwd=ROOT, capture_output=True, text=True) query_body = json.loads(query.stdout) if query.returncode == 0 else {} check("registry query returns interactive-learning patterns and page archetypes", {"causal-learning-loop", "learning-feedback-recovery"}.issubset( {item.get("id") for item in query_body.get("patterns", [])}) and {"interactive-learning-atlas", "interactive-learning-deep-dive"}.issubset( {item.get("id") for item in query_body.get("page-archetypes", [])})) print("== DESIGN.md diff and local duplicate adherence ==") generated_design = os.path.join(ROOT, "org-os", "08-design", "generated", "DESIGN.md") design_diff = subprocess.run([sys.executable, os.path.join(HOOKS, "compile_design_system.py"), "--diff", generated_design], cwd=ROOT, capture_output=True, text=True) check("DESIGN.md exact canonical diff is clean", design_diff.returncode == 0) drift_design = os.path.join(WS, "drift-DESIGN.md") with open(generated_design, encoding="utf-8") as source, open(drift_design, "w", encoding="utf-8") as target: target.write(source.read() + "\nmanual drift\n") design_drift = subprocess.run([sys.executable, os.path.join(HOOKS, "compile_design_system.py"), "--diff", drift_design], cwd=ROOT, capture_output=True, text=True) check("DESIGN.md drift emits unified diff", design_drift.returncode == 1 and "--- " in design_drift.stdout and "+++ " in design_drift.stdout) release = os.path.join(ROOT, "org-os", "08-design", "releases", "0.1.0.yaml") ui_report = os.path.join(WS, "ui-design.yaml") target_dir = os.path.join(WS, "design-target") os.makedirs(os.path.join(target_dir, "src", "components"), exist_ok=True) button_path = os.path.join(target_dir, "src", "components", "Button.tsx") with open(button_path, "w", encoding="utf-8") as handle: handle.write("export function Button(){ return null }\n") def write_ui_delta(components): with open(ui_report, "w", encoding="utf-8") as handle: yaml.safe_dump({"payload": {"design-system-bindings": [{ "release-id": "org-design-0.1.0", "release-ref": release, "release-sha256": sha(release), "component-ids": ["button"], "delta": {"tokens": [], "components": components}, }]}}, handle, sort_keys=False) write_ui_delta([]) adherence = subprocess.run([sys.executable, os.path.join(HOOKS, "lint_design_system_adherence.py"), "--ui-report", ui_report, "--target", target_dir], cwd=ROOT, capture_output=True, text=True) check("organization component local reimplementation is rejected", adherence.returncode != 0 and "organization component local duplicate" in adherence.stderr) write_ui_delta([{"id": "button", "reason": "project adapter boundary"}]) adherence_delta = subprocess.run([sys.executable, os.path.join(HOOKS, "lint_design_system_adherence.py"), "--ui-report", ui_report, "--target", target_dir], cwd=ROOT, capture_output=True, text=True) check("declared project component delta is accepted", adherence_delta.returncode == 0) os.makedirs(os.path.join(target_dir, "src", "ui"), exist_ok=True) with open(os.path.join(target_dir, "src", "ui", "Button.jsx"), "w", encoding="utf-8") as handle: handle.write("export const Button = () => null\n") adherence_duplicate = subprocess.run([ sys.executable, os.path.join(HOOKS, "lint_design_system_adherence.py"), "--ui-report", ui_report, "--target", target_dir], cwd=ROOT, capture_output=True, text=True) check("duplicate local component ids remain rejected despite delta", adherence_duplicate.returncode != 0 and "local duplicate component" in adherence_duplicate.stderr) print("== Hyeonworks controlled first-draft experiment contract ==") experiment_hook = os.path.join(HOOKS, "first_draft_experiment.py") planned_manifest = os.path.join(ROOT, "hyeonworks", "experiments", "experience-foundation-ab", "experiment.yaml") planned = subprocess.run([sys.executable, experiment_hook, "validate", planned_manifest], cwd=ROOT, capture_output=True, text=True) check("Hyeonworks planned experiment validates without claiming completion", planned.returncode == 0) planned_complete = subprocess.run([sys.executable, experiment_hook, "validate", planned_manifest, "--require-complete"], cwd=ROOT, capture_output=True, text=True) check("planned experiment cannot claim completed evidence", planned_complete.returncode != 0) experiment_dir = os.path.join(WS, "completed-ab") os.makedirs(experiment_dir, exist_ok=True) request_path = os.path.join(experiment_dir, "request.md") with open(request_path, "w", encoding="utf-8") as handle: handle.write("same controlled request\n") input_kinds = ["competitive-experience-benchmark", "experience-blueprint", "wireframe-set", "design-md", "component-registry"] input_bindings = [] for kind in input_kinds: path = os.path.join(experiment_dir, kind + ".yaml") with open(path, "w", encoding="utf-8") as handle: handle.write(f"kind: {kind}\n") input_bindings.append({"kind": kind, "ref": path, "sha256": sha(path)}) outputs = {} evaluations = {} for arm_id, score, revisions, tokens in (("A", 2, 4, 12000), ("B", 5, 1, 7000)): output_path = os.path.join(experiment_dir, f"arm-{arm_id}.html") desktop = os.path.join(experiment_dir, f"arm-{arm_id}-desktop.png") mobile = os.path.join(experiment_dir, f"arm-{arm_id}-mobile.png") with open(output_path, "w", encoding="utf-8") as handle: handle.write(f"
arm {arm_id}
\n") for screenshot in (desktop, mobile): with open(screenshot, "wb") as handle: handle.write(b"\x89PNG\r\n\x1a\n" + (f"render-{arm_id}-" * 300).encode()) output = {"ref": output_path, "sha256": sha(output_path)} outputs[arm_id] = output evaluation_path = os.path.join(experiment_dir, f"evaluation-{arm_id}.yaml") metrics = {key: score for key in ( "product-purpose-understood-in-5s", "primary-action-found", "information-hierarchy", "category-quality-parity", "visual-craft", "mobile-clarity", "design-system-consistency", "human-preference")} metrics.update({"revision-count-to-acceptance": revisions, "tokens-to-acceptance": tokens}) with open(evaluation_path, "w", encoding="utf-8") as handle: yaml.safe_dump({ "experiment-id": "fixture-ab", "subject": "Hyeonworks", "arm-id": arm_id, "model-id": "same-model", "request-sha256": sha(request_path), "first-result-only": True, "revision-count-at-capture": 0, "output-ref": output_path, "output-sha256": sha(output_path), "screenshots": { "desktop": {"path": desktop, "sha256": sha(desktop)}, "mobile": {"path": mobile, "sha256": sha(mobile)}}, "evaluator-blinded": True, "metrics": metrics, }, handle, sort_keys=False) evaluations[arm_id] = {"ref": evaluation_path, "sha256": sha(evaluation_path)} completed_manifest = os.path.join(experiment_dir, "experiment.yaml") control = {"same-model": True, "same-request-sha256": True, "first-result-only": True, "generation-attempts-per-arm": 1, "revision-count-at-capture": 0, "evaluator-blinded": True} with open(completed_manifest, "w", encoding="utf-8") as handle: yaml.safe_dump({"first-draft-experiment": { "version": 1, "experiment-id": "fixture-ab", "subject": "Hyeonworks", "status": "completed", "model-id": "same-model", "request": {"ref": request_path, "sha256": sha(request_path)}, "control": control, "arms": { "A": {"treatment": "current-harness", "required-input-kinds": ["request"], "forbidden-input-kinds": input_kinds, "inputs": [], "output": outputs["A"], "evaluation": evaluations["A"]}, "B": {"treatment": "experience-foundation", "required-input-kinds": input_kinds, "generation-scope": "representative-section-or-core-screen", "inputs": input_bindings, "output": outputs["B"], "evaluation": evaluations["B"]}, }}}, handle, sort_keys=False) completed = subprocess.run([sys.executable, experiment_hook, "validate", completed_manifest, "--require-complete"], cwd=ROOT, capture_output=True, text=True) check("completed A/B requires exact model/request/input/output/evaluation evidence", completed.returncode == 0) comparison = subprocess.run([sys.executable, experiment_hook, "compare", completed_manifest], cwd=ROOT, capture_output=True, text=True) comparison_body = json.loads(comparison.stdout) if comparison.returncode == 0 else {} check("first-draft metrics comparison applies explicit decision rule", comparison.returncode == 0 and comparison_body.get("treatment-supported") is True) print("== HUMAN none-of-the-above path ==") dset_path = os.path.join(WS, "direction-set.yaml") with open(dset_path, "w", encoding="utf-8") as handle: yaml.safe_dump({"directions": [{"id": "A"}, {"id": "B"}, {"id": "C"}]}, handle) none_path = os.path.join(WS, "none-selection.yaml") with open(none_path, "w", encoding="utf-8") as handle: yaml.safe_dump({ "direction-set-ref": dset_path, "direction-set-sha256": sha(dset_path), "selection-decision": "none-of-the-above", "rejected-directions": [{"id": value, "reason": "benchmark-relative quality floor 미달"} for value in ("A", "B", "C")], "parent-workflow-id": "parent", "product-decision-id": "decision", "direction-input-brief-sha256": "0" * 64, "selection-acceptance-receipt": "human-receipt", }, handle) hard, _warn = LDD.lint_selected_direction(none_path, dset_path) check("none-of-the-above rejects all without averaging", not hard) contracts = SE.load_contracts() selected_contract = contracts["artifact-kinds"]["selected-direction"] check("selected-direction decision remains HUMAN-only", selected_contract.get("required-reviewer-roles") == ["HUMAN-001"]) dd_transitions = contracts["workflows"]["design-direction"].get("additional-transitions", []) check("none decision routes back to discovery", any( item.get("from") == "design-direction-decision" and item.get("to") == "design-direction-discovery" and "none-of-the-above-recorded" in item.get("required-conditions", []) for item in dd_transitions)) print(f"\n{passed} passed, {failed} failed") shutil.rmtree(WS, ignore_errors=True) raise SystemExit(1 if failed else 0)