uctm 1.5.4 → 2.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/.claude-plugin/plugin.json +2 -2
- package/README.md +179 -287
- package/agents/builder.md +10 -24
- package/agents/committer.md +13 -33
- package/agents/orchestrator.md +310 -0
- package/agents/planner.md +10 -24
- package/agents/specifier.md +27 -50
- package/agents/verifier.md +5 -24
- package/lib/constants.mjs +31 -7
- package/lib/init.mjs +9 -15
- package/lib/update.mjs +10 -2
- package/package.json +2 -6
- package/references/agent-flow.md +159 -118
- package/references/context-policy.md +26 -7
- package/references/file-content-schema.md +58 -18
- package/references/shared-prompt-sections.md +46 -17
- package/references/work-activity-log.md +40 -16
- package/references/xml-schema.md +211 -39
- package/skills/sdd-pipeline/SKILL.md +1 -1
- package/skills/uctm-init/SKILL.md +1 -2
- package/skills/work-pipeline/SKILL.md +38 -22
- package/.agent/router_rule_config.json +0 -47
- package/agents/scheduler.md +0 -152
- package/references/callback-protocol.md +0 -40
- package/references/ref-cache-protocol.md +0 -31
- package/skills/init/SKILL.md +0 -95
package/references/agent-flow.md
CHANGED
|
@@ -1,179 +1,220 @@
|
|
|
1
1
|
# Agent Flow — Main Claude 역할 가이드
|
|
2
2
|
|
|
3
|
-
> Main Claude는
|
|
4
|
-
>
|
|
5
|
-
>
|
|
6
|
-
>
|
|
3
|
+
> Main Claude는 **트리거와 게이트 경계**만 담당합니다.
|
|
4
|
+
> 파이프라인 내부 진행(WORK 생성 → 설계 → TASK 실행 → 완료)은 **orchestrator**가 전담합니다.
|
|
5
|
+
> Main Claude는 orchestrator 외의 다른 에이전트를 **직접 spawn하지 않습니다**.
|
|
6
|
+
>
|
|
7
|
+
> **예외 — 축퇴 모드(§7)**: 실행 환경이 중첩 spawn을 지원하지 않으면 Main Claude가 orchestrator 역할을 넘겨받아 자식을 직접 spawn합니다.
|
|
7
8
|
|
|
8
9
|
---
|
|
9
10
|
|
|
10
|
-
##
|
|
11
|
+
## 1. Main Claude 역할 (트리거 + 게이트 경계)
|
|
11
12
|
|
|
12
|
-
Main Claude
|
|
13
|
-
당신의 역할은 흐름에 따라 실행하는 것이지
|
|
13
|
+
Main Claude가 직접 수행하는 일은 다음 5가지뿐입니다.
|
|
14
14
|
|
|
15
|
-
|
|
15
|
+
1. **트리거 감지** — `[tag]` 메시지 또는 WORK 재개 요청(예: "WORK-01 계속실행", "resume WORK-01")을 감지.
|
|
16
|
+
2. **orchestrator 1회 spawn** — 다음을 전달:
|
|
17
|
+
- `REFERENCES_DIR={절대 경로}`
|
|
18
|
+
- `mode=gated|auto` — 사용자 메시지에 "auto"/"자동으로"가 포함되면 `auto`, 그 외는 기본값 `gated`
|
|
19
|
+
- 사용자 요청 원문 (재개 요청이면 대상 `WORK_ID`)
|
|
20
|
+
- spawn 결과로 받는 **agentId를 보관**한다(재개 시 name이 아니라 **agentId**로 지정 — 이름 재사용 오배달 방지).
|
|
21
|
+
3. **축퇴 신호 처리** — orchestrator가 `<capability-degraded>`를 반환하면 §7 축퇴 모드로 전환한다.
|
|
22
|
+
4. **게이트 처리** — orchestrator가 `<gate type="stage">` 또는 `<gate type="decision">`을 반환하고 **yield(파킹)** 하면:
|
|
23
|
+
1. 게이트 내용을 사용자에게 그대로 제시한다 — `type="stage"`는 완료 요약, `type="decision"`은 배경(`<context>`) + 선택지(`<options>`) + 권고안(`<recommended>`)(`AskUserQuestion` 등으로 선택 요청).
|
|
24
|
+
2. 사용자의 승인 또는 선택을 기다린다.
|
|
25
|
+
3. 응답을 받으면 **`SendMessage(agentId, 결정내용)`으로 컨텍스트를 유지한 채 재개**한다.
|
|
26
|
+
4. `SendMessage`가 실패하면(파킹 핸들 유실 등) **폴백**: `works/{WORK_ID}/work_{WORK_ID}.log` + `DECISIONS.md`를 근거로 orchestrator를 `WORK_ID`와 함께 새로 spawn해 재개시킨다.
|
|
27
|
+
5. **완료 처리** — orchestrator가 최종 WORK 요약을 반환하면 사용자에게 그대로 릴레이하고 **`TaskStop(agentId)`로 파킹 핸들을 해제**한다.
|
|
16
28
|
|
|
17
|
-
|
|
18
|
-
[] 태그 감지 → specifier 호출
|
|
19
|
-
│
|
|
20
|
-
specifier 실행 mode 판단
|
|
21
|
-
│
|
|
22
|
-
├─ direct mode → specifier 수행 → planner 역할 수행
|
|
23
|
-
│
|
|
24
|
-
└─ pipeline/full → specifier 수행 → planner dispatch XML 반환
|
|
25
|
-
|
|
26
|
-
```
|
|
29
|
+
`mode=auto`인 경우 orchestrator가 게이트/의사결정 정지 없이 1회 spawn으로 완주하므로, 4단계(게이트 처리)는 발생하지 않는다 — Main Claude는 spawn 후 최종 결과만 수신·릴레이하고 `TaskStop`으로 마무리한다.
|
|
27
30
|
|
|
28
31
|
---
|
|
29
32
|
|
|
30
|
-
##
|
|
33
|
+
## 2. Orchestrator 내부 흐름
|
|
31
34
|
|
|
32
|
-
|
|
33
|
-
1. specifier 호출 → planner 역할 수행 + builder dispatch XML 반환
|
|
34
|
-
2. ⛔ 정지 — 요약을 사용자에게 제시하고 승인 대기
|
|
35
|
-
3. builder 호출
|
|
36
|
-
4. verifier 호출
|
|
37
|
-
5. committer 호출
|
|
38
|
-
```
|
|
35
|
+
Main Claude가 관여하지 않는 orchestrator 내부 진행이다. 상세 절차와 로그 규칙은 `develop/agents/orchestrator.md`를 정본으로 하며, 아래는 Main Claude가 게이트 신호를 올바르게 해석하기 위한 요약이다.
|
|
39
36
|
|
|
40
|
-
|
|
37
|
+
### STEP A. Specifier spawn (WORK 생성)
|
|
41
38
|
|
|
42
|
-
|
|
39
|
+
- orchestrator가 specifier를 중첩 spawn → `Requirement.md` + WORK 폴더 생성, 복잡도 판정(단순/복잡).
|
|
40
|
+
- `mode=gated`: 활동 로그에 `GATE_WAIT — stage=specifier` 기록 → `<gate type="stage" work="{WORK}" stage="specifier">` 반환 후 **yield**.
|
|
41
|
+
- `mode=auto`: 게이트 생략, `STAGE_DONE — stage=specifier` 즉시 기록 후 STEP B로 진행.
|
|
43
42
|
|
|
44
|
-
|
|
45
|
-
1. specifier 호출
|
|
46
|
-
2. planner 호출
|
|
47
|
-
3. ⛔ 정지 — Requirement.md + PLAN.md + TASK 목록을 제시하고 승인 대기
|
|
48
|
-
4. 각 TASK에 대해 (오름차순):
|
|
49
|
-
a. builder 호출 TASK별
|
|
50
|
-
b. verifier 호출 TASK별
|
|
51
|
-
c. committer 호출 TASK별
|
|
52
|
-
d. 미완료 TASK가 남아있으면 다음 TASK로 계속
|
|
53
|
-
```
|
|
43
|
+
### STEP B. Planner spawn
|
|
54
44
|
|
|
55
|
-
|
|
45
|
+
- planner를 중첩 spawn → `PLAN.md` + TASK DAG 생성.
|
|
46
|
+
- `mode=gated`: `GATE_WAIT — stage=planner` 기록 → `<gate type="stage" work="{WORK}" stage="planner">` 반환 후 **yield**.
|
|
47
|
+
- `mode=auto`: 게이트 생략, `STAGE_DONE — stage=planner` 즉시 기록 후 STEP C로 진행.
|
|
56
48
|
|
|
57
|
-
|
|
49
|
+
### STEP C. TASK DAG 실행 — 게이트 없음
|
|
58
50
|
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
2
|
|
62
|
-
3. ⛔ 정지 — Requirement.md + PLAN.md + TASK 목록을 제시하고 승인 대기
|
|
63
|
-
4. scheduler 호출
|
|
64
|
-
5. builder 호출
|
|
65
|
-
6. verifier 호출
|
|
66
|
-
7. committer 호출
|
|
67
|
-
8. 미완료 TASK가 남아있으면 4.scheduler 호출
|
|
68
|
-
```
|
|
51
|
+
- `work_{WORK}.log` + `PLAN.md`로 DAG를 해석해 READY TASK를 오름차순으로 판정한다. 복수 READY면 builder를 병렬로 중첩 spawn한다.
|
|
52
|
+
- TASK별로 builder → verifier → committer를 순차 spawn한다. 이 단계는 사용자 승인 대상이 아니므로 고정 게이트가 없다.
|
|
53
|
+
- verifier/committer가 FAIL을 반환하면 builder에 최대 2회 재디스패치(총 3회 시도)한다. 3회 모두 실패하면 자식이 `<needs-decision>`으로 orchestrator에 상향하고, `mode=gated`면 게이트로 승격, `mode=auto`면 권고안 자동결정 후 계속한다.
|
|
69
54
|
|
|
70
|
-
|
|
55
|
+
### STEP D. 로그 일괄 기록
|
|
71
56
|
|
|
72
|
-
|
|
57
|
+
- 활동 로그를 기록하는 주체는 **orchestrator뿐**이다.
|
|
58
|
+
- 이벤트 순서: `ORCHESTRATOR_START` → (`STAGE_START` → [`GATE_WAIT`/`DECISION_WAIT` → `DECISION`] → `STAGE_DONE`)를 단계마다 반복 → `ORCHESTRATOR_DONE`.
|
|
73
59
|
|
|
74
|
-
|
|
60
|
+
### 재개 규칙 (마지막 로그 이벤트 기준)
|
|
75
61
|
|
|
76
|
-
|
|
62
|
+
| 마지막 로그 이벤트 | 판정 | 처리 |
|
|
63
|
+
|---|---|---|
|
|
64
|
+
| 로그 없음 | 신규 WORK | STEP A부터 시작 |
|
|
65
|
+
| `{STAGE}_START`만 있고 대응하는 `STAGE_DONE`/`GATE_WAIT`/`DECISION_WAIT` 없음 | 자식 실행 중 중단됨 | 자식 재실행 |
|
|
66
|
+
| `GATE_WAIT — stage=X` | 게이트 미승인 | 자식 재실행 없이 디스크 산출물 재사용, **동일 게이트를 재제시** |
|
|
67
|
+
| `DECISION_WAIT — stage=X` | 결정 미확정 | `DECISIONS.md`의 `상태: PENDING` 항목을 동일 배경/선택지/권고안으로 재제시 |
|
|
68
|
+
| `DECISION — ... by=...` | 결정 확정, 후속 `STAGE_DONE` 없음 | 결정을 반영해 해당 단계 이어서 진행 |
|
|
69
|
+
| `STAGE_DONE — stage=X` | 해당 단계 완료(게이트 통과됨) | 다음 단계로 진행 |
|
|
70
|
+
| `ORCHESTRATOR_DONE` | WORK 이미 완료 | 재개 불필요 — 완료 상태 보고 |
|
|
77
71
|
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
- PLANNER_START → 중단됨, planner 재수행
|
|
90
|
-
- SPECIFIER_DONE → specifier 완료, planner 호출
|
|
91
|
-
- SPECIFIER_START → 중단됨, specifier 재수행
|
|
92
|
-
- 로그 파일 없음 → 처음부터 시작
|
|
93
|
-
|
|
94
|
-
2. 남은 각 TASK에 대해:
|
|
95
|
-
a. builder 호출 → 구현
|
|
96
|
-
b. verifier 호출 → 검증
|
|
97
|
-
c. committer 호출 → 커밋
|
|
98
|
-
```
|
|
72
|
+
> **핵심 불변식**: `STAGE_DONE`은 게이트가 있는 단계에서는 게이트가 해소(RESOLVED)된 이후에만 기록된다. 따라서 **미승인 게이트는 로그에 `STAGE_DONE`이 남지 않아 재개 시 절대 스킵되지 않는다.**
|
|
73
|
+
|
|
74
|
+
### 슬라이딩 윈도우 (컨텍스트 핸드오프)
|
|
75
|
+
|
|
76
|
+
orchestrator가 자식 프롬프트를 구성할 때 이전 단계 결과를 다음 기준으로 압축해 전달한다.
|
|
77
|
+
|
|
78
|
+
| 단계 거리 | 상세 레벨 | 포함 필드 |
|
|
79
|
+
|---|---|---|
|
|
80
|
+
| 직전 (1단계) | `FULL` | what + why + caution + incomplete |
|
|
81
|
+
| 2단계 전 | `SUMMARY` | what만 (1-3줄) |
|
|
82
|
+
| 3단계+ | `DROP` | 전달하지 않음 |
|
|
99
83
|
|
|
100
84
|
---
|
|
101
85
|
|
|
102
|
-
##
|
|
86
|
+
## 3. 승인 게이트 (CRITICAL)
|
|
103
87
|
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
88
|
+
게이트는 orchestrator가 자율 실행을 멈추고 반환하는 정지 신호다. 중첩 sub-agent는 사용자에게 직접 질문할 수 없으므로, **승인/결정의 실제 처리(사용자에게 묻고 응답을 받는 것)는 항상 Main Claude 경계에서 이뤄진다.**
|
|
89
|
+
|
|
90
|
+
> **반드시 정지하고 명시적 사용자 승인/결정을 기다려야 합니다.**
|
|
91
|
+
> 유일한 예외는 auto 모드 — 사용자의 원본 메시지에 "auto" 또는 "자동으로"가 포함된 경우뿐이다.
|
|
92
|
+
|
|
93
|
+
게이트는 두 종류이며 Main Claude의 처리 방식은 동일하다(§1-3 참조).
|
|
94
|
+
|
|
95
|
+
### 고정 게이트 (2개, `type="stage"`)
|
|
96
|
+
|
|
97
|
+
| 게이트 | 발생 지점 | `stage` 값 | 승인 후 다음 |
|
|
98
|
+
|---|---|---|---|
|
|
99
|
+
| GATE-1 | specifier 완료 후 | `specifier` | planner spawn |
|
|
100
|
+
| GATE-2 | planner 완료 후 | `planner` | STEP C(builder) |
|
|
101
|
+
|
|
102
|
+
### 동적 게이트 (`type="decision"`)
|
|
103
|
+
|
|
104
|
+
- 고정 게이트 사이 **어느 단계에서든**(설계·구현·검증 포함) orchestrator 또는 자식이 사용자 결정이 필요하다고 판단하면 즉시 발생한다.
|
|
105
|
+
- 판단 기준 예: 요구 해석의 다의성, 설계 트레이드오프, 명시된 범위 초과, 파괴적/비가역적 변경, 재시도 3회 실패.
|
|
106
|
+
- 자식은 `<needs-decision>`으로 orchestrator에 먼저 상향하며, orchestrator가 자동 결정 가능 여부를 판단한 뒤 불가능하면 `<gate type="decision">`으로 승격해 Main Claude에 전달한다.
|
|
107
|
+
- `<gate type="decision">`은 `<context>`(배경)·`<options>`(선택지)·`<recommended>`(권고안)를 반드시 포함한다.
|
|
108
|
+
|
|
109
|
+
### auto 모드
|
|
110
|
+
|
|
111
|
+
| 모드 | 정지 횟수 | 처리 |
|
|
112
|
+
|---|:---:|---|
|
|
113
|
+
| gated (기본값) | 고정 게이트 1~2회 + 동적 게이트 발생 시마다 | Main Claude가 매번 승인/선택 후 재개 |
|
|
114
|
+
| auto ("auto"/"자동으로") | 0 | orchestrator 1회 spawn으로 완주. 모든 판단 지점은 권고안으로 자동결정되어 최종 보고서 `## 자동 결정 사항`과 `DECISIONS.md`에 기록 |
|
|
115
|
+
|
|
116
|
+
### 승인 요청 방법 (Main Claude)
|
|
117
|
+
|
|
118
|
+
1. `<gate>` 내용을 그대로 사용자에게 제시(요약 또는 배경+선택지+권고안).
|
|
119
|
+
2. "진행할까요?" 또는 동등한 질문(`type="decision"`이면 선택 요청).
|
|
120
|
+
3. **사용자 응답 대기** — 응답 전까지 `SendMessage`로 재개하지 말 것.
|
|
112
121
|
|
|
113
122
|
---
|
|
114
123
|
|
|
115
|
-
##
|
|
124
|
+
## 4. 모드/스폰 수
|
|
125
|
+
|
|
126
|
+
| Main → Orchestrator | Orchestrator → Specifier | → Planner | → Builder | → Verifier | → Committer | 합계 |
|
|
127
|
+
|:---:|:---:|:---:|:---:|:---:|:---:|:---:|
|
|
128
|
+
| 1 | 1 | 1 | N | N | N | **3 + 3N** |
|
|
116
129
|
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
| direct | 1 (겸임) | — | — | 1 | 1 | 1 | **4** |
|
|
120
|
-
| pipeline (N TASK) | 1 | 1 | — | N | N | N | **2 + 3N** |
|
|
121
|
-
| full (N TASK) | 1 | 1 | 1 | N | N | N | **3 + 3N** |
|
|
130
|
+
- `gated`/`auto` 여부는 spawn 수에 영향을 주지 않는다 — 게이트 정지 발생 여부만 다르다(§3).
|
|
131
|
+
- 위 표는 orchestrator 내부 자식 spawn만 집계한다. Main Claude가 spawn하는 대상은 오직 orchestrator 1개다.
|
|
122
132
|
|
|
123
133
|
---
|
|
124
134
|
|
|
125
|
-
##
|
|
135
|
+
## 5. 기존 WORK 재개
|
|
126
136
|
|
|
127
|
-
|
|
128
|
-
> "approve", "승인", "proceed", "진행" 등의 응답이 올 때까지 다음 에이전트를 호출하지 말 것.
|
|
129
|
-
> 유일한 예외는 auto 모드 — 사용자의 원본 메시지에 "auto" 또는 "자동으로"가 포함된 경우.
|
|
137
|
+
Main Claude는 재개 요청을 감지하면 대상 `WORK_ID`를 orchestrator에 전달하는 것으로 끝난다. 재개 지점 판정(§2 "재개 규칙")은 orchestrator가 로그를 읽어 스스로 수행한다.
|
|
130
138
|
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
| pipeline/full | 2 | Specifier 완료 후, Planner 완료 후 | Requirement.md 요약, PLAN.md + TASK-00.md 요약|
|
|
135
|
-
| auto-approve | 0 | — | 모든 승인 게이트 생략 |
|
|
139
|
+
1. 파킹된 agentId를 보관하고 있으면 → `SendMessage(agentId, "WORK-{NN} 계속")`으로 컨텍스트를 유지한 채 재개.
|
|
140
|
+
2. 세션이 끊겨 핸들이 없으면(예: 새 세션에서 "WORK-01 계속실행") → orchestrator를 `WORK_ID` + `REFERENCES_DIR` + (승계된) `mode`와 함께 새로 spawn → orchestrator가 `work_{WORK_ID}.log`의 마지막 이벤트로 재개 지점을 판정한다.
|
|
141
|
+
3. 단순/복잡 분기는 다시 묻지 않는다 — orchestrator가 `PLAN.md`와 TASK 구성에서 판정한다.
|
|
136
142
|
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
143
|
+
---
|
|
144
|
+
|
|
145
|
+
## 6. 에이전트 역할 요약
|
|
146
|
+
|
|
147
|
+
| 에이전트 | 역할 | 모델 |
|
|
148
|
+
|---|---|---|
|
|
149
|
+
| orchestrator | 파이프라인 전체 조정 + TASK DAG 스케줄링 + 게이트/의사결정 중재 + 로그 일괄 기록 | opus |
|
|
150
|
+
| specifier | 요구사항 분석 | opus |
|
|
151
|
+
| planner | 실행계획 수립 + TASK 분해 | opus |
|
|
152
|
+
| builder | 코드 구현 | sonnet |
|
|
153
|
+
| verifier | 빌드/린트/테스트 검증 | haiku |
|
|
154
|
+
| committer | 결과 보고서 + git commit | haiku |
|
|
141
155
|
|
|
142
156
|
---
|
|
143
157
|
|
|
144
158
|
## References Directory 전달 (필수)
|
|
145
159
|
|
|
146
|
-
Main Claude는
|
|
147
|
-
설치 방법(npm 또는 plugin)에 관계없이
|
|
160
|
+
Main Claude는 orchestrator spawn 시(신규/재개 모두) references 디렉토리 경로를 전달해야 합니다.
|
|
161
|
+
설치 방법(npm 또는 plugin)에 관계없이 orchestrator가 레퍼런스 파일을 찾을 수 있도록 합니다. 이 경로를 받는 것은 orchestrator뿐이며, 자식에게는 전달되지 않습니다.
|
|
148
162
|
|
|
149
163
|
**전달 방법:**
|
|
150
|
-
-
|
|
164
|
+
- orchestrator spawn 프롬프트 상단에 `REFERENCES_DIR={absolute_path}` 추가
|
|
151
165
|
- npm 설치: `.claude/references` 사용 (프로젝트 루트 기준 기본값)
|
|
152
166
|
- plugin 설치: 스킬의 "Base directory"에서 유도 (`{base_dir}/../../references`)
|
|
153
167
|
|
|
154
168
|
**예시:**
|
|
155
169
|
```
|
|
156
170
|
REFERENCES_DIR=C:/Users/me/.claude/plugins/cache/uc-taskmanager/abc123/references
|
|
171
|
+
mode=gated
|
|
157
172
|
|
|
158
|
-
|
|
159
|
-
...
|
|
160
|
-
</dispatch>
|
|
173
|
+
[WORK] 사용자 요청 원문...
|
|
161
174
|
```
|
|
162
175
|
|
|
163
|
-
REFERENCES_DIR를 사용할 수 없는 경우
|
|
176
|
+
REFERENCES_DIR를 사용할 수 없는 경우(예: plugin 없는 npm 설치), orchestrator는 `.claude/references/`를 폴백으로 사용합니다. orchestrator는 자신이 읽은 레퍼런스 중 각 자식에게 필요한 섹션만 잘라 `<ref-cache>`(`xml-schema.md` § 4)로 **반드시** 재전달합니다.
|
|
164
177
|
|
|
165
178
|
---
|
|
166
179
|
|
|
167
|
-
##
|
|
180
|
+
## 레퍼런스 로딩
|
|
168
181
|
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
182
|
+
**정상 경로**: Main Claude는 레퍼런스 파일을 읽지 않으며 — `agent-flow.md`만 읽습니다. `{REFERENCES_DIR}/`의 레퍼런스 파일을 읽는 주체는 **orchestrator 하나뿐**입니다(기동 시 1회, 5개 파일).
|
|
183
|
+
|
|
184
|
+
**축퇴 모드(§7)**: orchestrator 역할이 Main Claude로 넘어오므로 Main Claude가 그 5개 파일을 읽습니다. 읽는 주체만 바뀌고 횟수·범위는 동일합니다.
|
|
185
|
+
|
|
186
|
+
어느 경우든 자식 에이전트(specifier/planner/builder/verifier/committer)는 디스크를 읽지 않고, 각 파일 상단의 **섹션 소비 매트릭스**를 기준으로 잘라 전달된 `<ref-cache>`만 사용합니다 → `xml-schema.md` § 4.
|
|
174
187
|
|
|
175
188
|
---
|
|
176
189
|
|
|
177
|
-
##
|
|
190
|
+
## 7. 축퇴 모드 — Main Claude가 orchestrator 역할 수행
|
|
191
|
+
|
|
192
|
+
### 진입 조건
|
|
193
|
+
|
|
194
|
+
orchestrator가 `<capability-degraded reason="no-agent-tool">`(→ `xml-schema.md` § 8)을 반환한 경우. 일부 CLI 버전·환경에서 서브에이전트에 `Agent` 도구가 주입되지 않아 중첩 spawn이 불가능할 때 발생합니다. orchestrator는 이때 아무 산출물도 만들지 않고 즉시 반환하므로, 디스크에는 아무것도 남아 있지 않은 상태입니다.
|
|
195
|
+
|
|
196
|
+
### 처리 절차
|
|
197
|
+
|
|
198
|
+
1. **사용자에게 1줄 알린다** — 예: "중첩 spawn을 지원하지 않는 환경입니다. Main Claude가 직접 오케스트레이션합니다." 승인을 기다리지 않고 그대로 진행합니다(`mode=auto`의 무정지 완주 원칙 유지).
|
|
199
|
+
2. **`{REFERENCES_DIR}/orchestrator.md`와 레퍼런스 5종을 읽는다** — `file-content-schema.md`, `shared-prompt-sections.md`, `xml-schema.md`, `work-activity-log.md`, `context-policy.md`.
|
|
200
|
+
3. **`orchestrator.md`의 절차를 그대로 수행한다.** 정본은 `orchestrator.md` 하나이며 축퇴용 별도 절차는 없습니다. STEP A~D, TASK DAG 스케줄링, 재시도, 컨텍스트 핸드오프, ref-cache 조립(STEP 1-1), 활동 로그 규칙이 **전부 동일하게** 적용됩니다.
|
|
201
|
+
4. **활동 로그**에 `ORCHESTRATOR_START` 직후 `ORCHESTRATOR_DEGRADED — reason=no-agent-tool`을 1회 기록합니다.
|
|
202
|
+
|
|
203
|
+
### 정상 경로와 다른 점 — 3가지뿐
|
|
204
|
+
|
|
205
|
+
| 항목 | 정상 | 축퇴 |
|
|
206
|
+
|------|------|------|
|
|
207
|
+
| 자식 spawn depth | 2 (orchestrator가 spawn) | **1** (Main Claude가 직접 spawn) |
|
|
208
|
+
| 게이트 처리 | orchestrator가 `<gate>` 반환 후 yield → Main Claude가 사용자에게 질의 | **Main Claude가 사용자에게 직접 질의** — `<gate>` XML·`SendMessage`·`TaskStop` 불필요 |
|
|
209
|
+
| 레퍼런스를 읽는 주체 | orchestrator | **Main Claude** |
|
|
210
|
+
|
|
211
|
+
그 외 산출물 형식, 로그 이벤트 체계, ref-cache 조립 규칙, 재개 판정은 모두 같습니다.
|
|
212
|
+
|
|
213
|
+
### 금지 사항
|
|
214
|
+
|
|
215
|
+
- **자식 역할을 인라인으로 대행하지 않는다.** 축퇴 모드에서도 specifier/planner/builder/verifier/committer는 반드시 별도 spawn한다. Main Claude가 직접 코드를 작성하거나 커밋하면 파이프라인의 역할 분리가 사라진다.
|
|
216
|
+
- `<ref-cache>` 없이 자식을 spawn하지 않는다 — 정상 경로와 동일하게 필수다.
|
|
217
|
+
|
|
218
|
+
### 재개
|
|
178
219
|
|
|
179
|
-
|
|
220
|
+
축퇴 모드로 진행 중이던 WORK를 재개할 때도 동일하다. Main Claude는 `works/{WORK_ID}/work_{WORK_ID}.log`의 마지막 이벤트로 재개 지점을 판정한다(§2 "재개 규칙"). 로그에 `ORCHESTRATOR_DEGRADED`가 있으면 그 WORK는 축퇴 모드로 시작됐다는 뜻이지만, 재개 시점의 환경이 바뀌었을 수 있으므로 **매번 orchestrator를 먼저 spawn해 다시 판정**한다.
|
|
@@ -2,7 +2,24 @@
|
|
|
2
2
|
|
|
3
3
|
에이전트 간 슬라이딩 윈도우 컨텍스트 전달 규칙.
|
|
4
4
|
|
|
5
|
-
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
## 섹션 소비 매트릭스
|
|
8
|
+
|
|
9
|
+
orchestrator가 자식 spawn 시 `<ref-cache>`에 담을 섹션을 결정하는 기준표 → `xml-schema.md` § 4.
|
|
10
|
+
|
|
11
|
+
| § | 내용 | orch | spec | plan | build | verif | commit |
|
|
12
|
+
|---|------|:----:|:----:|:----:|:-----:|:-----:|:------:|
|
|
13
|
+
| 1 | 슬라이딩 윈도우 | ✅ | | | ✅ | ✅ | ✅ |
|
|
14
|
+
| 2 | Context-Handoff 4개 필드 | ✅ | | | ✅ | ✅ | ✅ |
|
|
15
|
+
| 3 | 파이프라인 단계별 입출력 | | | | ✅ | ✅ | ✅ |
|
|
16
|
+
| 4 | TASK 간 의존성 전달 | ✅ | | | ✅ | | |
|
|
17
|
+
| 5 | Orchestrator 디스패치 | ✅ | | | | | |
|
|
18
|
+
| 6 | Committer 재시도 | ✅ | | | | | |
|
|
19
|
+
|
|
20
|
+
---
|
|
21
|
+
|
|
22
|
+
## § 1. 슬라이딩 윈도우
|
|
6
23
|
|
|
7
24
|
| 단계 거리 | 상세 레벨 | 규칙 |
|
|
8
25
|
|-----------|----------|------|
|
|
@@ -10,7 +27,7 @@
|
|
|
10
27
|
| 2단계 전 | `SUMMARY` | `what` 필드만, 1-3줄 |
|
|
11
28
|
| 3단계+ | `DROP` | 생략 |
|
|
12
29
|
|
|
13
|
-
## Context-Handoff 4개 필드
|
|
30
|
+
## § 2. Context-Handoff 4개 필드
|
|
14
31
|
|
|
15
32
|
| 필드 | FULL | SUMMARY | 내용 |
|
|
16
33
|
|------|:----:|:-------:|------|
|
|
@@ -19,7 +36,7 @@
|
|
|
19
36
|
| `caution` | ✅ | ❌ | 주의사항, 조건부 완료 (1-3줄) |
|
|
20
37
|
| `incomplete` | ✅ | ❌ | 미완료 항목 (1-2줄, 없으면 "None") |
|
|
21
38
|
|
|
22
|
-
## 파이프라인 단계별 입출력
|
|
39
|
+
## § 3. 파이프라인 단계별 입출력
|
|
23
40
|
|
|
24
41
|
### Builder
|
|
25
42
|
|
|
@@ -55,15 +72,17 @@
|
|
|
55
72
|
1. builder 성공 여부 확인 (context-handoff 상태 확인)
|
|
56
73
|
2. result.md 작성 + git commit
|
|
57
74
|
|
|
58
|
-
출력:
|
|
75
|
+
출력: `works/{WORK_ID}/TASK-XX_result.md` + task-result XML
|
|
59
76
|
|
|
60
|
-
## TASK 간 의존성 전달
|
|
77
|
+
## § 4. TASK 간 의존성 전달
|
|
61
78
|
|
|
62
79
|
- 직전 의존 TASK: context-handoff **FULL** (4개 필드 모두)
|
|
63
80
|
- 2단계 전: **SUMMARY** (what만)
|
|
64
81
|
- 3단계+: **DROP**
|
|
65
82
|
|
|
66
|
-
##
|
|
83
|
+
## § 5. Orchestrator 디스패치
|
|
84
|
+
|
|
85
|
+
TASK DAG 실행 중 다음 자식(중첩 spawn)의 프롬프트를 구성하는 주체는 **orchestrator**다 — dispatch XML을 만들어 자식 spawn 프롬프트에 포함한다.
|
|
67
86
|
|
|
68
87
|
```xml
|
|
69
88
|
<!-- Verifier: Builder FULL -->
|
|
@@ -86,7 +105,7 @@
|
|
|
86
105
|
</dispatch>
|
|
87
106
|
```
|
|
88
107
|
|
|
89
|
-
## Committer 재시도
|
|
108
|
+
## § 6. Committer 재시도
|
|
90
109
|
|
|
91
110
|
1. 실패 원인: 검증 FAIL / 변경 파일 없음
|
|
92
111
|
2. builder에 재디스패치
|
|
@@ -2,15 +2,35 @@
|
|
|
2
2
|
|
|
3
3
|
파이프라인 산출물 파일 형식의 단일 정의 소스.
|
|
4
4
|
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
## 섹션 소비 매트릭스
|
|
8
|
+
|
|
9
|
+
orchestrator가 자식 spawn 시 `<ref-cache>`에 담을 섹션을 결정하는 기준표 → `xml-schema.md` § 4.
|
|
10
|
+
|
|
11
|
+
| § | 내용 | orch | spec | plan | build | verif | commit |
|
|
12
|
+
|---|------|:----:|:----:|:----:|:-----:|:-----:|:------:|
|
|
13
|
+
| — | 준수사항 (아래 표) | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ |
|
|
14
|
+
| 0 | Requirement.md | | ✅ | ✅ | | | |
|
|
15
|
+
| 1 | PLAN.md | ✅ | | ✅ | | | |
|
|
16
|
+
| 2 | TASK-XX.md | | | ✅ | ✅ | ✅ | |
|
|
17
|
+
| 3 | TASK-XX_result.md | | | | ✅ | | ✅ |
|
|
18
|
+
| 4 | DECISIONS.md | ✅ | | | | | |
|
|
19
|
+
| 5 | 파일 이름 규칙 | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ |
|
|
20
|
+
|
|
21
|
+
> "준수사항" 표는 § 번호가 없다. 모든 에이전트가 공통으로 필요로 하므로 이 파일을 전달할 때는 **항상 함께 싣고**, `sections` 속성에는 표기하지 않는다.
|
|
22
|
+
|
|
23
|
+
---
|
|
24
|
+
|
|
5
25
|
## 준수사항
|
|
6
26
|
|
|
7
27
|
| 생성 파일 | 참조 섹션 | 위반 시 결과 |
|
|
8
28
|
|-----------|----------|-------------|
|
|
9
29
|
| `Requirement.md` | § 0 | |
|
|
10
|
-
| `PLAN.md` | § 1 | `parsePlanMd()` 파싱 실패,
|
|
30
|
+
| `PLAN.md` | § 1 | `parsePlanMd()` 파싱 실패, orchestrator 파이프라인 작동 불가 |
|
|
11
31
|
| `TASK-XX.md` | § 2 | `parseTaskFilename()` DB 등록 누락 |
|
|
12
32
|
| `TASK-XX_result.md` | § 3 | context-handoff 누락 |
|
|
13
|
-
| `
|
|
33
|
+
| `DECISIONS.md` | § 4 | 재개(resume) 시 PENDING 결정 재제시 불가 |
|
|
14
34
|
|
|
15
35
|
---
|
|
16
36
|
|
|
@@ -50,7 +70,6 @@
|
|
|
50
70
|
|
|
51
71
|
> Created: {YYYY-MM-DD}
|
|
52
72
|
> Requirement: {REQ-XXX | 사용자 요청 텍스트}
|
|
53
|
-
> Execution-Mode: {direct | pipeline | full}
|
|
54
73
|
> Project: {프로젝트 이름}
|
|
55
74
|
> Tech Stack: {스택}
|
|
56
75
|
> Language: {lang_code}
|
|
@@ -178,7 +197,7 @@
|
|
|
178
197
|
|
|
179
198
|
---
|
|
180
199
|
|
|
181
|
-
## § 3. TASK-XX_result.md
|
|
200
|
+
## § 3. TASK-XX_result.md
|
|
182
201
|
|
|
183
202
|
경로: `works/{WORK_ID}/TASK-XX_result.md`
|
|
184
203
|
|
|
@@ -231,27 +250,47 @@ None
|
|
|
231
250
|
|
|
232
251
|
---
|
|
233
252
|
|
|
234
|
-
## § 4.
|
|
253
|
+
## § 4. DECISIONS.md
|
|
254
|
+
|
|
255
|
+
경로: `works/{WORK_ID}/DECISIONS.md`
|
|
256
|
+
|
|
257
|
+
orchestrator가 `<gate type="decision">` 또는 자식 에이전트의 `<needs-decision>`(→ `xml-schema.md` § 5, § 6)을 수신할 때마다 항목을 추가하는 결정 로그. 게이트가 yield된 시점에는 항목을 **PENDING**으로 먼저 기록하고, 승인/자동결정으로 해소되면 같은 항목을 **RESOLVED**로 갱신한다.
|
|
235
258
|
|
|
236
259
|
```markdown
|
|
237
|
-
#
|
|
260
|
+
# DECISIONS — WORK-NN
|
|
238
261
|
|
|
239
|
-
|
|
240
|
-
>
|
|
241
|
-
>
|
|
242
|
-
>
|
|
262
|
+
## D-01
|
|
263
|
+
> 시각: {YYYY-MM-DDTHH:MM:SSZ}
|
|
264
|
+
> 단계: {specifier|planner|builder|verifier|committer}
|
|
265
|
+
> 상태: {PENDING|RESOLVED}
|
|
266
|
+
|
|
267
|
+
### 배경
|
|
268
|
+
{결정이 필요한 이유}
|
|
243
269
|
|
|
244
|
-
|
|
245
|
-
{1
|
|
270
|
+
### 선택지
|
|
271
|
+
1. {선택지 1}
|
|
272
|
+
2. {선택지 2}
|
|
246
273
|
|
|
247
|
-
|
|
248
|
-
|
|
274
|
+
### 권고안
|
|
275
|
+
{orchestrator/자식 에이전트가 제시한 권고}
|
|
249
276
|
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
277
|
+
### 확정값
|
|
278
|
+
{확정된 선택 — PENDING 상태에서는 공란 또는 "(대기 중)"}
|
|
279
|
+
|
|
280
|
+
### 결정주체
|
|
281
|
+
{user 승인 | auto}
|
|
253
282
|
```
|
|
254
283
|
|
|
284
|
+
| 필드 | PENDING (게이트 yield 시) | RESOLVED (해소 후) |
|
|
285
|
+
|------|---------------------------|---------------------|
|
|
286
|
+
| 확정값 | 공란 / `(대기 중)` | 채움 |
|
|
287
|
+
| 결정주체 | 공란 | `user 승인` 또는 `auto` |
|
|
288
|
+
|
|
289
|
+
- **재개(resume) 근거**: orchestrator가 중단 후 재개할 때 DECISIONS.md에서 `상태: PENDING` 항목을 찾아 동일한 배경·선택지·권고안으로 게이트를 다시 제시한다. 이 상태 필드가 없으면 재개 시 이미 물었던 결정인지 판단할 수 없어, 미승인 결정을 건너뛰거나 사용자에게 같은 질문을 중복 제시하는 오류가 발생한다.
|
|
290
|
+
- 활동 로그의 `DECISION_WAIT`/`DECISION` 이벤트와 1:1로 대응한다 → `work-activity-log.md` 참조.
|
|
291
|
+
|
|
292
|
+
생성 주체: orchestrator
|
|
293
|
+
|
|
255
294
|
---
|
|
256
295
|
|
|
257
296
|
## § 5. 파일 이름 규칙
|
|
@@ -262,6 +301,7 @@ None
|
|
|
262
301
|
| WORK 계획 | `PLAN.md` | planner / specifier |
|
|
263
302
|
| TASK 계획 | `TASK-NN.md` | planner / specifier |
|
|
264
303
|
| TASK 결과 | `TASK-NN_result.md` | committer |
|
|
265
|
-
|
|
|
304
|
+
| 결정 로그 | `DECISIONS.md` | orchestrator |
|
|
305
|
+
| 활동 로그 | `work_WORK-NN.log` | orchestrator (추가) |
|
|
266
306
|
|
|
267
307
|
`WORK-NN-TASK-NN.md` 형식 금지 → `parseTaskFilename()`이 인식할 수 없음.
|
|
@@ -1,6 +1,27 @@
|
|
|
1
1
|
# 공유 프롬프트 섹션
|
|
2
2
|
|
|
3
|
-
각 에이전트가
|
|
3
|
+
각 에이전트가 참조하는 공통 재사용 섹션.
|
|
4
|
+
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
## 섹션 소비 매트릭스
|
|
8
|
+
|
|
9
|
+
orchestrator가 자식 spawn 시 `<ref-cache>`에 담을 섹션을 결정하는 기준표 → `xml-schema.md` § 4.
|
|
10
|
+
|
|
11
|
+
| § | 내용 | orch | spec | plan | build | verif | commit |
|
|
12
|
+
|---|------|:----:|:----:|:----:|:-----:|:-----:|:------:|
|
|
13
|
+
| 1 | 출력 언어 규칙 | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ |
|
|
14
|
+
| 2 | 빌드 및 린트 명령 | | | | ✅ | ✅ | |
|
|
15
|
+
| 3 | WORK 및 TASK 파일 경로 패턴 | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ |
|
|
16
|
+
| 4 | 파일 시스템 Discovery 스크립트 | ✅ | | | | | |
|
|
17
|
+
| 5 | Task Result XML 형식 | | | | ✅ | ✅ | ✅ |
|
|
18
|
+
| 6 | 자동결정 기록 관례 | ✅ | | | | | |
|
|
19
|
+
| 7 | PLAN.md 필수 메타 정보 | | | ✅ | | | |
|
|
20
|
+
| 8 | WORK-LIST.md 업데이트 규칙 | | ✅ | | | | ✅ |
|
|
21
|
+
| 9 | 로케일 감지 | ✅ | ✅ | | | | |
|
|
22
|
+
| 12 | Bash 명령 규칙 | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ |
|
|
23
|
+
|
|
24
|
+
> § 10·§ 11은 존재하지 않는다(과거 삭제분). 기존 상호참조 호환을 위해 번호를 재사용하지 않는다.
|
|
4
25
|
|
|
5
26
|
---
|
|
6
27
|
|
|
@@ -71,29 +92,26 @@ works/{WORK_ID}/
|
|
|
71
92
|
# Glob 도구 사용: pattern "works/WORK-*/" → 모든 WORK 디렉토리 목록 (정렬)
|
|
72
93
|
# 각 WORK (내림차순)에 대해 works/WORK-NN/work_WORK-NN.log 마지막 줄 읽기
|
|
73
94
|
# - 로그 파일 없음 → 시작 안 됨
|
|
74
|
-
# - 마지막
|
|
95
|
+
# - 마지막 줄이 "ORCHESTRATOR_DONE" → 완료됨
|
|
75
96
|
# 완전히 완료되지 않은 첫 번째 WORK가 활성 WORK
|
|
76
97
|
|
|
77
98
|
# 모든 WORK 목록
|
|
78
99
|
# Glob 도구 사용: pattern "works/WORK-*/"
|
|
79
100
|
|
|
80
|
-
# 활동 로그의 마지막 줄로 WORK/TASK 상태 파악
|
|
101
|
+
# 활동 로그의 마지막 줄로 WORK/TASK 상태 파악 (orchestrator가 일괄 기록 → work-activity-log.md 참조)
|
|
81
102
|
# works/${WORK_ID}/work_${WORK_ID}.log 마지막 줄 읽기
|
|
82
103
|
# 형식: [timestamp] EVENT — description
|
|
83
104
|
#
|
|
84
|
-
# 핵심 규칙:
|
|
105
|
+
# 핵심 규칙: STAGE_START에 대응하는 STAGE_DONE/GATE_WAIT/DECISION_WAIT가 없으면 = 자식 실행 중 중단됨, 해당 단계 재수행 필요
|
|
85
106
|
#
|
|
86
|
-
#
|
|
87
|
-
#
|
|
88
|
-
#
|
|
89
|
-
#
|
|
90
|
-
#
|
|
91
|
-
#
|
|
92
|
-
#
|
|
93
|
-
#
|
|
94
|
-
# SPECIFIER_DONE → specifier 완료, planner 필요
|
|
95
|
-
# SPECIFIER_START → specifier 중단됨, specifier 재수행
|
|
96
|
-
# 로그 파일 없음 → 처음부터 시작
|
|
107
|
+
# ORCHESTRATOR_DONE → WORK 전체 완료
|
|
108
|
+
# STAGE_DONE — stage=X[ task=TASK-NN] → 해당 단계 완료(게이트 통과됨), 다음 단계로
|
|
109
|
+
# GATE_WAIT — stage=X → 게이트 미승인, 자식 재실행 없이 동일 게이트 재제시
|
|
110
|
+
# DECISION_WAIT — stage=X[ task=TASK-NN] → 결정 미확정, DECISIONS.md의 PENDING 항목 재제시
|
|
111
|
+
# DECISION — stage=X by=user|auto → 결정 확정됨, 후속 STAGE_DONE 없으면 해당 단계 이어서 진행
|
|
112
|
+
# STAGE_START — stage=X[ task=TASK-NN] → (대응 DONE/WAIT 없으면) 자식 실행 중 중단됨, 재실행
|
|
113
|
+
# ORCHESTRATOR_START → orchestrator 시작됨, 하위 이벤트로 세부 판정
|
|
114
|
+
# 로그 파일 없음 → 처음부터 시작 (신규 WORK)
|
|
97
115
|
```
|
|
98
116
|
|
|
99
117
|
---
|
|
@@ -115,15 +133,26 @@ works/{WORK_ID}/
|
|
|
115
133
|
|
|
116
134
|
---
|
|
117
135
|
|
|
136
|
+
## § 6. 자동결정 기록 관례
|
|
137
|
+
|
|
138
|
+
권고안을 자동결정(결정주체 `auto`)한 경우, 판단 근거를 남겨 추적 가능하게 한다.
|
|
139
|
+
|
|
140
|
+
- **기록 위치**: `works/{WORK_ID}/DECISIONS.md`(항목별 배경/선택지/권고안/확정값/결정주체/상태) + 최종 결과보고서 `## 자동 결정 사항` 목록.
|
|
141
|
+
- **기록 시점**: 결정 확정 즉시 `RESOLVED`로 기록. `mode=auto`뿐 아니라 `mode=gated`에서 orchestrator가 경미한 사항으로 판단해 게이트 없이 자체 확정(`by=auto`)한 경우도 동일하게 기록.
|
|
142
|
+
- **최소 기재 항목**: 대상(stage 또는 task) · 확정값 · 근거 1줄.
|
|
143
|
+
|
|
144
|
+
→ 상세 포맷: `file-content-schema.md` § 4 참조. 기록 주체·이벤트: `work-activity-log.md`의 `DECISION` 이벤트 참조.
|
|
145
|
+
|
|
146
|
+
---
|
|
147
|
+
|
|
118
148
|
## § 7. PLAN.md 필수 메타 정보 — 7개 필드
|
|
119
149
|
|
|
120
|
-
→ `
|
|
150
|
+
→ `file-content-schema.md` § 1 참조
|
|
121
151
|
|
|
122
152
|
| 필드 | 필수 | 설명 |
|
|
123
153
|
|------|------|------|
|
|
124
154
|
| `> Created:` | ✅ | YYYY-MM-DD |
|
|
125
155
|
| `> Requirement:` | ✅ | `REQ-XXX` 또는 사용자 요청 텍스트 |
|
|
126
|
-
| `> Execution-Mode:` | ✅ | `direct` / `pipeline` / `full` |
|
|
127
156
|
| `> Project:` | ✅ | 프로젝트 이름 |
|
|
128
157
|
| `> Tech Stack:` | ✅ | 감지된 기술 스택 |
|
|
129
158
|
| `> Language:` | ✅ | 언어 코드 (`ko`, `en` 등) |
|