init: company-haness 설계
This commit is contained in:
@@ -0,0 +1,748 @@
|
||||
---
|
||||
status: historical-snapshot
|
||||
applies-to-version: "registry 62 roles / 26 families / 11 lenses (이 계획 실행 시점)"
|
||||
superseded-by: "현재 정본 registry 73 roles / 28 families / 12 lenses — org-os/00-role-registry/*"
|
||||
exclude-from: [must-read, default-search]
|
||||
note: "구현 완료된 과거 계획. 본문의 62/26/11 수치는 당시 스냅샷이며 현재 정본은 org-os 레지스트리다(finding #20)."
|
||||
---
|
||||
|
||||
# 협업 효율화 + 다양성 보존 오버레이 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:** Org OS에 발산/수렴 모드 × 경량/표준/중대 티어 × 11개 불가침 렌즈로 이뤄진 협업 오버레이를 명세 파일로 추가해, 협업 handoff 비용을 낮추면서 관점 다양성을 구조적으로 보존한다.
|
||||
|
||||
**Architecture:** 가산적 오버레이 — `org-os` 아래 5개 신규 YAML을 추가하고 기존 4개 파일에는 참조 필드/규칙만 덧붙인다. 코드·실행체(.claude)는 만들지 않는다. 각 파일은 단일 관심사만 담고 id/참조로만 연결된다.
|
||||
|
||||
**Tech Stack:** YAML 명세, 검증은 python3 + pyyaml(설치 확인됨 6.0.1)로 임시(비커밋) 스크립트를 scratchpad에서 실행. Markdown 문서.
|
||||
|
||||
## Global Constraints
|
||||
|
||||
- 기준 스펙: `docs/superpowers/specs/2026-07-05-collaboration-efficiency-design.md` (모든 값의 단일 원천).
|
||||
- 범위: **명세만.** `.claude/*`, MCP, hook, 영구 validator 스크립트 생성 금지(후속 라운드).
|
||||
- 기존 62개 role을 삭제/추가하지 않는다. `roles.yaml`은 참조 분류체계로 보존한다.
|
||||
- 기존 파일 변경은 **참조 추가뿐** — 기존 rigor(특히 High/Critical→인간, Approved 조건)의 의미를 제거하지 않는다. **TIER-HEAVY == 오늘 동작.**
|
||||
- 신규/수정 YAML은 모두 `python3 -c "import yaml,sys; yaml.safe_load(open(f))"`로 파싱되어야 한다.
|
||||
- 모든 참조 id(role-id/family-id/lens-id)는 실제 정의에 존재해야 한다(orphan 0).
|
||||
- 고정 id 집합(대소문자·하이픈 정확히 준수):
|
||||
- 렌즈 11개: `LENS-VALUE, LENS-TECH, LENS-PRODUCT, LENS-FINANCE, LENS-OPS, LENS-INTEGRATION, LENS-SECURITY, LENS-LEGAL, LENS-CUSTOMER, LENS-REVENUE, LENS-CONTRARIAN`
|
||||
- 패밀리 26개: `FAM-CEO, FAM-ORCH, FAM-CTO, FAM-CPO, FAM-CFO, FAM-COO, FAM-CPTO, FAM-VPENG, FAM-PRODUCT-MGMT, FAM-UX-RESEARCH, FAM-DESIGN, FAM-STRATEGY, FAM-ENG-FRONTEND, FAM-ENG-BACKEND, FAM-ENG-SPECIAL, FAM-PLATFORM-INFRA, FAM-ARCHITECTURE-TECH, FAM-ARCHITECTURE-BIZ, FAM-DATA, FAM-QA, FAM-SECURITY, FAM-OPS-DELIVERY, FAM-GTM-GROWTH, FAM-GTM-SALES, FAM-REVOPS, FAM-LEGAL`
|
||||
- 티어 3개: `light, standard, heavy` / 모드 2개: `divergent, converge`
|
||||
|
||||
---
|
||||
|
||||
## File Structure
|
||||
|
||||
| 파일 | 책임 | 신규/수정 |
|
||||
|---|---|---|
|
||||
| `org-os/00-role-registry/capability-families.yaml` | 62 role → 26 패밀리 매핑 | 신규 (Task 1) |
|
||||
| `org-os/00-role-registry/lens-registry.yaml` | 11 렌즈 정의 + 렌즈↔패밀리 | 신규 (Task 2) |
|
||||
| `org-os/06-agent-work/governance-tiers.yaml` | 위험→티어 파생 + 티어별 요구 | 신규 (Task 3) |
|
||||
| `org-os/06-agent-work/execution-policy.yaml` | 파이프라인·병렬감사·재적재 제어 | 신규 (Task 4) |
|
||||
| `org-os/06-agent-work/collaboration-modes.yaml` | 발산/수렴 실행형태 | 신규 (Task 5) |
|
||||
| `org-os/00-role-registry/role-selection-scorecard.yaml` | mode/tier/lens 필드·규칙 | 수정 (Task 6) |
|
||||
| `org-os/06-agent-work/context-package-spec.yaml` | mode/tier/lens 필드 | 수정 (Task 6) |
|
||||
| `org-os/00-role-registry/state-transition-rules.yaml` | 상태어휘 정합 + tier-modifiers | 수정 (Task 7) |
|
||||
| `org-os/README.md` | 신규 파일 등재 + 03-products 정리 | 수정 (Task 8) |
|
||||
|
||||
의존 순서: Task 1(families) → Task 2(lenses, families 참조) → Task 3,4(독립) → Task 5(lenses·execution 참조) → Task 6,7(기존 파일) → Task 8(README + 통합 게이트).
|
||||
|
||||
---
|
||||
|
||||
## Task 0: 리포지토리 준비
|
||||
|
||||
**Files:** 없음 (환경 초기화)
|
||||
|
||||
- [ ] **Step 1: git 저장소 초기화**
|
||||
|
||||
Run:
|
||||
```bash
|
||||
cd /home/donghyeon/dev/company-haness
|
||||
git init && git add -A && git commit -m "chore: baseline org-os spec before collaboration overlay"
|
||||
```
|
||||
Expected: `Initialized empty Git repository ...` 후 baseline 커밋 생성. (이미 repo면 `git init`은 무해.)
|
||||
|
||||
- [ ] **Step 2: pyyaml 확인**
|
||||
|
||||
Run: `python3 -c "import yaml; print(yaml.__version__)"`
|
||||
Expected: `6.0.1` (또는 임의 버전 출력). 실패 시 `pip install pyyaml`.
|
||||
|
||||
- [ ] **Step 3: 검증 헬퍼 위치 확인 (scratchpad, 비커밋)**
|
||||
|
||||
Run: `mkdir -p /tmp/orgos-verify && echo ok`
|
||||
Expected: `ok`. 이후 모든 검증 python은 이 경로에 임시 저장하며 **repo에 커밋하지 않는다**.
|
||||
|
||||
---
|
||||
|
||||
## Task 1: capability-families.yaml (62 → 26 패밀리)
|
||||
|
||||
**Files:**
|
||||
- Create: `org-os/00-role-registry/capability-families.yaml`
|
||||
- Verify(temp): `/tmp/orgos-verify/check_families.py`
|
||||
|
||||
**Interfaces:**
|
||||
- Consumes: `org-os/00-role-registry/roles.yaml` (role-id 집합)
|
||||
- Produces: `family-id` 26개 + 각 패밀리의 `member-role-ids`, `carries-lenses`, `audit-capable` — Task 2/5/6에서 참조.
|
||||
|
||||
- [ ] **Step 1: 실패하는 검증 작성**
|
||||
|
||||
Create `/tmp/orgos-verify/check_families.py`:
|
||||
```python
|
||||
import yaml, sys
|
||||
ROOT = "/home/donghyeon/dev/company-haness/org-os/00-role-registry"
|
||||
roles = yaml.safe_load(open(f"{ROOT}/roles.yaml"))
|
||||
role_ids = {r["role-id"] for r in roles["role-registry"]["roles"]}
|
||||
fam = yaml.safe_load(open(f"{ROOT}/capability-families.yaml"))
|
||||
families = fam["capability-families"]["families"]
|
||||
mapped = [rid for f in families for rid in f["member-role-ids"]]
|
||||
assert len(families) == 26, f"expected 26 families, got {len(families)}"
|
||||
assert len(mapped) == len(set(mapped)), "duplicate role in families"
|
||||
assert set(mapped) == role_ids, f"mismatch: missing={role_ids-set(mapped)} extra={set(mapped)-role_ids}"
|
||||
print("OK families:", len(families), "roles:", len(mapped))
|
||||
```
|
||||
Run: `python3 /tmp/orgos-verify/check_families.py`
|
||||
Expected: FAIL — `FileNotFoundError: capability-families.yaml`.
|
||||
|
||||
- [ ] **Step 2: 파일 작성**
|
||||
|
||||
Create `org-os/00-role-registry/capability-families.yaml`:
|
||||
```yaml
|
||||
capability-families:
|
||||
version: 1
|
||||
purpose: >
|
||||
62개 참조 role(roles.yaml)을 실제 인스턴스화·라우팅 단위인 26개 패밀리로 묶는다.
|
||||
같은 렌즈/역량을 공유하는 role만 한 패밀리로 묶으며, 서로 다른 렌즈는 병합하지 않는다.
|
||||
source-of-roles: org-os/00-role-registry/roles.yaml
|
||||
reference-taxonomy-preserved: true
|
||||
family-count: 26
|
||||
role-count-covered: 62
|
||||
rules:
|
||||
- 모든 role-id는 정확히 하나의 패밀리에 속한다(중복·누락 금지).
|
||||
- 서로 다른 lens를 carry하는 role은 같은 패밀리로 병합하지 않는다(lens-registry R1).
|
||||
- audit-capable=true 패밀리만 감사/검증 역할로 배정할 수 있다.
|
||||
- 임원 8개 패밀리는 각자 distinct 렌즈라 통합하지 않는다(다양성 보존).
|
||||
families:
|
||||
- { family-id: FAM-CEO, member-role-ids: [EXEC-CEO], carries-lenses: [LENS-VALUE], audit-capable: false, default-team-types: [Leadership], instantiation-priority: mvp }
|
||||
- { family-id: FAM-ORCH, member-role-ids: [OPS-ORCH], carries-lenses: [], audit-capable: false, default-team-types: [Operations], instantiation-priority: mvp }
|
||||
- { family-id: FAM-CTO, member-role-ids: [EXEC-CTO], carries-lenses: [LENS-TECH], audit-capable: false, default-team-types: [Leadership, Platform], instantiation-priority: mvp }
|
||||
- { family-id: FAM-CPO, member-role-ids: [EXEC-CPO], carries-lenses: [LENS-PRODUCT], audit-capable: false, default-team-types: [Leadership, Stream-aligned], instantiation-priority: mvp }
|
||||
- { family-id: FAM-CFO, member-role-ids: [EXEC-CFO], carries-lenses: [LENS-FINANCE], audit-capable: false, default-team-types: [Leadership, Enabling], instantiation-priority: mvp }
|
||||
- { family-id: FAM-COO, member-role-ids: [EXEC-COO], carries-lenses: [LENS-OPS], audit-capable: false, default-team-types: [Leadership, Enabling], instantiation-priority: standard }
|
||||
- { family-id: FAM-CPTO, member-role-ids: [EXEC-CPTO], carries-lenses: [LENS-INTEGRATION], audit-capable: false, default-team-types: [Leadership], instantiation-priority: standard }
|
||||
- { family-id: FAM-VPENG, member-role-ids: [EXEC-VPENG], carries-lenses: [LENS-TECH], audit-capable: true, default-team-types: [Leadership, Enabling], instantiation-priority: mvp }
|
||||
- { family-id: FAM-PRODUCT-MGMT, member-role-ids: [PROD-PM, PROD-PO, PROD-TPO, PROD-PPO], carries-lenses: [LENS-PRODUCT], audit-capable: false, default-team-types: [Stream-aligned, Complicated Subsystem, Platform], instantiation-priority: mvp }
|
||||
- { family-id: FAM-UX-RESEARCH, member-role-ids: [UX-RESEARCHER, DATA-ANALYST], carries-lenses: [LENS-CUSTOMER], audit-capable: false, default-team-types: [Enabling, Stream-aligned], instantiation-priority: standard }
|
||||
- { family-id: FAM-DESIGN, member-role-ids: [DES-PROD, DES-PLATFORM, DES-INTERNAL], carries-lenses: [LENS-CUSTOMER], audit-capable: false, default-team-types: [Stream-aligned, Platform], instantiation-priority: standard }
|
||||
- { family-id: FAM-STRATEGY, member-role-ids: [STR-ANALYST], carries-lenses: [LENS-VALUE, LENS-FINANCE], audit-capable: false, default-team-types: [Enabling], instantiation-priority: standard }
|
||||
- { family-id: FAM-ENG-FRONTEND, member-role-ids: [ENG-FE, ENG-FEPLAT, ENG-FEUX], carries-lenses: [LENS-TECH], audit-capable: false, default-team-types: [Stream-aligned, Platform], instantiation-priority: mvp }
|
||||
- { family-id: FAM-ENG-BACKEND, member-role-ids: [ENG-BE, ENG-BEGEN, ENG-PRODSERVER, ENG-PLATSERVER, ENG-PRODUCTMINDED, ENG-SW], carries-lenses: [LENS-TECH], audit-capable: false, default-team-types: [Stream-aligned, Platform], instantiation-priority: mvp }
|
||||
- { family-id: FAM-ENG-SPECIAL, member-role-ids: [ENG-DESKTOP, ENG-PRODCHAPTER], carries-lenses: [LENS-TECH], audit-capable: false, default-team-types: [Complicated Subsystem, Platform], instantiation-priority: later }
|
||||
- { family-id: FAM-PLATFORM-INFRA, member-role-ids: [INFRA-DEV, INFRA-PLATFORM, INFRA-DEVOPS, SRE, SEC-DEVSECOPS], carries-lenses: [LENS-TECH, LENS-SECURITY], audit-capable: true, default-team-types: [Platform], instantiation-priority: standard }
|
||||
- { family-id: FAM-ARCHITECTURE-TECH, member-role-ids: [ARCH-EA, ARCH-SOLUTION, ARCH-APP, ARCH-TECH, ARCH-IT, ARCH-SYSANALYST, ARCH-SWAT], carries-lenses: [LENS-TECH], audit-capable: true, default-team-types: [Complicated Subsystem, Enabling, Platform], instantiation-priority: standard }
|
||||
- { family-id: FAM-ARCHITECTURE-BIZ, member-role-ids: [ARCH-BA, ARCH-BIZANALYST], carries-lenses: [LENS-OPS, LENS-VALUE], audit-capable: false, default-team-types: [Enabling], instantiation-priority: later }
|
||||
- { family-id: FAM-DATA, member-role-ids: [ARCH-DATA, DATA-ENGINEER, DATA-BIGDATA], carries-lenses: [LENS-TECH], audit-capable: false, default-team-types: [Platform, Complicated Subsystem], instantiation-priority: standard }
|
||||
- { family-id: FAM-QA, member-role-ids: [QA], carries-lenses: [], audit-capable: true, default-team-types: [Enabling, Stream-aligned], instantiation-priority: mvp }
|
||||
- { family-id: FAM-SECURITY, member-role-ids: [SEC-ENGINEER, SEC-APPSEC, SEC-CHAMPION], carries-lenses: [LENS-SECURITY], audit-capable: true, default-team-types: [Enabling, Complicated Subsystem, Stream-aligned], instantiation-priority: standard }
|
||||
- { family-id: FAM-OPS-DELIVERY, member-role-ids: [OPS-CH, OPS-CREW], carries-lenses: [LENS-OPS, LENS-CUSTOMER], audit-capable: false, default-team-types: [Stream-aligned], instantiation-priority: later }
|
||||
- { family-id: FAM-GTM-GROWTH, member-role-ids: [GTM-GROWTHPM, GTM-DEMANDGEN, GTM-PMM, GTM-CI], carries-lenses: [LENS-REVENUE], audit-capable: false, default-team-types: [GTM Revenue, Stream-aligned, Enabling], instantiation-priority: standard }
|
||||
- { family-id: FAM-GTM-SALES, member-role-ids: [GTM-SALES, GTM-CS, GTM-PARTNER], carries-lenses: [LENS-REVENUE, LENS-CUSTOMER], audit-capable: false, default-team-types: [GTM Revenue, Stream-aligned], instantiation-priority: standard }
|
||||
- { family-id: FAM-REVOPS, member-role-ids: [GTM-REVOPS, GTM-PRICING], carries-lenses: [LENS-REVENUE, LENS-FINANCE], audit-capable: false, default-team-types: [GTM Revenue, Platform, Enabling], instantiation-priority: mvp }
|
||||
- { family-id: FAM-LEGAL, member-role-ids: [GTM-LEGAL], carries-lenses: [LENS-LEGAL], audit-capable: true, default-team-types: [GTM Revenue, Enabling], instantiation-priority: standard }
|
||||
```
|
||||
|
||||
- [ ] **Step 3: 검증 통과 확인**
|
||||
|
||||
Run: `python3 /tmp/orgos-verify/check_families.py`
|
||||
Expected: PASS — `OK families: 26 roles: 62`
|
||||
|
||||
- [ ] **Step 4: 커밋**
|
||||
|
||||
```bash
|
||||
git add org-os/00-role-registry/capability-families.yaml
|
||||
git commit -m "feat(org-os): add capability-families overlay (62 roles -> 26 families)"
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Task 2: lens-registry.yaml (11 불가침 렌즈)
|
||||
|
||||
**Files:**
|
||||
- Create: `org-os/00-role-registry/lens-registry.yaml`
|
||||
- Verify(temp): `/tmp/orgos-verify/check_lenses.py`
|
||||
|
||||
**Interfaces:**
|
||||
- Consumes: Task 1의 `capability-families.yaml` (`carries-lenses` 역방향)
|
||||
- Produces: `lens-id` 11개 + 각 렌즈 `carrier-families` — Task 5/6에서 참조.
|
||||
|
||||
- [ ] **Step 1: 실패하는 검증 작성**
|
||||
|
||||
Create `/tmp/orgos-verify/check_lenses.py`:
|
||||
```python
|
||||
import yaml
|
||||
ROOT = "/home/donghyeon/dev/company-haness/org-os/00-role-registry"
|
||||
fam = yaml.safe_load(open(f"{ROOT}/capability-families.yaml"))["capability-families"]["families"]
|
||||
lens = yaml.safe_load(open(f"{ROOT}/lens-registry.yaml"))["lens-registry"]
|
||||
lenses = {l["lens-id"]: l for l in lens["lenses"]}
|
||||
fam_ids = {f["family-id"] for f in fam}
|
||||
# invert families -> lens -> carriers
|
||||
inv = {}
|
||||
for f in fam:
|
||||
for L in f["carries-lenses"]:
|
||||
inv.setdefault(L, set()).add(f["family-id"])
|
||||
assert len(lenses) == 11, f"expected 11 lenses, got {len(lenses)}"
|
||||
for lid, l in lenses.items():
|
||||
carriers = set(l.get("carrier-families", []))
|
||||
# LENS-CONTRARIAN is rotation-based: allowed to be empty/special
|
||||
if lid == "LENS-CONTRARIAN":
|
||||
continue
|
||||
assert carriers, f"{lid} has no carrier"
|
||||
assert carriers <= fam_ids, f"{lid} carriers not in families: {carriers-fam_ids}"
|
||||
assert carriers == inv.get(lid, set()), f"{lid} carrier mismatch: registry={carriers} families={inv.get(lid)}"
|
||||
print("OK lenses:", len(lenses))
|
||||
```
|
||||
Run: `python3 /tmp/orgos-verify/check_lenses.py`
|
||||
Expected: FAIL — `FileNotFoundError: lens-registry.yaml`.
|
||||
|
||||
- [ ] **Step 2: 파일 작성**
|
||||
|
||||
Create `org-os/00-role-registry/lens-registry.yaml`:
|
||||
```yaml
|
||||
lens-registry:
|
||||
version: 1
|
||||
purpose: >
|
||||
서로 구별되는 11개 평가 렌즈를 다양성의 바닥으로 고정한다.
|
||||
다양성은 렌즈 수에서 나오며 role headcount가 아니다. 효율화(패밀리 통합)는 이 바닥을 줄이지 않는다.
|
||||
source-document: org-os/00-role-registry/team-topology-map.yaml (executive-balance)
|
||||
rules:
|
||||
- R1. 패밀리 통합 시 서로 다른 lens는 절대 병합 금지. 같은 lens의 중복 role만 합친다.
|
||||
- R2. divergent 모드는 tier별 최소 렌즈 수 이상을 병렬로 커버해야 한다.
|
||||
- R3. converge 모드(특히 heavy)는 렌즈 의견을 하나로 뭉치지 말고 트레이드오프째 노출한다.
|
||||
- R4. LENS-CONTRARIAN 담당 패밀리는 해당 옵션을 작성한 패밀리와 달라야 한다(이해상충 방지).
|
||||
lenses:
|
||||
- { lens-id: LENS-VALUE, name: 장기가치, question: 장기 회사가치·포트폴리오 적합성?, carrier-families: [FAM-CEO, FAM-STRATEGY, FAM-ARCHITECTURE-BIZ], primary: FAM-CEO }
|
||||
- { lens-id: LENS-TECH, name: 기술, question: 아키텍처·안정성·확장성·기술부채?, carrier-families: [FAM-CTO, FAM-VPENG, FAM-ENG-FRONTEND, FAM-ENG-BACKEND, FAM-ENG-SPECIAL, FAM-PLATFORM-INFRA, FAM-ARCHITECTURE-TECH, FAM-DATA], primary: FAM-CTO }
|
||||
- { lens-id: LENS-PRODUCT, name: 제품, question: 고객문제·제품가치·로드맵·P/L?, carrier-families: [FAM-CPO, FAM-PRODUCT-MGMT], primary: FAM-CPO }
|
||||
- { lens-id: LENS-FINANCE, name: 재무, question: 비용·ROI·자본효율·기회비용?, carrier-families: [FAM-CFO, FAM-STRATEGY, FAM-REVOPS], primary: FAM-CFO }
|
||||
- { lens-id: LENS-OPS, name: 운영, question: 운영타당성·프로세스·지원부담?, carrier-families: [FAM-COO, FAM-OPS-DELIVERY, FAM-ARCHITECTURE-BIZ], primary: FAM-COO }
|
||||
- { lens-id: LENS-INTEGRATION, name: 제품기술통합, question: 제품-기술 통합·충돌 감소?, carrier-families: [FAM-CPTO], primary: FAM-CPTO }
|
||||
- { lens-id: LENS-SECURITY, name: 보안, question: 위협·shift-left·데이터 무결성?, carrier-families: [FAM-SECURITY, FAM-PLATFORM-INFRA], primary: FAM-SECURITY }
|
||||
- { lens-id: LENS-LEGAL, name: 법무, question: 계약·컴플라이언스·프라이버시?, carrier-families: [FAM-LEGAL], primary: FAM-LEGAL }
|
||||
- { lens-id: LENS-CUSTOMER, name: 고객, question: 사용자 리서치·고객의 소리·경험?, carrier-families: [FAM-UX-RESEARCH, FAM-DESIGN, FAM-GTM-SALES, FAM-OPS-DELIVERY], primary: FAM-UX-RESEARCH }
|
||||
- { lens-id: LENS-REVENUE, name: 매출, question: 매출영향·GTM motion·lead-to-cash?, carrier-families: [FAM-REVOPS, FAM-GTM-GROWTH, FAM-GTM-SALES], primary: FAM-REVOPS }
|
||||
- { lens-id: LENS-CONTRARIAN, name: 역발상, question: 이걸 하지 말아야 할 이유·무엇이 깨지나?, carrier-families: [], carrier-policy: rotation-any-audit-capable-non-authoring-family, primary: null }
|
||||
```
|
||||
|
||||
- [ ] **Step 3: 검증 통과 확인**
|
||||
|
||||
Run: `python3 /tmp/orgos-verify/check_lenses.py`
|
||||
Expected: PASS — `OK lenses: 11`
|
||||
|
||||
- [ ] **Step 4: 커밋**
|
||||
|
||||
```bash
|
||||
git add org-os/00-role-registry/lens-registry.yaml
|
||||
git commit -m "feat(org-os): add lens-registry overlay (11 inviolable lenses)"
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Task 3: governance-tiers.yaml (경량/표준/중대 티어)
|
||||
|
||||
**Files:**
|
||||
- Create: `org-os/06-agent-work/governance-tiers.yaml`
|
||||
- Verify(temp): `/tmp/orgos-verify/check_tiers.py`
|
||||
|
||||
**Interfaces:**
|
||||
- Produces: `tiers.{light,standard,heavy}` + `derivation` — Task 5/7에서 참조.
|
||||
|
||||
- [ ] **Step 1: 실패하는 검증 작성**
|
||||
|
||||
Create `/tmp/orgos-verify/check_tiers.py`:
|
||||
```python
|
||||
import yaml
|
||||
P = "/home/donghyeon/dev/company-haness/org-os/06-agent-work/governance-tiers.yaml"
|
||||
g = yaml.safe_load(open(P))["governance-tiers"]
|
||||
tiers = g["tiers"]
|
||||
assert set(tiers) == {"light", "standard", "heavy"}, f"tiers={set(tiers)}"
|
||||
for t in tiers.values():
|
||||
assert "converge" in t and "divergent" in t, "tier missing converge/divergent"
|
||||
assert g["derivation"]["rule"]["base"]["High"] == "heavy"
|
||||
assert g["derivation"]["rule"]["base"]["Critical"] == "heavy"
|
||||
hg = tiers["heavy"]["converge"]["human-gate"]["human-decider-when"]
|
||||
assert "risk-High-or-Critical" in hg and "blast-production-customer-revenue" in hg
|
||||
print("OK tiers:", list(tiers))
|
||||
```
|
||||
Run: `python3 /tmp/orgos-verify/check_tiers.py`
|
||||
Expected: FAIL — `FileNotFoundError`.
|
||||
|
||||
- [ ] **Step 2: 파일 작성**
|
||||
|
||||
Create `org-os/06-agent-work/governance-tiers.yaml`:
|
||||
```yaml
|
||||
governance-tiers:
|
||||
version: 1
|
||||
purpose: 위험도에 비례해 협업 의식의 무게를 조절한다. HEAVY는 기존 DRAI 동작과 동일.
|
||||
backward-compatibility: >
|
||||
TIER-HEAVY == 기존 drai-matrix + state-transition Approved 조건. 기존 High/Critical 경로는 자동으로 HEAVY.
|
||||
derivation:
|
||||
inputs:
|
||||
risk-level: [Low, Med, High, Critical]
|
||||
reversibility: [two-way-door, one-way-door]
|
||||
blast-radius: [single-role, cross-team, production-customer-revenue]
|
||||
rule:
|
||||
base: { Low: light, Med: standard, High: heavy, Critical: heavy }
|
||||
modifiers:
|
||||
- { if: reversibility-is-one-way-door, effect: bump-up-one-level }
|
||||
- { if: blast-radius-is-cross-team, effect: bump-up-one-level }
|
||||
hard-floor:
|
||||
- { if: blast-radius-is-production-customer-revenue, effect: min-tier-heavy }
|
||||
cap: heavy
|
||||
no-auto-downgrade-below: base
|
||||
human-can-escalate-up: true
|
||||
examples:
|
||||
- { risk: Low, reversibility: one-way-door, blast: single-role, result: standard }
|
||||
- { risk: Med, reversibility: one-way-door, blast: cross-team, result: heavy }
|
||||
- { risk: Low, reversibility: two-way-door, blast: single-role, result: light }
|
||||
tiers:
|
||||
light:
|
||||
converge:
|
||||
deciders: [owner-role-agent]
|
||||
reviewers: 1
|
||||
auditors: 0
|
||||
auditor-added-when: [security, legal, privacy]
|
||||
evidence-grade-min: E2
|
||||
human: not-required
|
||||
divergent: { min-distinct-lenses: 3, contrarian-required: false, synthesis: 1 }
|
||||
wave-execution: pipeline
|
||||
standard:
|
||||
converge:
|
||||
deciders: [decider-role-agent]
|
||||
recommenders: parallel
|
||||
auditors: 1
|
||||
evidence-grade-min: E3
|
||||
human: informed-non-blocking
|
||||
divergent: { min-distinct-lenses: 5, contrarian-required: true, synthesis: 1 }
|
||||
wave-execution: pipeline
|
||||
heavy:
|
||||
converge:
|
||||
drai: full-per-drai-matrix
|
||||
audit-fanout: { min-independent-verifiers: 3, kill-on: majority-refute }
|
||||
evidence-grade-min: E3
|
||||
unresolved-critical-risks: false
|
||||
human-gate:
|
||||
human-decider-when: [risk-High-or-Critical, blast-production-customer-revenue]
|
||||
else: { decider: EXEC-CEO, human: informed-non-blocking }
|
||||
divergent: { min-distinct-lenses: all-relevant, contrarian-required: true, synthesis: tradeoff-matrix }
|
||||
wave-execution: pipeline-with-barrier-at-synthesis
|
||||
```
|
||||
|
||||
- [ ] **Step 3: 검증 통과 확인**
|
||||
|
||||
Run: `python3 /tmp/orgos-verify/check_tiers.py`
|
||||
Expected: PASS — `OK tiers: ['light', 'standard', 'heavy']`
|
||||
|
||||
- [ ] **Step 4: 커밋**
|
||||
|
||||
```bash
|
||||
git add org-os/06-agent-work/governance-tiers.yaml
|
||||
git commit -m "feat(org-os): add governance-tiers overlay (light/standard/heavy)"
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Task 4: execution-policy.yaml (파이프라인·병렬감사)
|
||||
|
||||
**Files:**
|
||||
- Create: `org-os/06-agent-work/execution-policy.yaml`
|
||||
- Verify(temp): `/tmp/orgos-verify/check_exec.py`
|
||||
|
||||
**Interfaces:**
|
||||
- Produces: `pipeline-default`, `parallel-audit-fanout`, `re-hydration-control` — Task 5에서 참조.
|
||||
|
||||
- [ ] **Step 1: 실패하는 검증 작성**
|
||||
|
||||
Create `/tmp/orgos-verify/check_exec.py`:
|
||||
```python
|
||||
import yaml
|
||||
P = "/home/donghyeon/dev/company-haness/org-os/06-agent-work/execution-policy.yaml"
|
||||
e = yaml.safe_load(open(P))["execution-policy"]
|
||||
assert e["pipeline-default"] is True
|
||||
assert e["parallel-audit-fanout"]["min-independent-verifiers"] >= 3
|
||||
assert e["wave"]["semantics"] == "concurrency-cap-not-barrier"
|
||||
assert "divergent-synthesis" in e["barrier-allowed-only-when"]
|
||||
print("OK execution-policy")
|
||||
```
|
||||
Run: `python3 /tmp/orgos-verify/check_exec.py`
|
||||
Expected: FAIL — `FileNotFoundError`.
|
||||
|
||||
- [ ] **Step 2: 파일 작성**
|
||||
|
||||
Create `org-os/06-agent-work/execution-policy.yaml`:
|
||||
```yaml
|
||||
execution-policy:
|
||||
version: 1
|
||||
purpose: wave를 배리어가 아닌 파이프라인으로 실행하고, 감사를 병렬화하며, 재적재 비용을 통제한다.
|
||||
pipeline-default: true
|
||||
barrier-allowed-only-when:
|
||||
- divergent-synthesis
|
||||
- dedup-across-all-findings
|
||||
- early-exit-on-zero
|
||||
- cross-item-comparison-required
|
||||
wave:
|
||||
max-concurrent-role-agents: 5
|
||||
semantics: concurrency-cap-not-barrier
|
||||
note: scorecard의 wave-size 5는 동시성 상한이며 wave 완료를 기다리는 배리어가 아니다.
|
||||
parallel-audit-fanout:
|
||||
applies-to-tier: heavy
|
||||
min-independent-verifiers: 3
|
||||
verifier-prompt-stance: refute
|
||||
verifier-lens-diversity: required
|
||||
kill-on: majority-refute
|
||||
on-kill: set-state-Blocked
|
||||
verifier-independence:
|
||||
rule: 검증자 패밀리는 자기 패밀리가 작성한 산출물을 검증할 수 없다
|
||||
source: roles.yaml independent-audit-policy 이해상충 규칙과 정합
|
||||
re-hydration-control:
|
||||
pass-forward: structured-summary-and-evidence-links-only
|
||||
forbid: raw-logs
|
||||
enforce: org-os/06-agent-work/context-package-spec.yaml compression-policy
|
||||
```
|
||||
|
||||
- [ ] **Step 3: 검증 통과 확인**
|
||||
|
||||
Run: `python3 /tmp/orgos-verify/check_exec.py`
|
||||
Expected: PASS — `OK execution-policy`
|
||||
|
||||
- [ ] **Step 4: 커밋**
|
||||
|
||||
```bash
|
||||
git add org-os/06-agent-work/execution-policy.yaml
|
||||
git commit -m "feat(org-os): add execution-policy overlay (pipeline + parallel audit)"
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Task 5: collaboration-modes.yaml (발산/수렴)
|
||||
|
||||
**Files:**
|
||||
- Create: `org-os/06-agent-work/collaboration-modes.yaml`
|
||||
- Verify(temp): `/tmp/orgos-verify/check_modes.py`
|
||||
|
||||
**Interfaces:**
|
||||
- Consumes: Task 2(lens-registry), Task 3(governance-tiers), Task 4(execution-policy)
|
||||
- Produces: `modes.{divergent,converge}` — Task 6에서 scorecard가 참조.
|
||||
|
||||
- [ ] **Step 1: 실패하는 검증 작성**
|
||||
|
||||
Create `/tmp/orgos-verify/check_modes.py`:
|
||||
```python
|
||||
import yaml
|
||||
P = "/home/donghyeon/dev/company-haness/org-os/06-agent-work/collaboration-modes.yaml"
|
||||
m = yaml.safe_load(open(P))["collaboration-modes"]
|
||||
assert set(m["modes"]) == {"divergent", "converge"}, f"modes={set(m['modes'])}"
|
||||
assert m["mode-selection"]["declared-at"] == "intake"
|
||||
d = m["modes"]["divergent"]
|
||||
assert d["synthesis"]["must-not"], "divergent synthesis must forbid merging/deciding"
|
||||
assert d["barrier"] == "allowed"
|
||||
print("OK modes:", list(m["modes"]))
|
||||
```
|
||||
Run: `python3 /tmp/orgos-verify/check_modes.py`
|
||||
Expected: FAIL — `FileNotFoundError`.
|
||||
|
||||
- [ ] **Step 2: 파일 작성**
|
||||
|
||||
Create `org-os/06-agent-work/collaboration-modes.yaml`:
|
||||
```yaml
|
||||
collaboration-modes:
|
||||
version: 1
|
||||
purpose: 발산(아이디어 생성)과 수렴(결정·승인)을 분리해 각각 최적 실행형태로 돌린다.
|
||||
mode-selection:
|
||||
declared-at: intake
|
||||
declared-by: EXEC-CEO
|
||||
values: [divergent, converge]
|
||||
default: converge
|
||||
modes:
|
||||
divergent:
|
||||
goal: 다양한 옵션·아이디어 생성
|
||||
mechanism: per-lens-parallel-fanout
|
||||
fanout:
|
||||
assign: 각 에이전트에 서로 다른 lens와 divergent-framing 부여
|
||||
source-of-lenses: org-os/00-role-registry/lens-registry.yaml
|
||||
min-distinct-lenses: from-governance-tiers
|
||||
contrarian: LENS-CONTRARIAN 포함(티어 규칙에 따름), 옵션 작성 패밀리와 다른 패밀리가 담당
|
||||
synthesis:
|
||||
role: 합성 에이전트 1명
|
||||
must: 옵션 수집·정리, 렌즈별 트레이드오프 노출
|
||||
must-not: 단일 추천으로 병합하거나 결정하기
|
||||
barrier: allowed
|
||||
output: option-set (옵션별 lens 트레이드오프)
|
||||
converge:
|
||||
goal: 책임소재 있는 결정·승인
|
||||
mechanism: tier-weighted-DRAI
|
||||
execution: { recommenders: parallel, auditors: parallel-when-heavy, decider: consumes }
|
||||
output: decision-record (선택 옵션 + 인정된 트레이드오프 + dissent 기록)
|
||||
rule: High/Critical → 인간 decider (governance-tiers human-gate 준수)
|
||||
two-phase:
|
||||
divergent-then-converge:
|
||||
when: 사용자가 아이디어 후 결정을 함께 원할 때
|
||||
execution: pipeline (발산 option-set → 수렴 입력)
|
||||
```
|
||||
|
||||
- [ ] **Step 3: 검증 통과 확인**
|
||||
|
||||
Run: `python3 /tmp/orgos-verify/check_modes.py`
|
||||
Expected: PASS — `OK modes: ['divergent', 'converge']`
|
||||
|
||||
- [ ] **Step 4: 커밋**
|
||||
|
||||
```bash
|
||||
git add org-os/06-agent-work/collaboration-modes.yaml
|
||||
git commit -m "feat(org-os): add collaboration-modes overlay (divergent/converge)"
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Task 6: scorecard + context-package 참조 배선
|
||||
|
||||
**Files:**
|
||||
- Modify: `org-os/00-role-registry/role-selection-scorecard.yaml`
|
||||
- Modify: `org-os/06-agent-work/context-package-spec.yaml`
|
||||
- Verify(temp): `/tmp/orgos-verify/check_wiring.py`
|
||||
|
||||
**Interfaces:**
|
||||
- Consumes: Task 3(tier), Task 5(mode), Task 2(lens)
|
||||
- Produces: scorecard output-template의 `mode/tier/assigned-lens/lens-coverage`, context-package의 동일 필드.
|
||||
|
||||
- [ ] **Step 1: 실패하는 검증 작성**
|
||||
|
||||
Create `/tmp/orgos-verify/check_wiring.py`:
|
||||
```python
|
||||
import yaml
|
||||
R = "/home/donghyeon/dev/company-haness/org-os"
|
||||
sc = yaml.safe_load(open(f"{R}/00-role-registry/role-selection-scorecard.yaml"))["role-selection-scorecard"]
|
||||
ot = sc["output-template"]
|
||||
for k in ["mode", "tier", "assigned-lens", "lens-coverage"]:
|
||||
assert k in ot, f"scorecard output-template missing {k}"
|
||||
hr = "\n".join(sc["hard-rules"])
|
||||
assert "mode" in hr and "tier" in hr and "lens" in hr, "scorecard hard-rules missing mode/tier/lens rule"
|
||||
cp = yaml.safe_load(open(f"{R}/06-agent-work/context-package-spec.yaml"))["context-package-spec"]
|
||||
for k in ["mode", "tier", "assigned-lens", "divergent-framing"]:
|
||||
assert k in cp["schema"], f"context-package schema missing {k}"
|
||||
print("OK wiring")
|
||||
```
|
||||
Run: `python3 /tmp/orgos-verify/check_wiring.py`
|
||||
Expected: FAIL — `AssertionError: scorecard output-template missing mode`.
|
||||
|
||||
- [ ] **Step 2: scorecard output-template에 필드 추가**
|
||||
|
||||
`org-os/00-role-registry/role-selection-scorecard.yaml`의 `output-template:` 블록에서 마지막 `reason:` 줄 아래에 다음을 같은 들여쓰기로 추가:
|
||||
```yaml
|
||||
mode: divergent / converge
|
||||
tier: light / standard / heavy
|
||||
assigned-lens:
|
||||
lens-coverage:
|
||||
```
|
||||
|
||||
- [ ] **Step 3: scorecard hard-rules에 규칙 추가**
|
||||
|
||||
같은 파일의 `hard-rules:` 리스트 끝에 다음 3개 항목 추가(기존 항목과 같은 `- ` 들여쓰기):
|
||||
```yaml
|
||||
- A workflow must declare mode and tier before the first execution wave.
|
||||
- Divergent mode must cover at least the tier's min-distinct-lenses in parallel (governance-tiers).
|
||||
- Converge heavy must expose lens tradeoffs and must not merge distinct lenses into one recommendation.
|
||||
```
|
||||
|
||||
- [ ] **Step 4: context-package-spec schema에 필드 추가**
|
||||
|
||||
`org-os/06-agent-work/context-package-spec.yaml`의 `schema:` 블록에서 `task-id:` 아래(또는 `objective:` 위)에 다음을 같은 들여쓰기로 추가:
|
||||
```yaml
|
||||
mode: divergent / converge
|
||||
tier: light / standard / heavy
|
||||
assigned-lens:
|
||||
divergent-framing:
|
||||
```
|
||||
그리고 같은 파일의 `required-fields:` 리스트에 `- mode`, `- tier` 두 줄을 추가.
|
||||
|
||||
- [ ] **Step 5: 두 파일 파싱 + 검증 통과 확인**
|
||||
|
||||
Run:
|
||||
```bash
|
||||
python3 -c "import yaml; yaml.safe_load(open('org-os/00-role-registry/role-selection-scorecard.yaml')); yaml.safe_load(open('org-os/06-agent-work/context-package-spec.yaml')); print('parse ok')"
|
||||
python3 /tmp/orgos-verify/check_wiring.py
|
||||
```
|
||||
Expected: `parse ok` 다음 `OK wiring`
|
||||
|
||||
- [ ] **Step 6: 커밋**
|
||||
|
||||
```bash
|
||||
git add org-os/00-role-registry/role-selection-scorecard.yaml org-os/06-agent-work/context-package-spec.yaml
|
||||
git commit -m "feat(org-os): wire mode/tier/lens into scorecard and context-package"
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Task 7: state-transition-rules 정합 배선
|
||||
|
||||
**Files:**
|
||||
- Modify: `org-os/00-role-registry/state-transition-rules.yaml`
|
||||
- Verify(temp): `/tmp/orgos-verify/check_states.py`
|
||||
|
||||
**Interfaces:**
|
||||
- Consumes: Task 3(governance-tiers, tier-modifiers 단일 원천)
|
||||
- Produces: `state-vocabulary-map`, `tier-modifiers` — hook 구현(후속 라운드)이 참조.
|
||||
|
||||
- [ ] **Step 1: 실패하는 검증 작성**
|
||||
|
||||
Create `/tmp/orgos-verify/check_states.py`:
|
||||
```python
|
||||
import yaml
|
||||
P = "/home/donghyeon/dev/company-haness/org-os/00-role-registry/state-transition-rules.yaml"
|
||||
s = yaml.safe_load(open(P))["state-transition-rules"]
|
||||
svm = s["state-vocabulary-map"]
|
||||
assert svm["source-of-truth"] == "workflow-stage"
|
||||
for k in ["workflow-stage", "document-state", "review-state"]:
|
||||
assert k in svm, f"missing {k}"
|
||||
assert "light" in s["tier-modifiers"] and "heavy" in s["tier-modifiers"]
|
||||
print("OK states")
|
||||
```
|
||||
Run: `python3 /tmp/orgos-verify/check_states.py`
|
||||
Expected: FAIL — `KeyError: 'state-vocabulary-map'`.
|
||||
|
||||
- [ ] **Step 2: state-vocabulary-map + tier-modifiers 블록 추가**
|
||||
|
||||
`org-os/00-role-registry/state-transition-rules.yaml`의 최상위(`transitions:` 블록 아래, 같은 `state-transition-rules:` 자식 들여쓰기 2칸)에 다음을 추가:
|
||||
```yaml
|
||||
state-vocabulary-map:
|
||||
source-of-truth: workflow-stage
|
||||
workflow-stage: [intake, discovery, design, review, implementation, verification, release, blocked, closed]
|
||||
document-state: [Draft, Review, Approved, Closed]
|
||||
review-state: [Submitted-for-Review, Accepted, Changes-Requested, Blocked]
|
||||
mapping:
|
||||
- workflow-stage가 워크플로우의 단일 원천이다.
|
||||
- 각 stage 내부에서 개별 산출물은 document-state를, 부모-자식 수용 1건은 review-state를 가진다.
|
||||
- hook은 document-state와 review-state를 전이시킨다.
|
||||
- 해당 stage의 게이팅 문서가 Approved 또는 Accepted에 도달하면 workflow-stage가 전진한다.
|
||||
tier-modifiers:
|
||||
source-of-truth: org-os/06-agent-work/governance-tiers.yaml
|
||||
light: { evidence-grade-min: E2, auditor-required: only-when-security-legal-privacy, human: not-required }
|
||||
standard: { evidence-grade-min: E3, auditor-required: true, human: informed-non-blocking }
|
||||
heavy: { evidence-grade-min: E3, auditor-required: parallel-fanout, human: gate-per-governance-tiers }
|
||||
note: 실제 값의 단일 원천은 governance-tiers.yaml이며 여기는 상태전이 관점의 참조다. HEAVY는 기존 Approved 조건과 동일.
|
||||
```
|
||||
|
||||
- [ ] **Step 3: 파싱 + 검증 통과 확인**
|
||||
|
||||
Run:
|
||||
```bash
|
||||
python3 -c "import yaml; yaml.safe_load(open('org-os/00-role-registry/state-transition-rules.yaml')); print('parse ok')"
|
||||
python3 /tmp/orgos-verify/check_states.py
|
||||
```
|
||||
Expected: `parse ok` 다음 `OK states`
|
||||
|
||||
- [ ] **Step 4: 커밋**
|
||||
|
||||
```bash
|
||||
git add org-os/00-role-registry/state-transition-rules.yaml
|
||||
git commit -m "feat(org-os): reconcile state vocabularies and reference tier-modifiers"
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Task 8: README 등재 + 전체 통합 게이트
|
||||
|
||||
**Files:**
|
||||
- Modify: `org-os/README.md`
|
||||
- Verify(temp): `/tmp/orgos-verify/check_all.py`
|
||||
|
||||
**Interfaces:**
|
||||
- Consumes: Task 1–7 모든 산출물. 최종 성공기준(스펙 §7) 게이트.
|
||||
|
||||
- [ ] **Step 1: 통합 검증 작성 (성공기준 1–6)**
|
||||
|
||||
Create `/tmp/orgos-verify/check_all.py`:
|
||||
```python
|
||||
import yaml, glob
|
||||
R = "/home/donghyeon/dev/company-haness/org-os"
|
||||
# parse all org-os yaml
|
||||
for f in glob.glob(f"{R}/**/*.yaml", recursive=True):
|
||||
yaml.safe_load(open(f))
|
||||
roles = yaml.safe_load(open(f"{R}/00-role-registry/roles.yaml"))["role-registry"]["roles"]
|
||||
role_ids = {r["role-id"] for r in roles}
|
||||
fams = yaml.safe_load(open(f"{R}/00-role-registry/capability-families.yaml"))["capability-families"]["families"]
|
||||
fam_ids = {f["family-id"] for f in fams}
|
||||
lenses = yaml.safe_load(open(f"{R}/00-role-registry/lens-registry.yaml"))["lens-registry"]["lenses"]
|
||||
lens_ids = {l["lens-id"] for l in lenses}
|
||||
# 1: 62 roles mapped exactly once
|
||||
mapped = [rid for f in fams for rid in f["member-role-ids"]]
|
||||
assert set(mapped) == role_ids and len(mapped) == len(set(mapped)) == 62
|
||||
# 2: family carries-lenses reference real lenses
|
||||
for f in fams:
|
||||
assert set(f["carries-lenses"]) <= lens_ids, f"{f['family-id']} orphan lens"
|
||||
# 3+5: every lens has >=1 carrier (except contrarian rotation) + carriers are real families
|
||||
for l in lenses:
|
||||
cf = set(l.get("carrier-families", []))
|
||||
assert cf <= fam_ids, f"{l['lens-id']} orphan family {cf-fam_ids}"
|
||||
if l["lens-id"] != "LENS-CONTRARIAN":
|
||||
assert cf, f"{l['lens-id']} no carrier"
|
||||
# 4: tier x mode all defined
|
||||
g = yaml.safe_load(open(f"{R}/06-agent-work/governance-tiers.yaml"))["governance-tiers"]["tiers"]
|
||||
assert set(g) == {"light","standard","heavy"}
|
||||
for t in g.values(): assert "converge" in t and "divergent" in t
|
||||
m = yaml.safe_load(open(f"{R}/06-agent-work/collaboration-modes.yaml"))["collaboration-modes"]["modes"]
|
||||
assert set(m) == {"divergent","converge"}
|
||||
# 6: heavy preserves human gate on High/Critical
|
||||
hg = g["heavy"]["converge"]["human-gate"]["human-decider-when"]
|
||||
assert "risk-High-or-Critical" in hg
|
||||
print("OK ALL: 62 roles, 26 families,", len(lens_ids), "lenses, tiers", set(g), "modes", set(m))
|
||||
```
|
||||
Run: `python3 /tmp/orgos-verify/check_all.py`
|
||||
Expected: 이 시점엔 README 미갱신이어도 통과해야 함(README는 검증 대상 아님). PASS — `OK ALL: 62 roles, 26 families, 11 lenses ...`. 실패 시 이전 Task로 돌아가 수정.
|
||||
|
||||
- [ ] **Step 2: README Directory Map 갱신**
|
||||
|
||||
`org-os/README.md`의 ` ```text ... ``` ` 디렉토리 맵에서:
|
||||
- `00-role-registry/` 항목 목록에 `lens-registry.yaml`, `capability-families.yaml` 두 줄 추가.
|
||||
- `06-agent-work/` 항목 목록에 `collaboration-modes.yaml`, `governance-tiers.yaml`, `execution-policy.yaml` 세 줄 추가.
|
||||
|
||||
- [ ] **Step 3: README Rules 추가**
|
||||
|
||||
`## Rules` 목록 끝에 다음 3줄 추가:
|
||||
```markdown
|
||||
- `lens-registry.yaml`는 11개 불가침 평가 렌즈의 단일 원천이며, 다양성 바닥을 정의한다.
|
||||
- 실제 인스턴스화·라우팅 단위는 `capability-families.yaml`의 26개 패밀리이고, `roles.yaml`의 62개 role은 참조 분류체계로 보존한다.
|
||||
- 협업 실행은 `collaboration-modes.yaml`(발산/수렴) × `governance-tiers.yaml`(light/standard/heavy)로 결정하며, TIER-HEAVY는 기존 DRAI 동작과 동일하다.
|
||||
```
|
||||
|
||||
- [ ] **Step 4: 03-products 드리프트 정리**
|
||||
|
||||
`## Directory Map`의 `03-products/` 항목이 정본(`{product-id}/pr-faq.md·roadmap.md·metrics.md`)임을 유지하고, Rules 목록에 다음 한 줄 추가:
|
||||
```markdown
|
||||
- `03-products` 표기는 이 README의 `{product-id}/` 구조를 정본으로 한다(Claude Code 구성 명세 문서의 `03-products/README.md` 표기는 후속 라운드에 이에 맞춘다).
|
||||
```
|
||||
|
||||
- [ ] **Step 5: 최종 파싱 + 통합 게이트 재확인**
|
||||
|
||||
Run:
|
||||
```bash
|
||||
python3 /tmp/orgos-verify/check_all.py
|
||||
```
|
||||
Expected: PASS — `OK ALL: 62 roles, 26 families, 11 lenses, tiers {'light','standard','heavy'} modes {'divergent','converge'}`
|
||||
|
||||
- [ ] **Step 6: 커밋**
|
||||
|
||||
```bash
|
||||
git add org-os/README.md
|
||||
git commit -m "docs(org-os): register overlay files and reconcile 03-products in README"
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Self-Review 결과 (작성자 점검)
|
||||
|
||||
- **Spec coverage:** 스펙 §3.1→Task2, §3.2→Task1, §3.3→Task5, §3.4→Task3, §3.5→Task4, §4.1→Task6, §4.2→Task6, §4.3→Task7, §4.4→Task8, §7 성공기준→Task8 게이트. 갭 없음.
|
||||
- **Placeholder scan:** 각 신규 파일 전체 내용과 각 수정의 정확한 삽입 블록 포함. "TBD/적절히 처리" 없음.
|
||||
- **Type consistency:** family-id 26개·lens-id 11개·tier 3개·mode 2개를 Global Constraints에 고정하고 전 Task가 동일 문자열 사용. check_all.py가 상호참조를 최종 검증.
|
||||
|
||||
## Notes
|
||||
- 검증 python은 모두 `/tmp/orgos-verify/`의 임시 파일로 **repo에 커밋하지 않는다**(범위: 명세만). 영구 validator는 후속 라운드.
|
||||
- 이 계획 완료 후 다음 라운드 입력: 스펙 §5의 흐름을 `.claude`(에이전트·command·hook)로 구현하는 thin vertical slice.
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,503 @@
|
||||
# 통합 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-selection` → `method_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.1–T1.3 |
|
||||
| **2** | P3-A 인프라(registry·gen v1/v2·gen_agents·ref/orphan/drift) | T2.1–T2.5 |
|
||||
| **3** | method_contracts.py policy engine + method-selection + activation(CLI·hash) | T3.1–T3.4 |
|
||||
| **4** | Enforcement(validate_report·spawn gate·transition gate·debt) | T4.1–T4.4 |
|
||||
| **5** | 대표 역할 계약 + golden task + active 승격 | T5(템플릿)×대표군 |
|
||||
| **6** | family wave 2–5 이행 | T6(wave 반복) |
|
||||
| **7** | cutover(참조 profile all-active·debt 0·v1 제거·재생성) | T7 |
|
||||
|
||||
**Phase 0–4 = 계약 machinery(완전 코드).** 계약 0개여도 v1 fallback으로 green. **Phase 5–7 = 계약 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 생성**
|
||||
|
||||
```bash
|
||||
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):
|
||||
```python
|
||||
#!/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`:
|
||||
```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) 그대로 이동(내용 불변). 분할은 스크립트로:
|
||||
|
||||
```python
|
||||
# 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.yaml`은 **v1 fallback로 잔존**(Phase 7서 제거).
|
||||
|
||||
- [ ] **Step 4: 통과 확인** — Run 테스트 → `✅ 파일분리 병합 75역할`.
|
||||
|
||||
- [ ] **Step 5: Commit** — `git 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)**
|
||||
```python
|
||||
_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`:
|
||||
```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`:
|
||||
```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: Commit** — `P3 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: Commit** — `P3 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 1–8을 **파일분리 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==2`면 **v2 렌더**(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 유지.
|
||||
|
||||
**핵심 렌더 함수(추가):**
|
||||
```python
|
||||
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: 작성**
|
||||
```python
|
||||
#!/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: Commit** — `P3 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: Commit** — `P3 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: Commit** — `P3 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 5–6은 **계약 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 2–5 이행
|
||||
|
||||
### 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 0–7 ↔ 본 plan Phase 0–7. §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(T5–T7). A spec: registry·gen·spine·무결성(Phase 2). 전 섹션 커버.
|
||||
|
||||
**Placeholder scan:** Phase 0–4는 완전 코드 TDD. Phase 5–7은 **의도적으로 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 0–4는 완전코드 TDD, Phase 5–7은 계약 authoring 템플릿×wave. P1·P2와 동일.
|
||||
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user