@dmsdc-ai/aigentry-deliberation 0.0.21 → 0.0.22

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
@@ -31,6 +31,8 @@ npx @dmsdc-ai/aigentry-deliberation install
31
31
  2. npm 의존성 설치
32
32
  3. `~/.claude/.mcp.json`에 MCP 서버 자동 등록
33
33
  4. Claude Code 재시작하면 바로 사용 가능
34
+ 5. Gemini CLI MCP 서버 자동 등록 (`~/.gemini/settings.json`)
35
+ 6. deliberation-gate 스킬 자동 설치 (`~/.claude/skills/deliberation-gate/`)
34
36
 
35
37
  ### 기타 설치 방법
36
38
 
@@ -53,6 +55,8 @@ cd aigentry-deliberation && npm install && node install.js
53
55
  npx @dmsdc-ai/aigentry-deliberation uninstall
54
56
  ```
55
57
 
58
+ MCP 서버 등록 해제 + 설치 파일 삭제 + 스킬 파일 정리까지 자동 처리됩니다.
59
+
56
60
  ## Forum Demo
57
61
 
58
62
  Deliberation이 완료되면 결과를 시각화하는 Forum View를 생성합니다.
@@ -68,6 +72,16 @@ Deliberation이 완료되면 결과를 시각화하는 Forum View를 생성합
68
72
  open demo/forum/index.html
69
73
  ```
70
74
 
75
+ ## Diagnostics
76
+
77
+ MCP 연결 문제 자동 진단:
78
+
79
+ ```bash
80
+ npx @dmsdc-ai/aigentry-deliberation doctor
81
+ ```
82
+
83
+ Claude Code, Codex CLI, Gemini CLI의 MCP 설정을 자동 점검하고 문제를 진단합니다.
84
+
71
85
  ## MCP Tools
72
86
 
73
87
  | Tool | Description |
@@ -109,7 +123,7 @@ open demo/forum/index.html
109
123
 
110
124
  ### deliberation-gate (Superpowers Integration)
111
125
 
