Skip to content

Commit 4817648

Browse files
authored
fix(workflow): AskUserQuestion Enforcement Protocol (§19 신설 + Red Flags 강화) (#708)
2026-04-24 세션에서 AskUserQuestion 미사용으로 [HARD] §1/§8 규칙 반복 위반 발생. 근본 원인 3단계 분석 후 systemic fix 적용. ## Root Cause Chain 1차: AskUserQuestion은 deferred tool. 세션 시작 시 schema 미로드 → 호출 시 InputValidationError → agent가 회피 → 산문 질문으로 우회. 2차: Red Flags/Verification 체크리스트에 "응답 말미 ? + AskUserQuestion 미호출" 탐지 규칙 부재. 3차: 규칙은 존재하나 enforcement 메커니즘 없이 해석 의존. "짧은 질문은 산문으로" 편의주의 관행. ## Fix Scope (Template-First rule 준수, 양쪽 동기화) ### CLAUDE.md (project + template) - §1 HARD Rules: "Deferred Tool Preload" 추가 (AskUserQuestion, TaskCreate/Update/List/Get 사전 로드 의무) - §8 User Interaction Architecture: "Deferred Tool Preload Protocol [HARD]" 신설 - Preload triggers (5개 조건) - ToolSearch 명령어 - 5가지 anti-patterns - Pre-response self-check (4단계) - Self-check failure = HARD 위반 선언 ### .claude/skills/moai/SKILL.md (project + template) - Common Rationalizations 테이블에 2 rows 추가: * "Schema 로드가 귀찮으니 산문으로" * "짧은 확인 질문은 산문으로" - Red Flags 섹션에 5 items 추가: * 응답 ?로 끝나는데 AskUserQuestion 미호출 * 선택지 markdown-only 나열 * 산문 decision request * ToolSearch preload 누락 * Silent wait state - Verification 섹션에 4 items 추가: * 세션 시작 ToolSearch preload * ? 있는 응답 + AskUserQuestion 동반 * Option list + structured question * Silent wait 없음 ### CLAUDE.local.md §19 AskUserQuestion Enforcement Protocol (신설, 82 lines) - §19.1 근본 원인 체인 (3 layers) - §19.2 [HARD] 세션 시작 Preload (ToolSearch 의무 명령어) - §19.3 [HARD] Pre-Response Self-Check (4 steps) - §19.4 [HARD] Anti-Patterns 표 (5 patterns × why/how) - §19.5 Role별 운영 적용 (orchestrator/subagent/user) - §19.6 Recovery Protocol (위반 탐지 시 5단계) - §19.7 관련 정책 cross-reference - Version 3.3.0 → 3.4.0 ### memory/feedback_askuserquestion_enforcement.md (신규, 별도) - 2026-04-24 incident 기록 - Root cause chain + how to apply + anti-examples - MEMORY.md index 업데이트 ## Non-breaking - 기존 §1, §8 HARD 규칙은 모두 유지 (추가 HARD만 신설) - Skill SKILL.md 기존 섹션 rows 유지 (append-only) - Output style moai.md 불변 (이미 AskUserQuestion max 4 options 규칙 존재) - Agent 호출 경로 불변 ## Validation - make build: success (embedded templates 재생성) - 양쪽 CLAUDE.md / SKILL.md 동기화 확인 (template-first rule 준수) - 세션 이미 ToolSearch(select:AskUserQuestion,...) preload 수행 중 ## Post-merge 이후 모든 세션은 자동으로 §19.2 preload 의무 + §19.3 self-check 적용. Enhanced GitHub Flow §18.6 label: type:fix, priority:P1, area:workflow + area:config 🗿 MoAI <email@mo.ai.kr>
1 parent 9b8e083 commit 4817648

5 files changed

Lines changed: 167 additions & 1 deletion

File tree

.claude/skills/moai/SKILL.md

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -312,6 +312,8 @@ Last Updated: 2026-02-25
312312
| "I can run /moai run without a SPEC, it is just a tweak" | Without a SPEC, there is no acceptance criterion to check. Every run without a SPEC silently degrades quality tracking. |
313313
| "Parallel agents will just race, sequential is safer" | Independent tool calls are explicitly required to run in parallel. Sequentializing them wastes user time. |
314314
| "I will respond in English since it is technical" | Conversation language is a HARD rule. User-facing output must match the configured language, always. |
315+
| "Schema 로드가 귀찮으니 이번엔 산문으로 질문하자" | AskUserQuestion/Task* 는 deferred tool. ToolSearch 한 번으로 session 전체 사용 가능. 산문 질문은 HARD 위반 (CLAUDE.md §1, §8 Deferred Tool Preload Protocol). |
316+
| "짧은 확인 질문은 산문으로 처리해도 된다" | 모든 user-facing 질문은 AskUserQuestion 경유 강제. "짧은 질문"은 예외 아님. Self-check: 응답에 "?" 있으면 AskUserQuestion 호출 동반 필수. |
315317

316318
<!-- moai:evolvable-end -->
317319

@@ -324,6 +326,11 @@ Last Updated: 2026-02-25
324326
- AskUserQuestion with more than 4 options or containing emoji
325327
- Agent invocation prompt contains absolute paths to the main project when isolation is worktree
326328
- /moai run executed without a corresponding SPEC-XXX document
329+
- Response ends with "?" but no AskUserQuestion tool call accompanies it
330+
- Options listed as markdown (`- A:`, `- B:`, `Option X:`) without structured AskUserQuestion
331+
- Prose decision requests ("진행할까요?", "어느 것 선호?", "A or B?") instead of AskUserQuestion
332+
- First AskUserQuestion call in session without prior ToolSearch preload (produces InputValidationError)
333+
- Waiting for user's next message after prose question without AskUserQuestion tool call
327334

328335
<!-- moai:evolvable-end -->
329336

@@ -337,5 +344,9 @@ Last Updated: 2026-02-25
337344
- [ ] For non-trivial tasks, approach was explained and approved before code changes
338345
- [ ] SPEC-ID is referenced when /moai run, /moai sync, or /moai fix is invoked
339346
- [ ] TodoList used to decompose multi-file changes (3+ files)
347+
- [ ] Session opened with ToolSearch preload of deferred tools (AskUserQuestion, TaskCreate/Update/List/Get)
348+
- [ ] Every response containing "?" is accompanied by a structured AskUserQuestion tool call
349+
- [ ] Option lists (`- A:`, `- B:`) are routed through AskUserQuestion, not markdown-only
350+
- [ ] No silent "wait for user input" state after prose question (§8 Deferred Tool Preload Protocol)
340351

341352
<!-- moai:evolvable-end -->

CLAUDE.local.md

Lines changed: 81 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1056,6 +1056,86 @@ v2.14.0 릴리스 과정에서 다음 문제 발생 → v2.15부터 방지:
10561056

10571057
---
10581058

1059+
---
1060+
1061+
## 19. AskUserQuestion Enforcement Protocol
1062+
1063+
2026-04-24 세션에서 `AskUserQuestion` 미사용으로 [HARD] 규칙(§1, §8) 위반 반복 발생. 근본 원인은 **deferred tool 사전 로드 부재** + **산문 질문 편의주의**. v3.4.0부터 본 Enforcement Protocol을 [HARD] 운영 방침으로 고정.
1064+
1065+
### §19.1 근본 원인 체인
1066+
1067+
1. **1차 원인**: `AskUserQuestion`은 deferred tool. 세션 시작 시 schema 미로드 → 직접 호출 시 `InputValidationError` → agent가 회피 → 산문 질문으로 우회.
1068+
2. **2차 원인**: Red Flags / Verification 체크리스트에 "응답 말미 `?` + AskUserQuestion 미호출" 탐지 규칙 부재.
1069+
3. **3차 원인**: 규칙은 존재하나 매 세션 agent 해석에 의존. 편의주의("짧은 질문은 산문으로") 허용 관행.
1070+
1071+
### §19.2 [HARD] 세션 시작 Preload (의무)
1072+
1073+
모든 MoAI 세션은 첫 사용자 입력 수신 직후 다음 `ToolSearch` 호출을 실행해야 한다:
1074+
1075+
```
1076+
ToolSearch({
1077+
query: "select:AskUserQuestion,TaskCreate,TaskUpdate,TaskList,TaskGet",
1078+
max_results: 5
1079+
})
1080+
```
1081+
1082+
Preload 완료 후에만 해당 tool 호출 가능. Preload 이전 호출 = HARD 위반 + `InputValidationError`.
1083+
1084+
### §19.3 [HARD] Pre-Response Self-Check (응답 전송 전 필수)
1085+
1086+
모든 사용자 응답 전송 전, 다음 4항목 자가 점검:
1087+
1088+
1. **Question mark detection**: 응답에 `?`가 포함되었는가? → 있으면 `AskUserQuestion` tool call 동반 필수
1089+
2. **Option list detection**: 응답에 선택지 구조(`- A:`, `- B:`, `Option X:`, `1.`)가 있는가? → structured `AskUserQuestion` 경유 필수
1090+
3. **Schema load check**: `AskUserQuestion` schema 로드 상태 확인. 미로드 시 `ToolSearch` 선행
1091+
4. **Silent-wait detection**: 산문 질문 후 사용자 응답 대기 상태인가? → `AskUserQuestion`으로 전환 필수
1092+
1093+
점검 실패 시 = [HARD] 규칙 위반. 즉시 수정 필요.
1094+
1095+
### §19.4 [HARD] Anti-Patterns (금지)
1096+
1097+
| 패턴 | 왜 금지 | 올바른 방법 |
1098+
|------|---------|-------------|
1099+
| 응답 말미 `?`로 끝나는 산문 질문 | 사용자에게 무엇을 원하는지 불명확, silent wait | `AskUserQuestion` 호출 필수 |
1100+
| "진행할까요?", "A or B?" 자연어 선택 요청 | structured 응답 아닌 free-form 기대 → 파싱 불가 | `AskUserQuestion` with 2-4 options |
1101+
| 선택지를 markdown `- A:`, `- B:`로만 나열 | 사용자가 자연어로 답해야 함 | `AskUserQuestion` structured options |
1102+
| `AskUserQuestion` 호출 전 `ToolSearch` 생략 | `InputValidationError` 발생 | §19.2 Preload 먼저 |
1103+
| Silent "wait for next message" after prose | 사용자에게 정확한 응답 형식 미제공 | `AskUserQuestion` 또는 구체적 지시 |
1104+
1105+
### §19.5 운영 적용 (Role별)
1106+
1107+
**MoAI orchestrator**:
1108+
- [HARD] 모든 사용자 결정 요청은 `AskUserQuestion` 경유
1109+
- [HARD] 세션 시작 시 §19.2 preload 실행
1110+
- [HARD] 응답 전송 전 §19.3 self-check 통과
1111+
1112+
**Subagent (manager-*, expert-*, builder-*)**:
1113+
- [HARD] `AskUserQuestion` 호출 금지 (agent-common-protocol §User Interaction Boundary)
1114+
- 사용자 결정 필요 시 "missing inputs" 보고서로 orchestrator에 반환
1115+
1116+
**User**:
1117+
- 산문 질문 탐지 시 즉시 지적 (2026-04-24 세션 사례처럼)
1118+
- 반복 위반 시 memory/feedback_askuserquestion_*.md에 기록
1119+
1120+
### §19.6 Recovery Protocol (위반 발생 시)
1121+
1122+
[HARD] 위반 탐지 즉시 다음 순서로 복구:
1123+
1124+
1. 위반 인정 + 근본 원인 명시 (1/2/3차)
1125+
2. `ToolSearch`로 schema preload
1126+
3. 동일 질문을 `AskUserQuestion`으로 재구성 + 재전송
1127+
4. `memory/feedback_askuserquestion_*.md`에 incident 기록
1128+
5. 다음 응답부터 §19.3 self-check 엄격 적용
1129+
1130+
### §19.7 관련 정책 참조
1131+
1132+
- CLAUDE.md §1 HARD Rules (AskUserQuestion-Only + Deferred Tool Preload)
1133+
- CLAUDE.md §8 User Interaction Architecture § Deferred Tool Preload Protocol
1134+
- .claude/skills/moai/SKILL.md § Red Flags + Verification (deferred tool 관련 5+4 항목)
1135+
- ~/.claude/projects/{hash}/memory/feedback_askuserquestion_enforcement.md (이번 incident 기록)
1136+
1137+
---
1138+
10591139
**Status**: Active (Local Development)
1060-
**Version**: 3.3.0 (Phase 8: §18.0 운영 원칙 5 Framework 명시화 + Release Drafter 구성 완료)
1140+
**Version**: 3.4.0 (Phase 9: §19 AskUserQuestion Enforcement Protocol 공식 채택)
10611141
**Last Updated**: 2026-04-24

CLAUDE.md

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ MoAI is the Strategic Orchestrator for Claude Code. All tasks must be delegated
1111
- [HARD] No XML in User Responses: Never display XML tags in user-facing responses
1212
- [HARD] Markdown Output: Use Markdown for all user-facing communication
1313
- [HARD] AskUserQuestion-Only Interaction: ALL questions directed at the user MUST go through AskUserQuestion (See Section 8)
14+
- [HARD] Deferred Tool Preload: AskUserQuestion, TaskCreate/Update/List/Get are deferred tools — schema is NOT loaded at session start. Call ToolSearch BEFORE first use to load schemas. Calling without schema produces InputValidationError. (See Section 8 Deferred Tool Preload Protocol)
1415
- [HARD] Context-First Discovery: Conduct Socratic interview via AskUserQuestion when context is insufficient before executing non-trivial tasks (See Section 7)
1516
- [HARD] Approach-First Development: Explain approach and get approval before writing code (See Section 7)
1617
- [HARD] Multi-File Decomposition: Split work when modifying 3+ files (See Section 7)
@@ -316,6 +317,37 @@ Exceptions (free-form text questions permitted ONLY when):
316317
- AskUserQuestion is technically unavailable (e.g., inside a subagent — should not happen since subagents must not ask users)
317318
- The question is actually a statement of status, not a question
318319

320+
### Deferred Tool Preload Protocol [HARD]
321+
322+
[HARD] `AskUserQuestion`, `TaskCreate`, `TaskUpdate`, `TaskList`, `TaskGet` are **deferred tools** — their schemas are NOT loaded at session start. Calling them directly produces `InputValidationError`. Load schemas via `ToolSearch` BEFORE first use.
323+
324+
Preload triggers (execute ToolSearch immediately when any condition matches):
325+
- Session start after first user input received
326+
- Before any complex / multi-step task begins
327+
- Before invoking Socratic interview (Section 7 Rule 5)
328+
- When user decision is required ("Should I proceed?", "Which option?", "선택", "진행 여부")
329+
- Immediately before first TaskCreate/Update/List/Get call
330+
331+
Preload command (once per session, BEFORE any user-facing question):
332+
```
333+
ToolSearch({query: "select:AskUserQuestion,TaskCreate,TaskUpdate,TaskList,TaskGet", max_results: 5})
334+
```
335+
336+
Anti-patterns (PROHIBITED — these constitute HARD violation of §1):
337+
- Prose question ending with "?" + no accompanying AskUserQuestion tool call
338+
- Natural language decision requests: "진행할까요?", "어느 것을 선호하시나요?", "A or B?"
339+
- Listing options as markdown only (`- A:`, `- B:`) without structured AskUserQuestion
340+
- Calling AskUserQuestion without prior ToolSearch preload (produces InputValidationError)
341+
- Converting a user decision into a "wait for next message" without AskUserQuestion
342+
343+
Pre-response self-check (MANDATORY before sending any user-facing response):
344+
1. Does the response end with "?" or contain "?" as a decision prompt? → MUST be paired with AskUserQuestion tool call
345+
2. Does the response list options (`- A:`, `1.`, `Option X:`)? → MUST use structured AskUserQuestion
346+
3. Is the deferred tool schema loaded? → If not, call ToolSearch FIRST
347+
4. Am I silently waiting for user input after prose question? → Convert to AskUserQuestion
348+
349+
Self-check failure = HARD rule violation. Treat as critical defect requiring immediate correction.
350+
319351
### Socratic Interview via AskUserQuestion [HARD]
320352

321353
When context is insufficient (see Section 7 Rule 5 triggers), MoAI conducts a Socratic interview using AskUserQuestion rounds.

internal/template/templates/.claude/skills/moai/SKILL.md

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -312,6 +312,8 @@ Last Updated: 2026-02-25
312312
| "I can run /moai run without a SPEC, it is just a tweak" | Without a SPEC, there is no acceptance criterion to check. Every run without a SPEC silently degrades quality tracking. |
313313
| "Parallel agents will just race, sequential is safer" | Independent tool calls are explicitly required to run in parallel. Sequentializing them wastes user time. |
314314
| "I will respond in English since it is technical" | Conversation language is a HARD rule. User-facing output must match the configured language, always. |
315+
| "Schema 로드가 귀찮으니 이번엔 산문으로 질문하자" | AskUserQuestion/Task* 는 deferred tool. ToolSearch 한 번으로 session 전체 사용 가능. 산문 질문은 HARD 위반 (CLAUDE.md §1, §8 Deferred Tool Preload Protocol). |
316+
| "짧은 확인 질문은 산문으로 처리해도 된다" | 모든 user-facing 질문은 AskUserQuestion 경유 강제. "짧은 질문"은 예외 아님. Self-check: 응답에 "?" 있으면 AskUserQuestion 호출 동반 필수. |
315317

316318
<!-- moai:evolvable-end -->
317319

@@ -324,6 +326,11 @@ Last Updated: 2026-02-25
324326
- AskUserQuestion with more than 4 options or containing emoji
325327
- Agent invocation prompt contains absolute paths to the main project when isolation is worktree
326328
- /moai run executed without a corresponding SPEC-XXX document
329+
- Response ends with "?" but no AskUserQuestion tool call accompanies it
330+
- Options listed as markdown (`- A:`, `- B:`, `Option X:`) without structured AskUserQuestion
331+
- Prose decision requests ("진행할까요?", "어느 것 선호?", "A or B?") instead of AskUserQuestion
332+
- First AskUserQuestion call in session without prior ToolSearch preload (produces InputValidationError)
333+
- Waiting for user's next message after prose question without AskUserQuestion tool call
327334

328335
<!-- moai:evolvable-end -->
329336

@@ -337,5 +344,9 @@ Last Updated: 2026-02-25
337344
- [ ] For non-trivial tasks, approach was explained and approved before code changes
338345
- [ ] SPEC-ID is referenced when /moai run, /moai sync, or /moai fix is invoked
339346
- [ ] TodoList used to decompose multi-file changes (3+ files)
347+
- [ ] Session opened with ToolSearch preload of deferred tools (AskUserQuestion, TaskCreate/Update/List/Get)
348+
- [ ] Every response containing "?" is accompanied by a structured AskUserQuestion tool call
349+
- [ ] Option lists (`- A:`, `- B:`) are routed through AskUserQuestion, not markdown-only
350+
- [ ] No silent "wait for user input" state after prose question (§8 Deferred Tool Preload Protocol)
340351

341352
<!-- moai:evolvable-end -->

internal/template/templates/CLAUDE.md

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ MoAI is the Strategic Orchestrator for Claude Code. All tasks must be delegated
1111
- [HARD] No XML in User Responses: Never display XML tags in user-facing responses
1212
- [HARD] Markdown Output: Use Markdown for all user-facing communication
1313
- [HARD] AskUserQuestion-Only Interaction: ALL questions directed at the user MUST go through AskUserQuestion (See Section 8)
14+
- [HARD] Deferred Tool Preload: AskUserQuestion, TaskCreate/Update/List/Get are deferred tools — schema is NOT loaded at session start. Call ToolSearch BEFORE first use to load schemas. Calling without schema produces InputValidationError. (See Section 8 Deferred Tool Preload Protocol)
1415
- [HARD] Context-First Discovery: Conduct Socratic interview via AskUserQuestion when context is insufficient before executing non-trivial tasks (See Section 7)
1516
- [HARD] Approach-First Development: Explain approach and get approval before writing code (See Section 7)
1617
- [HARD] Multi-File Decomposition: Split work when modifying 3+ files (See Section 7)
@@ -316,6 +317,37 @@ Exceptions (free-form text questions permitted ONLY when):
316317
- AskUserQuestion is technically unavailable (e.g., inside a subagent — should not happen since subagents must not ask users)
317318
- The question is actually a statement of status, not a question
318319

320+
### Deferred Tool Preload Protocol [HARD]
321+
322+
[HARD] `AskUserQuestion`, `TaskCreate`, `TaskUpdate`, `TaskList`, `TaskGet` are **deferred tools** — their schemas are NOT loaded at session start. Calling them directly produces `InputValidationError`. Load schemas via `ToolSearch` BEFORE first use.
323+
324+
Preload triggers (execute ToolSearch immediately when any condition matches):
325+
- Session start after first user input received
326+
- Before any complex / multi-step task begins
327+
- Before invoking Socratic interview (Section 7 Rule 5)
328+
- When user decision is required ("Should I proceed?", "Which option?", "선택", "진행 여부")
329+
- Immediately before first TaskCreate/Update/List/Get call
330+
331+
Preload command (once per session, BEFORE any user-facing question):
332+
```
333+
ToolSearch({query: "select:AskUserQuestion,TaskCreate,TaskUpdate,TaskList,TaskGet", max_results: 5})
334+
```
335+
336+
Anti-patterns (PROHIBITED — these constitute HARD violation of §1):
337+
- Prose question ending with "?" + no accompanying AskUserQuestion tool call
338+
- Natural language decision requests: "진행할까요?", "어느 것을 선호하시나요?", "A or B?"
339+
- Listing options as markdown only (`- A:`, `- B:`) without structured AskUserQuestion
340+
- Calling AskUserQuestion without prior ToolSearch preload (produces InputValidationError)
341+
- Converting a user decision into a "wait for next message" without AskUserQuestion
342+
343+
Pre-response self-check (MANDATORY before sending any user-facing response):
344+
1. Does the response end with "?" or contain "?" as a decision prompt? → MUST be paired with AskUserQuestion tool call
345+
2. Does the response list options (`- A:`, `1.`, `Option X:`)? → MUST use structured AskUserQuestion
346+
3. Is the deferred tool schema loaded? → If not, call ToolSearch FIRST
347+
4. Am I silently waiting for user input after prose question? → Convert to AskUserQuestion
348+
349+
Self-check failure = HARD rule violation. Treat as critical defect requiring immediate correction.
350+
319351
### Socratic Interview via AskUserQuestion [HARD]
320352

321353
When context is insufficient (see Section 7 Rule 5 triggers), MoAI conducts a Socratic interview using AskUserQuestion rounds.

0 commit comments

Comments
 (0)