Files
company-haness/docs/superpowers/plans/2026-07-13-p3-unified-role-method-contract.md

33 KiB
Raw Permalink Blame History

통합 P3 (A 구조 인프라 + B 계약 강화) Implementation Plan

For agentic workers: REQUIRED SUB-SKILL: Use superpowers:subagent-driven-development (recommended) or superpowers:executing-plans to implement this plan task-by-task. Steps use checkbox (- [ ]) syntax for tracking.

Goal: 에이전트 절차를 (A) 카드→skill로 분리하고 (B) 실행 가능한 업무 계약(Contract v2)으로 강화한다. 하나의 브랜치·하나의 Contract v2·하나의 최종 cutover. 75역할 wave 이행, 참조 profile all-active.

Architecture: role-working-methods/(파일분리 SoT, Contract v2 다중 profile) → gen_method_skills.py(v1/v2 dual) → method-skill → 카드 skills. 런타임: context-package method-selectionmethod_contracts.py(공용 policy engine)가 프로필 해석·handoff·execution 검증. 강제: validate_report(step-results 증명) + spawn/transition 2지점 handoff gate + activation registry(trusted CLI).

Tech Stack: Python 3(stdlib+PyYAML), 기존 하네스 hook 패턴. 테스트=standalone check()(pytest 아님), run_all.py 자동발견.

Specs: docs/superpowers/specs/2026-07-13-p3-prompt-skill-separation-design.md(A), docs/superpowers/specs/2026-07-13-p3b-role-method-contract-design.md(B v2.1). B가 상위 — Phase 순서·계약 구조는 B spec 기준.

Global Constraints

  • 하나의 브랜치·최종 1회 cutover: feat/p3-prompt-skill-separation. 카드/skill은 wave마다 재생성, 최종 cutover 1회. v1 flat은 브랜치 내부 migration용(최종 merge엔 없어도 됨).
  • 품질 중립(A) vs 강화(B) 분리: A(카드→skill 위치 이동)는 내용 불변. B(계약)는 내용 강화 — 단 wave·enforcement-status로 회귀 없이 점진.
  • 공용 policy engine 단일 지점: 정책 해석은 method_contracts.py 한 곳. 강제 시점만 3곳(context_package/subagent_register spawn, state_engine transition, validate_report). 별도 로직 복제 금지.
  • SoT/runtime 분리: role-working-methods/는 방법론 SoT — runtime이 수정 금지. 활성화는 method-contract-activations.yaml(trusted CLI activate_method_contract.py만 write, guard_tools 강제).
  • 자기신고 금지: method-execution step-results는 artifact/evidence/receipt hash로 증명. completed step은 required-output 실존, skipped는 허용 skip-rule 일치.
  • machine vs judgment: completion-gate·prohibited은 enforcement: hard|warning|instructional. machine-check 연결만 자동 Hard Fail, 자연어는 judgment/self-check(오탐 방지).
  • method-selection: standard/heavy 필수(auto-infer 금지), light 유일후보만. 보고서 method-id == context-package 선택 method.
  • handoff = profile-to-profile edge: from/to {role-id, method-id}·cardinality·schema-ref·required-state·binding·freshness. spawn·transition gate 동일 판정.
  • hash 규약: contract-sha256=정규화 계약 YAML hash(skill md 아님). capability는 section-sha256. historical-valid(감사 유지) vs current-usable(현 active와 hash 일치해야 후속 입력).
  • enforcement-status: draft(warning·trace만) / active(standard·heavy Hard Fail, 양쪽 active면 handoff hard gate) / retired(fallback 금지). draft→active는 golden+HUMAN acceptance.
  • 불변 개수: 에이전트 72·역할 75. 실행 환경: CLAUDE_PROJECT_DIR="$PWD" ORGOS_WORKSPACE=_sandbox. 커밋 trailer Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>. 커밋 전 git checkout -- .claude/tests/fixtures/.

Phase 맵 (B spec §3)

Phase 산출(테스트 가능 단위) 태스크
0 auto-load probe → generated-dir 확정 T0
1 Contract v2 스키마 + 파일분리 + gate/artifact vocabulary T1.1T1.3
2 P3-A 인프라(registry·gen v1/v2·gen_agents·ref/orphan/drift) T2.1T2.5
3 method_contracts.py policy engine + method-selection + activation(CLI·hash) T3.1T3.4
4 Enforcement(validate_report·spawn gate·transition gate·debt) T4.1T4.4
5 대표 역할 계약 + golden task + active 승격 T5(템플릿)×대표군
6 family wave 25 이행 T6(wave 반복)
7 cutover(참조 profile all-active·debt 0·v1 제거·재생성) T7