112
- Inserts multi-AI verification gates at key [superpowers](https://github.com/anthropics/superpowers) workflow decision points.
126
+ Inserts multi-AI verification gates at key [superpowers](https://github.com/obra/superpowers) workflow decision points.
113
127
 
114
128
  **Scenarios:**
115
129
  - **brainstorming** → multi-AI design validation before writing plans
@@ -118,11 +132,17 @@ Inserts multi-AI verification gates at key [superpowers](https://github.com/anth
118
132
 
119
133
  **Trigger:** Semi-automatic — skill recommends deliberation, user approves.
120
134
 
121
- **Install:**
135
+ **Fallback:** MCP 미설치 시 self-criticism 기반 자가 검증으로 대체 (Silver 등급). MCP 설치 시 멀티-AI 토론 (Gold 등급).
136
+
137
+ **Install:** `npx @dmsdc-ai/aigentry-deliberation install` 실행 시 자동 설치됩니다.
138
+
139
+ 수동 설치:
122
140
  ```bash
123
141
  cp skills/deliberation-gate/SKILL.md ~/.claude/skills/deliberation-gate/SKILL.md
124
142
  ```
125
143
 
144
+ **RFC:** [Prerequisites header for tool-dependent skills](https://github.com/obra/superpowers/issues/589)
145
+
126
146
  ## aigentry Ecosystem
127
147
 
128
148
  aigentry-deliberation is one component of the unified aigentry platform. All packages work together to make AI decisions transparent and auditable.
@@ -509,15 +509,6 @@ class DevToolsMcpAdapter extends BrowserControlPort {
509
509
  }
510
510
  }
511
511
 
512
- const sendResult = { ok: true };
513
-
514
- if (!sendResult.ok) {
515
- return makeResult(false, null, {
516
- code: "SEND_FAILED",
517
- message: `Send button not found: ${binding.selectors.sendButton}`,
518
- });
519
- }
520
-
521
512
  sent.add(turnId);
522
513
  return makeResult(true, { turnId, sent: true });
523
514
  } catch (err) {
package/index.js CHANGED
@@ -948,7 +948,7 @@ async function ensureCdpAvailable() {
948
948
 
949
949
  const launchArgs = [
950
950
  "--remote-debugging-port=9222",
951
- "--remote-allow-origins=*",
951
+ "--remote-allow-origins=http://127.0.0.1:9222",
952
952
  `--user-data-dir=${cdpDataDir}`,
953
953
  `--profile-directory=${profileDir}`,
954
954
  "--no-first-run",
@@ -965,7 +965,7 @@ async function ensureCdpAvailable() {
965
965
  }
966
966
 
967
967
  // Wait for Chrome to initialize CDP
968
- sleepMs(5000);
968
+ await new Promise(resolve => setTimeout(resolve, 5000));
969
969
 
970
970
  // Retry CDP connection after launch
971
971
  for (const endpoint of endpoints) {
@@ -3124,7 +3124,8 @@ server.tool(
3124
3124
  const { transport } = resolveTransportForSpeaker(state, speaker);
3125
3125
  if (transport === "cli_respond" || transport === "browser_auto") {
3126
3126
  // Check if caller is the same speaker (legitimate self-response) or an impersonator
3127
- const callerIsSpeaker = (speaker === "claude"); // orchestrator can only legitimately respond as "claude"
3127
+ const callerSpeaker = detectCallerSpeaker();
3128
+ const callerIsSpeaker = callerSpeaker && (speaker === callerSpeaker);
3128
3129
  if (!callerIsSpeaker) {
3129
3130
  return {
3130
3131
  content: [{
@@ -3448,15 +3449,36 @@ server.tool(
3448
3449
  // ── Request Review (auto-review) ───────────────────────────────
3449
3450
 
3450
3451
  function invokeCliReviewer(command, prompt, timeoutMs) {
3451
- const args = ["-p", prompt, "--no-input"];
3452
+ const hint = CLI_INVOCATION_HINTS[command];
3453
+ let args;
3454
+ let opts = { encoding: "utf-8", timeout: timeoutMs, stdio: ["pipe", "pipe", "pipe"], maxBuffer: 5 * 1024 * 1024, windowsHide: true };
3455
+ const env = { ...process.env };
3456
+
3457
+ switch (command) {
3458
+ case "claude":
3459
+ if (hint?.envPrefix?.includes("CLAUDECODE=")) delete env.CLAUDECODE;
3460
+ args = ["-p", "--output-format", "text", "--no-input"];
3461
+ opts.input = prompt;
3462
+ opts.stdio = ["pipe", "pipe", "pipe"];
3463
+ break;
3464
+ case "codex":
3465
+ args = ["exec", prompt];
3466
+ opts.stdio = ["ignore", "pipe", "pipe"];
3467
+ break;
3468
+ case "gemini":
3469
+ args = ["-p", prompt];
3470
+ opts.stdio = ["ignore", "pipe", "pipe"];
3471
+ break;
3472
+ default: {
3473
+ const flags = hint?.flags ? hint.flags.split(/\s+/).filter(Boolean) : ["-p"];
3474
+ args = [...flags, prompt];
3475
+ opts.stdio = ["ignore", "pipe", "pipe"];
3476
+ break;
3477
+ }
3478
+ }
3479
+
3452
3480
  try {
3453
- const result = execFileSync(command, args, {
3454
- encoding: "utf-8",
3455
- timeout: timeoutMs,
3456
- stdio: ["ignore", "pipe", "pipe"],
3457
- maxBuffer: 5 * 1024 * 1024,
3458
- windowsHide: true,
3459
- });
3481
+ const result = execFileSync(command, args, { ...opts, env });
3460
3482
  return { ok: true, response: result.trim() };
3461
3483
  } catch (error) {
3462
3484
  if (error && error.killed) {
package/observer.js CHANGED
@@ -261,7 +261,9 @@ function createServer(port) {
261
261
  const pathname = url.pathname;
262
262
 
263
263
  // CORS
264
- res.setHeader("Access-Control-Allow-Origin", "*");
264
+ const origin = req.headers.origin || "";
265
+ const allowedOrigins = [`http://127.0.0.1:${port}`, `http://localhost:${port}`];
266
+ res.setHeader("Access-Control-Allow-Origin", allowedOrigins.includes(origin) ? origin : allowedOrigins[0]);
265
267
  res.setHeader("Access-Control-Allow-Methods", "GET, POST, OPTIONS");
266
268
  res.setHeader("Access-Control-Allow-Headers", "Content-Type");
267
269
 
@@ -377,7 +379,13 @@ function createServer(port) {
377
379
 
378
380
  req.on("close", () => {
379
381
  const clients = sseClients.get(sessionId) || [];
380
- sseClients.set(sessionId, clients.filter(c => c !== res));
382
+ const remaining = clients.filter(c => c !== res);
383
+ if (remaining.length === 0) {
384
+ sseClients.delete(sessionId);
385
+ sessionSnapshots.delete(sessionId);
386
+ } else {
387
+ sseClients.set(sessionId, remaining);
388
+ }
381
389
  });
382
390
  return;
383
391
  }
@@ -468,7 +476,7 @@ const server = createServer(port);
468
476
  // Poll every 1 second
469
477
  const pollInterval = setInterval(pollSessions, 1000);
470
478
 
471
- server.listen(port, () => {
479
+ server.listen(port, "127.0.0.1", () => {
472
480
  console.log(`Deliberation Observer running at http://localhost:${port}`);
473
481
  console.log(` Dashboard: http://localhost:${port}/`);
474
482
  console.log(` API: http://localhost:${port}/api/sessions`);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@dmsdc-ai/aigentry-deliberation",
3
- "version": "0.0.21",
3
+ "version": "0.0.22",
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",
@@ -14,7 +14,7 @@ if (!sessionId) {
14
14
  }
15
15
 
16
16
  const HOME = process.env.HOME || process.env.USERPROFILE || "";
17
- const stateDir = path.join(HOME, ".local", "state", "mcp-deliberation", project);
17
+ const stateDir = path.join(HOME, ".local", "lib", "mcp-deliberation", "state", project);
18
18
  const stateFile = path.join(stateDir, `${sessionId}.json`);
19
19
 
20
20
  const BOLD = "\x1b[1m";