@walwal-harness/cli 7.1.1 → 7.1.3
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/assets/templates/AGENTS-ko.md.template +160 -0
- package/assets/templates/AGENTS.md.template +103 -72
- package/assets/templates/config.json +20 -192
- package/assets/templates/progress.json.template +4 -4
- package/bin/init.js +143 -48
- package/commands/goal.md +2 -0
- package/commands/hot-fix.md +10 -7
- package/package.json +1 -1
- package/scripts/harness-session-start.sh +6 -6
- package/scripts/harness-user-prompt-submit.sh +6 -6
- package/commands/play-harness.md +0 -22
- package/commands/release-harness.md +0 -22
- package/commands/stop-harness.md +0 -21
|
@@ -0,0 +1,160 @@
|
|
|
1
|
+
# AGENTS.md — {{PROJECT_NAME}}
|
|
2
|
+
# walwal-harness v7.1 | Company Mode
|
|
3
|
+
# 설치일: {{DATE}} | CLAUDE.md는 이 파일의 심볼릭 링크입니다.
|
|
4
|
+
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
## 1. 코딩 전 생각하기
|
|
8
|
+
|
|
9
|
+
**가정하지 않는다. 혼란을 숨기지 않는다. 트레이드오프를 드러낸다.**
|
|
10
|
+
|
|
11
|
+
구현 전:
|
|
12
|
+
- 가정을 명시적으로 밝힌다. 불확실하면 질문한다.
|
|
13
|
+
- 여러 해석이 가능하면 모두 제시한다 — 조용히 선택하지 않는다.
|
|
14
|
+
- 더 단순한 접근이 있으면 말한다. 필요할 때 반론을 제기한다.
|
|
15
|
+
- 불명확한 것이 있으면 멈춘다. 무엇이 혼란스러운지 명시하고 질문한다.
|
|
16
|
+
|
|
17
|
+
## 2. 단순함 우선
|
|
18
|
+
|
|
19
|
+
**문제를 해결하는 최소한의 코드. 추측성 구현은 없다.**
|
|
20
|
+
|
|
21
|
+
- 요청받은 것 이상의 기능을 추가하지 않는다.
|
|
22
|
+
- 단일 용도 코드에 추상화를 도입하지 않는다.
|
|
23
|
+
- 요청하지 않은 "유연성"이나 "설정 가능성"을 추가하지 않는다.
|
|
24
|
+
- 불가능한 시나리오에 대한 에러 처리를 추가하지 않는다.
|
|
25
|
+
- 200줄로 작성했는데 50줄로 될 수 있다면, 다시 작성한다.
|
|
26
|
+
|
|
27
|
+
스스로에게 물어본다: "시니어 엔지니어가 이것을 과도하게 복잡하다고 할까?" 그렇다면 단순화한다.
|
|
28
|
+
|
|
29
|
+
## 3. 외과적 변경
|
|
30
|
+
|
|
31
|
+
**반드시 필요한 것만 건드린다. 자신이 만든 혼란만 정리한다.**
|
|
32
|
+
|
|
33
|
+
기존 코드를 편집할 때:
|
|
34
|
+
- 인접한 코드, 주석, 포맷을 "개선"하지 않는다.
|
|
35
|
+
- 망가지지 않은 것을 리팩터링하지 않는다.
|
|
36
|
+
- 자신이 다르게 작성할 것이라도 기존 스타일을 따른다.
|
|
37
|
+
- 관련 없는 죽은 코드를 발견하면 언급한다 — 삭제하지 않는다.
|
|
38
|
+
|
|
39
|
+
변경으로 인해 고아가 생길 때:
|
|
40
|
+
- 자신의 변경이 만든 미사용 import/변수/함수를 제거한다.
|
|
41
|
+
- 기존에 있던 죽은 코드는 요청받지 않는 한 제거하지 않는다.
|
|
42
|
+
|
|
43
|
+
판단 기준: 변경된 모든 줄이 사용자의 요청으로 직접 추적 가능해야 한다.
|
|
44
|
+
|
|
45
|
+
## 4. 목표 주도 실행
|
|
46
|
+
|
|
47
|
+
**성공 기준을 정의한다. 검증될 때까지 반복한다.**
|
|
48
|
+
|
|
49
|
+
작업을 검증 가능한 목표로 변환한다:
|
|
50
|
+
- "유효성 검사 추가" → "잘못된 입력에 대한 테스트 작성 후 통과시키기"
|
|
51
|
+
- "버그 수정" → "버그를 재현하는 테스트 작성 후 통과시키기"
|
|
52
|
+
- "X 리팩터링" → "리팩터링 전후로 테스트가 통과함을 확인"
|
|
53
|
+
|
|
54
|
+
다단계 작업의 경우 간략한 계획을 제시한다:
|
|
55
|
+
```
|
|
56
|
+
1. [단계] → 검증: [확인 방법]
|
|
57
|
+
2. [단계] → 검증: [확인 방법]
|
|
58
|
+
3. [단계] → 검증: [확인 방법]
|
|
59
|
+
```
|
|
60
|
+
|
|
61
|
+
명확한 성공 기준은 독립적인 반복을 가능하게 한다. 모호한 기준("잘 동작하게 해줘")은 지속적인 확인을 요구한다.
|
|
62
|
+
|
|
63
|
+
---
|
|
64
|
+
|
|
65
|
+
**이 가이드라인이 작동하고 있다면:** diff에서 불필요한 변경이 줄고, 과도한 복잡성으로 인한 재작성이 줄고, 실수 후가 아닌 구현 전에 명확화 질문이 나온다.
|
|
66
|
+
|
|
67
|
+
---
|
|
68
|
+
---
|
|
69
|
+
|
|
70
|
+
# walwal-harness v7.1 — Company Mode
|
|
71
|
+
|
|
72
|
+
이 프로젝트는 walwal-harness company mode로 운영된다.
|
|
73
|
+
위 행동 가이드라인에 더해 아래 규칙이 추가로 적용된다.
|
|
74
|
+
|
|
75
|
+
## 5. 진입점
|
|
76
|
+
|
|
77
|
+
Owner가 회사에 접근하는 명령은 두 개뿐이다. 그 외의 경로는 없다.
|
|
78
|
+
|
|
79
|
+
| 명령 | 사용 시점 |
|
|
80
|
+
|---|---|
|
|
81
|
+
| `/goal` | 미션 설정, 수정, 추가 |
|
|
82
|
+
| `/hot-fix` | 활성 goal과 독립된 긴급 수정 |
|
|
83
|
+
|
|
84
|
+
`/ceo`, `/cto`, `/cqo`, `/coo`, `/cdo`, `/ops`, `/hiring`은 slash command가 아니다.
|
|
85
|
+
내부 라우팅은 agent/skill wiring으로만 처리한다.
|
|
86
|
+
|
|
87
|
+
## 6. Company 구조
|
|
88
|
+
|
|
89
|
+
```
|
|
90
|
+
Owner
|
|
91
|
+
└─ /goal 또는 /hot-fix
|
|
92
|
+
└─ harness-ceo 오케스트레이터 — Owner의 유일한 접점
|
|
93
|
+
├─ harness-coo 리서치, 가설, 서비스 방향
|
|
94
|
+
├─ harness-cdo 브랜딩, UI/UX, 디자인 리뷰
|
|
95
|
+
├─ harness-cto 아키텍처, API, 플랫폼, 구현 총괄
|
|
96
|
+
├─ harness-cqo 품질 게이트, 회귀, archive, gotcha/convention 관리
|
|
97
|
+
└─ harness-ops 빌드 모니터링, 로그 분석, 서비스 이벤트
|
|
98
|
+
```
|
|
99
|
+
|
|
100
|
+
각 CXX는:
|
|
101
|
+
- **독립된 fresh session 컨텍스트**에서 실행된다 — CEO 세션과 메모리를 공유하지 않는다
|
|
102
|
+
- 결정을 `.harness/documents/{mission_name}/{cxx}.md`에 기록한다
|
|
103
|
+
- 모든 전문 작업을 hired worker에게 위임한다 — 직접 실행하지 않는다
|
|
104
|
+
- 필요한 worker가 없으면 `harness-hiring`을 먼저 호출한다
|
|
105
|
+
|
|
106
|
+
CEO는 worker 기록 없이 완료된 산출물을 포함한 CXX 보고서를 거부한다.
|
|
107
|
+
|
|
108
|
+
## 7. 미션 플로우
|
|
109
|
+
|
|
110
|
+
### Goal
|
|
111
|
+
|
|
112
|
+
1. CEO가 Owner 요청을 읽고 판단한다: 브레인스토밍 먼저, 또는 즉시 실행.
|
|
113
|
+
2. CEO가 관련 CXX에게만 범위를 한정한 질문을 전달한다.
|
|
114
|
+
3. 각 CXX가 worker를 고용하고, 위임하고, 결과를 수집하여 `{cxx}.md`에 기록한다.
|
|
115
|
+
4. CEO가 CXX 산출물을 종합하여 다음 CXX에 라우팅하거나 Owner에게 보고한다.
|
|
116
|
+
|
|
117
|
+
**완료 기준:** `.harness/documents/{mission_name}/ceo.md`에 최종 Owner 보고가 존재한다.
|
|
118
|
+
|
|
119
|
+
### Hot Fix
|
|
120
|
+
|
|
121
|
+
1. CEO가 긴급 요청을 받고 즉시 CTO와 CQO를 소집한다.
|
|
122
|
+
2. CTO가 최소 패치 경로를 설계하고 구현 worker를 고용한다.
|
|
123
|
+
3. Worker가 구현한다. CTO가 worker 증거를 검증하고 `cto.md`를 작성한다.
|
|
124
|
+
4. CQO가 회귀 게이트를 실행한다. `.harness/gotchas/` 또는 `.harness/conventions/`에 교훈을 등록하고 `cqo.md`를 작성한다.
|
|
125
|
+
5. CQO 판정 **PASS** 이후에만 archive한다.
|
|
126
|
+
|
|
127
|
+
**완료 기준:** `cto.md`, `cqo.md`, 그리고 최소 하나의 신규 gotcha 또는 convention 항목이 존재한다.
|
|
128
|
+
|
|
129
|
+
주의: harness 문서(ceo.md, cto.md, cqo.md, worker 보고서)에 대한 docmeta skip 판단은 미션 프로토콜 단계를 건너뛸 권한을 부여하지 않는다. 이 파일들은 분석 산출물이 아니라 미션 기록이다.
|
|
130
|
+
|
|
131
|
+
## 8. 하네스 런타임
|
|
132
|
+
|
|
133
|
+
| 경로 | 역할 |
|
|
134
|
+
|---|---|
|
|
135
|
+
| `.harness/documents/{mission}/` | 미션별 CXX 결정 기록 및 worker 보고서 |
|
|
136
|
+
| `.harness/conventions/` | 지속 규칙 (CQO가 작성, 미션을 넘어 유지) |
|
|
137
|
+
| `.harness/gotchas/` | 재발 방지 기록 (CQO가 hot-fix마다 작성) |
|
|
138
|
+
| `.harness/memories/` | 장기 공유 컨텍스트 |
|
|
139
|
+
| `.harness/shared/HR-Resource/` | 채용 가능한 worker skill pool |
|
|
140
|
+
| `.harness/archive/` | CQO 승인 완료 미션 (불변) |
|
|
141
|
+
| `.harness/logs/YYYY-MM-DD/` | OPS 예외 로그 (비정상 케이스만) |
|
|
142
|
+
|
|
143
|
+
`.harness/`는 미션 상태 저장소다. 빌드 산출물이 아니다. 삭제하지 않는다.
|
|
144
|
+
|
|
145
|
+
## 9. 금지 규칙
|
|
146
|
+
|
|
147
|
+
1. **`{mission}/cto.md` 없이 소스 코드 편집 금지** — CTO의 범위 승인이 있어야 소스 파일을 수정할 수 있다.
|
|
148
|
+
2. **CXX 사칭 금지** — 현재 모델이 CEO/CTO/CQO를 인라인으로 대행하지 않는다. 설치된 harness skill을 fresh session에서 사용한다.
|
|
149
|
+
3. **이름 없는 worker 금지** — 모든 전문 작업은 `harness-hiring` → `harness-resource-manager`를 거친다.
|
|
150
|
+
4. **CQO 판정 없이 archive 금지** — 명시적 PASS가 담긴 `{mission}/cqo.md`가 존재해야 한다.
|
|
151
|
+
5. **gotcha 등록 생략 금지** — 모든 hot-fix는 `.harness/gotchas/` 또는 `.harness/conventions/`에 최소 하나의 항목을 만든다.
|
|
152
|
+
6. **미션 중 이 파일 편집 금지** — AGENTS.md를 수정하려면 별도 `/goal`을 제출한다.
|
|
153
|
+
|
|
154
|
+
---
|
|
155
|
+
|
|
156
|
+
## 10. 프로젝트 컨텍스트
|
|
157
|
+
|
|
158
|
+
- **기술 스택**: {{TECH_STACK}}
|
|
159
|
+
- **프로젝트 구조**: {{PROJECT_STRUCTURE}}
|
|
160
|
+
- **하네스 설치일**: {{DATE}}
|
|
@@ -1,83 +1,114 @@
|
|
|
1
|
-
# AGENTS.md —
|
|
1
|
+
# AGENTS.md — {{PROJECT_NAME}}
|
|
2
|
+
# walwal-harness v7.1 | Company Mode
|
|
3
|
+
# Installed: {{DATE}} | CLAUDE.md is a symlink to this file.
|
|
2
4
|
|
|
3
|
-
|
|
4
|
-
> CLAUDE.md는 이 파일의 심볼릭 링크입니다.
|
|
5
|
-
> Generated by walwal-harness ({{DATE}})
|
|
5
|
+
---
|
|
6
6
|
|
|
7
|
-
##
|
|
7
|
+
## 1. Entry Points
|
|
8
8
|
|
|
9
|
-
-
|
|
10
|
-
- **Description**: (Planner가 설정)
|
|
11
|
-
- **Phase**: INIT
|
|
12
|
-
- **Harness**: `.harness/HARNESS.md` 참조
|
|
9
|
+
Two Owner-facing commands. Nothing else reaches the company.
|
|
13
10
|
|
|
14
|
-
|
|
11
|
+
| Command | When |
|
|
12
|
+
|---|---|
|
|
13
|
+
| `/goal` | Set, update, or extend a mission |
|
|
14
|
+
| `/hot-fix` | Emergency fix independent of the active goal |
|
|
15
15
|
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
- Database: (scan-project.sh가 감지)
|
|
16
|
+
`/ceo`, `/cto`, `/cqo`, `/coo`, `/cdo`, `/ops`, `/hiring` are not slash commands.
|
|
17
|
+
Internal routing uses agent/skill wiring only.
|
|
19
18
|
|
|
20
|
-
|
|
19
|
+
---
|
|
21
20
|
|
|
22
|
-
|
|
23
|
-
|
|
21
|
+
## 2. Think Before Acting
|
|
22
|
+
|
|
23
|
+
Don't assume. Don't hide confusion.
|
|
24
|
+
|
|
25
|
+
- State assumptions before implementing. If uncertain, ask.
|
|
26
|
+
- If multiple approaches exist, name them — don't pick silently.
|
|
27
|
+
- Minimum change that solves the problem. No speculative scope.
|
|
28
|
+
- If something is unclear, stop. Name what is unclear. Ask.
|
|
29
|
+
|
|
30
|
+
For hot-fix: smallest correct patch only. Do not "improve" adjacent code.
|
|
31
|
+
For goal: define verifiable success criteria before CEO routes to CXX.
|
|
32
|
+
|
|
33
|
+
---
|
|
34
|
+
|
|
35
|
+
## 3. Company Structure
|
|
24
36
|
|
|
25
37
|
```
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
38
|
+
Owner
|
|
39
|
+
└─ /goal or /hot-fix
|
|
40
|
+
└─ harness-ceo orchestrator — Owner's only contact
|
|
41
|
+
├─ harness-coo research, hypothesis, service direction
|
|
42
|
+
├─ harness-cdo branding, UI/UX, design review
|
|
43
|
+
├─ harness-cto architecture, API, platform, implementation
|
|
44
|
+
├─ harness-cqo quality gates, regression, archive, gotcha/convention
|
|
45
|
+
└─ harness-ops build monitoring, log analysis, service events
|
|
30
46
|
```
|
|
31
47
|
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
|
70
|
-
|
|
71
|
-
|
|
|
72
|
-
|
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
48
|
+
Each CXX:
|
|
49
|
+
- Runs in a **fresh session context** — no shared memory with CEO's session
|
|
50
|
+
- Records decisions in `.harness/documents/{mission_name}/{cxx}.md`
|
|
51
|
+
- Delegates all specialist work to hired workers — never executes directly
|
|
52
|
+
- If a required worker is absent, invokes `harness-hiring` before assigning
|
|
53
|
+
|
|
54
|
+
CEO rejects any CXX report that contains completed deliverables without matching worker records.
|
|
55
|
+
|
|
56
|
+
---
|
|
57
|
+
|
|
58
|
+
## 4. Mission Flow
|
|
59
|
+
|
|
60
|
+
### Goal
|
|
61
|
+
|
|
62
|
+
1. CEO reads the Owner request. Decides: brainstorm first, or assign immediately.
|
|
63
|
+
2. CEO sends scoped questions to relevant CXX only.
|
|
64
|
+
3. Each CXX hires workers, collects reports, records decisions in `{cxx}.md`.
|
|
65
|
+
4. CEO aggregates CXX outputs, routes to next CXX or reports to Owner.
|
|
66
|
+
|
|
67
|
+
**Complete when:** `.harness/documents/{mission_name}/ceo.md` contains a final Owner report.
|
|
68
|
+
|
|
69
|
+
### Hot Fix
|
|
70
|
+
|
|
71
|
+
1. CEO receives emergency request. Immediately summons CTO and CQO.
|
|
72
|
+
2. CTO designs the minimum patch path. Hires implementation workers.
|
|
73
|
+
3. Workers implement. CTO verifies evidence, writes `cto.md`.
|
|
74
|
+
4. CQO runs regression gate. Registers a lesson in `.harness/gotchas/` or `.harness/conventions/`. Writes `cqo.md`.
|
|
75
|
+
5. Archive only after CQO verdict: **PASS**.
|
|
76
|
+
|
|
77
|
+
**Complete when:** `cto.md`, `cqo.md`, and at least one new gotcha or convention entry exist.
|
|
78
|
+
|
|
79
|
+
Note: A docmeta skip decision on harness documents (ceo.md, cto.md, cqo.md, worker reports) does not authorize skipping any mission protocol step. These are mission records, not derived output documents.
|
|
80
|
+
|
|
81
|
+
---
|
|
82
|
+
|
|
83
|
+
## 5. Harness Runtime
|
|
84
|
+
|
|
85
|
+
| Path | Role |
|
|
86
|
+
|---|---|
|
|
87
|
+
| `.harness/documents/{mission}/` | CXX decisions and worker reports per mission |
|
|
88
|
+
| `.harness/conventions/` | Durable rules (CQO writes, survives missions) |
|
|
89
|
+
| `.harness/gotchas/` | Recurrence-prevention records (CQO writes per hot-fix) |
|
|
90
|
+
| `.harness/memories/` | Long-term shared context |
|
|
91
|
+
| `.harness/shared/HR-Resource/` | Hireable worker skill pool |
|
|
92
|
+
| `.harness/archive/` | CQO-approved completed missions (immutable) |
|
|
93
|
+
| `.harness/logs/YYYY-MM-DD/` | OPS exception logs (non-happy-path only) |
|
|
94
|
+
|
|
95
|
+
`.harness/` is the mission state store. Not a build artifact. Do not delete.
|
|
96
|
+
|
|
97
|
+
---
|
|
98
|
+
|
|
99
|
+
## 6. Hard Rules
|
|
100
|
+
|
|
101
|
+
1. **No source edit without `{mission}/cto.md`** — CTO scope sign-off is required before any source file is modified.
|
|
102
|
+
2. **No CXX impersonation** — The active model must not act as CEO/CTO/CQO inline. Use installed harness skills in fresh sessions.
|
|
103
|
+
3. **No unnamed workers** — All specialist work routes through `harness-hiring` → `harness-resource-manager`.
|
|
104
|
+
4. **No archive without CQO verdict** — `{mission}/cqo.md` with explicit PASS must exist.
|
|
105
|
+
5. **No gotcha skip** — Every hot-fix produces at least one `.harness/gotchas/` or `.harness/conventions/` entry.
|
|
106
|
+
6. **This file is read-only during missions** — Raise a separate `/goal` to update AGENTS.md.
|
|
107
|
+
|
|
108
|
+
---
|
|
109
|
+
|
|
110
|
+
## 7. Project Context
|
|
111
|
+
|
|
112
|
+
- **Tech Stack**: {{TECH_STACK}}
|
|
113
|
+
- **Structure**: {{PROJECT_STRUCTURE}}
|
|
114
|
+
- **Harness installed**: {{DATE}}
|
|
@@ -1,200 +1,28 @@
|
|
|
1
1
|
{
|
|
2
2
|
"harness": {
|
|
3
3
|
"name": "walwal-harness — NEXUS company harness",
|
|
4
|
-
"version": "
|
|
5
|
-
"description": "
|
|
4
|
+
"version": "7.1.1",
|
|
5
|
+
"description": "v7 company harness. Owner uses /goal or /hot-fix, CEO coordinates CXX agents, CXX agents use resource-manager/hiring, and hired workers produce mission evidence under .harness/documents/{mission}/workers/.",
|
|
6
6
|
"source": "https://www.anthropic.com/engineering/harness-design-long-running-apps"
|
|
7
7
|
},
|
|
8
8
|
"agents": {
|
|
9
|
-
"
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
},
|
|
17
|
-
"
|
|
18
|
-
"role": "사용자의 러프한 요구사항을 대화형으로 구체화하여 Planner가 바로 쓸 수 있는 brainstorm-spec.md로 변환.",
|
|
19
|
-
"skill": "harness-brainstorming",
|
|
20
|
-
"inputs": ["(user conversation)"],
|
|
21
|
-
"outputs": ["actions/brainstorm-spec.md"],
|
|
22
|
-
"conditional": true,
|
|
23
|
-
"trigger_conditions": {
|
|
24
|
-
"comment": "Dispatcher가 아래 조건 중 하나 이상 충족 시 사용자에게 브레인스토밍 제안",
|
|
25
|
-
"rules": [
|
|
26
|
-
"사용자 요청에 구체적 기능명/엔드포인트/화면명이 없고 추상적 목표만 있을 때",
|
|
27
|
-
"PRD/OpenAPI 등 구조화된 입력 문서가 없을 때",
|
|
28
|
-
"'뭔가 만들고 싶은데', '아이디어가 있는데' 등 탐색적 표현이 포함될 때"
|
|
29
|
-
],
|
|
30
|
-
"skip_when": [
|
|
31
|
-
"사용자가 PRD, OpenAPI spec, 또는 구체적 feature list를 제공한 경우",
|
|
32
|
-
"사용자가 '브레인스토밍 없이', 'skip brainstorming'을 명시한 경우",
|
|
33
|
-
"이미 brainstorm-spec.md가 actions/에 존재하는 경우"
|
|
34
|
-
]
|
|
35
|
-
},
|
|
36
|
-
"invoked_by": "dispatcher (user opt-in after suggestion)",
|
|
37
|
-
"next_on_complete": "planner",
|
|
38
|
-
"model": "opus",
|
|
39
|
-
"thinking_mode": "plan",
|
|
40
|
-
"thinking_mode_description": "Claude Code plan 모드로 실행. 구조화된 계획 수립 후 실행.",
|
|
41
|
-
"attribution": "Derived from obra/superpowers skills/brainstorming (MIT License)"
|
|
42
|
-
},
|
|
43
|
-
"planner": {
|
|
44
|
-
"role": "제품 사양 + API 계약서 + 서비스 분할 설계",
|
|
45
|
-
"skill": "harness-planner",
|
|
46
|
-
"inputs": ["actions/brainstorm-spec.md (optional)"],
|
|
47
|
-
"outputs": [
|
|
48
|
-
"actions/plan.md",
|
|
49
|
-
"actions/feature-list.json",
|
|
50
|
-
"actions/api-contract.json"
|
|
51
|
-
],
|
|
52
|
-
"model": "opus",
|
|
53
|
-
"thinking_mode": null,
|
|
54
|
-
"thinking_mode_description": null
|
|
55
|
-
},
|
|
56
|
-
"generator-backend": {
|
|
57
|
-
"role": "NestJS MSA 서비스 구현, API 엔드포인트, DB 스키마",
|
|
58
|
-
"skill": "harness-generator-backend",
|
|
59
|
-
"inputs": ["actions/plan.md", "actions/feature-list.json", "actions/api-contract.json", "actions/sprint-contract.md"],
|
|
60
|
-
"outputs": ["code:backend", "actions/sprint-contract.md"],
|
|
61
|
-
"order": 1,
|
|
62
|
-
"model": "sonnet",
|
|
63
|
-
"thinking_mode": null,
|
|
64
|
-
"model_rationale": "코드 생성은 Sonnet이 비용 대비 효율적. 계획은 Planner가 이미 완료."
|
|
65
|
-
},
|
|
66
|
-
"generator-frontend": {
|
|
67
|
-
"role": "React/Next.js UI 컴포넌트, 상태관리, API 연동",
|
|
68
|
-
"skill": "harness-generator-frontend",
|
|
69
|
-
"inputs": ["actions/plan.md", "actions/feature-list.json", "actions/api-contract.json", "actions/sprint-contract.md"],
|
|
70
|
-
"outputs": ["code:frontend", "actions/sprint-contract.md"],
|
|
71
|
-
"order": 2,
|
|
72
|
-
"model": "sonnet",
|
|
73
|
-
"thinking_mode": null,
|
|
74
|
-
"model_rationale": "코드 생성은 Sonnet이 비용 대비 효율적. 계획은 Planner가 이미 완료."
|
|
75
|
-
},
|
|
76
|
-
"evaluator-code-quality": {
|
|
77
|
-
"role": "코드 자체의 유지보수성/아키텍처/Best Practice 검사 (BE/FE/libs 공통, 브라우저 없음)",
|
|
78
|
-
"skill": "harness-evaluator-code-quality",
|
|
79
|
-
"tools": ["Read", "Grep", "Glob", "Bash(tsc,eslint,biome,lint 스크립트 한정)"],
|
|
80
|
-
"inputs": ["actions/sprint-contract.md", "actions/feature-list.json", "actions/api-contract.json"],
|
|
81
|
-
"outputs": ["actions/evaluation-code-quality.md"],
|
|
82
|
-
"model": "opus",
|
|
83
|
-
"thinking_mode": "ultrathink",
|
|
84
|
-
"thinking_mode_description": "시니어 리뷰어 관점. 변경 파일 전수 정적 분석 + C1-C5 축 적대적 채점.",
|
|
85
|
-
"adversarial_rules": {
|
|
86
|
-
"comment": "Code-Quality Evaluator 적대적 행동 규칙 — rubber-stamping 금지",
|
|
87
|
-
"rules": [
|
|
88
|
-
"브라우저 없이 코드만으로 판정. '동작하니 PASS' 금지.",
|
|
89
|
-
"변경 파일(git diff)은 전수 검사. '시간 제약' 핑계 금지.",
|
|
90
|
-
"모든 Score 주장은 파일:라인 evidence 동반. Evidence 없는 Score = 0.",
|
|
91
|
-
"toolchain(tsc/eslint) 에러 1건 이상이면 나머지 축 채점 전 즉시 FAIL.",
|
|
92
|
-
"api-contract.json ↔ 실제 DTO/시그니처 불일치 1건 이상 = FAIL.",
|
|
93
|
-
"레이어 역방향 의존 / MSA 직접 DB 접근 / FE view→fetch 직결 1건 이상 = C1 Score 0.",
|
|
94
|
-
"unhandled promise 1건 이상 또는 비타당한 any 3건 이상 = C4 Score 0.",
|
|
95
|
-
"PASS를 주기 전에 자문하라: '내가 이 코드를 머지 승인할 수 있는가?' NO이면 FAIL.",
|
|
96
|
-
"반복 페널티: 같은 축에서 이전 스프린트 대비 악화 시 Score 최대 1."
|
|
97
|
-
],
|
|
98
|
-
"forbidden": [
|
|
99
|
-
"'동작은 Functional 에서 확인됐으니 OK' 식의 책임 전가",
|
|
100
|
-
"'관용적 any', '사소한 중복' 같은 자기설득",
|
|
101
|
-
"'제안사항만 남기고 Pass' — 필수 개선은 FAIL",
|
|
102
|
-
"파일 수정/커밋 (이 평가자는 읽기 전용)"
|
|
103
|
-
]
|
|
104
|
-
}
|
|
105
|
-
},
|
|
106
|
-
"evaluator-functional": {
|
|
107
|
-
"role": "Playwright로 E2E 기능 검증, API 응답/DB 상태 확인",
|
|
108
|
-
"skill": "harness-evaluator-functional",
|
|
109
|
-
"tools": ["playwright:browser_*"],
|
|
110
|
-
"inputs": ["actions/sprint-contract.md", "actions/feature-list.json", "actions/api-contract.json"],
|
|
111
|
-
"outputs": ["actions/evaluation-functional.md"],
|
|
112
|
-
"model": "opus",
|
|
113
|
-
"thinking_mode": "ultrathink",
|
|
114
|
-
"thinking_mode_description": "최고 수준의 사고 모드. 적대적 검증에 깊은 추론이 필요. 각 항목을 비판적으로 분석.",
|
|
115
|
-
"evaluation_template": "assets/templates/evaluation-functional.md.template",
|
|
116
|
-
"adversarial_rules": {
|
|
117
|
-
"comment": "Evaluator 적대적 행동 규칙 — 통과 편향 제거를 위한 강제 규칙",
|
|
118
|
-
"rules": [
|
|
119
|
-
"Generator의 '구현 완료' 주장을 절대 신뢰하지 마라. 모든 엔드포인트에 직접 요청을 보내고 응답을 확인하라.",
|
|
120
|
-
"정상 경로(happy path) 1개당 비정상 경로(unhappy path) 최소 2개를 반드시 테스트하라.",
|
|
121
|
-
"api-contract.json과 실제 응답을 필드 단위로 비교하라. 누락 필드, 타입 불일치, 추가 필드 모두 FAIL 사유.",
|
|
122
|
-
"PASS를 주기 전에 자문하라: '내가 이 코드를 직접 작성했다면 이 수준으로 PR을 올리겠는가?' NO이면 FAIL.",
|
|
123
|
-
"AC 항목 하나라도 미통과이면 전체 FAIL. 부분 통과는 인정하지 않는다.",
|
|
124
|
-
"Evidence(증거)가 없는 Score는 0점이다. '확인했다'는 주장은 증거가 아니다.",
|
|
125
|
-
"이전 Sprint에서 PASS된 기능이 하나라도 깨졌으면 신규 기능 점수와 무관하게 FAIL.",
|
|
126
|
-
"Score 3을 주려면 엣지케이스(빈 값, 초과값, 동시 요청, 특수문자)까지 테스트한 증거가 있어야 한다."
|
|
127
|
-
],
|
|
128
|
-
"forbidden": [
|
|
129
|
-
"'전반적으로 잘 구현되었습니다' 류의 모호한 긍정 평가",
|
|
130
|
-
"'사소한 이슈이므로 PASS' — 사소함은 Evaluator가 판단할 사항이 아니다",
|
|
131
|
-
"'시간 제약상 일부만 테스트' — 전수 테스트가 불가하면 FAIL 처리",
|
|
132
|
-
"Generator에게 유리한 방향으로 기준을 해석하는 행위"
|
|
133
|
-
]
|
|
134
|
-
}
|
|
135
|
-
},
|
|
136
|
-
"evaluator-visual": {
|
|
137
|
-
"role": "디자인 일관성, 반응형, 접근성, AI슬롭 감지",
|
|
138
|
-
"skill": "harness-evaluator-visual",
|
|
139
|
-
"tools": ["playwright:browser_take_screenshot", "playwright:browser_resize", "playwright:browser_snapshot"],
|
|
140
|
-
"inputs": ["actions/sprint-contract.md", "actions/evaluation-functional.md", "actions/feature-list.json"],
|
|
141
|
-
"outputs": ["actions/evaluation-visual.md"],
|
|
142
|
-
"model": "opus",
|
|
143
|
-
"thinking_mode": "ultrathink",
|
|
144
|
-
"thinking_mode_description": "최고 수준의 사고 모드. 시각적 결함, 접근성, AI슬롭을 비판적으로 탐지.",
|
|
145
|
-
"evaluation_template": "assets/templates/evaluation-visual.md.template",
|
|
146
|
-
"adversarial_rules": {
|
|
147
|
-
"comment": "Visual Evaluator 적대적 행동 규칙",
|
|
148
|
-
"rules": [
|
|
149
|
-
"모든 페이지를 반드시 3개 뷰포트(375px, 768px, 1280px)에서 스크린샷 촬영하라. 1개라도 누락이면 해당 페이지 Score 산정 불가.",
|
|
150
|
-
"axe-core 접근성 검사를 실제로 실행하라. Critical 또는 Serious 위반이 1건이라도 있으면 V3 = 0.",
|
|
151
|
-
"AI슬롭 패턴(무의미한 그라데이션, 과도한 그림자, 장식 아이콘 남발)을 적극 탐지하라. 2건 이상이면 V4 최대 1점.",
|
|
152
|
-
"evaluation-functional.md의 Cross-Validation Data와 교차 검증하라. API 성공인데 UI에 에러 표시 = 불일치 = FAIL 사유.",
|
|
153
|
-
"이전 Sprint 스크린샷 대비 의도치 않은 시각 변경이 있으면 점수 무관 FAIL.",
|
|
154
|
-
"PASS를 주기 전에 자문하라: '이 UI를 실사용자에게 보여줄 수 있는가?' NO이면 FAIL.",
|
|
155
|
-
"로딩/에러/빈 상태가 하나라도 미구현이면 V5 최대 1점.",
|
|
156
|
-
"Evidence(스크린샷 경로 또는 DOM 스냅샷)가 없는 Score는 0점이다."
|
|
157
|
-
],
|
|
158
|
-
"forbidden": [
|
|
159
|
-
"'디자인이 깔끔합니다' 류의 주관적 긍정 평가",
|
|
160
|
-
"'접근성은 추후 개선' — 접근성은 기본 요건이지 부가 기능이 아니다",
|
|
161
|
-
"'모바일 뷰포트는 생략' — 3개 뷰포트 전수 검사는 필수",
|
|
162
|
-
"스크린샷 없이 '확인했다'고 주장하는 행위"
|
|
163
|
-
]
|
|
164
|
-
}
|
|
165
|
-
}
|
|
9
|
+
"ceo": { "role": "Owner-facing mission intake, CXX orchestration, and final reports", "skill": "harness-ceo", "model": "sonnet" },
|
|
10
|
+
"coo": { "role": "Planning, research, hypothesis, mission fit", "skill": "harness-coo", "model": "sonnet" },
|
|
11
|
+
"cdo": { "role": "Branding, UI/UX, design review", "skill": "harness-cdo", "model": "sonnet" },
|
|
12
|
+
"cto": { "role": "Architecture, platform, API, implementation coordination", "skill": "harness-cto", "model": "opus" },
|
|
13
|
+
"cqo": { "role": "Quality gates, regression, archive criteria", "skill": "harness-cqo", "model": "opus" },
|
|
14
|
+
"ops": { "role": "Build/service environment monitoring and exception logging", "skill": "harness-ops", "model": "sonnet" },
|
|
15
|
+
"hiring": { "role": "Hire missing workers from HR-Resource", "skill": "harness-hiring", "model": "sonnet" },
|
|
16
|
+
"resource-manager": { "role": "Resolve hired-worker availability and invocation wording", "skill": "harness-resource-manager", "model": "haiku" },
|
|
17
|
+
"brick-office": { "role": "Company status and dashboard support", "skill": "harness-brick-office", "model": "haiku" }
|
|
166
18
|
},
|
|
167
19
|
"flow": {
|
|
168
|
-
"sequence": ["
|
|
169
|
-
"
|
|
170
|
-
|
|
171
|
-
"execution": "serial_with_early_exit",
|
|
172
|
-
"order_rationale": "code-quality(정적, 저비용) → functional(동작, 중비용) → visual(렌더, 고비용). 구조가 깨진 코드에 동작 테스트를 낭비하지 않기 위함.",
|
|
173
|
-
"on_any_fail": "reroute_to_generator",
|
|
174
|
-
"on_all_pass": "advance_sprint"
|
|
175
|
-
},
|
|
176
|
-
"pipeline_selection": {
|
|
177
|
-
"comment": "Dispatcher가 pipeline.json으로 활성 에이전트를 결정.",
|
|
178
|
-
"pipelines": {
|
|
179
|
-
"FULLSTACK": ["planner", "generator-backend", "generator-frontend", "evaluator-code-quality", "evaluator-functional", "evaluator-visual"],
|
|
180
|
-
"FE-ONLY": ["planner:light", "generator-frontend", "evaluator-code-quality", "evaluator-functional", "evaluator-visual"],
|
|
181
|
-
"BE-ONLY": ["planner", "generator-backend", "evaluator-code-quality", "evaluator-functional:api-only"]
|
|
182
|
-
},
|
|
183
|
-
"evaluator_chains": {
|
|
184
|
-
"comment": "파이프라인별 평가자 체인. Dispatcher가 pipeline.json.evaluator_chain 으로 기록.",
|
|
185
|
-
"FULLSTACK": ["evaluator-code-quality", "evaluator-functional", "evaluator-visual"],
|
|
186
|
-
"FE-ONLY": ["evaluator-code-quality", "evaluator-functional", "evaluator-visual"],
|
|
187
|
-
"BE-ONLY": ["evaluator-code-quality", "evaluator-functional"]
|
|
188
|
-
}
|
|
189
|
-
},
|
|
190
|
-
"sprint_execution": {
|
|
191
|
-
"comment": "Backend 먼저 → API 안정 후 Frontend 연동 → 기능 QA → 비주얼 QA (FULLSTACK 기준)",
|
|
192
|
-
"backend_first": true,
|
|
193
|
-
"reason": "프론트가 존재하지 않는 API를 호출하는 실패 방지"
|
|
194
|
-
},
|
|
20
|
+
"sequence": ["ceo", "coo", "cdo", "cto", "cqo", "ops"],
|
|
21
|
+
"worker_gate": "CXX agents must use harness-resource-manager and harness-hiring before specialist deliverables.",
|
|
22
|
+
"worker_reports_required": ".harness/documents/{mission}/workers/{worker-name}.md",
|
|
195
23
|
"retry_on_fail": true,
|
|
196
24
|
"max_retries_per_sprint": 5,
|
|
197
|
-
"
|
|
25
|
+
"escalate_to_ceo_after": 3,
|
|
198
26
|
"archive_on_sprint_complete": true,
|
|
199
27
|
"pre_eval_gate": {
|
|
200
28
|
"comment": "Generator → Evaluator 전환 전 결정론적 검증. 실패 시 Evaluator 세션을 열지 않고 Generator로 자동 리라우팅.",
|
|
@@ -338,9 +166,9 @@
|
|
|
338
166
|
}
|
|
339
167
|
},
|
|
340
168
|
"behavior": {
|
|
341
|
-
"comment": "하네스 동작 플래그. UserPromptSubmit 훅이 이 값을 읽어
|
|
342
|
-
"
|
|
343
|
-
"
|
|
169
|
+
"comment": "하네스 동작 플래그. UserPromptSubmit 훅이 이 값을 읽어 v7 CEO/CXX 라우팅 안내를 결정한다.",
|
|
170
|
+
"auto_route_ceo": true,
|
|
171
|
+
"auto_route_ceo_description": "true 이면 /goal 또는 /hot-fix 이후 Owner 입력을 v7 CEO/CXX mission flow 기준으로 안내한다. 사용자가 'harness skip' 등을 말하면 단일 메시지 한정으로 건너뛴다."
|
|
344
172
|
},
|
|
345
173
|
"token_limit": {
|
|
346
174
|
"comment": "모델 토큰 제한으로 작업이 중단됐을 때의 저비용 재개 정책. 별도 probe 호출 없이 시간 기반으로만 재개 알림을 계산한다.",
|
|
@@ -350,9 +178,9 @@
|
|
|
350
178
|
"owner": "session-start"
|
|
351
179
|
},
|
|
352
180
|
"company_mode": {
|
|
353
|
-
"comment": "
|
|
181
|
+
"comment": "v7 — 회사모드는 항시 활성이다. Owner entrypoint는 /goal, /hot-fix이며 CEO가 CXX와 hired worker 흐름을 조정한다.",
|
|
354
182
|
"default_mode": "company",
|
|
355
|
-
"owner": "
|
|
183
|
+
"owner": "ceo",
|
|
356
184
|
"worker_concurrency": 3,
|
|
357
185
|
"worker_spawn": "claude",
|
|
358
186
|
"worker_spawn_description": "claude 이면 idle worker 배정 시 `claude -p` 백그라운드 프로세스를 띄운다. record 로 두면 prompt/log만 생성한다.",
|
|
@@ -2,10 +2,10 @@
|
|
|
2
2
|
"version": 4,
|
|
3
3
|
"mode": "company",
|
|
4
4
|
"mode_decision": {
|
|
5
|
-
"owner": "
|
|
5
|
+
"owner": "ceo",
|
|
6
6
|
"decided_at": null,
|
|
7
|
-
"rationale": "company mode is
|
|
8
|
-
"policy": "
|
|
7
|
+
"rationale": "v7 company mode is CEO-led",
|
|
8
|
+
"policy": "owner_goal_to_ceo_cxx_workers"
|
|
9
9
|
},
|
|
10
10
|
"project_name": "",
|
|
11
11
|
"pipeline": null,
|
|
@@ -21,7 +21,7 @@
|
|
|
21
21
|
"current_agent": null,
|
|
22
22
|
"agent_status": "pending",
|
|
23
23
|
"completed_agents": [],
|
|
24
|
-
"next_agent": "
|
|
24
|
+
"next_agent": "ceo",
|
|
25
25
|
"failure": {
|
|
26
26
|
"agent": null,
|
|
27
27
|
"location": null,
|
package/bin/init.js
CHANGED
|
@@ -859,10 +859,10 @@ function installStatusline() {
|
|
|
859
859
|
}
|
|
860
860
|
|
|
861
861
|
// ─────────────────────────────────────────
|
|
862
|
-
// 3d. UserPromptSubmit hook (
|
|
862
|
+
// 3d. UserPromptSubmit hook (v7 CEO routing guidance)
|
|
863
863
|
// ─────────────────────────────────────────
|
|
864
864
|
function installUserPromptSubmitHook() {
|
|
865
|
-
log('Installing UserPromptSubmit hook (
|
|
865
|
+
log('Installing UserPromptSubmit hook (v7 CEO routing guidance)...');
|
|
866
866
|
|
|
867
867
|
const settingsDir = path.join(PROJECT_ROOT, '.claude');
|
|
868
868
|
|
|
@@ -896,9 +896,9 @@ function installUserPromptSubmitHook() {
|
|
|
896
896
|
});
|
|
897
897
|
writeClaudeSettings(settings);
|
|
898
898
|
log('UserPromptSubmit hook installed in .claude/settings.json');
|
|
899
|
-
log(' →
|
|
899
|
+
log(' → /goal and /hot-fix are guided through harness-ceo and CXX workflow');
|
|
900
900
|
log(' → Opt-out per message: say "harness skip" or "without harness"');
|
|
901
|
-
log(' → Disable globally: set .harness/config.json behavior.
|
|
901
|
+
log(' → Disable globally: set .harness/config.json behavior.auto_route_ceo = false');
|
|
902
902
|
} else {
|
|
903
903
|
log('UserPromptSubmit hook already installed');
|
|
904
904
|
}
|
|
@@ -1185,7 +1185,9 @@ function detectMigrationNeeded() {
|
|
|
1185
1185
|
const memoryTplPath = path.join(PKG_ROOT, 'assets', 'templates', 'memory.md');
|
|
1186
1186
|
const flags = {
|
|
1187
1187
|
progressV3toV4: false,
|
|
1188
|
+
progressLegacyRouting: false,
|
|
1188
1189
|
configMissingCompanyMode: false,
|
|
1190
|
+
configLegacyRouting: false,
|
|
1189
1191
|
memoryMissingSystemEntries: [],
|
|
1190
1192
|
gotchaMissingEntries: {}, // { "<filename>": [G-IDs...] }
|
|
1191
1193
|
conventionMissingEntries: {}, // { "<filename>": [C-IDs...] }
|
|
@@ -1246,12 +1248,22 @@ function detectMigrationNeeded() {
|
|
|
1246
1248
|
try {
|
|
1247
1249
|
const p = JSON.parse(fs.readFileSync(progressPath, 'utf8'));
|
|
1248
1250
|
if ((p.version ?? 0) < TARGET_PROGRESS_VERSION) flags.progressV3toV4 = true;
|
|
1251
|
+
if (
|
|
1252
|
+
['dispatcher', 'planner', 'generator-backend', 'generator-frontend', 'evaluator-functional', 'evaluator-visual', 'service-ops'].includes(p.next_agent) ||
|
|
1253
|
+
p.mode_decision?.owner === 'conductor'
|
|
1254
|
+
) flags.progressLegacyRouting = true;
|
|
1249
1255
|
} catch {}
|
|
1250
1256
|
}
|
|
1251
1257
|
if (fs.existsSync(configPath)) {
|
|
1252
1258
|
try {
|
|
1253
1259
|
const c = JSON.parse(fs.readFileSync(configPath, 'utf8'));
|
|
1254
1260
|
if (!c.company_mode || c.mode_selection) flags.configMissingCompanyMode = true;
|
|
1261
|
+
if (
|
|
1262
|
+
c.behavior?.auto_route_dispatcher !== undefined ||
|
|
1263
|
+
c.behavior?.auto_route_dispatcher_description ||
|
|
1264
|
+
c.company_mode?.owner === 'conductor' ||
|
|
1265
|
+
c.agents?.dispatcher?.skill === 'harness-dispatcher'
|
|
1266
|
+
) flags.configLegacyRouting = true;
|
|
1255
1267
|
} catch {}
|
|
1256
1268
|
}
|
|
1257
1269
|
if (fs.existsSync(memoryPath) && fs.existsSync(memoryTplPath)) {
|
|
@@ -1327,15 +1339,21 @@ function extractConventionEntryBlock(md, id) {
|
|
|
1327
1339
|
function showMigrationProposal(flags) {
|
|
1328
1340
|
console.log('');
|
|
1329
1341
|
console.log('╔══════════════════════════════════════════════════════════╗');
|
|
1330
|
-
console.log('║ walwal-harness
|
|
1342
|
+
console.log('║ walwal-harness v7 — 자동 마이그레이션 사용 가능 ║');
|
|
1331
1343
|
console.log('╚══════════════════════════════════════════════════════════╝');
|
|
1332
1344
|
if (flags.progressV3toV4) {
|
|
1333
1345
|
console.log(' • progress.json: legacy mode → "company"');
|
|
1334
1346
|
console.log(' legacy mode 값은 보존하지 않고 회사모드로 정규화됩니다.');
|
|
1335
1347
|
}
|
|
1348
|
+
if (flags.progressLegacyRouting) {
|
|
1349
|
+
console.log(' • progress.json: legacy dispatcher/conductor routing → v7 CEO routing');
|
|
1350
|
+
}
|
|
1336
1351
|
if (flags.configMissingCompanyMode) {
|
|
1337
1352
|
console.log(' • config.json: company_mode 섹션 동기화 가능');
|
|
1338
|
-
console.log('
|
|
1353
|
+
console.log(' Owner /goal, /hot-fix → CEO/CXX/worker 흐름으로 고정합니다.');
|
|
1354
|
+
}
|
|
1355
|
+
if (flags.configLegacyRouting) {
|
|
1356
|
+
console.log(' • config.json: legacy dispatcher/conductor wording → v7 CEO/CXX wording');
|
|
1339
1357
|
}
|
|
1340
1358
|
if (flags.memoryMissingSystemEntries && flags.memoryMissingSystemEntries.length) {
|
|
1341
1359
|
console.log(' • memory.md: 시스템 entry 누락 — append 가능');
|
|
@@ -1376,7 +1394,9 @@ function runMigrate(opts = {}) {
|
|
|
1376
1394
|
const conventionMissingTotal = Object.values(flags.conventionMissingEntries || {}).reduce((n, a) => n + a.length, 0);
|
|
1377
1395
|
if (
|
|
1378
1396
|
!flags.progressV3toV4 &&
|
|
1397
|
+
!flags.progressLegacyRouting &&
|
|
1379
1398
|
!flags.configMissingCompanyMode &&
|
|
1399
|
+
!flags.configLegacyRouting &&
|
|
1380
1400
|
(!flags.memoryMissingSystemEntries || flags.memoryMissingSystemEntries.length === 0) &&
|
|
1381
1401
|
gotchaMissingTotal === 0 &&
|
|
1382
1402
|
conventionMissingTotal === 0 &&
|
|
@@ -1385,7 +1405,7 @@ function runMigrate(opts = {}) {
|
|
|
1385
1405
|
console.log('');
|
|
1386
1406
|
let pkgVer = 'unknown';
|
|
1387
1407
|
try { pkgVer = JSON.parse(fs.readFileSync(path.join(PKG_ROOT, 'package.json'), 'utf8')).version; } catch {}
|
|
1388
|
-
log(`이미 최신 — bundle v${pkgVer} 일치, progress v${TARGET_PROGRESS_VERSION}, config.company_mode, memory 시스템 entry, gotcha entry 모두 sync.`);
|
|
1408
|
+
log(`이미 최신 — bundle v${pkgVer} 일치, progress v${TARGET_PROGRESS_VERSION} v7 routing, config.company_mode, memory 시스템 entry, gotcha entry 모두 sync.`);
|
|
1389
1409
|
return;
|
|
1390
1410
|
}
|
|
1391
1411
|
|
|
@@ -1398,7 +1418,7 @@ function runMigrate(opts = {}) {
|
|
|
1398
1418
|
|
|
1399
1419
|
// 1. progress.json
|
|
1400
1420
|
const progressPath = path.join(HARNESS_DIR, 'progress.json');
|
|
1401
|
-
if (flags.progressV3toV4 && fs.existsSync(progressPath)) {
|
|
1421
|
+
if ((flags.progressV3toV4 || flags.progressLegacyRouting) && fs.existsSync(progressPath)) {
|
|
1402
1422
|
const original = fs.readFileSync(progressPath, 'utf8');
|
|
1403
1423
|
const p = JSON.parse(original);
|
|
1404
1424
|
const oldMode = p.mode ?? 'company';
|
|
@@ -1407,14 +1427,17 @@ function runMigrate(opts = {}) {
|
|
|
1407
1427
|
version: TARGET_PROGRESS_VERSION,
|
|
1408
1428
|
mode: 'company',
|
|
1409
1429
|
mode_decision: {
|
|
1410
|
-
owner: '
|
|
1430
|
+
owner: 'ceo',
|
|
1411
1431
|
decided_at: null,
|
|
1412
|
-
rationale: `migration — legacy mode="${oldMode}" normalized to company`,
|
|
1413
|
-
policy: '
|
|
1432
|
+
rationale: `migration — legacy mode="${oldMode}" normalized to v7 CEO-led company`,
|
|
1433
|
+
policy: 'owner_goal_to_ceo_cxx_workers',
|
|
1414
1434
|
user_override: null,
|
|
1415
1435
|
},
|
|
1436
|
+
next_agent: ['dispatcher', 'planner', 'generator-backend', 'generator-frontend', 'evaluator-functional', 'evaluator-visual', 'service-ops'].includes(p.next_agent)
|
|
1437
|
+
? 'ceo'
|
|
1438
|
+
: (p.next_agent ?? 'ceo'),
|
|
1416
1439
|
};
|
|
1417
|
-
log(` progress.json:
|
|
1440
|
+
log(` progress.json: v7 routing normalized, mode "${oldMode}" → "company", next_agent="${p.next_agent ?? 'null'}" → "${newP.next_agent}"`);
|
|
1418
1441
|
if (!dryRun) {
|
|
1419
1442
|
fs.writeFileSync(path.join(backupDir, 'progress.json'), original);
|
|
1420
1443
|
fs.writeFileSync(progressPath, JSON.stringify(newP, null, 2) + '\n');
|
|
@@ -1424,14 +1447,26 @@ function runMigrate(opts = {}) {
|
|
|
1424
1447
|
// 2. config.json — inject company_mode from template if missing
|
|
1425
1448
|
const configPath = path.join(HARNESS_DIR, 'config.json');
|
|
1426
1449
|
const tplPath = path.join(PKG_ROOT, 'assets', 'templates', 'config.json');
|
|
1427
|
-
if (flags.configMissingCompanyMode && fs.existsSync(configPath) && fs.existsSync(tplPath)) {
|
|
1450
|
+
if ((flags.configMissingCompanyMode || flags.configLegacyRouting) && fs.existsSync(configPath) && fs.existsSync(tplPath)) {
|
|
1428
1451
|
const original = fs.readFileSync(configPath, 'utf8');
|
|
1429
1452
|
const c = JSON.parse(original);
|
|
1430
1453
|
const tpl = JSON.parse(fs.readFileSync(tplPath, 'utf8'));
|
|
1431
1454
|
if (tpl.company_mode) {
|
|
1432
|
-
c.company_mode =
|
|
1455
|
+
c.company_mode = {
|
|
1456
|
+
...tpl.company_mode,
|
|
1457
|
+
comment: 'v7 — 회사모드는 CEO/CXX/worker 문서 흐름으로 운영된다.',
|
|
1458
|
+
owner: 'ceo',
|
|
1459
|
+
};
|
|
1460
|
+
c.harness = tpl.harness || c.harness;
|
|
1461
|
+
c.agents = tpl.agents || c.agents;
|
|
1462
|
+
c.flow = tpl.flow || c.flow;
|
|
1463
|
+
c.behavior = c.behavior || {};
|
|
1464
|
+
c.behavior.auto_route_ceo = c.behavior.auto_route_ceo ?? c.behavior.auto_route_dispatcher ?? true;
|
|
1465
|
+
c.behavior.auto_route_ceo_description = 'true 이면 /goal 또는 /hot-fix 이후 Owner 입력을 v7 CEO/CXX mission flow 기준으로 안내한다.';
|
|
1466
|
+
delete c.behavior.auto_route_dispatcher;
|
|
1467
|
+
delete c.behavior.auto_route_dispatcher_description;
|
|
1433
1468
|
delete c.mode_selection;
|
|
1434
|
-
log(' config.json:
|
|
1469
|
+
log(' config.json: v7 CEO/CXX routing 섹션 동기화');
|
|
1435
1470
|
if (!dryRun) {
|
|
1436
1471
|
fs.writeFileSync(path.join(backupDir, 'config.json'), original);
|
|
1437
1472
|
fs.writeFileSync(configPath, JSON.stringify(c, null, 2) + '\n');
|
|
@@ -1524,60 +1559,90 @@ function runMigrate(opts = {}) {
|
|
|
1524
1559
|
log('Dry-run 완료 — 실제 변경 적용하려면 `npx walwal-harness migrate` 실행');
|
|
1525
1560
|
} else {
|
|
1526
1561
|
log(`Migration 완료. 백업: ${backupDir}`);
|
|
1527
|
-
log('
|
|
1562
|
+
log('v7 routing 기준으로 /goal 또는 /hot-fix 가 CEO/CXX/worker 흐름을 시작합니다.');
|
|
1528
1563
|
log('회사모드는 기본값이며 사용자 override 는 사용하지 않습니다.');
|
|
1529
1564
|
}
|
|
1530
1565
|
console.log('');
|
|
1531
1566
|
}
|
|
1532
1567
|
|
|
1533
1568
|
// ─────────────────────────────────────────
|
|
1534
|
-
// Verify —
|
|
1569
|
+
// Verify — v7 CXX/core skill invariants + progress schema
|
|
1535
1570
|
// ─────────────────────────────────────────
|
|
1536
1571
|
function runVerify() {
|
|
1537
1572
|
const expectedSkills = [
|
|
1538
|
-
'
|
|
1539
|
-
'
|
|
1540
|
-
'generator-backend', 'generator-frontend', 'generator-designer', 'generator-devops',
|
|
1541
|
-
'evaluator-code-quality', 'evaluator-functional', 'evaluator-visual',
|
|
1542
|
-
'evaluator-architecture', 'evaluator-security',
|
|
1543
|
-
'coo-developer', 'documentationer',
|
|
1544
|
-
'brainstorming',
|
|
1573
|
+
'ceo', 'coo', 'cdo', 'cto', 'cqo', 'ops',
|
|
1574
|
+
'hiring', 'resource-manager', 'brick-office',
|
|
1545
1575
|
];
|
|
1546
1576
|
const requiredFrontmatter = ['name', 'description'];
|
|
1547
1577
|
|
|
1548
1578
|
console.log('');
|
|
1549
|
-
log('=== Verify: skill invariants +
|
|
1579
|
+
log('=== Verify: v7 command/skill invariants + progress schema ===');
|
|
1550
1580
|
let pass = 0;
|
|
1551
1581
|
let fail = 0;
|
|
1552
1582
|
const issues = [];
|
|
1553
1583
|
|
|
1554
1584
|
// 1) skill files
|
|
1585
|
+
const skillRoots = [
|
|
1586
|
+
['.claude', CLAUDE_SKILLS_DIR],
|
|
1587
|
+
['.codex', CODEX_SKILLS_DIR],
|
|
1588
|
+
];
|
|
1555
1589
|
for (const s of expectedSkills) {
|
|
1556
|
-
const
|
|
1557
|
-
|
|
1558
|
-
|
|
1559
|
-
|
|
1560
|
-
|
|
1561
|
-
|
|
1590
|
+
for (const [toolName, root] of skillRoots) {
|
|
1591
|
+
const local = path.join(root, `harness-${s}`, 'SKILL.md');
|
|
1592
|
+
const exists = fs.existsSync(local);
|
|
1593
|
+
if (!exists) {
|
|
1594
|
+
issues.push(` ✗ ${toolName}/skills/harness-${s}/SKILL.md MISSING`);
|
|
1595
|
+
fail++;
|
|
1596
|
+
continue;
|
|
1597
|
+
}
|
|
1598
|
+
const body = fs.readFileSync(local, 'utf8');
|
|
1599
|
+
const fmMatch = body.match(/^---\n([\s\S]*?)\n---/);
|
|
1600
|
+
if (!fmMatch) {
|
|
1601
|
+
issues.push(` ✗ ${toolName}/skills/harness-${s}: frontmatter 누락`);
|
|
1602
|
+
fail++;
|
|
1603
|
+
continue;
|
|
1604
|
+
}
|
|
1605
|
+
const missing = requiredFrontmatter.filter((k) => !new RegExp(`^${k}:`, 'm').test(fmMatch[1]));
|
|
1606
|
+
if (missing.length) {
|
|
1607
|
+
issues.push(` ✗ ${toolName}/skills/harness-${s}: frontmatter [${missing.join(',')}] 누락`);
|
|
1608
|
+
fail++;
|
|
1609
|
+
continue;
|
|
1610
|
+
}
|
|
1611
|
+
pass++;
|
|
1562
1612
|
}
|
|
1563
|
-
|
|
1564
|
-
|
|
1565
|
-
|
|
1566
|
-
|
|
1567
|
-
|
|
1568
|
-
|
|
1613
|
+
}
|
|
1614
|
+
log(` skills: ${pass}/${expectedSkills.length * skillRoots.length} OK`);
|
|
1615
|
+
|
|
1616
|
+
// 2) owner-facing commands
|
|
1617
|
+
const allowedCommands = new Set(['goal.md', 'hot-fix.md']);
|
|
1618
|
+
const forbiddenCommands = new Set(['ceo.md', 'coo.md', 'cdo.md', 'cto.md', 'cqo.md', 'ops.md', 'hiring.md', 'resource-manager.md', 'brick-office.md']);
|
|
1619
|
+
const commandRoots = [
|
|
1620
|
+
['.claude', CLAUDE_COMMANDS_DIR],
|
|
1621
|
+
['.codex', CODEX_COMMANDS_DIR],
|
|
1622
|
+
];
|
|
1623
|
+
for (const [toolName, root] of commandRoots) {
|
|
1624
|
+
for (const cmd of allowedCommands) {
|
|
1625
|
+
if (!fs.existsSync(path.join(root, cmd))) {
|
|
1626
|
+
issues.push(` ✗ ${toolName}/commands/${cmd} MISSING`);
|
|
1627
|
+
fail++;
|
|
1628
|
+
} else {
|
|
1629
|
+
pass++;
|
|
1630
|
+
}
|
|
1569
1631
|
}
|
|
1570
|
-
|
|
1571
|
-
|
|
1572
|
-
|
|
1573
|
-
|
|
1574
|
-
|
|
1632
|
+
if (fs.existsSync(root)) {
|
|
1633
|
+
for (const cmd of fs.readdirSync(root).filter(f => f.endsWith('.md'))) {
|
|
1634
|
+
if (forbiddenCommands.has(cmd)) {
|
|
1635
|
+
issues.push(` ✗ ${toolName}/commands/${cmd} forbidden in v7`);
|
|
1636
|
+
fail++;
|
|
1637
|
+
} else if (!allowedCommands.has(cmd)) {
|
|
1638
|
+
issues.push(` ⚠ ${toolName}/commands/${cmd} is outside walwal v7 owner-facing command set`);
|
|
1639
|
+
}
|
|
1640
|
+
}
|
|
1575
1641
|
}
|
|
1576
|
-
pass++;
|
|
1577
1642
|
}
|
|
1578
|
-
log(`
|
|
1643
|
+
log(` commands: /goal + /hot-fix checked`);
|
|
1579
1644
|
|
|
1580
|
-
//
|
|
1645
|
+
// 3) progress.json schema (v6+ = version 4 + mode_decision)
|
|
1581
1646
|
const progressPath = path.join(HARNESS_DIR, 'progress.json');
|
|
1582
1647
|
if (fs.existsSync(progressPath)) {
|
|
1583
1648
|
try {
|
|
@@ -1586,6 +1651,10 @@ function runVerify() {
|
|
|
1586
1651
|
if ((p.version ?? 0) < 4) schemaIssues.push(`version=${p.version} (<4)`);
|
|
1587
1652
|
if (!p.mode_decision) schemaIssues.push('mode_decision 누락');
|
|
1588
1653
|
if (!p.dispatch) schemaIssues.push('dispatch 누락');
|
|
1654
|
+
if (p.mode_decision?.owner === 'conductor') schemaIssues.push('mode_decision.owner=conductor legacy');
|
|
1655
|
+
if (['dispatcher', 'planner', 'generator-backend', 'generator-frontend', 'evaluator-functional', 'evaluator-visual', 'service-ops'].includes(p.next_agent)) {
|
|
1656
|
+
schemaIssues.push(`next_agent=${p.next_agent} legacy`);
|
|
1657
|
+
}
|
|
1589
1658
|
if (schemaIssues.length) {
|
|
1590
1659
|
issues.push(` ✗ progress.json schema: ${schemaIssues.join(', ')} → npx walwal-harness migrate`);
|
|
1591
1660
|
fail++;
|
|
@@ -1607,6 +1676,13 @@ function runVerify() {
|
|
|
1607
1676
|
if (!c.company_mode) {
|
|
1608
1677
|
issues.push(' ✗ config.json: company_mode 누락 → npx walwal-harness migrate');
|
|
1609
1678
|
fail++;
|
|
1679
|
+
} else if (
|
|
1680
|
+
c.company_mode.owner === 'conductor' ||
|
|
1681
|
+
c.behavior?.auto_route_dispatcher !== undefined ||
|
|
1682
|
+
c.agents?.dispatcher?.skill === 'harness-dispatcher'
|
|
1683
|
+
) {
|
|
1684
|
+
issues.push(' ✗ config.json: legacy dispatcher/conductor routing → npx walwal-harness migrate');
|
|
1685
|
+
fail++;
|
|
1610
1686
|
} else {
|
|
1611
1687
|
pass++;
|
|
1612
1688
|
log(` config.json: company_mode.owner=${c.company_mode.owner} OK`);
|
|
@@ -1636,6 +1712,20 @@ function runVerify() {
|
|
|
1636
1712
|
issues.push(' ⚠ .claude/commands/harness-next.md 존재 — v6.0.3 부터 회사 내부 도구로 전환됨. `npx walwal-harness --force` 또는 직접 삭제 권장');
|
|
1637
1713
|
}
|
|
1638
1714
|
|
|
1715
|
+
// 6) installed script guidance must not claim removed dispatcher/planner flow.
|
|
1716
|
+
const routeScript = path.join(PROJECT_ROOT, 'scripts', 'harness-user-prompt-submit.sh');
|
|
1717
|
+
const sessionScript = path.join(PROJECT_ROOT, 'scripts', 'harness-session-start.sh');
|
|
1718
|
+
for (const scriptPath of [routeScript, sessionScript]) {
|
|
1719
|
+
if (!fs.existsSync(scriptPath)) continue;
|
|
1720
|
+
const body = fs.readFileSync(scriptPath, 'utf8');
|
|
1721
|
+
if (/harness-dispatcher|pipeline=none\/dispatcher|dispatch -> CEO meeting|planner\(COO\)|gen\/eval/.test(body)) {
|
|
1722
|
+
issues.push(` ✗ ${path.relative(PROJECT_ROOT, scriptPath)}: legacy dispatcher/planner guidance → npx walwal-harness init migrate --force`);
|
|
1723
|
+
fail++;
|
|
1724
|
+
} else {
|
|
1725
|
+
pass++;
|
|
1726
|
+
}
|
|
1727
|
+
}
|
|
1728
|
+
|
|
1639
1729
|
console.log('');
|
|
1640
1730
|
if (fail === 0) {
|
|
1641
1731
|
log(`✓ Verify PASS — ${pass} 개 invariant 통과.`);
|
|
@@ -1702,7 +1792,9 @@ function main() {
|
|
|
1702
1792
|
const gotchaMissing = Object.keys(migFlags.gotchaMissingEntries || {}).length > 0;
|
|
1703
1793
|
const hasContentDrift =
|
|
1704
1794
|
migFlags.progressV3toV4 ||
|
|
1795
|
+
migFlags.progressLegacyRouting ||
|
|
1705
1796
|
migFlags.configMissingCompanyMode ||
|
|
1797
|
+
migFlags.configLegacyRouting ||
|
|
1706
1798
|
(migFlags.memoryMissingSystemEntries && migFlags.memoryMissingSystemEntries.length) ||
|
|
1707
1799
|
gotchaMissing;
|
|
1708
1800
|
if (hasContentDrift) {
|
|
@@ -1715,7 +1807,7 @@ function main() {
|
|
|
1715
1807
|
} catch {}
|
|
1716
1808
|
}
|
|
1717
1809
|
|
|
1718
|
-
//
|
|
1810
|
+
// Brick Office dashboard one-liner
|
|
1719
1811
|
console.log('');
|
|
1720
1812
|
console.log('╔══════════════════════════════════════════════════════════╗');
|
|
1721
1813
|
console.log('║ Brick Office — 라이브 운영 대시보드 (선택) ║');
|
|
@@ -1732,8 +1824,7 @@ function main() {
|
|
|
1732
1824
|
log('╔═══════════════════════════════════════════════════════════╗');
|
|
1733
1825
|
log('║ Restart Claude Code for skills & commands to activate! ║');
|
|
1734
1826
|
log('║ ║');
|
|
1735
|
-
log('║ Then
|
|
1736
|
-
log('║ Or invoke: /harness-dispatcher ║');
|
|
1827
|
+
log('║ Then invoke /goal or /hot-fix ║');
|
|
1737
1828
|
log('║ ║');
|
|
1738
1829
|
log('║ 기본은 회사모드: 병렬 · 자율 진행. 추가 입력 불필요. ║');
|
|
1739
1830
|
log('╚═══════════════════════════════════════════════════════════╝');
|
|
@@ -1744,6 +1835,10 @@ function main() {
|
|
|
1744
1835
|
log(' 3. Internal agents call hired agents/skills, not slash commands.');
|
|
1745
1836
|
}
|
|
1746
1837
|
console.log('');
|
|
1838
|
+
|
|
1839
|
+
if (subcommand === 'init' && subcommandArgs.includes('migrate')) {
|
|
1840
|
+
runMigrate({ dryRun: args.includes('--dry-run') });
|
|
1841
|
+
}
|
|
1747
1842
|
}
|
|
1748
1843
|
|
|
1749
1844
|
main();
|
package/commands/goal.md
CHANGED
|
@@ -18,6 +18,8 @@ Required flow:
|
|
|
18
18
|
8. CEO must require worker report paths under `.harness/documents/{mission_name}/workers/` before accepting CXX completion.
|
|
19
19
|
9. Do not invoke internal roles through slash commands; commands are Owner entrypoints only.
|
|
20
20
|
|
|
21
|
+
Note: Harness documents (ceo.md, cto.md, cqo.md, worker reports) are mission records, not derived output documents. A docmeta skip decision on these files does not authorize skipping any harness protocol step.
|
|
22
|
+
|
|
21
23
|
Owner request:
|
|
22
24
|
|
|
23
25
|
```
|
package/commands/hot-fix.md
CHANGED
|
@@ -9,14 +9,17 @@ Route the Owner request to the installed `harness-ceo` agent/skill as an emergen
|
|
|
9
9
|
|
|
10
10
|
Required flow:
|
|
11
11
|
1. Create `.harness/documents/{hotfix_name}/ceo.md`.
|
|
12
|
-
2. CEO summons CTO and CQO; summon COO/CDO only when planning or UX decisions are involved.
|
|
12
|
+
2. CEO summons CTO and CQO first; summon COO/CDO only when planning or UX decisions are involved.
|
|
13
13
|
3. CTO applies the smallest correct patch path through hired implementation skills.
|
|
14
|
-
4. CXX roles must
|
|
15
|
-
5.
|
|
16
|
-
6.
|
|
17
|
-
7.
|
|
18
|
-
8.
|
|
19
|
-
9.
|
|
14
|
+
4. CXX roles must start in a fresh session context. Do not let the default model impersonate a missing CXX or worker.
|
|
15
|
+
5. CXX roles must not directly execute specialist deliverables. They must use hired workers for implementation, QA, ops checks, and documentation even when the fix is small.
|
|
16
|
+
6. If a required worker is missing, CEO or the responsible CXX must invoke the installed `harness-hiring` skill before assigning the work.
|
|
17
|
+
7. CEO must require worker report paths under `.harness/documents/{hotfix_name}/workers/` before accepting CXX completion.
|
|
18
|
+
8. CQO must register durable lessons in `.harness/gotchas/`, `.harness/conventions/`, or `.harness/memories/`. This step is mandatory, not optional, even for small fixes.
|
|
19
|
+
9. Archive only after CQO has accepted the fix.
|
|
20
|
+
10. Do not invoke internal roles through slash commands; commands are Owner entrypoints only.
|
|
21
|
+
|
|
22
|
+
Note: Harness documents (ceo.md, cto.md, cqo.md, worker reports) are mission records, not derived output documents. A docmeta skip decision on these files does not authorize skipping any harness protocol step.
|
|
20
23
|
|
|
21
24
|
Hot-fix request:
|
|
22
25
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@walwal-harness/cli",
|
|
3
|
-
"version": "7.1.
|
|
3
|
+
"version": "7.1.3",
|
|
4
4
|
"description": "Company-style AI agent harness for Claude and Codex. Installs commands, CXX agents, skills, HR-Resource hiring pool, and project-local .harness runtime state.",
|
|
5
5
|
"bin": {
|
|
6
6
|
"walwal-harness": "bin/init.js"
|
|
@@ -168,24 +168,24 @@ fi
|
|
|
168
168
|
# init 상태: 첫 안내
|
|
169
169
|
# ─────────────────────────────────────────
|
|
170
170
|
if [ "$sprint_status" = "init" ]; then
|
|
171
|
-
if [ "$next_agent" != "null" ] && [ "$next_agent" != "none" ] && [ "$next_agent" != "
|
|
171
|
+
if [ "$next_agent" != "null" ] && [ "$next_agent" != "none" ] && [ "$next_agent" != "ceo" ]; then
|
|
172
172
|
echo "# Harness Company Mode active"
|
|
173
173
|
echo "# Sprint is init, but next_agent=${next_agent}; continue the autonomous loop instead of waiting for Owner."
|
|
174
174
|
else
|
|
175
|
-
echo "# Harness ready —
|
|
176
|
-
echo "# 기본 경로는 회사 루프입니다:
|
|
175
|
+
echo "# Harness ready — use /goal or /hot-fix"
|
|
176
|
+
echo "# 기본 경로는 v7 회사 루프입니다: CEO -> 필요한 CXX -> resource-manager/hiring -> worker reports -> CXX review -> CEO report."
|
|
177
177
|
exit 0
|
|
178
178
|
fi
|
|
179
179
|
fi
|
|
180
180
|
|
|
181
181
|
# ─────────────────────────────────────────
|
|
182
|
-
# Audit lifecycle:
|
|
182
|
+
# Audit lifecycle: CEO 시작 시 리셋
|
|
183
183
|
# ─────────────────────────────────────────
|
|
184
184
|
init_audit "$PROJECT_ROOT"
|
|
185
|
-
if [ "$next_agent" = "
|
|
185
|
+
if [ "$next_agent" = "ceo" ]; then
|
|
186
186
|
# 새 사이클 — 이전 audit을 archive로 이동하고 새로 시작
|
|
187
187
|
reset_audit "$PROJECT_ROOT" "$sprint_num"
|
|
188
|
-
audit_log "system" "cycle" "start" "sprint-${sprint_num}" "new
|
|
188
|
+
audit_log "system" "cycle" "start" "sprint-${sprint_num}" "new CEO mission cycle"
|
|
189
189
|
fi
|
|
190
190
|
|
|
191
191
|
# ─────────────────────────────────────────
|
|
@@ -14,7 +14,7 @@ SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"
|
|
|
14
14
|
# 조건 2: opt-out 플래그 확인
|
|
15
15
|
AUTO_ROUTE="true"
|
|
16
16
|
if command -v jq >/dev/null 2>&1; then
|
|
17
|
-
AUTO_ROUTE=$(jq -r '.behavior.auto_route_dispatcher // true' "$CWD/.harness/config.json" 2>/dev/null || echo "true")
|
|
17
|
+
AUTO_ROUTE=$(jq -r '.behavior.auto_route_ceo // .behavior.auto_route_dispatcher // true' "$CWD/.harness/config.json" 2>/dev/null || echo "true")
|
|
18
18
|
fi
|
|
19
19
|
if [ "$AUTO_ROUTE" != "true" ]; then exit 0; fi
|
|
20
20
|
|
|
@@ -114,13 +114,13 @@ cat <<EOF
|
|
|
114
114
|
[harness] company | S${SPRINT_NUM} | ${PIPELINE} | agent=${CURRENT_AGENT} (${AGENT_STATUS}) | next=${NEXT_AGENT} | queue=${T_PASSED}/${T_TOTAL} passed | failed=${T_FAILED}
|
|
115
115
|
${CONTEXT_WARNING}
|
|
116
116
|
## Route
|
|
117
|
-
- pipeline=none/
|
|
118
|
-
- 기본 경로는
|
|
119
|
-
-
|
|
117
|
+
- pipeline=none/init → harness-ceo 스킬로 Owner goal/hot-fix를 접수하고 mission 문서를 생성
|
|
118
|
+
- 기본 경로는 v7 CXX 회사 루프다: CEO -> COO/CDO/CTO/CQO/OPS -> harness-resource-manager -> harness-hiring -> hired workers -> CXX review -> CEO report
|
|
119
|
+
- CXX는 직접 전문 산출물을 만들지 않고 worker report를 `.harness/documents/{mission}/workers/`에 남겨야 한다
|
|
120
120
|
- Owner에게 "계속 진행", "진행할까요?", "다음 명령을 입력하세요"를 요구하지 않는다. GOAL이 있고 escalation이 아니면 즉시 next_agent/current_agent 업무를 수행한다
|
|
121
121
|
- Owner 입력은 목표 변경·사고·결과 확인용이지 회사 진행을 펌프하는 신호가 아니다
|
|
122
|
-
-
|
|
123
|
-
- 기능 요청 →
|
|
122
|
+
- CEO는 필요한 CXX만 호출하고, CXX는 resource-manager/hiring 없이 worker 업무를 수행하지 않는다
|
|
123
|
+
- 기능 요청 → CEO mission flow | 긴급 수정 → hot-fix flow | 메타 질문 → 짧게 응답 (skip)
|
|
124
124
|
- 활성 pipeline → next_agent/current_agent 컨텍스트로 계속
|
|
125
125
|
- skip: "harness skip", "just answer" 등 명시 시 단일 메시지 건너뜀
|
|
126
126
|
EOF
|
package/commands/play-harness.md
DELETED
|
@@ -1,22 +0,0 @@
|
|
|
1
|
-
---
|
|
2
|
-
description: Run the harness play build and notify OPS monitoring.
|
|
3
|
-
argument-hint: "[additional play args]"
|
|
4
|
-
---
|
|
5
|
-
|
|
6
|
-
# /play-harness
|
|
7
|
-
|
|
8
|
-
Run the target project's harness play mode.
|
|
9
|
-
|
|
10
|
-
Required flow:
|
|
11
|
-
1. Confirm `.harness/` exists in the current project.
|
|
12
|
-
2. Run `bash scripts/play.sh $ARGUMENTS`.
|
|
13
|
-
3. Treat play mode and release mode as mutually exclusive. If release mode is active, stop it first with `/stop-harness` or report the conflict to the Owner.
|
|
14
|
-
4. After the script returns, read the emitted OPS report path and notify the installed `harness-ops` skill/agent that play monitoring has started.
|
|
15
|
-
5. Record the build result in `.harness/documents/{mission_name}/ops.md` when a mission is active.
|
|
16
|
-
6. Do not route this through `/goal`; this command is an Owner-facing runtime control entrypoint.
|
|
17
|
-
|
|
18
|
-
Play arguments:
|
|
19
|
-
|
|
20
|
-
```
|
|
21
|
-
$ARGUMENTS
|
|
22
|
-
```
|
|
@@ -1,22 +0,0 @@
|
|
|
1
|
-
---
|
|
2
|
-
description: Run the harness release build, start service operation, and notify OPS monitoring.
|
|
3
|
-
argument-hint: "[additional release args]"
|
|
4
|
-
---
|
|
5
|
-
|
|
6
|
-
# /release-harness
|
|
7
|
-
|
|
8
|
-
Run the target project's harness release mode and begin service operation.
|
|
9
|
-
|
|
10
|
-
Required flow:
|
|
11
|
-
1. Confirm `.harness/` exists in the current project.
|
|
12
|
-
2. Run `bash scripts/release.sh release $ARGUMENTS`.
|
|
13
|
-
3. Treat play mode and release mode as mutually exclusive. If play mode is active, stop it first with `/stop-harness` or report the conflict to the Owner.
|
|
14
|
-
4. After the script returns, read the emitted OPS report path and notify the installed `harness-ops` skill/agent that release monitoring has started.
|
|
15
|
-
5. Record the release result in `.harness/documents/{mission_name}/ops.md` when a mission is active.
|
|
16
|
-
6. Do not route this through `/goal`; this command is an Owner-facing runtime control entrypoint.
|
|
17
|
-
|
|
18
|
-
Release arguments:
|
|
19
|
-
|
|
20
|
-
```
|
|
21
|
-
$ARGUMENTS
|
|
22
|
-
```
|
package/commands/stop-harness.md
DELETED
|
@@ -1,21 +0,0 @@
|
|
|
1
|
-
---
|
|
2
|
-
description: Stop any harness play or release process/session.
|
|
3
|
-
argument-hint: "[optional stop reason]"
|
|
4
|
-
---
|
|
5
|
-
|
|
6
|
-
# /stop-harness
|
|
7
|
-
|
|
8
|
-
Stop any active harness play or release runtime.
|
|
9
|
-
|
|
10
|
-
Required flow:
|
|
11
|
-
1. Confirm `.harness/` exists in the current project.
|
|
12
|
-
2. Run `bash scripts/harness-runtime-stop.sh $ARGUMENTS`.
|
|
13
|
-
3. Verify both play and release runtime state files are cleared or marked stopped.
|
|
14
|
-
4. Notify the installed `harness-ops` skill/agent that monitoring should stop for the terminated runtime mode.
|
|
15
|
-
5. Record the stop result in `.harness/documents/{mission_name}/ops.md` when a mission is active.
|
|
16
|
-
|
|
17
|
-
Stop reason:
|
|
18
|
-
|
|
19
|
-
```
|
|
20
|
-
$ARGUMENTS
|
|
21
|
-
```
|