Phase 04 = 계약 machinery(완전 코드). 계약 0개여도 v1 fallback으로 green. Phase 57 = 계약 authoring(반복 템플릿+게이트).


File Structure

신설:

  • org-os/00-role-registry/role-working-methods/{index.yaml, executive.yaml, product.yaml, design.yaml, architecture.yaml, engineering.yaml, platform-security-data.yaml, gtm-operations.yaml, consulting-documentation.yaml} — 파일분리 SoT(v1 이행 + v2 계약).
  • org-os/00-role-registry/method-skill-registry.yaml — role→method-skill 배선(A).
  • org-os/00-role-registry/method-contract-activations.yaml — 활성화 registry.
  • org-os/06-agent-work/artifact-type-vocabulary.yaml — artifact-type·handoff 어휘.
  • .claude/hooks/method_contracts.py — 공용 policy engine.
  • .claude/hooks/gen_method_skills.py — v1/v2 dual 렌더 + --check.
  • .claude/hooks/skill_refs.py — skill 참조 헬퍼.
  • .claude/hooks/activate_method_contract.py — activation trusted CLI.
  • .claude/schemas/method-execution.schema.json — trace 스키마(공통 report additive).
  • .claude/skills/generated/<role>-method/SKILL.md — 생성물.
  • .claude/tests/test_p3_infra.py, test_p3b_contracts.py, test_p3b_enforcement.py — 강제기.
  • <ws>/state/method-contract-debt.jsonl — debt event 원장(런타임 산출).

개정:

  • .claude/hooks/gen_agents.py(spine+registry skills), validate_report.py(method-execution), state_engine.py(transition handoff gate), context_package.py+subagent_register.py(spawn gate·method-selection), doctor.py(P3 배선), lint_refs.py(skills 참조), guard_tools.py(activation write 차단).
  • .claude/skills/design-craft/SKILL.md(capability-sections manifest), CLAUDE.md.

Phase 0 — Baseline + skill auto-load probe (load-bearing)

Task 0: auto-load probe → generated-dir 확정

Files: (임시 probe — 커밋 안 함)

런타임 동작 검증이라 pytest 아님 — controller가 live subagent로 실측.

  • Step 1: probe skill + agent 생성
mkdir -p .claude/skills/generated/probe-method
printf -- '---\nname: probe-method\ndescription: Use when the user says PROBE-P3.\n---\n# Probe\nReply exactly: PROBE-LOADED-OK-7F3A\n' > .claude/skills/generated/probe-method/SKILL.md
printf -- '---\nname: probe-p3\ndescription: P3 phase-0 probe.\ntools: Read\nmodel: inherit\nskills: [probe-method]\n---\nprobe-method skill 지시를 따르세요.\n' > .claude/agents/probe-p3.md
  • Step 2: controller가 probe-p3 서브에이전트를 "PROBE-P3"로 dispatch. sentinel PROBE-LOADED-OK-7F3A 반환 → 중첩 auto-load 확인.

  • Step 3: 레이아웃 확정 + 제거

  • 반환 O → generated-dir: .claude/skills/generated.

  • 반환 X → flat 폴백 generated-dir: .claude/skills(이름 규약 <role>-method).

  • ledger에 결과 기록. rm -rf .claude/skills/generated/probe-method .claude/agents/probe-p3.md.

  • Step 4: baseline 회귀 기준 기록: run_all.py green·doctor OK·agents 72·roles 75를 ledger에 스냅샷.


Phase 1 — Contract v2 스키마 + 파일분리 + vocabulary

Task 1.1: role-working-methods 파일분리 + index (v1 이행)

Files:

  • Create: org-os/00-role-registry/role-working-methods/index.yaml + 8 family 파일
  • Test: .claude/tests/test_p3_infra.py

Interfaces:

  • Produces: load_role_methods() 규약 — index.includes를 병합해 {role-id: entry} 반환. 중복/누락/미include=에러.

  • Step 1: 실패 테스트

.claude/tests/test_p3_infra.py(신규, 헤더 + 첫 check):

