Files
company-haness/docs/superpowers/specs/2026-07-12-p1-company-venture-bootstrap-design.md
T

528 lines
33 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# P1 — Company / Venture Bootstrap (설계)
- 날짜: 2026-07-12
- 상태: 설계 확정 대기 → (승인 후) 구현 계획(writing-plans)
- 범위: 리뷰 반영 로드맵의 **P1**. 리뷰 핵심결함 #1(회사를 정의하기 전에 회사 문맥을 요구하는 순환의존) 해소.
- 관련: 리뷰 로드맵의 P0(실행 무결성, 대부분 완료·재검증)·P2(디자인 방향)·P3(프롬프트/스킬 분리)·P4(벤치마크)는 **별도 사이클**. 본 스펙은 P1만 다룬다.
---
## 1. 문제 (순환의존)
현재 cascade는 `intake → discovery → decide → design → spec → build → …`이며, `/ground`·`/decide`·`/design`은 이미 회사 방향·제품 제약(`company-context.yaml`)을 전제한다. 그런데 `company-context.yaml``status: demo`(빈 템플릿)이고 `projects: []`다. 즉:
```
아이디어를 고르려면 회사의 전략·제약이 필요함
회사 전략을 정하려면 아이디어를 먼저 골라야 함
```
지금은 이 공백을 매 intake 문장과 임시 가정으로 메우므로 아이디어 검토 결과가 일관되지 않는다.
**해소 원리:** `founder-context`(회사 정의 이전에도 사람이 채울 수 있는 유일한 입력)를 **입력**으로 하는 별도 `venture-bootstrap` plan을 두고, 그 plan의 **terminal 산출물**로 `company-context.yaml (status: provisional)`을 **생산**한다. 이후 제품 cascade는 그 산출물을 **입력으로 소비**만 한다. bootstrap 내부에서는 company-context를 요구하지 않으므로 순환이 끊긴다.
## 2. 목표 / 비목표
**목표**
- 회사 lifecycle(1회성 수립)과 제품 lifecycle(반복)을 **별도 plan**으로 분리한다.
- `founder-context.yaml`(사람 입력) → 기회탐색 → 벤처검증 → 벤처결정 → company-context commit의 강제된 stage 그래프를 만든다.
- `company-context.yaml`을 **항목별 provenance**를 갖는 facts / strategic-decisions / hypotheses 구조로 재편하고, 공식 SoT 상태 어휘를 `template|provisional|operating`(3-상태)로 교체한다(작성 중은 공식 status가 아니라 candidate-status/workflow stage로 표현 — §7.3).
- 회사 문맥 인용 상한을 **항목 단위**로 정밀화하되(전체 보고서 강등 금지), 신뢰경계(worker는 전이 불가)와 원자적 commit을 지킨다.
- 제품 cascade가 bootstrap 결과를 정확히 참조할 **진입 계약**을 정의한다(단, product-definition stage 자체는 P1에서 만들지 않는다).
**비목표(YAGNI / 이후 사이클)**
- `product-definition` stage 신설 — 제품 lifecycle 소관. seam(진입 계약)만 정의.
- 보고서별 **완전 citation-provenance 추적**(모든 보고서에서 인용 출처를 파싱해 항목별 ceiling) — 최소 형태(회사 문맥을 evidence로 포함한 보고서에만, hypothesis 인용은 Med 상한)만 구현.
- 자연어 **의미 기반** hypothesis-as-fact 오분류 판정 — Hard Fail이 아니라 Warning.
- DES-VISUAL/DES-DIRECTOR·디자인 단계(P2), skill 분리(P3), 벤치마크(P4).
---
## 3. 아키텍처 개요 — 두 lifecycle과 seam
```
Company lifecycle (1회성, plan=venture-bootstrap)
founder-context.yaml (사람)
→ opportunity-discovery
→ venture-validation
→ venture-decision (+ HUMAN acceptance receipt)
→ company-context-commit (candidate → atomic replace)
→ bootstrap-complete ⇒ 공식 company-context.yaml (status: provisional)
│ seam = company-context-ready 진입 계약
Product lifecycle (반복, plan=cascade)
selected venture → (product-definition) → design → spec → build → …
↑ company-context.yaml + venture-decision-id + company-decision-ids 를 입력으로 참조
```
핵심: 공식 `company-context.yaml`(SoT)은 bootstrap **도중에는 바뀌지 않는다**. candidate 파일에 작성·검증한 뒤, 마지막에 **한 번, 원자적으로** 교체한다(§9.3).
---
## 4. 신규/변경 아티팩트 인벤토리
| 파일 | 위치 | 성격 | 변경 |
|---|---|---|---|
| `founder-context.yaml` | `org-os/01-company/` | 사람 입력 | 신규 |
| `venture-option-spec.yaml` | `org-os/06-agent-work/` | 데이터 스키마 계약 | 신규 |
| `venture-validation-map.yaml` | `org-os/06-agent-work/` | 역할·게이트 매핑 계약 | 신규 |
| `company-context.yaml` | `org-os/01-company/` | 회사 SoT | **재구조화** |
| `state-transition-rules.yaml` | `org-os/00-role-registry/` | 전이 SSOT | venture-bootstrap 전이·조건 추가 |
| `execution-plans.yaml` | `org-os/06-agent-work/` | plan 프리셋 | `venture-bootstrap` plan 추가 |
| `ceo-intake.md` | `.claude/commands/` | 커맨드 | `--plan` 선택·founder-context 유도 |
| `venture-validate.md` | `.claude/commands/` | 커맨드 | 신규 |
| `company-bootstrap.md` | `.claude/commands/` | 커맨드 | 신규 |
| `state_engine.py` | `.claude/hooks/` | 전이 강제기 | 신규 predicate 6종 |
| `validate_report.py` | `.claude/hooks/` | 보고 검증 | status 어휘 + 항목 ceiling |
| `lint_company_context.py` | `.claude/hooks/` | 파일 린터 | 신규(Hard Fail + Warning) |
| `commit_company_context.py` | `.claude/hooks/` | trusted commit CLI | 신규(atomic replace) |
| `acceptance_log.py` / `acceptance-event.schema.json` | `.claude/hooks/`·`schemas/` | 수락 원장 | 선택 `report-sha256` 바인딩 추가 |
| `guard_tools.py` | `.claude/hooks/` | 권한 경계 | 공식 company-context.yaml 직접쓰기 보호 |
| `doctor.py` | `.claude/hooks/` | preflight | 신규 아티팩트·plan 배선 점검 |
| 테스트 | `.claude/tests/` | 단위테스트 | `test_venture_bootstrap.py`(신규) 외 |
---
## 5. `founder-context.yaml` (사람 입력)
회사 정의 이전에도 사람이 채울 수 있는 유일 입력. **여러 venture validation에서 재사용**되며, 누락되면 founder-fit 판단 전체가 무효 → 독립 stage(`founder-setup`)의 게이팅 아티팩트.
```yaml
schema-version: 1
status: template # template | filled
founder:
strengths: [backend, database, infrastructure]
available-time: "" # 예: "solo, 주 50h"
available-capital: ""
desired-business-size: "" # 예: "$1-5M ARR, solo-operable"
preferred-market: ""
distribution-capability: "" # self-serve? community? outbound?
sales-tolerance: "" # low|med|high
operation-tolerance: ""
risk-tolerance: ""
hard-constraints:
- solo-operable
- self-serve-distribution
- no-enterprise-sales-dependency
strategic-preferences:
- recurring-revenue
- technical-moat
- global-developer-market
```
- 위치: `org-os/01-company/founder-context.yaml`(회사 SoT 옆).
- `status: filled`이어야 `founder-setup → opportunity-discovery` 통과.
- 비밀/키는 두지 않는다(company-context와 동일 정책).
---
## 6. 벤처 계약 — 두 파일로 분리 (리뷰 #8)
스키마(산출물 구조)와 역할 매핑(협업 방식)은 변경 이유가 달라 분리한다.
### 6.1 `venture-option-spec.yaml` (데이터 스키마)
```yaml
venture-option-spec:
version: 1
opportunity-cluster: # opportunity-discovery 산출(제품명 이전, 문제 클러스터)
required: [id, problem-domain, target-user, triggering-event,
current-alternative, why-now, founder-fit]
venture-option: # venture-validation 산출(옵션별)
required: [id, customer, painful-job, current-alternative, wedge,
monetization, expected-price, reachable-customers,
rough-revenue-ceiling, acquisition-channel, build-cost,
operation-cost, founder-fit, defensibility, kill-criteria,
unresolved-assumptions]
notes:
- "unknown 은 허용값이다(모른다고 적을 수 있어야 한다) — 단 unresolved-assumptions 에 명시."
- "kill-criteria 는 필수(없으면 venture-validation→venture-decision 차단)."
validation-result: # 게이트별 판정 스냅샷
required: [option-id, gate, verdict, evidence, dissent]
verdict-enum: [pass, fail, unknown]
```
### 6.2 `venture-validation-map.yaml` (역할·게이트 매핑) — 리뷰 역할 보강 반영
9-게이트를 **CFO 1인이 대신할 수 없으므로**(가격/WTP/유통/획득/기술해자/운영) 역할을 보강한다. 각 게이트는 primary(작성) + contrarian/auditor(반증) + synthesis-owner를 가진다. 렌즈 다양성·이해상충 방지(작성자≠감사자).
| Gate | Primary | Contrarian/Auditor |
|---|---|---|
| 문제 강도·빈도 | UX-RESEARCHER | PROD-PM |
| 경쟁·대체재 | GTM-CI | STR-ANALYST |
| 지불 의사(WTP) | GTM-PRICING | CFO |
| 매출모델·단위경제 | CFO · GTM-REVOPS | GTM-PRICING |
| 기술 가능성·해자 | (CTO) ARCH-TECH | CFO |
| 운영 가능성 | (COO) CONSULT-OPS | ARCH-TECH |
| 유통 가능성 | GTM-GROWTHPM · GTM-SALES | CFO |
| 창업자 적합성 | EXEC-CEO | ARCH-TECH |
| 실패·중단 기준 | CFO | EXEC-CEO |
```yaml
venture-validation-map:
version: 1
synthesis-owner: EXEC-CEO # 종합(수렴)은 CEO, 최종 선택은 사람
gates:
- { gate: problem-intensity, primary: [UX-RESEARCHER], auditor: [PROD-PM] }
- { gate: competition-alternatives, primary: [GTM-CI], auditor: [STR-ANALYST] }
- { gate: willingness-to-pay, primary: [GTM-PRICING], auditor: [CFO] }
- { gate: revenue-unit-economics, primary: [CFO, GTM-REVOPS], auditor: [GTM-PRICING] }
- { gate: tech-feasibility-moat, primary: [ARCH-TECH], auditor: [CFO] }
- { gate: operability, primary: [CONSULT-OPS], auditor: [ARCH-TECH] }
- { gate: distribution, primary: [GTM-GROWTHPM, GTM-SALES], auditor: [CFO] }
- { gate: founder-fit, primary: [EXEC-CEO], auditor: [ARCH-TECH] }
- { gate: kill-criteria, primary: [CFO], auditor: [EXEC-CEO] }
opportunity-discovery-roles: # 기회탐색(발산) 참여 역할
diverge: [EXEC-CEO, FAM-CPO, STR-ANALYST, PROD-PM, UX-RESEARCHER, GTM-PMM]
contrarian: [CFO] # 왜 실패하는가 — 초기 아이디어의 경제구조 반증
```
> **CFO의 위치(리뷰 강조):** CFO는 "마지막에 돈이 되는지 확인"이 아니라 **초기 아이디어의 경제구조를 반증**하는 역할로 opportunity-discovery부터 contrarian으로 참여한다.
> 파일을 늘리기 싫으면 한 파일 두 섹션으로 둘 수 있으나, 본 스펙은 변경축 분리를 위해 2파일을 채택한다.
---
## 7. `company-context.yaml` 재구조화 — 항목별 provenance (리뷰 #1)
### 7.1 왜 블록 단위 evidence-cap을 제거하는가
`fact/decision/hypothesis`는 **정보의 종류**이고 `E1~E5`는 **증거의 강도**다. 둘은 독립이다. 창업자 자가입력 사실은 fact지만 E1~E2일 수 있고, 코드 실행으로 확인한 스택은 fact이며 E4~E5일 수 있다. 전략 결정은 "E3 증거"가 아니라 **HUMAN 권한**으로 유효해진다. 따라서 블록 cap을 제거하고 **항목별 provenance**를 둔다.
### 7.2 구조
```yaml
schema-version: 2
status: provisional # 공식 SoT는 3-상태만: template | provisional | operating (bootstrap 아님)
company:
facts:
- id: FACT-001
statement: "창업자는 백엔드·인프라 개발 역량을 보유한다."
category: founder-capability
provenance:
- { source-uri: org-os/01-company/founder-context.yaml, grade: E2 }
verified-at: "2026-07-12"
status: active # active | retired
strategic-decisions:
- id: DEC-001
statement: "초기 고객은 소규모 백엔드·DB 운영팀으로 한정한다."
decision-type: target-market
accepted-by: HUMAN-001
accepted-at: "2026-07-12"
source-decision-id: VD-001 # venture-decision report 계보
supporting-evidence:
- { source-uri: completion-records/<wf>/exec-packet-*.report.yaml, grade: E2 }
status: active
hypotheses:
- id: HYP-001
statement: "대상 고객은 월 $79 이상 지불 의사가 있다."
hypothesis-type: willingness-to-pay
confidence: Med
validation-status: untested # untested | validated | refuted
evidence:
- { source-uri: completion-records/<wf>/pricing-*.report.yaml, grade: E2 }
promotion-criteria: ["유료 사전판매 5+"]
falsification-criteria: ["2주 랜딩 유료전환 < 1%"]
validation-state:
stage: pre-traction
validated: []
open: [HYP-001]
refuted: []
projects: [] # 기존 유지(제품 lifecycle 소관)
```
- 단일 `decision-provenance` 객체 **제거** — 결정은 여러 개 누적되므로 **각 decision이 자기 provenance**(accepted-by/accepted-at/source-decision-id/supporting-evidence)를 갖는다.
- `schema-version: 1 → 2`. 기존 `company:` 블록(자유서술)은 마이그레이션 시 facts/decisions로 이전하거나 보존(§12).
### 7.3 상태 어휘 — 공식 SoT는 3-상태만
**공식 `company-context.yaml`의 `status`는 다음 3개만 가진다.** `bootstrap`은 공식 SoT 상태가 **아니다**(중간·모호 상태 방지 — 리뷰 2차 반영).
```
공식 SoT status:
template : 초기(빈) — 회사 미정의
provisional : bootstrap 산출. 결정은 유효, 시장 가설은 검증 상태에 종속
operating : 실검증·실운영 데이터로 승격(operating 승격 acceptance event 필요)
공식 SoT 상태 전이(§9.3):
template ──(atomic commit)──▶ provisional ──(human-approved promotion)──▶ operating
```
"작성 중인 bootstrap"은 **공식 status로 표현하지 않는다**. 두 가지로만 표현한다:
- **candidate 파일**의 별도 필드 `candidate-status: bootstrap`(공식 `status` 필드와 분리 — §9.3), 그리고
- **workflow stage** `company-context-commit`(진행 중).
이로써 "공식 status=bootstrap인데 candidate인가? commit 중인가? cascade가 읽어도 되나?" 같은 애매한 상태가 원천 차단된다. 제품 cascade는 공식 status가 `provisional|operating`일 때만 읽는다(§11).
`demo/populated`(구 어휘)는 **읽기 호환 + deprecation warning + 일회성 migration**으로 처리(영구 별칭 아님, §12: demo→template, populated→operating).
---
## 8. 상태머신 — `venture-bootstrap` plan (리뷰 #4, #5)
### 8.1 stage 그래프 (terminal 이전에 commit·lint 전이 존재)
`company-bootstrap`에 "진입하는 순간 terminal 도달" 문제를 피하기 위해 commit과 완료를 분리한다.
```yaml
# execution-plans.yaml
plans:
venture-bootstrap:
description: >
회사 수립(1회성). founder-context 를 입력으로 기회탐색→벤처검증→벤처결정→
company-context commit 을 거쳐 company-context.yaml(provisional) 을 산출한다.
제품 cascade 의 선행이며 별도 lifecycle 이다.
stages: [intake, founder-setup, opportunity-discovery, venture-validation,
venture-decision, company-context-commit, bootstrap-complete]
terminal-stage: bootstrap-complete
default-tier: standard
outputs: "org-os/01-company/company-context.yaml (status: provisional)"
```
### 8.2 전이·조건 (state-transition-rules.yaml `workflow-stage-transitions`에 추가)
전이 **집행 주체는 OPS-ORCH(trusted) 단독**. C-Level·전문역할은 intake·결정·추천 **보고서만** 생산하고 상태 원장을 직접 전이하지 않는다(리뷰 #5·2차 반영, 기존 신뢰경계와 정합). `-role-agent` placeholder와 `EXEC-CEO`를 allowed-by에서 **전부 제거**해 worker/C-Level-authored 전이 경로를 원천 차단한다 — venture-bootstrap의 **모든** 전이는 `allowed-by: [OPS-ORCH]`로 통일한다.
| 전이 | allowed-by | required-conditions(신규 predicate) |
|---|---|---|
| intake → founder-setup | `[OPS-ORCH]` | `decision-brief-present` |
| founder-setup → opportunity-discovery | `[OPS-ORCH]` | `founder-context-present` |
| opportunity-discovery → venture-validation | `[OPS-ORCH]` | `opportunity-clusters-present`(≥2) |
| venture-validation → venture-decision | `[OPS-ORCH]` | `venture-options-validated` |
| venture-decision → company-context-commit | `[OPS-ORCH]` | `venture-decision-accepted` + `human-acceptance-receipt-present` |
| company-context-commit → bootstrap-complete | `[OPS-ORCH]` | `company-context-provisional-committed` + `company-context-lint-passed` + `company-context-artifact-recorded` |
> `EXEC-CEO`는 intake 보고서(decision-brief)·venture-decision 종합을 **생산**할 수 있지만, 그 산출물을 근거로 stage를 전이하는 것은 OPS-ORCH다. (기존 cascade 일부 전이는 `[OPS-ORCH, discovery-role-agent]`처럼 placeholder를 병기하지만 — 실제 집행자는 항상 OPS-ORCH이고 엔진이 `EXEC-CEO` actor를 거부함 — venture-bootstrap은 그 잠재 경로마저 없애기 위해 OPS-ORCH 단독으로 못박는다.)
이 분리 덕에 "결정은 승인됐지만 company-context 쓰기·검증은 실패" 상태를 정확히 표현·재개할 수 있다.
### 8.3 신규 condition-catalog (state_engine.py가 원장 사실로 평가)
```yaml
condition-catalog:
founder-context-present: "org-os/01-company/founder-context.yaml status=filled"
opportunity-clusters-present: "opportunity-cluster 산출 ≥ 2 (ledger.artifacts/보고서)"
venture-options-validated: "각 venture-option 이 venture-option-spec required 필드 충족 + kill-criteria 존재 + 9-gate 결과 present"
venture-decision-accepted: "venture-decision 보고서 존재 + validate_report 통과 + acceptance_log accepted 이벤트(=report-id·workflow-id 바인딩)"
human-acceptance-receipt-present: "HUMAN-001 acceptance 이벤트가 그 venture-decision report-id/hash/workflow-id 에 바인딩(§9.4)"
company-context-provisional-committed: "공식 company-context.yaml status=provisional 로 원자적 교체 완료(commit_company_context receipt)"
company-context-lint-passed: "lint_company_context Hard Fail 0 (candidate 및 최종)"
company-context-artifact-recorded: "commit receipt 가 evidence-ledger/통합원장에 기록됨"
```
### 8.4 human-gate는 boolean이 아니라 바인딩된 receipt (리뷰 #5)
`human_gate_approved: true` 단일 boolean 금지. `venture-decision-accepted`+`human-acceptance-receipt-present`는 다음을 모두 요구:
1. venture-decision report 존재, 2. `validate_report` 통과, 3. `HUMAN-001` acceptance 이벤트 존재, 4. 이벤트가 **동일 report-id + report-sha256 + workflow-id**에 바인딩. (report-sha256 바인딩은 acceptance-event에 추가하는 신규 필드 — §9.4.)
---
## 9. 강제기 (hook / validator)
### 9.1 `validate_report` — 항목 단위 상한 (리뷰 #2, 자기수정 포함)
**정정:** 기존 코드는 이미 **항목 단위**로 동작한다. [validate_report.py:474-480](.claude/hooks/validate_report.py#L474-L480)의 `_is_unpopulated_company_ref(source-uri)`는 **개별 evidence 항목의 source-uri가 회사 네임스페이스를 가리키고 status != populated일 때 그 항목만** E2로 상한한다(외부·코드·테스트 증거는 원래 등급 유지). 전체 보고서 강등이 아니다. 따라서 리뷰 #2의 우려(전역 강등)는 **기존 구현엔 없으며**, 변경은 아래 두 가지로 한정한다:
1. **상태 어휘 확장:** `_company_context_populated()` → 공식 status가 `operating`일 때만 상한 해제. `template/provisional`(및 구 `demo`)은 회사 네임스페이스 인용을 계속 E2/Med 상한. 구 `populated``operating`으로 읽기 호환. (공식 SoT에 `bootstrap`은 존재하지 않으므로 처리 대상 아님 — §7.3.)
2. **hypothesis 항목 ceiling(신규 최소구현):** 회사 문맥 인용의 `source-uri`가 특정 항목(`company-context.yaml#HYP-001` 형태 anchor)을 가리키면:
- `hypotheses` 항목 → 회사별 결론 **confidence ≤ Med**, grade ≤ E2 (검증 상태 무관하게 가설 기반).
- `facts`/`strategic-decisions` 항목(provenance 有) → 항목 provenance grade까지 허용(단 status=operating 또는 결정은 결정으로서 유효).
- anchor 미지정(파일 전체 인용) → 기존 네임스페이스 상한(coarse).
3. **불변:** 외부 E3/E4/E5(코드 실행·테스트·외부 조사)는 회사 status와 **독립**으로 원등급 유지.
### 9.2 `lint_company_context.py` — 구조는 Hard Fail, 의미는 Warning (리뷰 #3)
자연어 의미로 "이건 가설인데 fact로 위장"을 정적 판정하는 것은 오탐·누락이 크다 → **Warning**. 구조·참조·권한·상태 정합만 **Hard Fail**.
**Hard Fail**
- 항목 ID 누락 / 중복 ID
- 공식 파일의 `status``template|provisional|operating`(3-상태) 밖 — 특히 공식 파일에 `status: bootstrap`이면 Hard Fail(§7.3)
- 항목 `status`가 허용값 밖
- candidate 파일이 아닌데 `candidate-status` 필드가 존재(또는 공식 파일에 `candidate-status: bootstrap`이 남아있음)
- `fact`의 provenance 누락
- `decision``accepted-by`/`accepted-at`/`source-decision-id` 누락
- `hypothesis``validation-status`/`confidence`/`falsification-criteria` 누락
- hypothesis ID를 fact reference 자리에 사용
- 존재하지 않는 evidence 경로(source-uri)
- `provisional`인데 human 승인 decision이 하나도 없음
- `operating`인데 operating 승격 acceptance event 부재
**Warning**
- fact 문장이 추정 표현("~일 것", "예상") 포함
- hypothesis와 fact 내용이 의미상 중복 의심
- 시장 규모·WTP가 fact에 들어간 것으로 의심
- 장기 미검증 hypothesis(오래된 verified/updated 없음)
- provenance는 있으나 근거 내용이 주장과 약하게 연결
- candidate 파일(§9.3)과 최종 파일 **둘 다** 검증 가능해야 한다.
- `run_all.py`·`doctor.py`에 배선. 구 `demo/populated`는 읽기 호환하되 **deprecation warning** 발생.
### 9.3 `commit_company_context.py` — candidate → 원자적 교체 (리뷰 #6)
bootstrap 도중 공식 SoT를 수정하면 중간 상태를 제품 cascade가 소비할 위험이 있다. 따라서:
```
공식 company-context.yaml (status: template) ← bootstrap 동안 불변, 공식 status에 bootstrap 없음
candidate 생성:
<workspace>/completion-records/<workflow-id>/company-context.candidate.yaml
· status: provisional # 최종 목표 상태(공식 3-상태 중 하나)
· candidate-status: bootstrap # candidate임을 표시하는 별도 필드(공식 파일엔 없음)
↓ schema validation
↓ lint_company_context (Hard Fail 0; candidate-status:bootstrap 허용은 candidate에 한함)
↓ venture-decision + human acceptance receipt 검증(바인딩)
↓ trusted commit: candidate-status 필드 제거 → 임시파일 write → os.replace() 원자 교체
공식 company-context.yaml (status: provisional) ← candidate-status 없음
```
- `commit_company_context.py`**trusted CLI**(OPS-ORCH가 실행). 위 게이트를 모두 통과할 때만 `candidate-status`를 벗겨 `os.replace()`로 교체. 실패 시 기존 파일 **무변경**.
- 공식 SoT는 `template → provisional → operating` 3-상태만 실질 사용(§7.3). "작성 중"은 공식 status가 아니라 **candidate 파일의 `candidate-status: bootstrap`** 및 **workflow stage `company-context-commit`**으로만 표현한다.
- commit은 `evidence-ledger`/통합원장에 receipt를 남긴다(`company-context-artifact-recorded`).
### 9.4 `acceptance_log` / `acceptance-event.schema.json` — 해시 바인딩 추가 (리뷰 #5, tests #3/#4)
현재 이벤트는 report-id + workflow-id + 실존(`_resolve_report_path`, ghost-acceptance 차단)만 바인딩하고 **content hash는 없다**. venture-decision human-gate의 위조·재사용을 막기 위해 **선택적 `report-sha256`** 필드를 추가(스키마 `additionalProperties: true`라 additive):
- `acceptance_log.py append ... --report-sha256 <hash>` 지원.
- `human-acceptance-receipt-present` predicate는 acceptance 이벤트의 `report-sha256`가 **현재 venture-decision 파일의 해시와 일치**하고 `workflow-id`가 같을 때만 통과. 불일치(결정 변경/타 workflow 재사용) → 거부.
### 9.5 `guard_tools.py` — 공식 SoT 직접쓰기 보호
공식 `org-os/01-company/company-context.yaml`은 fan-out worker/일반 Edit·Write로 **직접 수정 금지**. `commit_company_context.py`(trusted) 경로로만 교체. `founder-context.yaml`은 사람 입력이므로 별도(사람이 편집; worker 쓰기는 금지).
---
## 10. 커맨드 (리뷰 #7, #9)
기존 fan-out(divergent)·converge 인프라 위 **얇은 드라이버**. `/decide` **명령**을 호출하지 않고 공통 **converge contract**(collaboration-modes.yaml)를 재사용한다.
### 10.1 `/ceo-intake` (보강)
- `--plan venture-bootstrap` 명시로만 회사 부트스트랩 선택(자동 선택 금지 — 기존 제품 cascade와 충돌 방지).
- founder-context가 `template`이면 사람에게 채우도록 유도(또는 `/venture-validate` 진입 시 상태 확인해 founder-setup으로 유도).
### 10.2 `/venture-validate` (신규)
- **opportunity-discovery(발산):** `venture-validation-map.opportunity-discovery-roles`로 fan-out → opportunity-cluster ≥2(중복·완전성 검사). 제품명 이전, 문제 클러스터부터.
- **venture-validation:** option별 9-gate fan-out(primary/auditor, dissent 보존). `unknown` 허용, `kill-criteria` 필수. 산출 = validation-result + venture-option 보고서.
- 진입 시 `state_engine guard`, 종료 시 OPS-ORCH가 `transition`(worker 아님).
### 10.3 `/company-bootstrap` (신규)
- **venture-decision(수렴):** 공통 converge contract로 C-Level 독립 평가(CPO·CFO·CTO·COO·CPTO) → CEO synthesis(dissent 보존) → **ExecutiveDecisionPacket** 산출.
- **HUMAN acceptance:** 사람이 하나를 선택 → `acceptance_log append`(report-id + report-sha256 + workflow-id 바인딩).
- **company-context-commit:** candidate 생성 → schema/lint/acceptance 검증 → `commit_company_context.py`로 원자적 교체(§9.3).
- 모든 stage 전이는 OPS-ORCH가 집행.
### 10.4 공통 converge contract의 위치
재사용 단위는 slash command가 아니라 다음 중 하나로 둔다(구현 계획에서 택1):
- `collaboration-modes.yaml``converge` 계약(이미 존재: synthesis + report-header) + `context_package`(mode=divergent 평가 → converge 종합) 조합을 커맨드 문서가 **참조**.
- 필요 시 얇은 orchestrator helper/command fragment로 절차를 공유(중복 서술 금지).
---
## 11. 제품 cascade 진입 계약 (seam, 리뷰 #9)
product-definition stage는 P1에서 만들지 않되, **후속 cascade가 bootstrap 결과를 정확히 참조**할 계약만 정의한다.
```yaml
# 제품 cascade 진입 조건(신규 predicate: company-context-ready)
company-context-ready:
all:
- "company-context.status in [provisional, operating]"
- "selected-venture-decision-id exists (company.strategic-decisions[].source-decision-id 또는 별도 pointer)"
- "selected venture accepted by HUMAN (acceptance event 바인딩)"
- "no unresolved bootstrap blocker"
```
제품 intake(decision-brief)에는 다음 참조를 포함한다:
```yaml
company-context-ref: org-os/01-company/company-context.yaml
venture-decision-id: VD-001
company-decision-ids: [DEC-001, DEC-002]
```
- `template` 상태(또는 company-context-commit 미완)에서 제품 cascade 진입은 **advisory 체크**로 가드된다 — 오케스트레이터가 진입 시 `python3 .claude/hooks/state_engine.py check-company-context-ready --workflow <wf>`(exit 2 = NOT READY)를 실행·확인하되, **기존 cascade 전이의 하드 선행조건으로는 넣지 않는다**(부트스트랩되지 않은 회사에서 도는 데모/샌드박스 cascade 회귀 방지 — 구현상 의도적 advisory, Task 12). `provisional/operating`은 READY. **후속 과제**: 이 advisory 체크를 `/ground`·`/decide` 커맨드 프롬프트의 진입 스텝으로 명시 배선(하드 게이트 승격은 데모 cascade 회귀와 상충하므로 신중)."
- 이 계약은 state_engine의 cascade 진입 guard에 predicate로 추가(제품 stage 자체는 불변).
---
## 12. 마이그레이션 (`demo/populated` → 신 어휘)
영구 별칭이 아니라 **읽기 호환 + deprecation warning + 일회성 migration**:
1. **읽기 호환:** validate_report·lint은 `demo``template`으로, `populated``operating`으로 **해석**하되 **deprecation warning** 출력.
2. **일회성 migration:** `lint_company_context.py --migrate`(또는 별도 스니펫)로 현재 `company-context.yaml`을 schema-version 2 구조로 1회 변환(자유서술 `company:` → facts/decisions 이전, 나머지는 hypotheses/보존). 변환 후 status를 명시 어휘로 교체.
3. 변환 뒤에는 구 어휘 사용 시 Hard Fail로 승격(후속 사이클).
---
## 13. 데이터 흐름 (확정)
```
/ceo-intake --plan venture-bootstrap
→ intake (decision-brief-present)
→ founder-setup (founder-context.yaml status=filled)
/venture-validate
→ opportunity-discovery (독립 fan-out, cluster ≥2, 중복·완전성)
→ venture-validation (option별 9-gate, unknown 허용, kill-criteria 필수, dissent 보존)
/company-bootstrap
→ venture-decision (C-Level 독립평가 → CEO synthesis → HUMAN acceptance receipt[hash 바인딩])
→ company-context-commit (candidate → schema → lint → atomic os.replace)
→ bootstrap-complete (company-context.status=provisional, artifact receipt 기록)
│ seam: company-context-ready
[product cascade] /ground /decide /design … (company-context + venture/decision ids 를 입력으로)
```
전이는 전부 OPS-ORCH가 집행. 각 stage 산출물은 불변 보고서. 공식 SoT는 마지막 1회 원자 교체.
---
## 14. 테스트 (TDD, RED→GREEN, run_all 유지)
기존 제안(신규 predicate 게이팅, lint, status 어휘 캡)에 더해 **반드시 포함**:
1. worker agent가 state transition을 요청하면 거부(allowed-by=OPS-ORCH만).
2. human boolean만 있고 acceptance receipt 없으면 거부.
3. 다른 workflow의 decision report를 재사용하면 거부(workflow-id 불일치).
4. decision hash ≠ acceptance hash면 거부(report-sha256 바인딩).
5. candidate lint 실패 시 공식 company-context **무변경**.
6. commit 중 실패해도 기존 파일 유지(atomic).
7. `template` 상태(또는 company-context-commit 미완)에서 제품 cascade 진입 거부.
8. `provisional` 상태에서 제품 cascade 진입 허용.
9. 외부 E4 증거가 provisional 때문에 E2로 강등되지 **않음**.
10. hypothesis를 참조한 회사별 주장은 Med ceiling 적용.
11. `demo/populated` 읽기 호환은 되지만 deprecation warning 발생.
12. 재실행 시 이미 완료된 fan-out을 중복 실행하지 않음(idempotent stage).
13. 동일 candidate commit 재실행 idempotent.
14. decision 변경 시 이전 candidate commit 거부.
추가 커버리지: lint Hard Fail 항목별(ID 누락/중복/provenance 누락/hypothesis 필드 누락/hypothesis-id-as-fact/nonexistent evidence path), founder-context 미충족 게이팅, opportunity-cluster <2 차단, kill-criteria 누락 차단.
---
## 15. 열린 사항 / 리스크
- **converge contract 재사용 형태**(collaboration-modes 참조 vs helper vs fragment)는 구현 계획에서 확정. 어느 쪽이든 `/decide` 명령 직접 호출 금지 원칙은 불변.
- **hypothesis 항목 ceiling**의 anchor 규약(`company-context.yaml#HYP-001`) — 인용 표기 컨벤션을 context-package/보고 스키마 문서에 명시해야 실효.
- **역할 보강**(GTM-PRICING·GTM-GROWTHPM·ARCH-TECH·CONSULT-OPS 등)이 venture-validation-map에서 실제 agent-card로 존재하는지 gen_agents 대조(doctor 체크 후보).
- **company-context는 repo-level SoT**(회사 사실 + projects[]). bootstrap은 회사 수립이므로 repo SoT를 교체하는 것이 맞다. candidate는 workspace completion-records에 두고 최종만 repo로 원자 교체.
---
## 16. 확정 체크리스트(리뷰 9개 반영)
1. ✅ 블록 단위 evidence-cap 제거, 항목별 provenance(§7)
2. ✅ company status가 보고서 전체 evidence를 강등하지 않도록 항목 단위로 한정(§9.1, 기존 구현이 이미 항목 단위임을 확인·확장)
3. ✅ semantic hypothesis-as-fact는 Warning, 구조·참조·권한만 Hard Fail(§9.2)
4.`company-context-commit → bootstrap-complete` 전이 추가(§8.18.2)
5. ✅ 상태 전이는 worker 아니라 OPS-ORCH/trusted hook만 + acceptance receipt hash 바인딩(§8.28.4, §9.4)
6. ✅ candidate 작성 후 공식 SoT 원자적 commit(§9.3)
7.`/decide` 명령이 아니라 공통 converge contract 재사용(§10)
8. ✅ GTM-PRICING·GTM-GROWTHPM·ARCH-TECH·CONSULT-OPS 등 역할 보강(§6.2)
9. ✅ product cascade 진입 계약만 P1에서 정의(product-definition stage 미신설)(§11)
**2차 반영(구현 직전):**
10. ✅ 상태 전이 권한 완전 통일 — venture-bootstrap 모든 전이 `allowed-by: [OPS-ORCH]` 단독(intake 행의 `EXEC-CEO` 제거). C-Level은 보고서 생산만(§8.2).
11. ✅ 공식 `company-context.yaml` status는 3-상태(`template|provisional|operating`)만 — `bootstrap` 제거. "작성 중"은 candidate 파일의 `candidate-status: bootstrap` + workflow stage `company-context-commit`로만 표현(§7.3, §9.29.3).