@dmsdc-ai/aigentry-deliberation 0.0.19 → 0.0.21

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/README.md CHANGED
@@ -107,6 +107,22 @@ open demo/forum/index.html
107
107
  | `researcher` | Data, benchmarks, references |
108
108
  | `free` | No role constraint (default) |
109
109
 
110
+ ### deliberation-gate (Superpowers Integration)
111
+
112
+ Inserts multi-AI verification gates at key [superpowers](https://github.com/anthropics/superpowers) workflow decision points.
113
+
114
+ **Scenarios:**
115
+ - **brainstorming** → multi-AI design validation before writing plans
116
+ - **code-review** → multi-AI review via `deliberation_request_review`
117
+ - **debugging** → multi-AI hypothesis verification when stuck
118
+
119
+ **Trigger:** Semi-automatic — skill recommends deliberation, user approves.
120
+
121
+ **Install:**
122
+ ```bash
123
+ cp skills/deliberation-gate/SKILL.md ~/.claude/skills/deliberation-gate/SKILL.md
124
+ ```
125
+
110
126
  ## aigentry Ecosystem
111
127
 
112
128
  aigentry-deliberation is one component of the unified aigentry platform. All packages work together to make AI decisions transparent and auditable.
package/index.js CHANGED
@@ -2739,9 +2739,24 @@ server.tool(
2739
2739
 
2740
2740
  const speaker = state.current_speaker;
2741
2741
  const { transport, profile, reason } = resolveTransportForSpeaker(state, speaker);
2742
- const guidance = formatTransportGuidance(transport, state, speaker);
2743
2742
  const turnId = state.pending_turn_id || null;
2744
2743
 
2744
+ // ── Self-speaker detection ──
2745
+ // If the current speaker is the same CLI as the orchestrator (caller),
2746
+ // cli_auto_turn would recursively spawn the same process and timeout.
2747
+ // Instead, instruct the orchestrator to respond directly.
2748
+ const callerSpeaker = detectCallerSpeaker();
2749
+ const isSelfSpeaker = callerSpeaker && speaker === callerSpeaker && transport === "cli_respond";
2750
+
2751
+ let guidance;
2752
+ if (isSelfSpeaker) {
2753
+ guidance = `🟢 **본인 턴입니다.** 당신(${speaker})이 현재 speaker입니다.\n\n` +
2754
+ `직접 응답을 작성하여 \`deliberation_respond(session_id: "${state.id}", speaker: "${speaker}", content: "...")\`로 제출하세요.\n\n` +
2755
+ `⚠️ **cli_auto_turn 사용 금지**: 자기 자신을 재귀 호출하면 타임아웃이 발생합니다. 반드시 직접 deliberation_respond를 사용하세요.`;
2756
+ } else {
2757
+ guidance = formatTransportGuidance(transport, state, speaker);
2758
+ }
2759
+
2745
2760
  let extra = "";
2746
2761
 
2747
2762
  if (transport === "browser_auto") {
@@ -2963,6 +2978,17 @@ server.tool(
2963
2978
  return { content: [{ type: "text", text: `speaker "${speaker}"는 CLI 타입이 아닙니다 (transport: ${transport}). 브라우저 speaker는 deliberation_browser_auto_turn을 사용하세요.` }] };
2964
2979
  }
2965
2980
 
2981
+ // Block recursive self-spawn: if the speaker is the same CLI as the caller,
2982
+ // spawning it would create infinite recursion and timeout.
2983
+ const callerSpeaker = detectCallerSpeaker();
2984
+ if (callerSpeaker && speaker === callerSpeaker) {
2985
+ return { content: [{ type: "text", text:
2986
+ `⚠️ **재귀 호출 차단**: speaker "${speaker}"는 현재 오케스트레이터와 동일한 CLI입니다.\n\n` +
2987
+ `cli_auto_turn으로 자기 자신을 spawn하면 타임아웃이 발생합니다.\n` +
2988
+ `직접 응답을 작성하여 \`deliberation_respond(session_id: "${resolved}", speaker: "${speaker}", content: "...")\`로 제출하세요.`
2989
+ }] };
2990
+ }
2991
+
2966
2992
  const hint = CLI_INVOCATION_HINTS[speaker];
2967
2993
  if (!hint) {
2968
2994
  return { content: [{ type: "text", text: `speaker "${speaker}"에 대한 CLI 호출 정보가 없습니다. CLI_INVOCATION_HINTS에 등록되지 않은 speaker입니다.` }] };
package/install.js CHANGED
@@ -13,6 +13,7 @@
13
13
  * 3. Registers MCP server in ~/.claude/.mcp.json (Claude Code)
14
14
  * 4. Registers MCP server in ~/.gemini/settings.json (Gemini CLI)
15
15
  * 5. Ready to use — next Claude Code or Gemini CLI session will auto-load
16
+ * 6. 스킬 파일 설치 (~/.claude/skills/deliberation-gate/SKILL.md)
16
17
  */
17
18
 
18
19
  import { execSync } from "node:child_process";
@@ -28,6 +29,10 @@ const INSTALL_DIR = IS_WIN
28
29
  : path.join(HOME, ".local", "lib", "mcp-deliberation");
29
30
  const MCP_CONFIG = path.join(HOME, ".claude", ".mcp.json");
30
31
  const GEMINI_CONFIG = path.join(HOME, ".gemini", "settings.json");
32
+ const SKILL_SRC = path.join(__dirname, "skills", "deliberation-gate", "SKILL.md");
33
+ const SKILL_DEST_DIR = path.join(HOME, ".claude", "skills", "deliberation-gate");
34
+ const SKILL_DEST = path.join(SKILL_DEST_DIR, "SKILL.md");
35
+ const MANIFEST_PATH = path.join(INSTALL_DIR, ".install-manifest.json");
31
36
 
32
37
  /** Normalize path to forward slashes for JSON config (Windows backslash → forward slash) */
33
38
  function toForwardSlash(p) {
@@ -175,12 +180,53 @@ function install() {
175
180
  } catch { /* ignore on Windows */ }
176
181
  }
177
182
 
178
- // Step 6: Preserve existing config
183
+ // Step 6b: Preserve existing config
179
184
  const configPath = path.join(INSTALL_DIR, "config.json");
180
185
  if (!fs.existsSync(configPath)) {
181
186
  fs.writeFileSync(configPath, JSON.stringify({}, null, 2));
182
187
  }
183
188
 
189
+ // Step 7: Deploy deliberation-gate skill
190
+ log("🎓 deliberation-gate 스킬 파일 설치...");
191
+ if (!fs.existsSync(SKILL_SRC)) {
192
+ log(" ⚠️ 스킬 소스 파일 없음, 스킵: " + SKILL_SRC);
193
+ } else {
194
+ try {
195
+ fs.mkdirSync(SKILL_DEST_DIR, { recursive: true });
196
+ let shouldCopy = true;
197
+ if (fs.existsSync(SKILL_DEST) && !FORCE) {
198
+ const existing = fs.readFileSync(SKILL_DEST, "utf-8");
199
+ const incoming = fs.readFileSync(SKILL_SRC, "utf-8");
200
+ if (existing === incoming) {
201
+ log(" → 이미 최신 상태, 스킵");
202
+ shouldCopy = false;
203
+ } else {
204
+ fs.copyFileSync(SKILL_DEST, SKILL_DEST + ".backup");
205
+ log(" → 기존 파일 백업: SKILL.md.backup");
206
+ }
207
+ }
208
+ if (shouldCopy) {
209
+ fs.copyFileSync(SKILL_SRC, SKILL_DEST);
210
+ log(" → " + SKILL_DEST);
211
+ }
212
+ } catch (err) {
213
+ log(` ⚠️ 스킬 설치 실패: ${err.message}`);
214
+ }
215
+ }
216
+
217
+ // Write install manifest
218
+ try {
219
+ const pkg = JSON.parse(fs.readFileSync(path.join(__dirname, "package.json"), "utf-8"));
220
+ const manifest = {
221
+ version: pkg.version,
222
+ installedAt: new Date().toISOString(),
223
+ skills: [SKILL_DEST],
224
+ };
225
+ fs.writeFileSync(MANIFEST_PATH, JSON.stringify(manifest, null, 2));
226
+ } catch (err) {
227
+ log(` ⚠️ manifest 작성 실패: ${err.message}`);
228
+ }
229
+
184
230
  // Done
185
231
  console.log("\n✅ 설치 완료!\n");
186
232
  console.log(" 다음 단계:");
@@ -191,6 +237,7 @@ function install() {
191
237
 
192
238
  // Entry point
193
239
  const args = process.argv.slice(2);
240
+ const FORCE = args.includes("--force");
194
241
  if (args.includes("--help") || args.includes("-h")) {
195
242
  console.log(`
196
243
  Deliberation MCP Server Installer
@@ -202,10 +249,18 @@ Usage:
202
249
  Options:
203
250
  --help, -h 이 도움말 표시
204
251
  --uninstall 서버 제거
252
+ --force 기존 스킬 파일 비교 없이 강제 덮어쓰기
253
+
254
+ 기능:
255
+ - 서버 파일을 설치 경로에 복사
256
+ - npm 의존성 설치
257
+ - Claude Code / Gemini CLI MCP 서버 등록
258
+ - 스킬 파일 설치 (~/.claude/skills/deliberation-gate/SKILL.md)
205
259
 
206
260
  설치 경로: ${INSTALL_DIR}
207
261
  MCP 설정: ${MCP_CONFIG}
208
262
  Gemini: ${GEMINI_CONFIG}
263
+ 스킬 경로: ${SKILL_DEST}
209
264
  `);
210
265
  } else if (args.includes("--uninstall") || args.includes("uninstall")) {
211
266
  console.log("\n🗑️ Deliberation MCP Server 제거\n");
@@ -234,6 +289,39 @@ Gemini: ${GEMINI_CONFIG}
234
289
  } catch { /* ignore */ }
235
290
  }
236
291
 
292
+ // Remove skill files tracked by manifest (or fall back to default path)
293
+ let skillsToRemove = [SKILL_DEST];
294
+ const manifestFile = path.join(INSTALL_DIR, ".install-manifest.json");
295
+ if (fs.existsSync(manifestFile)) {
296
+ try {
297
+ const manifest = JSON.parse(fs.readFileSync(manifestFile, "utf-8"));
298
+ if (Array.isArray(manifest.skills) && manifest.skills.length > 0) {
299
+ skillsToRemove = manifest.skills;
300
+ }
301
+ } catch { /* use default */ }
302
+ }
303
+ for (const skillPath of skillsToRemove) {
304
+ if (fs.existsSync(skillPath)) {
305
+ try {
306
+ fs.rmSync(skillPath, { force: true });
307
+ log(`스킬 파일 삭제: ${skillPath}`);
308
+ const backupPath = skillPath + ".backup";
309
+ if (fs.existsSync(backupPath)) {
310
+ log(` 💡 백업 파일이 남아 있습니다: ${backupPath}`);
311
+ log(` 복원하려면: cp "${backupPath}" "${skillPath}"`);
312
+ }
313
+ // Remove directory if empty
314
+ const dir = path.dirname(skillPath);
315
+ if (fs.existsSync(dir) && fs.readdirSync(dir).length === 0) {
316
+ fs.rmdirSync(dir);
317
+ log(`빈 스킬 디렉토리 삭제: ${dir}`);
318
+ }
319
+ } catch (err) {
320
+ log(` ⚠️ 스킬 파일 삭제 실패: ${err.message}`);
321
+ }
322
+ }
323
+ }
324
+
237
325
  // Remove install directory
238
326
  if (fs.existsSync(INSTALL_DIR)) {
239
327
  fs.rmSync(INSTALL_DIR, { recursive: true, force: true });
@@ -0,0 +1,224 @@
1
+ // model-router.js
2
+ // Dynamic model selection based on deliberation prompt context
3
+
4
+ const CATEGORY_KEYWORDS = {
5
+ reasoning: [
6
+ 'analyze', 'analysis', 'debug', 'debugging', 'complex', 'logic', 'reasoning',
7
+ 'problem', 'solve', 'evaluate', 'assess', 'critique', 'argument', 'inference',
8
+ 'contradiction', 'flaw', 'why', 'explain', 'cause', 'effect', 'implication',
9
+ 'consequence', 'tradeoff', 'compare', 'pros', 'cons', 'decision', 'strategy',
10
+ 'architecture', 'design pattern', 'refactor', 'optimize', 'performance',
11
+ ],
12
+ coding: [
13
+ 'code', 'implement', 'function', 'class', 'module', 'api', 'library',
14
+ 'algorithm', 'data structure', 'typescript', 'javascript', 'python', 'rust',
15
+ 'build', 'deploy', 'test', 'unit test', 'integration', 'bug', 'fix', 'error',
16
+ 'syntax', 'runtime', 'compile', 'script', 'program', 'software', 'feature',
17
+ 'endpoint', 'schema', 'database', 'query', 'sql', 'migration', 'lint',
18
+ ],
19
+ creative: [
20
+ 'write', 'writing', 'design', 'brainstorm', 'idea', 'creative', 'story',
21
+ 'narrative', 'style', 'tone', 'voice', 'draft', 'outline', 'concept',
22
+ 'vision', 'imagine', 'suggest', 'propose', 'generate', 'name', 'brand',
23
+ 'ui', 'ux', 'interface', 'experience', 'aesthetic', 'layout', 'visual',
24
+ ],
25
+ research: [
26
+ 'research', 'find', 'search', 'fact', 'data', 'statistic', 'source',
27
+ 'reference', 'study', 'survey', 'report', 'paper', 'documentation', 'docs',
28
+ 'compare', 'benchmark', 'review', 'overview', 'summary', 'what is', 'who is',
29
+ 'history', 'background', 'context', 'information', 'knowledge',
30
+ ],
31
+ simple: [
32
+ 'yes', 'no', 'confirm', 'ok', 'okay', 'agree', 'disagree', 'correct',
33
+ 'hello', 'hi', 'thanks', 'thank you', 'sure', 'got it', 'understood',
34
+ 'clarify', 'quick', 'brief', 'simple', 'basic',
35
+ ],
36
+ };
37
+
38
+ const COMPLEXITY_KEYWORDS = {
39
+ high: [
40
+ 'complex', 'complicated', 'difficult', 'challenging', 'sophisticated',
41
+ 'advanced', 'deep', 'thorough', 'comprehensive', 'exhaustive', 'detailed',
42
+ 'multi-step', 'multi-faceted', 'nuanced', 'ambiguous', 'architecture',
43
+ 'system', 'scalable', 'distributed', 'concurrent', 'critical', 'production',
44
+ ],
45
+ low: [
46
+ 'simple', 'basic', 'quick', 'brief', 'short', 'easy', 'trivial',
47
+ 'straightforward', 'obvious', 'clear', 'confirm', 'yes', 'no', 'agree',
48
+ 'ok', 'sure', 'hello', 'hi',
49
+ ],
50
+ };
51
+
52
+ const ROLE_KEYWORDS = {
53
+ critic: 'reasoning',
54
+ implementer: 'coding',
55
+ mediator: 'creative',
56
+ researcher: 'research',
57
+ };
58
+
59
+ /**
60
+ * Count keyword matches in text for a given keyword list.
61
+ */
62
+ function countMatches(text, keywords) {
63
+ const lower = text.toLowerCase();
64
+ return keywords.reduce((count, kw) => {
65
+ return count + (lower.includes(kw.toLowerCase()) ? 1 : 0);
66
+ }, 0);
67
+ }
68
+
69
+ /**
70
+ * Analyze deliberation context to determine category and complexity.
71
+ * @param {string} topic - The deliberation topic
72
+ * @param {string} recentLog - Recent log text from deliberation
73
+ * @param {string} role - The speaker's role
74
+ * @returns {{ category: string, complexity: string }}
75
+ */
76
+ export function analyzePromptContext(topic, recentLog, role) {
77
+ const text = `${topic} ${recentLog}`;
78
+
79
+ // Role-based category hint
80
+ let roleCategory = null;
81
+ if (role) {
82
+ const lowerRole = role.toLowerCase();
83
+ for (const [keyword, category] of Object.entries(ROLE_KEYWORDS)) {
84
+ if (lowerRole.includes(keyword)) {
85
+ roleCategory = category;
86
+ break;
87
+ }
88
+ }
89
+ }
90
+
91
+ // Keyword-based category scoring
92
+ const scores = {};
93
+ for (const [category, keywords] of Object.entries(CATEGORY_KEYWORDS)) {
94
+ scores[category] = countMatches(text, keywords);
95
+ }
96
+
97
+ // Find top category by keyword score
98
+ let topCategory = 'simple';
99
+ let topScore = 0;
100
+ for (const [category, score] of Object.entries(scores)) {
101
+ if (score > topScore) {
102
+ topScore = score;
103
+ topCategory = category;
104
+ }
105
+ }
106
+
107
+ // Role hint takes precedence if no strong keyword signal
108
+ const category = topScore >= 2 ? topCategory : (roleCategory || topCategory);
109
+
110
+ // Complexity detection
111
+ const highCount = countMatches(text, COMPLEXITY_KEYWORDS.high);
112
+ const lowCount = countMatches(text, COMPLEXITY_KEYWORDS.low);
113
+
114
+ let complexity;
115
+ if (highCount > lowCount && highCount >= 1) {
116
+ complexity = 'high';
117
+ } else if (lowCount > 0 && highCount === 0) {
118
+ complexity = 'low';
119
+ } else {
120
+ complexity = 'medium';
121
+ }
122
+
123
+ return { category, complexity };
124
+ }
125
+
126
+ /**
127
+ * Select the optimal model for a given provider based on category and complexity.
128
+ * @param {string} provider - The AI provider identifier
129
+ * @param {string} category - Prompt category
130
+ * @param {string} complexity - Prompt complexity
131
+ * @returns {{ model: string, reason: string }}
132
+ */
133
+ export function selectModelForProvider(provider, category, complexity) {
134
+ const isHighReasoning = category === 'reasoning' || complexity === 'high';
135
+ const isSimple = complexity === 'low' || category === 'simple';
136
+ const isCoding = category === 'coding';
137
+
138
+ switch (provider) {
139
+ case 'chatgpt': {
140
+ if (isHighReasoning) return { model: 'o3', reason: 'High-complexity reasoning task' };
141
+ if (isCoding) return { model: 'o4-mini', reason: 'Coding/implementation task' };
142
+ if (isSimple) return { model: 'gpt-4o-mini', reason: 'Simple task, cost-efficient model' };
143
+ return { model: 'gpt-4o', reason: 'Creative or medium-complexity task' };
144
+ }
145
+
146
+ case 'claude': {
147
+ if (isHighReasoning) return { model: 'opus', reason: 'High-complexity reasoning task' };
148
+ if (isSimple) return { model: 'haiku', reason: 'Simple task, fast and cost-efficient' };
149
+ return { model: 'sonnet', reason: 'Coding or medium-complexity task' };
150
+ }
151
+
152
+ case 'gemini': {
153
+ if (isHighReasoning || complexity === 'high') return { model: '2.5 Pro', reason: 'High-complexity or reasoning task' };
154
+ if (isSimple) return { model: '2.0 Flash', reason: 'Simple task, fast response' };
155
+ return { model: '2.5 Flash', reason: 'Medium-complexity task' };
156
+ }
157
+
158
+ case 'deepseek': {
159
+ if (category === 'reasoning') return { model: 'DeepSeek-R1', reason: 'Reasoning-focused task' };
160
+ return { model: 'DeepSeek-V3', reason: 'General task' };
161
+ }
162
+
163
+ case 'grok': {
164
+ if (complexity === 'high' || isHighReasoning) return { model: 'grok-3', reason: 'High-complexity task' };
165
+ return { model: 'grok-3-mini', reason: 'Simple task' };
166
+ }
167
+
168
+ case 'mistral': {
169
+ if (complexity === 'high' || isHighReasoning) return { model: 'Mistral Large', reason: 'High-complexity task' };
170
+ return { model: 'Mistral Small', reason: 'Simple task' };
171
+ }
172
+
173
+ case 'poe': {
174
+ if (complexity === 'high' || isHighReasoning) return { model: 'Claude-3.5-Sonnet', reason: 'High-complexity task' };
175
+ if (isSimple) return { model: 'Claude-3-Haiku', reason: 'Simple task' };
176
+ return { model: 'GPT-4o', reason: 'Medium-complexity task' };
177
+ }
178
+
179
+ case 'qwen': {
180
+ if (complexity === 'high' || isHighReasoning) return { model: 'Qwen-Max', reason: 'High-complexity task' };
181
+ return { model: 'Qwen-Plus', reason: 'Simple task' };
182
+ }
183
+
184
+ case 'huggingchat': {
185
+ if (complexity === 'high' || isHighReasoning) return { model: 'Qwen/QwQ-32B', reason: 'High-complexity task' };
186
+ return { model: 'meta-llama/Llama-3.3-70B', reason: 'Simple task' };
187
+ }
188
+
189
+ case 'copilot': {
190
+ return { model: 'GPT-4o', reason: 'Copilot uses GPT-4o (no model selection)' };
191
+ }
192
+
193
+ case 'perplexity': {
194
+ return { model: 'default', reason: 'Perplexity uses default model (no model selection)' };
195
+ }
196
+
197
+ default: {
198
+ return { model: 'default', reason: `Unknown provider: ${provider}` };
199
+ }
200
+ }
201
+ }
202
+
203
+ /**
204
+ * High-level function: analyze state and return optimal model selection for a turn.
205
+ * @param {object} state - Deliberation state with topic, log, speaker_roles
206
+ * @param {string} speaker - The current speaker identifier
207
+ * @param {string} provider - The AI provider to use
208
+ * @returns {{ model: string, category: string, complexity: string, reason: string }}
209
+ */
210
+ export function getModelSelectionForTurn(state, speaker, provider) {
211
+ const topic = state.topic || '';
212
+ const role = (state.speaker_roles && state.speaker_roles[speaker]) || '';
213
+
214
+ // Use recent log entries (last 5) for context analysis
215
+ const recentEntries = Array.isArray(state.log) ? state.log.slice(-5) : [];
216
+ const recentLog = recentEntries
217
+ .map(entry => (typeof entry === 'string' ? entry : JSON.stringify(entry)))
218
+ .join(' ');
219
+
220
+ const { category, complexity } = analyzePromptContext(topic, recentLog, role);
221
+ const { model, reason } = selectModelForProvider(provider, category, complexity);
222
+
223
+ return { model, category, complexity, reason };
224
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@dmsdc-ai/aigentry-deliberation",
3
- "version": "0.0.19",
3
+ "version": "0.0.21",
4
4
  "description": "MCP Deliberation Server — Multi-session AI deliberation with smart speaker ordering and persona roles",
5
5
  "type": "module",
6
6
  "license": "MIT",
@@ -29,6 +29,7 @@
29
29
  },
30
30
  "files": [
31
31
  "index.js",
32
+ "model-router.js",
32
33
  "install.js",
33
34
  "doctor.js",
34
35
  "observer.js",
@@ -176,3 +176,8 @@ bash deliberation-monitor.sh --tmux
176
176
  4. 실시간 sync 파일은 state 디렉토리에 저장되며 완료 시 자동 삭제됨 (프로젝트 루트 오염 없음)
177
177
  5. `Transport closed` 발생 시 현재 CLI 세션 재시작 후 재시도 (stdio 연결은 세션 바인딩)
178
178
  6. 멀티 세션 운영 중 `pkill -f mcp-deliberation` 사용 금지 (다른 세션 연결까지 끊길 수 있음)
179
+
180
+ ## 관련 스킬
181
+
182
+ - **deliberation-gate**: superpowers 워크플로우 통합 스킬. brainstorming/code-review/debugging 의사결정 지점에 멀티-AI 검증 게이트를 삽입합니다. `~/.claude/skills/deliberation-gate/SKILL.md`에 설치.
183
+ - **deliberation-executor**: deliberation 합의안을 실제 코드 구현으로 전환하는 실행 전용 스킬.
@@ -0,0 +1,212 @@
1
+ ---
2
+ name: deliberation-gate
3
+ description: |
4
+ Use after brainstorming produces design doc, after code-review produces feedback,
5
+ when debugging hits dead end with failed hypotheses, or when user says
6
+ "deliberate this", "토론해줘", "검증해줘", "멀티-AI 리뷰", "multi-AI verify"
7
+ version: 0.1.0
8
+ prerequisites:
9
+ mcp: ["aigentry-deliberation"]
10
+ fallback: self-criticism
11
+ ---
12
+
13
+ # Deliberation Gate — Multi-AI Verification for Superpowers Workflows
14
+
15
+ Insert multi-AI deliberation gates at key decision points in superpowers workflow chains.
16
+ Uses aigentry-deliberation MCP tools to orchestrate structured debate between multiple AI systems.
17
+
18
+ **Semi-automatic**: Recommends deliberation at decision points. User approves before starting.
19
+
20
+ ## Context Detection
21
+
22
+ Detect the current workflow context by checking these signals IN ORDER:
23
+
24
+ | Priority | Signal | Context |
25
+ |----------|--------|---------|
26
+ | 1 | User says "deliberate", "토론", "debate", "검증", "멀티-AI" | explicit |
27
+ | 2 | Design doc recently written in session (docs/plans/*-design.md) | brainstorming |
28
+ | 3 | git diff output, PR number, or code review feedback in conversation | code-review |
29
+ | 4 | Error traces + failed hypotheses / "root cause" in conversation | debugging |
30
+ | 5 | None of above | general |
31
+
32
+ ### Scenario Preset Map
33
+
34
+ | Context | preset | rounds | roles | MCP path |
35
+ |---------|--------|--------|-------|----------|
36
+ | brainstorming | brainstorm | 2 | critic, implementer, researcher | deliberation_start → route_turn loop → synthesize |
37
+ | code-review | review | 1 | critic, implementer | deliberation_request_review (lightweight) |
38
+ | debugging | research | 2 | researcher, implementer, critic | deliberation_start → route_turn loop → synthesize |
39
+ | general | balanced | 3 | user-selected via AskUserQuestion | deliberation_start → route_turn loop → synthesize |
40
+
41
+ ## Recommendation Protocol (Semi-Automatic)
42
+
43
+ When you detect a decision point, recommend deliberation to the user.
44
+
45
+ ### Step 1: Detect and Announce
46
+
47
+ Announce the detected context:
48
+
49
+ > 🔔 **멀티-AI 검증 추천** — [context] 시나리오 감지
50
+ >
51
+ > 이 [설계안/코드 리뷰/디버깅 가설]을 다른 AI의 관점으로 검증하면 더 견고해질 수 있습니다.
52
+
53
+ ### Step 2: Ask User
54
+
55
+ Use AskUserQuestion to get approval:
56
+
57
+ ```
58
+ AskUserQuestion:
59
+ question: "이 [artifact]을 멀티-AI 토론으로 검증할까요?"
60
+ header: "멀티-AI 검증"
61
+ options:
62
+ - label: "시작 (Recommended)"
63
+ description: "[preset] preset, [N]라운드, [roles] 역할로 deliberation 시작"
64
+ - label: "설정 변경 후 시작"
65
+ description: "preset, rounds, roles를 직접 선택"
66
+ - label: "건너뛰기"
67
+ description: "deliberation 없이 원래 워크플로우 계속"
68
+ ```
69
+
70
+ ### Step 3: On Decline
71
+
72
+ If user chooses "건너뛰기":
73
+ - Do NOT persist or re-ask
74
+ - Continue the original workflow immediately
75
+ - No penalty, no warning
76
+
77
+ ## Deliberation Execution
78
+
79
+ When user approves, execute this sequence:
80
+
81
+ ### Standard Path (brainstorming, debugging, general)
82
+
83
+ 1. **Speaker discovery**: `deliberation_speaker_candidates` → get available CLI + browser speakers
84
+ 2. **Speaker selection**: `AskUserQuestion(multiSelect: true)` → user selects which speakers to include
85
+ 3. **Start deliberation**: `deliberation_start`
86
+ - `topic`: the artifact being validated (design summary / error description + hypotheses / user's question)
87
+ - `speakers`: user-selected list
88
+ - `speaker_roles`: from scenario preset map above
89
+ - `rounds`: from scenario preset map above
90
+ - `ordering_strategy`: "auto"
91
+ - `role_preset`: from scenario preset map above
92
+ 4. **Turn loop**: For each turn:
93
+ - Call `deliberation_route_turn` — it auto-detects the correct transport
94
+ - **Self-speaker** (you are the current speaker): Compose your response based on your role, submit via `deliberation_respond(speaker: "claude", content: "...")`
95
+ - **Other CLI speaker**: `deliberation_route_turn` will guide to `deliberation_cli_auto_turn` which spawns the actual CLI
96
+ - **Browser speaker**: `deliberation_route_turn` will auto-execute via CDP
97
+ 5. **Synthesize**: After all rounds complete, call `deliberation_synthesize` with a summary of the consensus
98
+ 6. **Apply synthesis**: Follow the Integration Rules below
99
+
100
+ ### Lightweight Path (code-review only)
101
+
102
+ 1. **Speaker discovery**: `deliberation_speaker_candidates` → get available speakers
103
+ 2. **Reviewer selection**: `AskUserQuestion(multiSelect: true)` → user selects reviewers
104
+ 3. **Request review**: `deliberation_request_review`
105
+ - `context`: the diff or code under review
106
+ - `question`: "이 코드 변경사항을 리뷰해주세요. 버그, 설계 문제, 보안 취약점을 중심으로."
107
+ - `reviewers`: user-selected list
108
+ - `mode`: "sync"
109
+ - `deadline_ms`: 120000
110
+ 4. **Apply results**: Follow the Integration Rules below
111
+
112
+ ## Synthesis Integration Rules
113
+
114
+ ### brainstorming → design doc update
115
+
116
+ After deliberation on a design:
117
+ 1. Read the synthesis from `deliberation_synthesize`
118
+ 2. Append a `## 멀티-AI 합의` section to the design doc with:
119
+ - **합의 사항**: Key agreements from all participants
120
+ - **이견**: Dissenting points (if any)
121
+ - **권장 변경**: Concrete changes recommended by consensus
122
+ 3. Apply the agreed changes to the design document
123
+ 4. Continue to `writing-plans` skill with the updated design
124
+
125
+ ### code-review → receiving-code-review
126
+
127
+ After multi-AI code review:
128
+ 1. Parse review results into severity categories:
129
+ - **Critical**: Must fix before merge
130
+ - **Major**: Should fix
131
+ - **Minor**: Optional improvements
132
+ 2. Present the categorized feedback to user
133
+ 3. Continue to `receiving-code-review` skill workflow
134
+
135
+ ### debugging → hypothesis reordering
136
+
137
+ After deliberation on debugging hypotheses:
138
+ 1. Extract the consensus hypothesis ranking from synthesis
139
+ 2. Update the debugging state:
140
+ - Move consensus-top hypothesis to position 1
141
+ - Mark disproven hypotheses as eliminated
142
+ - Add any new hypotheses suggested by other AIs
143
+ 3. Resume `systematic-debugging` with the new priorities
144
+
145
+ ### general → user-directed
146
+
147
+ For explicit or general deliberation:
148
+ 1. Present the synthesis summary to user
149
+ 2. Ask how to proceed with the consensus
150
+ 3. Follow user's direction
151
+
152
+ ## MCP 미설치 시 Fallback (Graceful Degradation)
153
+
154
+ deliberation MCP 도구(`deliberation_start`, `deliberation_speaker_candidates` 등)가 사용 불가능할 경우:
155
+
156
+ ### 감지 방법
157
+ - MCP 도구 호출 시 "tool not found" 또는 연결 실패 에러 발생
158
+ - `deliberation_speaker_candidates` 호출이 실패하면 MCP 미설치로 판단
159
+
160
+ ### Fallback 프로토콜
161
+
162
+ 1. **안내**: AskUserQuestion으로 상황 설명
163
+ ```
164
+ question: "멀티-AI 검증 MCP 서버가 감지되지 않았습니다. 단일 모델 자가 검증으로 대체할까요?"
165
+ options:
166
+ - label: "자가 검증 진행"
167
+ description: "3관점 self-criticism으로 검증 (Silver 등급)"
168
+ - label: "MCP 설치 안내"
169
+ description: "npx @dmsdc-ai/aigentry-deliberation install 실행 방법 안내"
170
+ - label: "건너뛰기"
171
+ description: "검증 없이 원래 워크플로우 계속"
172
+ ```
173
+
174
+ 2. **Self-Criticism 실행** (자가 검증 선택 시):
175
+ - 동일 artifact에 대해 3가지 관점으로 순차 분석:
176
+ - **비판적 분석가**: 약점, 리스크, 누락된 고려사항
177
+ - **현실적 실행가**: 구현 가능성, 비용, 복잡도
178
+ - **리서처**: 대안, 선례, 데이터 기반 근거
179
+ - 3관점 결과를 종합하여 합의 포맷으로 출력
180
+
181
+ 3. **투명성 라벨링**:
182
+ - 모든 검증 결과에 출처 라벨 필수 표시:
183
+ - `🥇 Verification: Multi-AI Deliberation (Gold)` — 실제 멀티-AI 토론 결과
184
+ - `🥈 Verification: Self-Criticism (Silver)` — 단일 모델 자가 검증 결과
185
+ - 라벨은 합의 섹션 상단에 표시
186
+
187
+ ### MCP 설치 안내 (선택 시)
188
+ ```
189
+ npx @dmsdc-ai/aigentry-deliberation install
190
+ ```
191
+ 설치 후 Claude Code 세션을 재시작하면 멀티-AI 검증이 활성화됩니다.
192
+
193
+ ## Anti-Patterns (NEVER)
194
+
195
+ 1. **NEVER skip user approval** — Always use AskUserQuestion before starting deliberation. This is a HARD GATE.
196
+ 2. **NEVER fabricate speaker responses** — Use `deliberation_route_turn` for other speakers. Never write responses on behalf of codex, gemini, or any other speaker. The MCP server blocks this.
197
+ 3. **NEVER use cli_auto_turn for self-speaker** — If you (claude) are the current speaker, compose your response and submit via `deliberation_respond` directly. Using `cli_auto_turn` would recursively spawn yourself and timeout.
198
+ 4. **NEVER re-ask after decline** — If user chooses "건너뛰기", respect it immediately. Do not ask again.
199
+ 5. **NEVER block on deliberation failure** — If MCP tools fail (server not running, speaker unavailable), warn the user and continue the original workflow. Deliberation is enhancement, not requirement.
200
+ 6. **NEVER modify existing superpowers skills** — This skill is purely additive. It works alongside existing skills without changing them.
201
+ 7. **NEVER omit verification source label** — 모든 검증 결과에 Gold/Silver 라벨을 반드시 표시. Self-criticism 결과를 Multi-AI 결과와 구분 없이 제시하면 신뢰도를 왜곡한다.
202
+
203
+ ## Workflow Position
204
+
205
+ ```
206
+ brainstorming ──────→ [deliberation-gate] → writing-plans → executing-plans
207
+ code-review ────────→ [deliberation-gate] → receiving-code-review
208
+ systematic-debugging → [deliberation-gate] → resume with consensus
209
+ explicit request ───→ [deliberation-gate] → context-dependent
210
+ ```
211
+
212
+ This skill is invoked BETWEEN existing superpowers skills, not within them. It consumes the output of one skill and feeds enhanced output to the next.