#!/usr/bin/env python3
"""P3 인프라 강제기 — standalone check(pytest 아님). exit 0=통과."""
import glob, importlib.util, os, sys, yaml
ROOT = os.environ.get("CLAUDE_PROJECT_DIR", os.getcwd())
REG = os.path.join(ROOT, "org-os", "00-role-registry")
RWM_DIR = os.path.join(REG, "role-working-methods")
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_role_methods():
    idx = yaml.safe_load(open(os.path.join(RWM_DIR, "index.yaml")))["role-method-contracts"]
    merged, srcs = {}, {}
    for inc in idx["includes"]:
        d = yaml.safe_load(open(os.path.join(RWM_DIR, inc))) or {}
        for rid, entry in (d.get("role-working-methods") or {}).items():
            assert rid not in merged, f"중복 role-id {rid} ({srcs.get(rid)} & {inc})"
            merged[rid] = entry; srcs[rid] = inc
    files_on_disk = {os.path.basename(p) for p in glob.glob(os.path.join(RWM_DIR, "*.yaml"))} - {"index.yaml"}
    assert files_on_disk == set(idx["includes"]), f"미include/유령 파일: {files_on_disk ^ set(idx['includes'])}"
    return merged

_rm = load_role_methods()
_fams = yaml.safe_load(open(os.path.join(REG, "capability-families.yaml")))["capability-families"]["families"]
_bound = set()
for f in _fams: _bound |= set(f["member-role-ids"])
check("파일분리 병합 75역할·중복0·미include0", set(_rm) == _bound and len(_rm) == 75)
  • Step 2: 실패 확인 — Run: CLAUDE_PROJECT_DIR="$PWD" python3 .claude/tests/test_p3_infra.py → FAIL(디렉터리 없음).

  • Step 3: 기존 role-working-methods.yaml을 family별로 분할

index.yaml:

role-method-contracts:
  version: 2
  includes: [executive.yaml, product.yaml, design.yaml, architecture.yaml, engineering.yaml, platform-security-data.yaml, gtm-operations.yaml, consulting-documentation.yaml]

분할 매핑(family→파일): executive=EXEC-·OPS-ORCH·STR-ANALYST; product=PROD-·UX-RESEARCHER·DATA-ANALYST; design=DES-; architecture=ARCH-; engineering=ENG-; platform-security-data=INFRA-·SRE·SEC-·DATA-ENGINEER·DATA-BIGDATA·QA; gtm-operations=GTM-·OPS-CH·OPS-CREW; consulting-documentation=CONSULT-·DOC-. 각 파일 최상위 키 role-working-methods: 아래 기존 v1 엔트리(working-method/key-frameworks/evidence-they-use/sources) 그대로 이동(내용 불변). 분할은 스크립트로:

# scratchpad/split_rwm.py — 기존 단일 파일을 family별로 분할(1회)
import yaml, os
src = yaml.safe_load(open("org-os/00-role-registry/role-working-methods.yaml"))["role-working-methods"]
fams = yaml.safe_load(open("org-os/00-role-registry/capability-families.yaml"))["capability-families"]["families"]
GROUP = {  # family-id -> 파일
  **{f: "executive.yaml" for f in ["FAM-CEO","FAM-CTO","FAM-CPO","FAM-CFO","FAM-COO","FAM-CPTO","FAM-VPENG","FAM-ORCH","FAM-STRATEGY"]},
  **{f: "product.yaml" for f in ["FAM-PRODUCT-MGMT","FAM-UX-RESEARCH"]},
  "FAM-DESIGN":"design.yaml",
  **{f: "architecture.yaml" for f in ["FAM-ARCHITECTURE-TECH","FAM-ARCHITECTURE-BIZ"]},
  **{f: "engineering.yaml" for f in ["FAM-ENG-BACKEND","FAM-ENG-FRONTEND","FAM-ENG-SPECIAL"]},
  **{f: "platform-security-data.yaml" for f in ["FAM-PLATFORM-INFRA","FAM-SECURITY","FAM-DATA","FAM-QA"]},
  **{f: "gtm-operations.yaml" for f in ["FAM-GTM-GROWTH","FAM-GTM-SALES","FAM-REVOPS","FAM-LEGAL","FAM-OPS-DELIVERY"]},
  **{f: "consulting-documentation.yaml" for f in ["FAM-CONSULTING","FAM-DOC-CONSULT"]},
}
buckets = {}
for f in fams:
    fn = GROUP[f["family-id"]]
    for rid in f["member-role-ids"]:
        if rid in src: buckets.setdefault(fn, {})[rid] = src[rid]
os.makedirs("org-os/00-role-registry/role-working-methods", exist_ok=True)
for fn, roles in buckets.items():
    yaml.safe_dump({"role-working-methods": roles}, open(f"org-os/00-role-registry/role-working-methods/{fn}","w"), allow_unicode=True, sort_keys=False)
print("split", sum(len(v) for v in buckets.values()))

실행 후 index.yaml 수기 작성. 원본 role-working-methods.yamlv1 fallback로 잔존(Phase 7서 제거).

  • Step 4: 통과 확인 — Run 테스트 → ✅ 파일분리 병합 75역할.

  • Step 5: Commitgit add org-os/00-role-registry/role-working-methods .claude/tests/test_p3_infra.py && git commit -m "P3 T1.1: role-working-methods 파일분리+index(75역할·중복0)"

