@walwal-harness/cli 5.9.6 → 6.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +140 -0
- package/assets/templates/config.json +29 -0
- package/assets/templates/memory.md +30 -2
- package/assets/templates/progress.json.template +8 -2
- package/bin/init.js +147 -9
- package/commands/harness-next.md +3 -1
- package/commands/harness-solo.md +20 -4
- package/commands/harness-team.md +21 -5
- package/gotchas/dispatcher.md +72 -0
- package/gotchas/generator-backend-laravel.md +85 -0
- package/package.json +11 -3
- package/scripts/harness-dashboard-up.sh +72 -0
- package/scripts/harness-goal-init.sh +72 -0
- package/scripts/harness-goal-show.sh +37 -0
- package/scripts/harness-next.sh +10 -11
- package/skills/conductor/SKILL.md +247 -0
- package/skills/cqo/SKILL.md +138 -0
- package/skills/cto/SKILL.md +133 -0
- package/skills/dispatcher/SKILL.md +28 -17
- package/skills/dispatcher/persona-ceo.md +168 -0
- package/skills/evaluator-architecture/SKILL.md +173 -0
- package/skills/evaluator-security/SKILL.md +172 -0
- package/skills/generator-designer/SKILL.md +219 -0
- package/skills/generator-devops/SKILL.md +201 -0
- package/skills/meeting-manager/SKILL.md +206 -0
- package/skills/planner/hr-onboard.md +134 -0
- package/skills/planner/hr-recruit.md +99 -0
- package/skills/planner/persona-coo-hr.md +165 -0
- package/skills/service-ops/SKILL.md +255 -0
package/CHANGELOG.md
ADDED
|
@@ -0,0 +1,140 @@
|
|
|
1
|
+
---
|
|
2
|
+
docmeta:
|
|
3
|
+
id: CHANGELOG
|
|
4
|
+
title: walwal-harness CHANGELOG
|
|
5
|
+
type: output
|
|
6
|
+
createdAt: 2026-05-07T00:00:00Z
|
|
7
|
+
updatedAt: 2026-05-07T00:00:00Z
|
|
8
|
+
source:
|
|
9
|
+
producer: agent
|
|
10
|
+
skillId: harness-release
|
|
11
|
+
inputs:
|
|
12
|
+
- documentId: agency-mapping
|
|
13
|
+
uri: .harness/agency-mapping.md
|
|
14
|
+
relation: output-from
|
|
15
|
+
sections:
|
|
16
|
+
- sourceRange: { startLine: 41, endLine: 53 }
|
|
17
|
+
targetRange: { startLine: 28, endLine: 40 }
|
|
18
|
+
- documentId: doctrine-nexus
|
|
19
|
+
uri: .harness/doctrine/nexus.md
|
|
20
|
+
relation: output-from
|
|
21
|
+
sections:
|
|
22
|
+
- sourceRange: { startLine: 32, endLine: 60 }
|
|
23
|
+
targetRange: { startLine: 41, endLine: 50 }
|
|
24
|
+
- documentId: package
|
|
25
|
+
uri: package.json
|
|
26
|
+
relation: output-from
|
|
27
|
+
tags: [changelog, release-notes, v6.0.0, nexus]
|
|
28
|
+
---
|
|
29
|
+
|
|
30
|
+
# Changelog
|
|
31
|
+
|
|
32
|
+
## 6.0.1 — Owner ↔ CEO 정체성 + 자율 실행 룰 강화 (2026-05-07)
|
|
33
|
+
|
|
34
|
+
v6.0.0 publish 직후 Owner 의 명시적 교정으로 발견된 두 가지 inviolable 룰 위반 패턴을 패키지에 정식 등재한 patch.
|
|
35
|
+
|
|
36
|
+
### 발견된 위반 패턴
|
|
37
|
+
- Dispatcher 응답이 사용자를 "CEO 직접 리뷰…" 로 호명 — 정체성 혼선
|
|
38
|
+
- "/harness-next 자동 진행하시겠습니까?" 식의 사용자 펌프 — NEXUS P3 자율 실행 위반
|
|
39
|
+
|
|
40
|
+
### Added
|
|
41
|
+
- `gotchas/dispatcher.md` — 신규 4개 entry ([G-001]~[G-004]) 정식 등재. install 시 사용자 `.harness/gotchas/dispatcher.md` 로 자동 복사.
|
|
42
|
+
- [G-001] 사용자를 CEO 로 다루지 말 것 (Owner ↔ CEO 정체성)
|
|
43
|
+
- [G-002] 사용자에게 진행 여부 묻지 말 것 (NEXUS P3 자율 실행)
|
|
44
|
+
- [G-003] GOAL 모호성 명료화는 짧게 한 번만
|
|
45
|
+
- [G-004] Owner ↔ Conductor/Planner/Generator/Evaluator 직접 라우팅 금지
|
|
46
|
+
- `assets/templates/memory.md` — 신규 [M-NEXUS-P3] 항목. 모든 신규 install 의 시작 memory 에 포함.
|
|
47
|
+
|
|
48
|
+
### Changed
|
|
49
|
+
- `skills/dispatcher/SKILL.md` 상단에 두 inviolable 섹션 신설:
|
|
50
|
+
- "정체성 — Owner ↔ CEO (NEXUS, Inviolable)"
|
|
51
|
+
- "자율 실행 원칙 (NEXUS P3, Inviolable)"
|
|
52
|
+
- `skills/conductor/SKILL.md` §0 "자율 시동 트리거" 신설 — Dispatcher GOAL 확정 / Planner feature-list 확정 / Eval PASS / Eval FAIL 4 시점에 자동 시동 명시.
|
|
53
|
+
|
|
54
|
+
### Why a patch (not a feature)
|
|
55
|
+
이 룰들은 v6.0.0 의 NEXUS 도큐트린에 이미 존재했지만 SKILL 본문에서 충분히 강제되지 않아 대화에서 위반이 발생. 룰 자체는 변경 없음, **명시화/강제력 강화** 만.
|
|
56
|
+
|
|
57
|
+
### Migration
|
|
58
|
+
이전 사용자 (v6.0.0 install 자) 가 patch 적용:
|
|
59
|
+
```bash
|
|
60
|
+
npm install @walwal-harness/cli@latest # 6.0.1 설치
|
|
61
|
+
# .claude/skills/ 와 .harness/gotchas/dispatcher.md 가 자동 갱신됨.
|
|
62
|
+
# .harness/memory.md 는 [G-NNN] entry 가 있으면 보존되므로
|
|
63
|
+
# [M-NEXUS-P3] 항목을 수동으로 메모에 추가하거나
|
|
64
|
+
# memory.md 백업 후 walwal-harness --force 로 template 재적용.
|
|
65
|
+
```
|
|
66
|
+
|
|
67
|
+
## 6.0.0 — NEXUS-Adapted Company Metaphor (2026-05-07)
|
|
68
|
+
|
|
69
|
+
회사 메타포로의 전면 전환. 기존 단일 dispatcher/planner/generator/evaluator 라인업을 NEXUS 도큐트린에 따라 7부서 + 14 에이전트 조직도로 재해석했습니다.
|
|
70
|
+
|
|
71
|
+
### Added
|
|
72
|
+
- **CEO (Dispatcher 격상)** — Owner ↔ 회사 단일 대화 창구. GOAL 협의·escalation 보고.
|
|
73
|
+
- **Conductor** — 자율 실행 엔진. Gen↔Eval 무인 루프.
|
|
74
|
+
- **Meeting-Manager** — 동기화 엔진. 5종 회의(standup/planning/review/all-hands/phase-gate) 적응형 cadence.
|
|
75
|
+
- **COO (Planner)** — Sprint·AC·HR·온보딩 통합.
|
|
76
|
+
- **CTO (Generator 총괄)** — Gen-BE/Gen-FE/Designer/DevOps 4팀 통솔.
|
|
77
|
+
- **CQO (Evaluator 총괄)** — Eval-Functional/Visual/CodeQuality + 신규 Architecture/Security.
|
|
78
|
+
- **Service-Ops** — 운용·모니터·인시던트·자율회고.
|
|
79
|
+
- 신규 14개 SKILL.md (`skills/{conductor,meeting-manager,cto,cqo,service-ops,evaluator-architecture,evaluator-security,generator-designer,generator-devops,...}/SKILL.md`).
|
|
80
|
+
- `.harness/doctrine/nexus.md` — Foundational Principles (P1~P5) + 7 Phase Lifecycle.
|
|
81
|
+
- `.harness/agency-mapping.md` — agency-agents → walwal-harness 매핑 (Phase A 결과).
|
|
82
|
+
- `.harness/memory.md` 기반 공유 학습 시스템 (gotcha 와 분리).
|
|
83
|
+
- Brainstormer 스킬 (obra/superpowers 파생, MIT, Visual Companion 포함).
|
|
84
|
+
- 적응형 ref-docs (`.harness/ref/<role>-<stack>.md`) — 단일 에이전트가 스택별 best-practice 동적 로드.
|
|
85
|
+
|
|
86
|
+
### Changed
|
|
87
|
+
- `agents` 섹션의 Flutter 변형 (`generator-frontend-flutter` / `evaluator-functional-flutter`) 제거. 단일 에이전트가 `.harness/ref/<role>-<stack>.md` 동적 로드.
|
|
88
|
+
- AGENTS.md IA-MAP — 부서 권한 매트릭스 25항 (이전 12항).
|
|
89
|
+
- progress.json 스키마 v3 — `org/goals/conductor/meetings/cto/cqo/service_ops` 슬롯 추가.
|
|
90
|
+
- Evaluator chain 명시화: `evaluator-code-quality → evaluator-functional → evaluator-visual` (FULLSTACK/FE-ONLY) / `code-quality → functional` (BE-ONLY).
|
|
91
|
+
|
|
92
|
+
### Removed
|
|
93
|
+
- Flutter "유령 스킬" 참조 ([M-001] resolved). config.json + dispatcher SKILL.md 의 fe_stack_substitution 폐기.
|
|
94
|
+
- 기존 PRE-NEXUS dispatcher 단일 라인업.
|
|
95
|
+
- **Dispatcher 의 Solo/Team 모드 질문**. 사용자 "harness-solo / harness-team 입력하세요" 안내 패턴 제거.
|
|
96
|
+
|
|
97
|
+
### Mode Decision — User → Conductor 이양 (Breaking)
|
|
98
|
+
- `progress.json.mode` 디폴트 `"solo"` → `"auto"`. version 3 → 4.
|
|
99
|
+
- 신규 필드 `progress.json.mode_decision = { owner, decided_at, rationale, user_override }`.
|
|
100
|
+
- `config.json.mode_selection` 신규 — `force_team_when`(ready≥3 + features≥6 + depth≤2) / `force_solo_when` / tie-breaker=solo.
|
|
101
|
+
- Conductor SKILL §7.5: Planner 의 feature-list 확정 직후 자동 결정. 결정은 progress.json + progress.log 에 rationale 명시.
|
|
102
|
+
- `/harness-solo`, `/harness-team` 은 사용자 override 명령으로 의미 변경. `mode_decision.user_override` 에 기록되어 현재 sprint 종료까지 유지. "auto 로 돌려" 발화로 자동결정 복귀.
|
|
103
|
+
- Dispatcher SKILL §"Mode 결정 위임" — 모드 질문/추천 출력 모두 폐기. 사용자 발화에서 명시적 모드 신호 감지 시만 user_override 로 기록.
|
|
104
|
+
|
|
105
|
+
### Migration (5.9.x → 6.0.0)
|
|
106
|
+
|
|
107
|
+
기존 walwal-harness 사용 프로젝트는 `npm install @walwal-harness/cli@latest` 후 다음 한 줄로 자동 마이그레이션 가능:
|
|
108
|
+
|
|
109
|
+
```bash
|
|
110
|
+
npx walwal-harness migrate --dry-run # 변경 미리보기
|
|
111
|
+
npx walwal-harness migrate # 실제 적용
|
|
112
|
+
```
|
|
113
|
+
|
|
114
|
+
**자동 처리되는 것**:
|
|
115
|
+
- `progress.json` v3 → v4 — 기존 `mode` 값 (`"solo"` 또는 `"team"`) 을 `mode_decision.user_override` 로 **그대로 보존**. 새 mode 는 `"auto"` 로 셋되지만 user_override 로 직전 sprint 의 사용자 의도 유지.
|
|
116
|
+
- `config.json` 의 `mode_selection` 누락 시 자동 주입 (rules: ready≥3 + features≥6 + depth≤2 → team / 그 외 → solo). 사용자 customization (`behavior`, `flow.pre_eval_gate.*`) 은 **모두 보존**.
|
|
117
|
+
- 변경 전 자동 백업: `.harness/archive/migration-<timestamp>/` (progress.json + config.json 원본).
|
|
118
|
+
|
|
119
|
+
**수동 처리 권장**:
|
|
120
|
+
1. AGENTS.md 의 IA-MAP 권한 매트릭스 신규 25항 검토.
|
|
121
|
+
2. 기존 sprint 진행 중이라면 `.harness/archive/` 로 수동 이관 후 새 dispatch 시작.
|
|
122
|
+
3. `.claude/skills/` 의 신규 14개 부서 SKILL.md 가 정상 설치되었는지 확인 (`ls .claude/skills/` 에 conductor / cto / cqo / meeting-manager / service-ops / evaluator-architecture / evaluator-security 포함).
|
|
123
|
+
4. Flutter 프로젝트 사용자: `pubspec.yaml` 자동 감지 + `.harness/ref/generator-frontend-flutter.md` (있을 시) 로 동작. 누락 시 Planner 가 ref 생성 권고.
|
|
124
|
+
|
|
125
|
+
**Postinstall 안내**: `npm install` 후 v3 detect 시 안내 banner 가 출력될 수 있으나 npm v9+ 의 quiet mode 에서는 누락될 수 있습니다. 의심 시 `npx walwal-harness migrate --dry-run` 으로 직접 확인하세요.
|
|
126
|
+
|
|
127
|
+
### Reference
|
|
128
|
+
Phase C "Brick Office 대시보드 MVP" 가 본 v6 organization 기반 첫 풀사이클 검증 (3 sprints, 25 features, 모든 평가 PASS).
|
|
129
|
+
|
|
130
|
+
## 5.9.6 — Queue Integrity & Lead Guard (이전)
|
|
131
|
+
- queue enqueue/integrity 명령 추가, dashboard orphan 경고, Lead 가드.
|
|
132
|
+
|
|
133
|
+
## 5.9.5 — Solo/Team Mode Drift Fix
|
|
134
|
+
- progress.json mode drift 시 dashboard/tmux 가 SOLO 로 잘못 표시되던 버그 수정.
|
|
135
|
+
|
|
136
|
+
## 5.9.4 — Graceful Crash Recovery
|
|
137
|
+
- progress.json 손상 시 dashboard crash → 안내 메시지로 graceful 처리.
|
|
138
|
+
|
|
139
|
+
## 5.9.3 — Compressed Output Fix
|
|
140
|
+
- 분할 패널에서 Conventions/Memory 가 3 줄만 보이던 압축 출력 수정.
|
|
@@ -342,6 +342,35 @@
|
|
|
342
342
|
"auto_route_dispatcher": true,
|
|
343
343
|
"auto_route_dispatcher_description": "true 이면 사용자의 모든 프롬프트가 harness-dispatcher 경유로 분류/라우팅 된다. 사용자가 'harness skip' 등을 말하면 단일 메시지 한정으로 건너뛴다."
|
|
344
344
|
},
|
|
345
|
+
"mode_selection": {
|
|
346
|
+
"comment": "v6.0 — Solo/Team 모드를 사용자가 아닌 Conductor 가 결정. progress.json.mode='auto' 일 때 Conductor 가 feature-list 의 ready_count + 의존성 깊이 + sprint feature 수를 보고 룰을 적용. 사용자는 /harness-solo 또는 /harness-team 으로 override 가능하며 그 결정은 progress.json.mode_decision.user_override 에 기록된다.",
|
|
347
|
+
"default_mode": "auto",
|
|
348
|
+
"owner": "conductor",
|
|
349
|
+
"rules": {
|
|
350
|
+
"force_team_when": {
|
|
351
|
+
"ready_at_start_gte": 3,
|
|
352
|
+
"feature_count_gte": 6,
|
|
353
|
+
"critical_path_depth_lte": 2,
|
|
354
|
+
"rationale": "ready≥3 + 작은 critical path = 3팀 동시 가동의 P4 Parallel Workstreams 효과 충족 (NEXUS 40~60% 단축)"
|
|
355
|
+
},
|
|
356
|
+
"force_solo_when": {
|
|
357
|
+
"ready_at_start_lte": 2,
|
|
358
|
+
"or_feature_count_lte": 3,
|
|
359
|
+
"or_critical_path_depth_gte": 4,
|
|
360
|
+
"rationale": "직렬 의존 우세 → Team 으로 띄워도 2팀이 유휴. tmux 운영 비용·토큰 3x 정당화 안 됨."
|
|
361
|
+
},
|
|
362
|
+
"tie_breaker": "solo",
|
|
363
|
+
"tie_breaker_rationale": "동률 시 비용 안전한 Solo 선호. 사용자가 명시적으로 team 선택 시만 force."
|
|
364
|
+
},
|
|
365
|
+
"user_override": {
|
|
366
|
+
"comment": "사용자가 명시적으로 모드 강제하면 Conductor 결정 무시. progress.json.mode_decision.user_override 에 기록.",
|
|
367
|
+
"channels": [
|
|
368
|
+
"/harness-solo (force solo)",
|
|
369
|
+
"/harness-team (force team)",
|
|
370
|
+
"사용자 발화: 'solo 로', 'team 으로', 'auto 다시' (auto 복귀)"
|
|
371
|
+
]
|
|
372
|
+
}
|
|
373
|
+
},
|
|
345
374
|
"paths": {
|
|
346
375
|
"actions": ".harness/actions",
|
|
347
376
|
"archive": ".harness/archive",
|
|
@@ -4,11 +4,25 @@ docmeta:
|
|
|
4
4
|
title: Harness Memory — 공유 학습 기록
|
|
5
5
|
type: input
|
|
6
6
|
createdAt: 2026-04-20T00:00:00Z
|
|
7
|
-
updatedAt: 2026-
|
|
7
|
+
updatedAt: 2026-05-07T00:00:00Z
|
|
8
8
|
source:
|
|
9
9
|
producer: user
|
|
10
10
|
skillId: harness
|
|
11
|
-
inputs:
|
|
11
|
+
inputs:
|
|
12
|
+
- documentId: doctrine-nexus
|
|
13
|
+
uri: ../../doctrine/nexus.md
|
|
14
|
+
relation: output-from
|
|
15
|
+
note: NEXUS Foundational Principle P3 (Continuous Loop > End-of-Pipeline) 의 권위 출처. M-NEXUS-P3 항목이 이를 운영 룰로 변환.
|
|
16
|
+
sections:
|
|
17
|
+
- sourceRange: { startLine: 32, endLine: 60 }
|
|
18
|
+
targetRange: { startLine: 56, endLine: 70 }
|
|
19
|
+
- documentId: gotchas-dispatcher
|
|
20
|
+
uri: ../../gotchas/dispatcher.md
|
|
21
|
+
relation: output-from
|
|
22
|
+
note: dispatcher [G-001]~[G-004] 가 본 memory 의 [M-NEXUS-P3] 적용 사례. inline 사용자 피드백 기반.
|
|
23
|
+
sections:
|
|
24
|
+
- sourceRange: { startLine: 17, endLine: 52 }
|
|
25
|
+
targetRange: { startLine: 56, endLine: 70 }
|
|
12
26
|
tags: [harness, memory, template]
|
|
13
27
|
---
|
|
14
28
|
|
|
@@ -53,6 +67,20 @@ docmeta:
|
|
|
53
67
|
- **Context**: 사용자가 대시보드 로그만 보고 진행 상황을 파악해야 하는데, 기존 축약 로그로는 4대 질문에 답이 안 보인다는 피드백.
|
|
54
68
|
- **Applies to**: Team Worker(Generator + Evaluator), Solo Mode Generator/Evaluator, 모든 `logev` 호출 지점.
|
|
55
69
|
|
|
70
|
+
### [M-NEXUS-P3] Owner ↔ CEO 단일 창구 + 자율 실행 (Inviolable)
|
|
71
|
+
- **Date**: 2026-05-07
|
|
72
|
+
- **Status**: verified
|
|
73
|
+
- **TTL**: 영구
|
|
74
|
+
- **Lesson**: walwal-harness 는 NEXUS 회사 메타포다. 다음 두 룰을 **절대로** 어기지 않는다.
|
|
75
|
+
1. **정체성**: 사용자 = **Owner** (회사 외부 주주), Dispatcher = **CEO** (Owner 와의 유일한 대화 창구). 응답·GOAL·로그 어디서도 사용자를 "CEO" 로 호칭하지 않는다. 회사 내부 결정 (sprint 분할, mode 선택, agent 호출, 평가 점수) 을 Owner 에게 떠넘기지 않는다.
|
|
76
|
+
2. **자율 실행 (NEXUS P3)**: GOAL 확정 직후 회사는 **사용자 펌프 없이** 자율 진행. "다음 단계로 진행할까요?", "/harness-next 실행하시겠습니까?" 같은 진행 여부 질문은 자율성 위반. Owner 가 돌아오는 시점은 (a) GOAL 모호성 명료화 (1~2 개 객관식 질문, 한 번만), (b) 결과 보고, (c) escalation 셋 뿐.
|
|
77
|
+
- **Context**: v6.0.0 publish 직후 dispatcher 응답이 사용자를 "CEO 직접 리뷰…" 로 호명하고 "/harness-next 자동 진행하시겠습니까?" 로 사용자 펌프를 요구함. Owner 의 명시적 교정.
|
|
78
|
+
- **Applies to**:
|
|
79
|
+
- **Dispatcher**: 사용자 호칭/응답 문구, GOAL 정립, 모든 inbound/outbound owner 통신. → anti-pattern: `.harness/gotchas/dispatcher.md` [G-001]~[G-004].
|
|
80
|
+
- **Conductor**: GOAL 확정 직후 자동 시동 (사용자 허락 X), Eval PASS/FAIL 직후 자동 advance/retry, mode 결정 (config.json `mode_selection.rules`).
|
|
81
|
+
- **Planner / CTO / CQO / Generator / Evaluator / Service-Ops**: Owner 와 직접 대화 X. 모든 통신은 Dispatcher 경유.
|
|
82
|
+
- **Why this matters**: 회사가 매 단계 사용자 허락을 구하면 NEXUS 메타포 자체가 무너진다. P3 "Continuous Loop > End-of-Pipeline" 가 약속하는 95% 결함 차단·40~60% 단축은 자율 루프에서만 성립한다.
|
|
83
|
+
|
|
56
84
|
### [M-002] FE Evaluation은 Playwright 필수
|
|
57
85
|
- **Date**: 2026-04-20
|
|
58
86
|
- **Status**: verified
|
package/bin/init.js
CHANGED
|
@@ -904,16 +904,19 @@ function showHelp() {
|
|
|
904
904
|
╚══════════════════════════════════════╝
|
|
905
905
|
|
|
906
906
|
Usage:
|
|
907
|
-
npx walwal-harness
|
|
908
|
-
npx walwal-harness --force
|
|
909
|
-
npx walwal-harness team
|
|
910
|
-
npx walwal-harness team --kill
|
|
911
|
-
npx walwal-harness
|
|
912
|
-
|
|
913
|
-
|
|
914
|
-
|
|
915
|
-
|
|
907
|
+
npx walwal-harness Initialize project for harness engineering
|
|
908
|
+
npx walwal-harness --force Re-initialize (overwrites existing files)
|
|
909
|
+
npx walwal-harness team Launch Team Mode (tmux studio + auto teams)
|
|
910
|
+
npx walwal-harness team --kill Kill Team Mode tmux session
|
|
911
|
+
npx walwal-harness migrate Apply v3 → v4 migration (mode→auto + Conductor)
|
|
912
|
+
npx walwal-harness migrate --dry-run Preview migration changes without applying
|
|
913
|
+
npx walwal-harness --help Show this help
|
|
914
|
+
|
|
915
|
+
Modes (v6.0+ — Conductor 자동 결정, 사용자 override 가능):
|
|
916
|
+
/harness-solo Solo Override — Conductor 결정을 Solo 로 강제
|
|
917
|
+
/harness-team Team Override — Conductor 결정을 Team 으로 강제 (tmux 부팅)
|
|
916
918
|
/harness-stop Stop Team mode (preserves queue state)
|
|
919
|
+
발화 "auto 로 돌려" → Conductor 자동결정 복귀
|
|
917
920
|
|
|
918
921
|
What it does:
|
|
919
922
|
1. Scaffolds .harness/ directory (actions, archive, gotchas, config)
|
|
@@ -965,6 +968,120 @@ function runTeamStudio() {
|
|
|
965
968
|
execSync(cmd, { stdio: 'inherit' });
|
|
966
969
|
}
|
|
967
970
|
|
|
971
|
+
// ─────────────────────────────────────────
|
|
972
|
+
// Migration — v3 → v4 (mode auto + Conductor ownership)
|
|
973
|
+
// ─────────────────────────────────────────
|
|
974
|
+
const TARGET_PROGRESS_VERSION = 4;
|
|
975
|
+
|
|
976
|
+
function detectMigrationNeeded() {
|
|
977
|
+
const progressPath = path.join(HARNESS_DIR, 'progress.json');
|
|
978
|
+
const configPath = path.join(HARNESS_DIR, 'config.json');
|
|
979
|
+
const flags = { progressV3toV4: false, configMissingModeSelection: false };
|
|
980
|
+
if (fs.existsSync(progressPath)) {
|
|
981
|
+
try {
|
|
982
|
+
const p = JSON.parse(fs.readFileSync(progressPath, 'utf8'));
|
|
983
|
+
if ((p.version ?? 0) < TARGET_PROGRESS_VERSION) flags.progressV3toV4 = true;
|
|
984
|
+
} catch {}
|
|
985
|
+
}
|
|
986
|
+
if (fs.existsSync(configPath)) {
|
|
987
|
+
try {
|
|
988
|
+
const c = JSON.parse(fs.readFileSync(configPath, 'utf8'));
|
|
989
|
+
if (!c.mode_selection) flags.configMissingModeSelection = true;
|
|
990
|
+
} catch {}
|
|
991
|
+
}
|
|
992
|
+
return flags;
|
|
993
|
+
}
|
|
994
|
+
|
|
995
|
+
function showMigrationProposal(flags) {
|
|
996
|
+
console.log('');
|
|
997
|
+
console.log('╔══════════════════════════════════════════════════════════╗');
|
|
998
|
+
console.log('║ walwal-harness v6 — 자동 마이그레이션 사용 가능 ║');
|
|
999
|
+
console.log('╚══════════════════════════════════════════════════════════╝');
|
|
1000
|
+
if (flags.progressV3toV4) {
|
|
1001
|
+
console.log(' • progress.json: v3 → v4 (mode → "auto" + mode_decision 추가)');
|
|
1002
|
+
console.log(' 기존 mode 값은 user_override 로 보존됩니다.');
|
|
1003
|
+
}
|
|
1004
|
+
if (flags.configMissingModeSelection) {
|
|
1005
|
+
console.log(' • config.json: mode_selection 섹션 누락 — 자동 주입 가능');
|
|
1006
|
+
console.log(' Conductor 가 ready≥3 + features≥6 + depth≤2 로 자동 모드 결정.');
|
|
1007
|
+
}
|
|
1008
|
+
console.log('');
|
|
1009
|
+
console.log(' 적용: npx walwal-harness migrate');
|
|
1010
|
+
console.log(' 미리보기: npx walwal-harness migrate --dry-run');
|
|
1011
|
+
console.log('');
|
|
1012
|
+
console.log(' ※ 자동 강제 X — 사용자가 명령을 실행할 때만 변경됩니다.');
|
|
1013
|
+
console.log(' ※ 변경 전 .harness/archive/migration-<ts>/ 에 자동 백업.');
|
|
1014
|
+
console.log('');
|
|
1015
|
+
}
|
|
1016
|
+
|
|
1017
|
+
function runMigrate(opts = {}) {
|
|
1018
|
+
const dryRun = opts.dryRun || false;
|
|
1019
|
+
const flags = detectMigrationNeeded();
|
|
1020
|
+
if (!flags.progressV3toV4 && !flags.configMissingModeSelection) {
|
|
1021
|
+
console.log('');
|
|
1022
|
+
log('이미 최신 버전입니다 (progress.json v' + TARGET_PROGRESS_VERSION + ' + config.json mode_selection 존재).');
|
|
1023
|
+
return;
|
|
1024
|
+
}
|
|
1025
|
+
|
|
1026
|
+
console.log('');
|
|
1027
|
+
log(dryRun ? '=== DRY RUN — 실제 변경 없음 ===' : '=== Migration 적용 ===');
|
|
1028
|
+
|
|
1029
|
+
const ts = new Date().toISOString().replace(/[:.]/g, '-');
|
|
1030
|
+
const backupDir = path.join(HARNESS_DIR, 'archive', `migration-${ts}`);
|
|
1031
|
+
if (!dryRun) ensureDir(backupDir);
|
|
1032
|
+
|
|
1033
|
+
// 1. progress.json
|
|
1034
|
+
const progressPath = path.join(HARNESS_DIR, 'progress.json');
|
|
1035
|
+
if (flags.progressV3toV4 && fs.existsSync(progressPath)) {
|
|
1036
|
+
const original = fs.readFileSync(progressPath, 'utf8');
|
|
1037
|
+
const p = JSON.parse(original);
|
|
1038
|
+
const oldMode = p.mode ?? 'solo';
|
|
1039
|
+
const newP = {
|
|
1040
|
+
...p,
|
|
1041
|
+
version: TARGET_PROGRESS_VERSION,
|
|
1042
|
+
mode: 'auto',
|
|
1043
|
+
mode_decision: {
|
|
1044
|
+
owner: 'conductor',
|
|
1045
|
+
decided_at: null,
|
|
1046
|
+
rationale: `migration v3→v4 — 기존 mode="${oldMode}" 를 user_override 로 보존`,
|
|
1047
|
+
user_override: oldMode === 'team' || oldMode === 'solo' ? oldMode : null,
|
|
1048
|
+
},
|
|
1049
|
+
};
|
|
1050
|
+
log(` progress.json: version 3 → ${TARGET_PROGRESS_VERSION}, mode "${oldMode}" → "auto" (user_override="${newP.mode_decision.user_override}")`);
|
|
1051
|
+
if (!dryRun) {
|
|
1052
|
+
fs.writeFileSync(path.join(backupDir, 'progress.json'), original);
|
|
1053
|
+
fs.writeFileSync(progressPath, JSON.stringify(newP, null, 2) + '\n');
|
|
1054
|
+
}
|
|
1055
|
+
}
|
|
1056
|
+
|
|
1057
|
+
// 2. config.json — inject mode_selection from template if missing
|
|
1058
|
+
const configPath = path.join(HARNESS_DIR, 'config.json');
|
|
1059
|
+
const tplPath = path.join(PKG_ROOT, 'assets', 'templates', 'config.json');
|
|
1060
|
+
if (flags.configMissingModeSelection && fs.existsSync(configPath) && fs.existsSync(tplPath)) {
|
|
1061
|
+
const original = fs.readFileSync(configPath, 'utf8');
|
|
1062
|
+
const c = JSON.parse(original);
|
|
1063
|
+
const tpl = JSON.parse(fs.readFileSync(tplPath, 'utf8'));
|
|
1064
|
+
if (tpl.mode_selection) {
|
|
1065
|
+
c.mode_selection = tpl.mode_selection;
|
|
1066
|
+
log(' config.json: mode_selection 섹션 주입 (default_mode=auto, owner=conductor, force_team_when ready≥3+features≥6+depth≤2, tie_breaker=solo)');
|
|
1067
|
+
if (!dryRun) {
|
|
1068
|
+
fs.writeFileSync(path.join(backupDir, 'config.json'), original);
|
|
1069
|
+
fs.writeFileSync(configPath, JSON.stringify(c, null, 2) + '\n');
|
|
1070
|
+
}
|
|
1071
|
+
}
|
|
1072
|
+
}
|
|
1073
|
+
|
|
1074
|
+
console.log('');
|
|
1075
|
+
if (dryRun) {
|
|
1076
|
+
log('Dry-run 완료 — 실제 변경 적용하려면 `npx walwal-harness migrate` 실행');
|
|
1077
|
+
} else {
|
|
1078
|
+
log(`Migration 완료. 백업: ${backupDir}`);
|
|
1079
|
+
log('Conductor 가 다음 sprint 시작 시 자동으로 모드 결정합니다.');
|
|
1080
|
+
log('자동 결정 무시하려면 /harness-solo 또는 /harness-team override.');
|
|
1081
|
+
}
|
|
1082
|
+
console.log('');
|
|
1083
|
+
}
|
|
1084
|
+
|
|
968
1085
|
function main() {
|
|
969
1086
|
if (isHelp) {
|
|
970
1087
|
showHelp();
|
|
@@ -976,6 +1093,11 @@ function main() {
|
|
|
976
1093
|
return;
|
|
977
1094
|
}
|
|
978
1095
|
|
|
1096
|
+
if (subcommand === 'migrate') {
|
|
1097
|
+
runMigrate({ dryRun: args.includes('--dry-run') });
|
|
1098
|
+
return;
|
|
1099
|
+
}
|
|
1100
|
+
|
|
979
1101
|
// Legacy subcommands — redirect to new equivalents
|
|
980
1102
|
if (subcommand === 'studio' || subcommand === 'studio-v4' || subcommand === 'v4') {
|
|
981
1103
|
log('NOTE: "studio" and "v4" subcommands are replaced by "team".');
|
|
@@ -1006,6 +1128,22 @@ function main() {
|
|
|
1006
1128
|
checkPlaywrightMcp();
|
|
1007
1129
|
checkRecommendedSkills();
|
|
1008
1130
|
|
|
1131
|
+
// v6.0 — propose migration if existing project is on v3
|
|
1132
|
+
const migFlags = detectMigrationNeeded();
|
|
1133
|
+
if (migFlags.progressV3toV4 || migFlags.configMissingModeSelection) {
|
|
1134
|
+
showMigrationProposal(migFlags);
|
|
1135
|
+
}
|
|
1136
|
+
|
|
1137
|
+
// v6.0 — Brick Office dashboard one-liner
|
|
1138
|
+
console.log('');
|
|
1139
|
+
console.log('╔══════════════════════════════════════════════════════════╗');
|
|
1140
|
+
console.log('║ Brick Office — 라이브 운영 대시보드 (선택) ║');
|
|
1141
|
+
console.log('╚══════════════════════════════════════════════════════════╝');
|
|
1142
|
+
console.log(' bash scripts/harness-dashboard-up.sh');
|
|
1143
|
+
console.log(' → http://localhost:3001 에서 .harness/ 상태 실시간 시각화');
|
|
1144
|
+
console.log(' → 첫 실행 시 git sparse-checkout 으로 ~5MB 만 가져옵니다.');
|
|
1145
|
+
console.log('');
|
|
1146
|
+
|
|
1009
1147
|
console.log('');
|
|
1010
1148
|
log('═══ Initialization Complete ═══');
|
|
1011
1149
|
log('');
|
package/commands/harness-next.md
CHANGED
|
@@ -32,7 +32,9 @@ bash scripts/harness-next.sh .
|
|
|
32
32
|
- 에스컬레이션 체크 (3회 실패 시 → Planner)
|
|
33
33
|
- 마지막 에이전트면 자동 archive 실행
|
|
34
34
|
|
|
35
|
-
### Step 2: handoff.json 읽고 다음 에이전트
|
|
35
|
+
### Step 2: handoff.json 읽고 다음 에이전트 **즉시 호출** (필수)
|
|
36
|
+
|
|
37
|
+
> **중요**: Step 1 완료 후 사용자에게 "다음 단계를 실행하시겠습니까?" 같은 추가 확인을 받지 마세요. 사용자가 이미 `/harness-next`를 호출한 시점에 다음 단계 실행에 동의한 것으로 간주합니다. 곧바로 Skill 도구로 `to` 필드의 스킬을 호출하세요.
|
|
36
38
|
|
|
37
39
|
```bash
|
|
38
40
|
cat .harness/handoff.json | jq '{from, to, sprint, prompt, model, thinking_mode, failure_context}'
|
package/commands/harness-solo.md
CHANGED
|
@@ -4,15 +4,31 @@ docmeta:
|
|
|
4
4
|
title: /harness-solo — Solo Mode 시작/전환
|
|
5
5
|
type: input
|
|
6
6
|
createdAt: 2026-04-20T00:00:00Z
|
|
7
|
-
updatedAt: 2026-
|
|
7
|
+
updatedAt: 2026-05-07T00:00:00Z
|
|
8
8
|
source:
|
|
9
9
|
producer: user
|
|
10
10
|
skillId: harness
|
|
11
|
-
inputs:
|
|
12
|
-
|
|
11
|
+
inputs:
|
|
12
|
+
- documentId: skill-conductor
|
|
13
|
+
uri: ../skills/conductor/SKILL.md
|
|
14
|
+
relation: output-from
|
|
15
|
+
sections:
|
|
16
|
+
- sourceRange: { startLine: 115, endLine: 145 } # §7.5 모드 결정 위임 룰 + user_override 채널
|
|
17
|
+
targetRange: { startLine: 17, endLine: 22 } # 본 명령의 v6.0 override 안내 블록
|
|
18
|
+
- documentId: config-template
|
|
19
|
+
uri: ../assets/templates/config.json
|
|
20
|
+
relation: output-from
|
|
21
|
+
sections:
|
|
22
|
+
- sourceRange: { startLine: 345, endLine: 372 } # mode_selection 룰 (force_solo_when 등)
|
|
23
|
+
targetRange: { startLine: 17, endLine: 22 }
|
|
24
|
+
tags: [harness, solo-mode, command, override, v6]
|
|
13
25
|
---
|
|
14
26
|
|
|
15
|
-
# /harness-solo — Solo Mode
|
|
27
|
+
# /harness-solo — Solo Mode 사용자 Override (v6.0+)
|
|
28
|
+
|
|
29
|
+
> v6.0 부터 모드 결정은 **Conductor 가 자동**으로 합니다 (config.json `mode_selection.rules`). 본 명령은 Conductor 의 자동 결정을 사용자가 강제로 덮어쓰는 **override** 입니다.
|
|
30
|
+
>
|
|
31
|
+
> **효과**: `progress.json.mode = "solo"` 강제 + `mode_decision.user_override = "solo"` 기록. 현재 sprint 끝까지 유지. 다음 sprint 진입 시 Conductor 가 재자동결정. **Auto 복귀**: 사용자 발화 "auto 로 돌려" 또는 "Conductor 결정으로".
|
|
16
32
|
|
|
17
33
|
프롬프트 기반으로 하네스 파이프라인을 순차 진행합니다.
|
|
18
34
|
Team 모드에서 전환 시, 진행 중이던 피처의 상태를 보존하고 Solo로 이어갑니다.
|
package/commands/harness-team.md
CHANGED
|
@@ -1,18 +1,34 @@
|
|
|
1
1
|
---
|
|
2
2
|
docmeta:
|
|
3
3
|
id: harness-team
|
|
4
|
-
title: /harness-team — Team Mode
|
|
4
|
+
title: /harness-team — Team Mode 사용자 Override (v6.0+)
|
|
5
5
|
type: input
|
|
6
6
|
createdAt: 2026-04-20T00:00:00Z
|
|
7
|
-
updatedAt: 2026-
|
|
7
|
+
updatedAt: 2026-05-07T00:00:00Z
|
|
8
8
|
source:
|
|
9
9
|
producer: user
|
|
10
10
|
skillId: harness
|
|
11
|
-
inputs:
|
|
12
|
-
|
|
11
|
+
inputs:
|
|
12
|
+
- documentId: skill-conductor
|
|
13
|
+
uri: ../skills/conductor/SKILL.md
|
|
14
|
+
relation: output-from
|
|
15
|
+
sections:
|
|
16
|
+
- sourceRange: { startLine: 115, endLine: 145 } # §7.5 모드 결정 + user_override
|
|
17
|
+
targetRange: { startLine: 17, endLine: 22 }
|
|
18
|
+
- documentId: config-template
|
|
19
|
+
uri: ../assets/templates/config.json
|
|
20
|
+
relation: output-from
|
|
21
|
+
sections:
|
|
22
|
+
- sourceRange: { startLine: 345, endLine: 372 } # mode_selection.rules.force_team_when
|
|
23
|
+
targetRange: { startLine: 17, endLine: 22 }
|
|
24
|
+
tags: [harness, team-mode, tmux, command, override, v6]
|
|
13
25
|
---
|
|
14
26
|
|
|
15
|
-
# /harness-team — Team Mode
|
|
27
|
+
# /harness-team — Team Mode 사용자 Override (v6.0+)
|
|
28
|
+
|
|
29
|
+
> v6.0 부터 모드 결정은 **Conductor 가 자동**으로 합니다 (config.json `mode_selection.rules.force_team_when`: ready≥3 + features≥6 + critical_path_depth≤2). 본 명령은 Conductor 의 자동 결정을 사용자가 강제로 덮어쓰는 **override** 입니다.
|
|
30
|
+
>
|
|
31
|
+
> **효과**: `progress.json.mode = "team"` 강제 + `mode_decision.user_override = "team"` 기록 + tmux 세션 부팅. 현재 sprint 끝까지 유지. 다음 sprint 진입 시 Conductor 가 재자동결정. **Auto 복귀**: 사용자 발화 "auto 로 돌려" 또는 "Conductor 결정으로".
|
|
16
32
|
|
|
17
33
|
Planner가 완료한 feature-list.json의 피처들을 최대 3개 팀이 병렬로 Gen→Eval 사이클을 수행합니다.
|
|
18
34
|
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
---
|
|
2
|
+
docmeta:
|
|
3
|
+
id: gotchas-dispatcher
|
|
4
|
+
title: Gotchas — Dispatcher (CEO)
|
|
5
|
+
type: input
|
|
6
|
+
createdAt: 2026-05-07T00:00:00Z
|
|
7
|
+
updatedAt: 2026-05-07T00:00:00Z
|
|
8
|
+
source:
|
|
9
|
+
producer: agent
|
|
10
|
+
skillId: harness-dispatcher
|
|
11
|
+
inputs:
|
|
12
|
+
- documentId: user-feedback-v6.0.0
|
|
13
|
+
uri: (inline — Owner 의 정체성/자율 실행 룰 위반 지적)
|
|
14
|
+
relation: output-from
|
|
15
|
+
note: inline 입력으로 sourceRange 는 단일 1..1 placeholder. 각 [G-NNN] 항목이 별개 발화 사건.
|
|
16
|
+
sections:
|
|
17
|
+
- sourceRange: { startLine: 1, endLine: 1 } # "왜 나를 CEO로 이해하지?" 발화
|
|
18
|
+
targetRange: { startLine: 17, endLine: 25 } # [G-001] Identity confusion
|
|
19
|
+
- sourceRange: { startLine: 1, endLine: 1 } # "왜 나에게 next를 물어볼까?" 발화
|
|
20
|
+
targetRange: { startLine: 27, endLine: 34 } # [G-002] 자율 실행 위반
|
|
21
|
+
- sourceRange: { startLine: 1, endLine: 1 } # G-002 의 명료화 boundary 추론
|
|
22
|
+
targetRange: { startLine: 36, endLine: 43 } # [G-003] 명료화는 짧게
|
|
23
|
+
- sourceRange: { startLine: 1, endLine: 1 } # AGENTS.md 단일 대화 창구 룰 (관련 docref)
|
|
24
|
+
targetRange: { startLine: 45, endLine: 52 } # [G-004] 직접 라우팅 금지
|
|
25
|
+
- documentId: AGENTS-md-template
|
|
26
|
+
uri: ../assets/templates/AGENTS.md.template
|
|
27
|
+
relation: output-from
|
|
28
|
+
note: 단일 대화 창구 룰 (Owner ↔ Dispatcher) 의 권위 출처.
|
|
29
|
+
sections:
|
|
30
|
+
- sourceRange: { startLine: 1, endLine: 1 }
|
|
31
|
+
targetRange: { startLine: 45, endLine: 52 }
|
|
32
|
+
tags: [gotchas, dispatcher, ceo, identity, autonomy]
|
|
33
|
+
---
|
|
34
|
+
|
|
35
|
+
# Gotchas — Dispatcher (CEO)
|
|
36
|
+
|
|
37
|
+
> Dispatcher 는 walwal-harness 의 CEO. **Owner(사용자)와 회사 사이의 유일한 대화 창구**입니다. 매 세션 시작 시 이 파일을 읽고 같은 실수를 반복하지 않습니다.
|
|
38
|
+
|
|
39
|
+
### [G-001] 정체성 혼선 — 사용자를 CEO 로 다루지 말 것
|
|
40
|
+
- **Date**: 2026-05-07
|
|
41
|
+
- **Status**: verified
|
|
42
|
+
- **Trigger**: 사용자 발화 "왜 나를 CEO로 이해하지? 내가 CEO에게 이야기 하는것인데?"
|
|
43
|
+
- **Wrong**: Dispatcher 가 응답에서 "CEO 직접 리뷰 기반…" 같이 사용자를 CEO 로 지칭하거나, 사용자가 CEO 의 권한 (GOAL 자유 변경, 부서 직접 명령) 을 가진 듯 동작.
|
|
44
|
+
- **Right**: 사용자 = **Owner**, Dispatcher = **CEO**. Owner 는 미션을 던지고, CEO 가 GOAL 으로 정립한 뒤 회사를 자율 운영한다. Owner 는 회사의 운영 방식이 아니라 **방향과 평가** 를 제시한다.
|
|
45
|
+
- **Why**: 정체성이 흐려지면 (a) Owner 에게 회사 내부 결정을 떠넘김, (b) Dispatcher 의 단일 대화 창구 룰이 약화, (c) Conductor/Planner 가 Owner 를 직접 호출하는 위반이 연쇄.
|
|
46
|
+
- **Scope**: 모든 응답 문구, GOAL 작성, 부서 호출 안내, escalation 보고.
|
|
47
|
+
|
|
48
|
+
### [G-002] 자율 실행 위반 — 사용자에게 진행 여부를 묻지 말 것
|
|
49
|
+
- **Date**: 2026-05-07
|
|
50
|
+
- **Status**: verified
|
|
51
|
+
- **Trigger**: 사용자 발화 "왜 나에게 next를 물어볼까? Goal이 정해졌으면 바로 하네스 넥서스 회사가 자율적으로 움직여야 하는것 아닌가?"
|
|
52
|
+
- **Wrong**: GOAL 확정 후에도 "/harness-next 자동 진행하시겠습니까?", "다음 단계로 진행할까요?" 같은 사용자 펌프 질문 출력.
|
|
53
|
+
- **Right**: GOAL 이 명확해지면 즉시 **Conductor 자율 시동**. 사용자 개입 없이 Planner → Gen → Eval chain 무인 진행. 사용자에게 돌아오는 시점은 (a) GOAL 자체가 모호해 명료화 필요, (b) 결과 보고, (c) escalation (3회 FAIL / 인시던트 / GOAL 위반) 셋 뿐.
|
|
54
|
+
- **Why**: NEXUS 도큐트린 P3 "Continuous Loop > End-of-Pipeline" 위반. 사용자 펌프 = 자율성 부재. 회사가 매 단계 사용자 허락을 구하면 NEXUS 메타포 자체가 무너짐.
|
|
55
|
+
- **Scope**: dispatcher → planner / dispatcher → conductor 핸드오프 모든 시점, eval PASS 후 다음 단계 진입, sprint 경계 (단 새 sprint 의 GOAL 이 모호하면 명료화 한 번만).
|
|
56
|
+
|
|
57
|
+
### [G-003] GOAL 모호성 명료화는 **짧게** 한 번만
|
|
58
|
+
- **Date**: 2026-05-07
|
|
59
|
+
- **Status**: unverified
|
|
60
|
+
- **Trigger**: G-002 의 boundary case
|
|
61
|
+
- **Wrong**: GOAL 명료화를 빌미로 사용자에게 5~10 개 질문 폭탄, 또는 매 sprint 시작 때마다 재명료화.
|
|
62
|
+
- **Right**: 미션이 진짜로 양 갈래일 때 단 1~2 개 질문, AskUserQuestion 으로 객관식. 그 외에는 합리적 해석으로 GOAL 작성 후 Conductor 시동. 결과가 의도와 다르면 사용자가 사후 교정.
|
|
63
|
+
- **Why**: 명료화 인터럽트가 자율성 위반의 우회 통로가 되지 않도록.
|
|
64
|
+
- **Scope**: dispatcher 의 GOAL 정립 단계.
|
|
65
|
+
|
|
66
|
+
### [G-004] Owner ↔ Conductor / Planner / Generator / Evaluator 직접 라우팅 금지
|
|
67
|
+
- **Date**: 2026-05-07
|
|
68
|
+
- **Status**: verified
|
|
69
|
+
- **Trigger**: AGENTS.md 단일 대화 창구 룰
|
|
70
|
+
- **Wrong**: Dispatcher 가 "Conductor 가 작업 중이니 직접 물어보세요" 또는 사용자 발화를 Conductor 응답으로 직접 전달.
|
|
71
|
+
- **Right**: 모든 부서 ↔ Owner 통신은 Dispatcher 경유. Conductor 의 escalation 도 Dispatcher 가 받아 Owner 에게 요약 보고. Owner 의 추가 입력도 Dispatcher 가 정제해 부서로 전달.
|
|
72
|
+
- **Scope**: 모든 inbound/outbound owner 통신.
|