@unlaxer/dge-toolkit 2.1.1 → 2.1.2

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/bin/dge-tool.js CHANGED
@@ -82,19 +82,112 @@ function cmdVersion() {
82
82
  console.log(`dge-tool v${VERSION}`);
83
83
  }
84
84
 
85
+ function cmdCompare() {
86
+ // Reads two JSON gap lists from stdin and generates comparison table
87
+ // Input format: { "dge": [...gaps], "plain": [...gaps] }
88
+ let input = '';
89
+ process.stdin.setEncoding('utf8');
90
+ process.stdin.on('data', chunk => { input += chunk; });
91
+ process.stdin.on('end', () => {
92
+ try {
93
+ const data = JSON.parse(input);
94
+ const dge = data.dge || [];
95
+ const plain = data.plain || [];
96
+
97
+ // Simple title-based dedup
98
+ const dgeSet = new Set(dge.map(g => g.gap.toLowerCase().trim()));
99
+ const plainSet = new Set(plain.map(g => g.gap.toLowerCase().trim()));
100
+
101
+ const both = [];
102
+ const dgeOnly = [];
103
+ const plainOnly = [];
104
+
105
+ for (const g of dge) {
106
+ const key = g.gap.toLowerCase().trim();
107
+ // Check if any plain gap is similar (substring match or word overlap)
108
+ let found = false;
109
+ for (const p of plain) {
110
+ const pKey = p.gap.toLowerCase().trim();
111
+ // Substring check (works for Japanese)
112
+ const isSubstring = key.includes(pKey) || pKey.includes(key);
113
+ // Word overlap for English
114
+ const gWords = new Set(key.split(/[\s/・、。]+/).filter(w => w.length > 1));
115
+ const pWords = new Set(pKey.split(/[\s/・、。]+/).filter(w => w.length > 1));
116
+ const overlap = [...gWords].filter(w => pWords.has(w)).length;
117
+ const similarity = overlap / Math.min(gWords.size, pWords.size);
118
+ if (isSubstring || similarity > 0.5) {
119
+ both.push({ ...g, source: '両方', plain_match: p.gap });
120
+ found = true;
121
+ plainSet.delete(pKey);
122
+ break;
123
+ }
124
+ }
125
+ if (!found) dgeOnly.push({ ...g, source: 'DGE のみ' });
126
+ }
127
+
128
+ for (const p of plain) {
129
+ const pKey = p.gap.toLowerCase().trim();
130
+ if (plainSet.has(pKey)) {
131
+ plainOnly.push({ ...p, source: '素のみ' });
132
+ }
133
+ }
134
+
135
+ // Stats
136
+ const dgeC = dge.filter(g => g.severity === 'Critical').length;
137
+ const dgeH = dge.filter(g => g.severity === 'High').length;
138
+ const plainC = plain.filter(g => g.severity === 'Critical').length;
139
+ const plainH = plain.filter(g => g.severity === 'High').length;
140
+
141
+ console.log('## マージ結果: DGE + 素の LLM(isolated)');
142
+ console.log('');
143
+ console.log('### 数値比較');
144
+ console.log('| 指標 | DGE | 素の LLM |');
145
+ console.log('|------|-----|---------|');
146
+ console.log(`| Gap 総数 | ${dge.length} | ${plain.length} |`);
147
+ console.log(`| Critical | ${dgeC} | ${plainC} |`);
148
+ console.log(`| High | ${dgeH} | ${plainH} |`);
149
+ console.log('');
150
+ console.log('### Gap 一覧(統合)');
151
+ console.log('| # | Gap | Source | Severity |');
152
+ console.log('|---|-----|--------|----------|');
153
+
154
+ let n = 1;
155
+ for (const g of both) {
156
+ console.log(`| ${n++} | ${g.gap} | 両方 | ${g.severity} |`);
157
+ }
158
+ for (const g of dgeOnly) {
159
+ console.log(`| ${n++} | ${g.gap} | DGE のみ | ${g.severity} |`);
160
+ }
161
+ for (const g of plainOnly) {
162
+ console.log(`| ${n++} | ${g.gap} | 素のみ | ${g.severity} |`);
163
+ }
164
+
165
+ console.log('');
166
+ console.log(`DGE のみ: ${dgeOnly.length} 件(深い洞察)`);
167
+ console.log(`素のみ: ${plainOnly.length} 件(網羅的チェック)`);
168
+ console.log(`両方: ${both.length} 件(確実に重要)`);
169
+ } catch (e) {
170
+ console.error('ERROR: invalid JSON input. Expected: { "dge": [...], "plain": [...] }');
171
+ process.exit(1);
172
+ }
173
+ });
174
+ }
175
+
85
176
  function cmdHelp() {
86
177
  console.log(`dge-tool v${VERSION} — DGE MUST enforcement CLI
87
178
 
88
179
  Commands:
89
180
  save <file> Save stdin to file (ensures MUST: always save)
90
181
  prompt [flow] Show numbered choices from flow YAML (ensures MUST: show choices)
182
+ compare Merge DGE + plain gaps from stdin JSON (isolated comparison)
91
183
  version Show version
92
184
  help Show this help
93
185
 
94
186
  Examples:
95
187
  echo "session content" | dge-tool save dge/sessions/auth-api.md
96
188
  dge-tool prompt quick
97
- dge-tool prompt design-review`);
189
+ dge-tool prompt design-review
190
+ echo '{"dge":[...],"plain":[...]}' | dge-tool compare`);
98
191
  }
99
192
 
100
193
  // Dispatch
@@ -105,6 +198,9 @@ switch (command) {
105
198
  case 'prompt':
106
199
  cmdPrompt();
107
200
  break;
201
+ case 'compare':
202
+ cmdCompare();
203
+ break;
108
204
  case 'version':
109
205
  case '-v':
110
206
  case '--version':
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@unlaxer/dge-toolkit",
3
- "version": "2.1.1",
3
+ "version": "2.1.2",
4
4
  "description": "DGE (Dialogue-driven Gap Extraction) — 会話劇で設計の穴を発見するメソッドkit",
5
5
  "license": "MIT",
6
6
  "repository": {
@@ -133,8 +133,62 @@ flow YAML の post_actions の id に応じて分岐:
133
133
  ### Step 9B: 前回コンテキスト + プロジェクトナビゲーション
134
134
  プロジェクトファイルがあれば TreeView 表示。なければ前回サマリー + 3 択。
135
135
 
136
- ### Step 9C: 素の LLM マージ
137
- subagent で同じテーマを素でレビュー → DGE Gap とマージ → DGE のみ / 素のみ / 両方 をラベル付け。
136
+ ### Step 9C: 素の LLM マージ(isolated subagent)
137
+
138
+ **重要: DGE の結果を知らない独立した agent で素のレビューを行う。** これにより DGE の Gap を「補完する」バイアスを排除する。
139
+
140
+ 1. **isolated subagent を起動**: Agent ツールで `isolation: "worktree"` を指定。
141
+ DGE session の context を一切持たない別プロセスが実行する。
142
+
143
+ subagent へのプロンプト:
144
+ ```
145
+ 以下の設計ドキュメントをレビューしてください。
146
+ 問題点、考慮漏れ、矛盾を全て挙げてください。
147
+ 各問題に Category と Severity (Critical / High / Medium / Low) をつけてください。
148
+ テーブル形式で出力: | # | Gap | Category | Severity |
149
+
150
+ [テーマの設計ドキュメント / コンテキスト]
151
+ ```
152
+
153
+ **subagent には DGE の Gap 一覧や会話劇を渡さない。** 完全に独立したレビュー。
154
+
155
+ 2. **素の Gap 一覧を受け取る**
156
+
157
+ 3. **DGE の Gap と素の Gap をマージ**:
158
+ - Gap タイトルの意味的類似度で重複を判定
159
+ - 同じ問題 → 「両方」ラベル(信頼度が高い)
160
+ - DGE のみ → 「DGE のみ」ラベル(深い洞察の可能性)
161
+ - 素のみ → 「素のみ」ラベル(網羅的チェック)
162
+
163
+ 4. **比較表を表示**:
164
+ ```
165
+ ## マージ結果: DGE + 素の LLM(isolated)
166
+
167
+ ### 数値比較
168
+ | 指標 | DGE | 素の LLM |
169
+ |------|-----|---------|
170
+ | Gap 総数 | N | N |
171
+ | Critical | N | N |
172
+ | High | N | N |
173
+ | カテゴリ数 | N/11 | N/11 |
174
+
175
+ ### Gap 一覧(統合)
176
+ | # | Gap | Source | Severity |
177
+ |---|-----|--------|----------|
178
+ | 1 | [gap] | DGE のみ | High |
179
+ | 2 | [gap] | 両方 | Critical |
180
+ | 3 | [gap] | 素のみ | Medium |
181
+
182
+ DGE のみ: N 件(深い洞察)
183
+ 素のみ: N 件(網羅的チェック)
184
+ 両方: N 件(確実に重要)
185
+
186
+ どうしますか?
187
+ 1. 実装する → マージ済み Gap から Spec 化
188
+ 2. 後で
189
+ ```
190
+
191
+ 5. **マージ結果をファイルに保存**: `dge/sessions/{theme}-merged.md`
138
192
 
139
193
  ### Step 10: 累積 Spec 化(design-review のみ)
140
194
  同テーマの全 session Gap を統合 → Critical/High を Spec 化 → `dge/specs/` に保存。
package/version.txt CHANGED
@@ -1 +1 @@
1
- 2.1.1
1
+ 2.1.2