Task 1.2: Contract v2 스키마 문서 + gate/artifact vocabulary

Files:

  • Create: org-os/06-agent-work/artifact-type-vocabulary.yaml
  • Create: .claude/schemas/method-execution.schema.json
  • Test: test_p3_infra.py append

Interfaces:

  • Produces: artifact-type 어휘(handoff·required-inputs가 참조), method-execution JSON schema(step-results/handoffs/decisions).

  • Step 1: 실패 테스트(append)

_av = yaml.safe_load(open(os.path.join(ROOT, "org-os/06-agent-work/artifact-type-vocabulary.yaml")))["artifact-types"]
check("artifact vocabulary has core types",
      all(t in _av for t in ["product-decision","direction-input-brief","selected-direction","locked-invariants","interaction-state-model","api-contract","design-decision-record"]))
import json
_me = json.load(open(os.path.join(ROOT, ".claude/schemas/method-execution.schema.json")))
check("method-execution schema requires step-results",
      "step-results" in _me.get("properties", {}) and "method-id" in _me["properties"])
  • Step 2: 실패 확인.

  • Step 3: 작성

artifact-type-vocabulary.yaml:

# handoff·required-inputs·output-artifacts가 참조하는 artifact-type 통제 어휘. schema-ref 로 스키마 연결.
artifact-types:
  product-decision: { producer-roles: [EXEC-CEO, PROD-PM], schema-ref: decision.schema.json }
  direction-input-brief: { producer-roles: [DES-PROD], schema-ref: null }
  direction-set: { producer-roles: [DES-DIRECTOR], schema-ref: null }
  selected-direction: { producer-roles: [DES-DIRECTOR], schema-ref: approved-direction.schema.json }
  locked-invariants: { producer-roles: [DES-DIRECTOR], schema-ref: null }
  interaction-state-model: { producer-roles: [DES-PROD], schema-ref: null, required-fields: [states, transitions, exceptions] }
  reference-cluster: { producer-roles: [DES-VISUAL], schema-ref: null }
  design-decision-record: { producer-roles: [DES-PROD, DES-VISUAL], schema-ref: null }
  api-contract: { producer-roles: [ARCH-TECH, ENG-BE], schema-ref: null }
  experience-constraints: { producer-roles: [DES-PROD], schema-ref: null }
# Phase 5–6 에서 역할 계약 작성 시 필요한 artifact-type 을 여기 추가(controlled vocabulary).

method-execution.schema.json:

{
  "$schema": "http://json-schema.org/draft-07/schema#",
  "type": "object",
  "required": ["role-id", "method-id", "contract-sha256", "step-results"],
  "properties": {
    "role-id": {"type": "string"},
    "method-id": {"type": "string"},
    "contract-sha256": {"type": "string"},
    "capability-bindings": {"type": "array", "items": {"type": "object",
      "required": ["skill-id","section-id","section-sha256"],
      "properties": {"skill-id":{"type":"string"},"section-id":{"type":"string"},"section-sha256":{"type":"string"}}}},
    "step-results": {"type": "array", "items": {"type": "object",
      "required": ["step-id","status"],
      "properties": {"step-id":{"type":"string"},"status":{"enum":["completed","skipped"]},
        "artifact-refs":{"type":"array","items":{"type":"object","required":["report-id","sha256"]}},
        "evidence-refs":{"type":"array","items":{"type":"object","required":["source-uri","grade"]}},
        "skip-rule-id":{"type":"string"},"reason":{"type":"string"}}}},
    "decisions": {"type": "array", "items": {"type": "object",
      "required": ["decision-id","alternatives","selected-option-id"],
      "properties": {"decision-id":{"type":"string"},
        "alternatives":{"type":"array","minItems":1,"items":{"type":"object","required":["option-id"]}},
        "selected-option-id":{"type":"string"},"rejection-rationales":{"type":"object"}}}},
    "handoffs": {"type": "array", "items": {"type": "object",
      "required": ["to-role","artifact-refs"],
      "properties": {"to-role":{"type":"string"},"to-method":{"type":"string"},
        "artifact-refs":{"type":"array","items":{"type":"object","required":["report-id","sha256"]}}}}}
  }
}
  • Step 4: 통과 확인.
  • Step 5: CommitP3 T1.2: artifact-type vocabulary + method-execution schema

Task 1.3: Contract v2 스키마 규약 문서(gate catalog)

Files: Modify role-working-methods/index.yaml(스키마 규약 주석 블록 추가); doc docs/superpowers/specs/...(이미 존재).

  • Step 1: index.yaml에 contract-v2-schema 규약 블록 추가(machine-check 어휘: artifact-field-present/artifact-fields-absent/artifact-field-matches/artifact-exists/receipt-exists; enforcement: hard|warning|instructional; profile 필드 목록). 이는 문서·validator 참조용.
  • Step 2: test_p3_infra append — check("index defines machine-check vocabulary", ...).
  • Step 3: CommitP3 T1.3: Contract v2 스키마 규약(gate catalog)

Phase 2 — P3-A 인프라 (registry · gen v1/v2 · gen_agents · 무결성)

Phase 2는 P3-A plan(docs/superpowers/plans/2026-07-13-p3-prompt-skill-separation.md) Task 18을 파일분리 SoT + v1/v2 dual 렌더 델타를 적용해 수행한다. 아래는 델타만; 나머지 코드는 그 plan을 task-brief로 참조.

Task 2.1: method-skill-registry.yaml

P3-A plan Task 1 그대로(75 roles + families). 변경 없음.

Task 2.2: gen_method_skills.py — v1/v2 dual 렌더

P3-A plan Task 2 기반 + 델타:

  • 입력 SoT를 단일 파일이 아니라 role-working-methods/ 병합(load_role_methods, Task 1.1)으로 로드.
  • 엔트리에 method-contract.version==2v2 렌더(B spec §10: profile별 섹션 — 역할경계/method(입력·워크플로 step[objective/uses-capability/machine·judgment gate/skippable]·판단규칙·근거·대안·산출·handoff·금지·self-check)), 없으면 v1 flat 렌더(P3-A 그대로).
  • --check drift 유지. self-check optional 유지.

핵심 렌더 함수(추가):

def _render_v2(rid, entry, prof, skill_name):
    L = [f"# {prof.get('role-name', rid)} ({rid}) 실무 계약", "", "## 역할 경계"]
    rb = entry.get("role-boundary", {})
    L += [f"- owns: {', '.join(rb.get('owns', []))}", f"- not-owns: {', '.join(rb.get('not-owns', []))}"]
    for m in entry.get("methods", []):
        tt = ", ".join((m.get("applies-when") or {}).get("task-types", []))
        L += ["", f"## Method: {m['method-id']}  (task-types: {tt})"]
        L.append("### 필수 입력")
        L += [f"- {i.get('artifact-type')}{' (optional)' if i.get('optional') else ''}" for i in m.get("required-inputs", [])]
        L.append("### 워크플로")
        for s in m.get("workflow", []):
            uc = s.get("uses-capability") or {}
            L.append(f"- **{s['step-id']}**: {s.get('objective','')}"
                     + (f" · 기법 `{uc.get('skill-id')}#{uc.get('section-id')}`" if uc else "")
                     + (f" · 산출 {s.get('required-output')}" if s.get('required-output') else "")
                     + (" · skippable" if s.get("skippable") else ""))
            for g in (s.get("completion-gates") or {}).get("machine", []):
                L.append(f"    - [machine:{g.get('enforcement','hard')}] {g['gate-id']}: {g.get('check')} {g.get('artifact','')}.{g.get('field','')}")
            for g in (s.get("completion-gates") or {}).get("judgment", []):
                L.append(f"    - [judgment] {g['gate-id']}: {g.get('criterion','')} (reviewer {g.get('reviewer-role','')})")
        for key, title in [("decision-rules","판단 규칙"),("prohibited-shortcuts","금지"),("self-check","자기검증")]:
            if m.get(key):
                L += [f"### {title}"] + [f"- {x if isinstance(x,str) else x}" for x in m[key]]
        if m.get("handoff-contract"):
            L.append("### Handoff")
            L += [f"- {h.get('edge-id')}: -> {h['to']['role-id']}/{h['to']['method-id']}" for h in m["handoff-contract"]]
    return "\n".join(L).rstrip() + "\n"

(frontmatter·GEN_HEADER는 P3-A method_skill_md와 동일 패턴으로 감싼다. v2면 body=_render_v2.)

Task 2.3: gen_agents.py — spine + registry skills

P3-A plan Task 4 그대로(wm_block→method_spine, router pointer, collapse union). v2 역할도 spine은 essence+프레임워크(계약 첫 method의 working 요지) — 카드는 여전히 얇게, 전체 계약은 skill.

Task 2.4: skill_refs.py + lint_refs 확장

P3-A plan Task 3·6 그대로.

Task 2.5: doctor check_method_skill_wiring + 재생성 + Phase2 green

P3-A plan Task 5·7·8 기반 + 델타: doctor가 파일분리 정합(중복/누락/미include 0)도 검사. 재생성 후 run_all green.

  • 각 태스크: P3-A plan 해당 task를 task-brief로 추출 → 위 델타 반영 → 구현·리뷰·커밋. Phase 2 종료 시 test_p3_infra.py + run_all.py green.

Phase 3 — Runtime contract resolution (policy engine · activation)

Task 3.1: method_contracts.py 공용 policy engine (읽기 API)

Files:

  • Create: .claude/hooks/method_contracts.py
  • Test: .claude/tests/test_p3b_contracts.py

Interfaces:

  • Produces: resolve_method_profile(role_id, method_id), resolve_activation(role_id, method_id), canonical_contract_hash(contract), validate_method_selection(cp), load_activations().

  • Step 1: 실패 테스트 (test_p3b_contracts.py 헤더 + check) — resolve_method_profile로 대표 계약 로드, canonical_contract_hash 결정성(같은 dict→같은 hash), validate_method_selection(standard·method-selection 없음→에러).

  • Step 2: 실패 확인.

  • Step 3: 작성

#!/usr/bin/env python3
"""method_contracts — Contract v2 정책 해석 단일 지점(P3-B §13.1). 강제는 호출측(spawn/transition/validate)."""
import glob, hashlib, json, os, yaml
ROOT = os.environ.get("CLAUDE_PROJECT_DIR") or os.path.dirname(os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
REG = os.path.join(ROOT, "org-os", "00-role-registry")
RWM_DIR = os.path.join(REG, "role-working-methods")
ACTIVATIONS = os.path.join(REG, "method-contract-activations.yaml")

def load_role_methods():
    idx = yaml.safe_load(open(os.path.join(RWM_DIR, "index.yaml")))["role-method-contracts"]
    merged = {}
    for inc in idx["includes"]:
        d = yaml.safe_load(open(os.path.join(RWM_DIR, inc))) or {}
        for rid, e in (d.get("role-working-methods") or {}).items():
            if rid in merged: raise AssertionError(f"중복 role-id {rid}")
            merged[rid] = e
    return merged

def resolve_method_profile(role_id, method_id):
    e = load_role_methods().get(role_id) or {}
    if (e.get("method-contract") or {}).get("version") != 2:
        return None  # v1 flat 역할 — 계약 강제 대상 아님
    for m in e.get("methods", []):
        if m.get("method-id") == method_id:
            return m
    return None

def load_activations():
    if not os.path.exists(ACTIVATIONS): return {}
    return (yaml.safe_load(open(ACTIVATIONS)) or {}).get("method-contract-activations", {}).get("roles", {})

def resolve_activation(role_id, method_id):
    return ((load_activations().get(role_id) or {}).get("methods") or {}).get(method_id) or {"status": "draft"}

def canonical_contract_hash(contract):
    blob = json.dumps(contract, sort_keys=True, ensure_ascii=False, separators=(",", ":"))
    return hashlib.sha256(blob.encode()).hexdigest()

def validate_method_selection(cp):
    """context-package dict -> 문제 리스트(빈=통과). standard/heavy 는 method-selection 필수."""
    tier = (cp.get("tier") or "standard")
    ms = cp.get("method-selection")
    role = cp.get("role-id") or (ms or {}).get("role-id")
    e = load_role_methods().get(role) or {}
    if (e.get("method-contract") or {}).get("version") != 2:
        return []  # v1 역할 — 미적용
    if not ms or not ms.get("method-id"):
        if tier in ("standard", "heavy"):
            return [f"{role}: standard/heavy 는 method-selection.method-id 필수(auto-infer 금지)"]
        cands = [m["method-id"] for m in e.get("methods", [])]
        return [] if len(cands) == 1 else [f"{role}: light 이나 method profile 복수({len(cands)}) — method-selection 필요"]
    if not any(m["method-id"] == ms["method-id"] for m in e.get("methods", [])):
        return [f"{role}: 미지 method-id {ms['method-id']}"]
    return []
  • Step 4: 통과 확인. Step 5: CommitP3 T3.1: method_contracts.py policy engine(읽기·해석)

Task 3.2: activation registry + activate_method_contract.py (trusted CLI)

Files: Create method-contract-activations.yaml(빈 골격), .claude/hooks/activate_method_contract.py; Modify guard_tools.py(직접 write 차단).

  • Step 1: 실패 테스트 — activate CLI가 (a) golden report 부재 시 거부, (b) HUMAN acceptance hash 불일치 거부, (c) 정상 입력 시 registry에 active + receipt. guard_tools가 activations 직접 Write 차단.
  • Step 2: 실패 확인.
  • Step 3: 작성 — CLI: --role --method --contract-sha256 --validation-report --acceptance-event 인자. 검증 순서: 계약 profile 실존 → canonical_contract_hash==인자 → validation-report 파일 실존·hash → acceptance-event(acceptance_log)에서 HUMAN accepted 이벤트 sha256 일치 → 임시파일 write → os.replace → activation receipt(evidence-ledger). guard_tools _bash_write_targets/Write deny에 method-contract-activations.yaml 추가(CLI만 예외).
  • Step 4: 통과 확인. Step 5: CommitP3 T3.2: activation trusted CLI + guard 차단

Task 3.3: context_package method-selection 배선

  • context_package.py가 spawn 컴파일 시 validate_method_selection 호출 → 문제 있으면 spawn 거부(standard/heavy method-selection 필수). 테스트 + 커밋.

Task 3.4: capability-sections manifest (design-craft)

  • design-craft SKILL.md frontmatter(또는 capability-sections.yaml)에 section-id manifest 추가(brief/reference-cluster/constraints/token-semantics/decisions). method_contracts.resolve_capability_section(skill_id, section_id) + doctor 검사. 테스트 + 커밋.

Phase 4 — Enforcement (validate_report · 2지점 handoff gate · debt)

Task 4.1: method_contracts.validate_method_execution + validate_report 배선

Interfaces: validate_method_execution(report, ws) -> errors[]; validate_report가 active·standard/heavy에서 호출.

  • Step 1: 실패 테스트(test_p3b_enforcement.py) — active 계약·standard 보고서에서: required step 누락→에러, completed인데 artifact-ref 부재→에러, skipped인데 허용 skip-rule 불일치→에러, alternatives<min→에러, method-id≠selection→에러. draft/light→무에러.
  • Step 2: 실패 확인.
  • Step 3: 작성validate_method_execution: 보고서 method-execution의 method-id로 profile 조회 → activation status active & tier≥standard일 때만 강제. 각 workflow step에 대해 completed면 artifact-ref 실존(+machine gate), skipped면 profile step.skippable & skip-rule-id∈허용. decisions는 alternatives-policy min·option 구조 검증. validate_report.py validate()에서 호출해 errors 병합.
  • Step 4: 통과 확인. Step 5: CommitP3 T4.1: validate_method_execution 배선(step-results 증명)

Task 4.2: evaluate_handoff_edge + spawn gate

  • method_contracts.evaluate_handoff_edge(edge, ws, phase): required-artifacts가 실존·required-state(Accepted)·binding(same workflow/decision)·freshness(current-usable) 충족인지. producer+consumer profile active면 hard(문제→차단), 한쪽 draft면 warning+debt event. context_package/subagent_register가 spawn 직전 consumer required-inputs에 대해 phase="spawn" 호출 → 미충족 시 spawn 거부. 테스트(consumer spawn 차단) + 커밋.

Task 4.3: state_engine transition handoff gate

  • state_engine에 handoff predicate 추가: stage 전이 시 해당 stage handoff edge 전부 충족(phase="transition"). _PROTECTED_FACTS. P2 gate와 동형. 테스트 + 커밋.

Task 4.4: migration-debt event 원장

  • method_contracts.record_debt(event)/unresolved_debt(ws)(opened/resolved fold). doctor가 status 분포 + unresolved debt 리포트. handoff gate가 draft 엣지에서 debt opened 기록. 테스트(fold=최신 opened) + 커밋.

Phase 5 — 대표 역할 계약 + golden task + 활성화 (반복 템플릿)

Phase 56은 계약 authoring이다. 각 (역할, method profile)마다 아래 반복 템플릿을 수행한다. 계약 본문은 B spec §3–§8 스키마대로 작성(사전 완전코드 아님 — 역할 전문성 반영).

Task 5.T (템플릿, 대표군 각 역할 반복)

대표군(B spec §18): DES-DIRECTOR, DES-PROD, DES-PLATFORM, DES-VISUAL, EXEC-CEO, EXEC-CFO, PROD-PM, ARCH-TECH, ENG-BE, SRE(또는 INFRA-PLATFORM), QA, GTM-PRICING, DOC-LEAD.

각 역할에 대해:

  • 작성: 해당 family 파일(role-working-methods/<fam>.yaml)의 역할 엔트리에 method-contract: {version: 2} + role-boundary(owns/not-owns) + methods[](호출목적별 profile: applies-when.task-types·required-inputs·workflow[step: uses-capability·completion-gates{machine/judgment}·skippable·skip-rules]·decision-rules·evidence-policy·alternatives-policy·output-artifacts·handoff-contract[profile-to-profile edge]·prohibited-shortcuts·approval-policy·escalation·self-check). 역할 경계 준수(다른 역할 owns 침범 금지, DES-PROD는 pre/post-direction profile 분리).
  • schema/lint: test_p3b_contracts.py가 profile 필드 완전·machine gate 어휘 유효·uses-capability section-id 해소·handoff edge from/to 유효 검사.
  • golden task: 해당 profile로 대표 task 실행(격리 subagent) → 산출물·step-results·handoff가 계약대로 나오는지 end-to-end 검증. golden report 산출.
  • contract review: 독립 리뷰(계약이 역할 전문성·경계·handoff 정합인지).
  • HUMAN acceptance: 사용자(또는 승인자)가 golden+계약 수용 → acceptance-event.
  • 활성화: activate_method_contract.py --role .. --method .. --contract-sha256 .. --validation-report golden.. --acceptance-event .. → registry active.
  • wave gate: 대표군 전부 active + 대표군 간 handoff edge debt 0.

대표군은 계약 유형 전부(발산·수렴/사업판단/기술설계/구현/운영·검증/가격/문서 handoff)를 커버 — machinery가 모든 유형에서 작동함을 증명.


Phase 6 — family wave 25 이행

Task 6.W (wave 반복: 2 임원·제품·전략·재무 / 3 디자인·아키텍처·데이터·보안 / 4 개발·인프라·QA / 5 GTM·운영·컨설팅·문서)

각 wave:

  • 해당 family 역할들의 계약 작성(Task 5.T 템플릿, draft).
  • schema/lint + 역할별 대표 task 검증.
  • handoff edge 정합(이 wave가 소비/생산하는 artifact-type을 vocabulary에 추가).
  • golden + HUMAN acceptance → active 승격.
  • wave gate: 이 wave 역할 active + 신규 handoff edge debt 0 → 다음 wave.
  • wave마다 gen_method_skills+gen_agents 재생성 + run_all green.

Phase 7 — cutover

Task 7: all-active cutover + v1 제거

  • 참조 profile 산출: commands + execution-plans + context-package method-selection + handoff graph 스캔 → 참조되는 (role, method) 집합.
  • cutover 게이트(doctor + test): 참조 profile ⊆ activation active AND unresolved debt=0 AND 모든 역할 ≥1 필수 profile 존재.
  • v1 제거: 원본 단일 role-working-methods.yaml 삭제(파일분리로 대체 완료). retired 처리 확인.
  • 최종 재생성: gen_method_skills + gen_agents → 72 agents·75 roles·전 skill.
  • git checkout -- .claude/tests/fixtures/; run_all.py green + doctor OK(P3 배선·debt 0·status all-active).
  • CLAUDE.md 갱신(Contract v2·다중 profile·2지점 gate·activation registry·policy engine·파일분리).
  • Commit + finishing-a-development-branch(사용자 선택 merge).

Self-Review

Spec coverage: B spec §3 Phase 07 ↔ 본 plan Phase 07. §4 다중 profile(T5.T/T6.W·gen v2 T2.2), §5 method-selection(T3.1·T3.3), §7 machine/judgment gate(T1.3·T4.1), §8 evidence/alternatives(T4.1·schema T1.2), §11 step-results(T1.2·T4.1), §13 2지점 handoff+policy engine(T3.1·T4.2·T4.3), §14 activation CLI(T3.2), §16 hash/section-id(T3.1·T3.4), §17 파일분리(T1.1), §18 wave+cutover(T5T7). A spec: registry·gen·spine·무결성(Phase 2). 전 섹션 커버.

Placeholder scan: Phase 04는 완전 코드 TDD. Phase 57은 의도적으로 authoring 템플릿(75 계약 본문은 역할 전문성 반영 실행물 — 사전 완전코드 불가, 대신 스키마·게이트·검증 절차를 완전 명시). 이는 writing-plans의 "content authoring은 반복 템플릿" 패턴.

Type consistency: method_contracts.py API(resolve_method_profile/resolve_activation/validate_method_selection/evaluate_handoff_edge/validate_method_execution/canonical_contract_hash)가 강제 3지점(spawn/transition/validate)에서 동일 시그니처로 소비. load_role_methods 병합 규약이 gen·doctor·policy engine 일관. contract-sha256·section-sha256 규약 일관.

Execution Handoff

Plan complete and saved to docs/superpowers/plans/2026-07-13-p3-unified-role-method-contract.md.

Subagent-Driven(권장) — Phase 0→7 순차, 태스크별 fresh subagent + 2단 리뷰. Phase 04는 완전코드 TDD, Phase 57은 계약 authoring 템플릿×wave. P1·P2와 동일.