@boyingliu01/xp-gate 0.6.0 → 0.6.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.
@@ -0,0 +1,30 @@
1
+ /**
2
+ * Shared filesystem path constants used across CLI modules.
3
+ * Cross-platform home directory resolution with os.homedir() fallback.
4
+ *
5
+ * @intent Eliminate duplicate path constants in init.js / uninstall.js / detect-deps.js
6
+ * @covers Issue #107 — duplicate code between init.js and uninstall.js
7
+ */
8
+ const path = require('path');
9
+ const os = require('os');
10
+
11
+ /**
12
+ * Resolve the user's home directory cross-platform.
13
+ * Fallback chain: HOME → USERPROFILE → os.homedir()
14
+ */
15
+ const HOME_DIR = process.env.HOME || process.env.USERPROFILE || os.homedir();
16
+
17
+ const CONFIG_DIR = path.join(HOME_DIR, '.config', 'xp-gate');
18
+ const CONFIG_FILE = path.join(CONFIG_DIR, 'xp-gate.json');
19
+ const TEMPLATE_DIR = path.join(HOME_DIR, '.config', 'opencode', 'git-hooks-template');
20
+ const GLOBAL_HOOKS_DIR = path.join(CONFIG_DIR, 'hooks');
21
+ const GLOBAL_ADAPTERS_DIR = path.join(CONFIG_DIR, 'adapters');
22
+
23
+ module.exports = {
24
+ HOME_DIR,
25
+ CONFIG_DIR,
26
+ CONFIG_FILE,
27
+ TEMPLATE_DIR,
28
+ GLOBAL_HOOKS_DIR,
29
+ GLOBAL_ADAPTERS_DIR,
30
+ };
@@ -0,0 +1,25 @@
1
+ /**
2
+ * Pure utility functions shared by CLI modules.
3
+ * No module-level state — safe for tests that mock fs/path/os.
4
+ */
5
+ const fs = require('fs');
6
+
7
+ /**
8
+ * Recursively copy a directory.
9
+ * Pure function: only uses fs/path params, no global config.
10
+ */
11
+ function copyDirRecursive(src, dest) {
12
+ fs.mkdirSync(dest, { recursive: true });
13
+ const entries = fs.readdirSync(src, { withFileTypes: true });
14
+ for (const entry of entries) {
15
+ const srcPath = require('path').join(src, entry.name);
16
+ const destPath = require('path').join(dest, entry.name);
17
+ if (entry.isDirectory()) {
18
+ copyDirRecursive(srcPath, destPath);
19
+ } else {
20
+ fs.copyFileSync(srcPath, destPath);
21
+ }
22
+ }
23
+ }
24
+
25
+ module.exports = { copyDirRecursive };
package/lib/ui-review.ts CHANGED
@@ -5,7 +5,7 @@ import { collectUiMatches, parseRenamedFile } from './ui-detector';
5
5
 
6
6
  const RESULT_FILE = '.ui-gate-result.json';
7
7
 
8
- interface UiReviewResult {
8
+ export interface UiReviewResult {
9
9
  commit: string;
10
10
  verdict: string;
11
11
  expires: string;
@@ -14,96 +14,101 @@ interface UiReviewResult {
14
14
  ui_changes_detected: string[];
15
15
  }
16
16
 
17
- function main(): void {
18
-
19
- console.log('═══ xp-gate ui-review ═══');
20
-
21
- console.log('');
22
-
23
- // Get staged + modified files
17
+ export function getChangedFilesForReview(): string[] {
24
18
  let files = '';
25
19
  try {
26
20
  files = execSync('git diff --cached --name-only && git diff --name-only', { encoding: 'utf8' }).trim();
27
21
  } catch {
28
-
29
22
  console.log('⚠️ No git repo or no changes. Running in current directory.');
30
23
  }
31
24
 
32
- const fileList = files
25
+ const fileList = parseFileList(files);
26
+ if (fileList.length > 0) {
27
+ return fileList;
28
+ }
29
+
30
+ console.log('No files staged or modified. Checking all tracked files.');
31
+ return getFallbackFileList();
32
+ }
33
+
34
+ export function parseFileList(files: string): string[] {
35
+ return files
33
36
  .split('\n')
34
37
  .map(parseRenamedFile)
35
38
  .filter(f => f.length > 0);
39
+ }
36
40
 
37
- if (fileList.length === 0) {
38
-
39
- console.log('No files staged or modified. Checking all tracked files.');
40
- try {
41
- files = execSync('git ls-files', { encoding: 'utf8' }).trim();
42
- } catch {
43
- files = execSync('find . -maxdepth 3 -type f -name "*.ts" -o -name "*.html" -o -name "*.css" -o -name "*.scss" -o -name "*.tsx" -o -name "*.vue" -o -name "*.svelte" 2>/dev/null | grep -v node_modules | grep -v .git', { encoding: 'utf8' }).trim();
44
- }
45
- fileList.push(...files.split('\n').filter(f => f.length > 0));
41
+ export function getFallbackFileList(): string[] {
42
+ try {
43
+ return parseFileList(execSync('git ls-files', { encoding: 'utf8' }).trim());
44
+ } catch {
45
+ const output = execSync(
46
+ 'find . -maxdepth 3 -type f -name "*.ts" -o -name "*.html" -o -name "*.css" -o -name "*.scss" -o -name "*.tsx" -o -name "*.vue" -o -name "*.svelte" 2>/dev/null | grep -v node_modules | grep -v .git',
47
+ { encoding: 'utf8' },
48
+ ).trim();
49
+ return parseFileList(output);
46
50
  }
51
+ }
52
+
53
+ export function buildUiReviewResult(matchedFiles: string[], now: Date = new Date()): UiReviewResult {
54
+ const commit = getCurrentCommit();
55
+ const expires = new Date(now.getTime() + 24 * 60 * 60 * 1000).toISOString();
56
+
57
+ return {
58
+ commit,
59
+ verdict: 'APPROVED',
60
+ expires,
61
+ design_review: 'APPROVED',
62
+ browser_qa: 'APPROVED',
63
+ ui_changes_detected: matchedFiles,
64
+ };
65
+ }
66
+
67
+ export function writeUiReviewResult(result: UiReviewResult, repoRoot: string = process.cwd()): void {
68
+ writeFileSync(join(repoRoot, RESULT_FILE), JSON.stringify(result, null, 2) + '\n', 'utf8');
69
+ }
70
+
71
+ function getCurrentCommit(): string {
72
+ return execSync('git rev-parse HEAD 2>/dev/null || echo "no-commit"', { encoding: 'utf8' }).trim();
73
+ }
74
+
75
+ export function main(): void {
76
+ console.log('═══ xp-gate ui-review ═══');
77
+ console.log('');
47
78
 
79
+ const fileList = getChangedFilesForReview();
48
80
  const result = collectUiMatches(fileList);
49
81
 
50
82
  if (!result.isUiSprint) {
51
-
52
83
  console.log('ℹ️ No UI changes detected in staged/modified files.');
53
-
54
84
  console.log(' Nothing to review. Exiting.');
55
85
  process.exit(0);
56
86
  }
57
87
 
58
-
59
88
  console.log(`🎨 UI changes detected (${result.matchedFiles.length} files):`);
60
89
  result.matchedFiles.forEach(f => console.log(` - ${f}`));
61
-
62
90
  console.log('');
63
91
 
64
-
65
92
  console.log('Next steps required before push:');
66
-
67
93
  console.log(' 1. Run /design-review in your AI agent session');
68
-
69
94
  console.log(' 2. Run /qa or /qa-only in your AI agent session');
70
-
71
95
  console.log(' 3. Ensure you have .delphi-config.json configured for Delphi review');
72
-
73
96
  console.log('');
74
97
 
75
- const commit = execSync('git rev-parse HEAD 2>/dev/null || echo "no-commit"', { encoding: 'utf8' }).trim();
76
- const expires = new Date(Date.now() + 24 * 60 * 60 * 1000).toISOString();
98
+ const uiResult = buildUiReviewResult(result.matchedFiles);
99
+ writeUiReviewResult(uiResult);
77
100
 
78
- const uiResult: UiReviewResult = {
79
- commit,
80
- verdict: 'APPROVED',
81
- expires,
82
- design_review: 'APPROVED',
83
- browser_qa: 'APPROVED',
84
- ui_changes_detected: result.matchedFiles,
85
- };
86
-
87
- writeFileSync(join(process.cwd(), RESULT_FILE), JSON.stringify(uiResult, null, 2) + '\n', 'utf8');
88
-
89
-
90
101
  console.log(`✅ Generated ${RESULT_FILE} with APPROVED verdict (template)`);
91
-
92
- console.log(` Commit: ${commit}`);
93
-
94
- console.log(` Expires: ${expires}`);
95
-
102
+ console.log(` Commit: ${uiResult.commit}`);
103
+ console.log(` Expires: ${uiResult.expires}`);
96
104
  console.log('');
97
-
98
105
  console.log('⚠️ REVIEW THIS FILE before push:');
99
-
100
106
  console.log(' - Ensure design_review and browser_qa are actually APPROVED');
101
-
102
107
  console.log(' - Edit verdict to REJECTED if issues found');
103
-
104
108
  console.log('');
105
-
106
109
  console.log('Then: git push (pre-push will validate this file)');
107
110
  }
108
111
 
109
- main();
112
+ if (require.main === module) {
113
+ main();
114
+ }
package/lib/uninstall.js CHANGED
@@ -1,16 +1,15 @@
1
1
  const fs = require('fs');
2
2
  const path = require('path');
3
- const os = require('os');
4
3
  const crypto = require('crypto');
4
+ const {
5
+ HOME_DIR,
6
+ CONFIG_DIR,
7
+ CONFIG_FILE,
8
+ TEMPLATE_DIR,
9
+ GLOBAL_HOOKS_DIR,
10
+ GLOBAL_ADAPTERS_DIR,
11
+ } = require('./shared-paths.js');
5
12
 
6
- // Cross-platform home directory resolution
7
- const HOME_DIR = process.env.HOME || process.env.USERPROFILE || os.homedir();
8
-
9
- const CONFIG_DIR = path.join(HOME_DIR, '.config', 'xp-gate');
10
- const CONFIG_FILE = path.join(CONFIG_DIR, 'xp-gate.json');
11
- const TEMPLATE_DIR = path.join(HOME_DIR, '.config', 'opencode', 'git-hooks-template');
12
- const GLOBAL_HOOKS_DIR = path.join(CONFIG_DIR, 'hooks');
13
- const GLOBAL_ADAPTERS_DIR = path.join(CONFIG_DIR, 'adapters');
14
13
  const BACKUP_DIR = path.join(CONFIG_DIR, '.uninstall-backup');
15
14
 
16
15
  /**
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@boyingliu01/xp-gate",
3
- "version": "0.6.0",
3
+ "version": "0.6.2",
4
4
  "description": "AI-driven development workflow: 6 quality gates + Delphi review + Sprint Flow",
5
5
  "bin": {
6
6
  "xp-gate": "./bin/xp-gate.js"
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "xp-gate",
3
- "version": "0.6.0",
3
+ "version": "0.6.2",
4
4
  "displayName": "XP-Gate",
5
5
  "description": "Extreme Programming quality gates + AI workflow skills for Claude Code. Includes 6 quality gates, Sprint Flow, and Delphi multi-expert review.",
6
6
  "author": {
@@ -1,10 +1,23 @@
1
1
  ---
2
2
  name: delphi-review
3
- description: "Delphi consensus review: multi-round anonymous expert review until unanimous APPROVAL. Supports design/code-walkthrough modes. 2-3 experts from different providers. MANDATORY before implementation, design, or architecture decisions. Trigger: 'review this design', '评审这个需求', 'design review', '多专家评审', 'consensus review', 'code walkthrough', 'push review', or any request for multi-expert review of requirements, design docs, architecture, or PRs."
3
+ description: "Use when asked to review a design, plan, or architecture; before implementation starts; or when multi-expert consensus is needed. Triggers: 'review this design', '评审这个需求', 'design review', '多专家评审', 'consensus review', 'code walkthrough', 'push review', 'architecture review', 'PR review', or any request for multi-expert evaluation of requirements, design docs, or PRs."
4
4
  ---
5
5
 
6
6
  # Delphi Consensus Review
7
7
 
8
+ ## Scope
9
+
10
+ **In Scope:**
11
+ - Multi-round anonymous expert consensus review (design + code-walkthrough modes)
12
+ - 2-3 experts from different providers with statistical consensus (>= 91%)
13
+ - Structured verdict: APPROVED / PASS_WITH_CAVEATS / REQUEST_CHANGES
14
+ - Domestic models only (no Anthropic/OpenAI/Google)
15
+
16
+ **Out of Scope:**
17
+ - Does NOT implement code changes (review only, implementation is separate)
18
+ - Does NOT replace testing or CI/CD verification
19
+ - Does NOT handle deployment or release decisions
20
+
8
21
  ## 核心原则
9
22
 
10
23
  **Delphi 方法只有一个目的:得到所有专家一致认可的可行方案。**
@@ -14,7 +27,7 @@ description: "Delphi consensus review: multi-round anonymous expert review until
14
27
  1. **匿名性** — Round 1 专家互不知道对方意见
15
28
  2. **迭代** — 多轮直到共识,不是固定轮数
16
29
  3. **受控反馈** — 每轮看到其他专家意见
17
- 4. **统计共识** — >=95% 一致才算共识
30
+ 4. **统计共识** — >=91% 一致才算共识
18
31
 
19
32
  ### 质量优先
20
33
 
@@ -82,24 +95,24 @@ description: "Delphi consensus review: multi-round anonymous expert review until
82
95
 
83
96
  | 阈值 | 说明 |
84
97
  |------|------|
85
- | **>=95%** | 推荐默认 |
98
+ | **>=91%** | 推荐默认 |
86
99
  | 100% | 完全一致(更严格) |
87
100
 
88
101
  ---
89
102
 
90
- ## 完整流程
103
+ ## Delphi 评审执行过程
91
104
 
92
105
  ```
93
106
  Phase 0: 准备 → Round 1: 匿名独立评审 → 共识检查
94
107
 
95
- ├─ 一致 + >=95% + APPROVED → ✅ 完成
108
+ ├─ 一致 + >=91% + APPROVED → ✅ 完成
96
109
 
97
- └─ 不一致 或 <95% 或 REQUEST_CHANGES
110
+ └─ 不一致 或 <91% 或 REQUEST_CHANGES
98
111
 
99
112
 
100
113
  Round 2: 交换意见 → 共识检查
101
114
 
102
- ├─ 一致 + >=95% + APPROVED → ✅ 完成
115
+ ├─ 一致 + >=91% + APPROVED → ✅ 完成
103
116
 
104
117
  └─ 仍分歧 或 REQUEST_CHANGES
105
118
 
@@ -202,14 +215,96 @@ Phase 0: 准备 → Round 1: 匿名独立评审 → 共识检查
202
215
 
203
216
  ---
204
217
 
218
+ ## Triggers
219
+
220
+ This skill activates on any request for multi-expert review. Common triggers:
221
+
222
+ **English:**
223
+ - "review this design"
224
+ - "design review"
225
+ - "architecture review"
226
+ - "consensus review"
227
+ - "code walkthrough"
228
+ - "push review"
229
+ - "multi-expert review"
230
+ - "PR review"
231
+
232
+ **Chinese:**
233
+ - "评审这个需求"
234
+ - "多专家评审"
235
+ - "设计评审"
236
+ - "架构评审"
237
+ - "代码走查"
238
+
239
+ **Related commands:**
240
+ - `/delphi-review` - Design review mode
241
+ - `/delphi-review --mode code-walkthrough` - Pre-push code walkthrough
242
+
243
+ ---
244
+
245
+ ## Workflow Steps
246
+
247
+ 1. **Determine mode** - Design review (default) or code-walkthrough (--mode code-walkthrough)
248
+ 2. **Dispatch anonymous experts** - 2-3 experts from ≥2 different domestic model providers
249
+ 3. **Collect Round 1 independent reviews** - Anonymous, no cross-expert bias
250
+ 4. **Synthesize feedback** - Measure consensus, identify disagreements
251
+ 5. **Run Round 2+ until consensus** - Exchange opinions, iterate until ≥91% agreement
252
+ 6. **Block on unresolved Critical/Major** - Zero-tolerance: all Critical/Major must be resolved
253
+ 7. **Emit verdict** - APPROVED (with specification.yaml) or REQUEST_CHANGES (fix + re-review)
254
+
255
+ **Consensus threshold:** ≥91% (project standard for Delphi review approval)
256
+ **Model policy:** Domestic models only (DeepSeek, Qwen, Kimi, GLM, MiniMax). Foreign models (Anthropic/OpenAI/Google) forbidden.
257
+
258
+ ---
259
+
260
+ ## Scope
261
+
262
+ **IN Scope:**
263
+ - Design document review (requirements, architecture, PRDs)
264
+ - Pre-implementation planning review
265
+ - Code walkthrough (git push validation, max 20 files/500 LOC)
266
+ - Multi-expert consensus building
267
+ - Specification extraction (design → specification.yaml)
268
+
269
+ **OUT Scope:**
270
+ - Single-expert review (use `/review` instead)
271
+ - Post-implementation review (use `/requesting-code-review`)
272
+ - Security audit (use `/security-research` or `/cso`)
273
+ - Performance benchmarking (use `/benchmark`)
274
+
275
+ ---
276
+
277
+ ## Examples
278
+
279
+ **Example 1: Design review**
280
+ ```bash
281
+ /delphi-review
282
+ ```
283
+ → 3 experts review design doc → consensus report + specification.yaml
284
+
285
+ **Example 2: Code walkthrough**
286
+ ```bash
287
+ /delphi-review --mode code-walkthrough
288
+ ```
289
+ → Pre-push validation → .code-walkthrough-result.json
290
+
291
+ **Example 3: Chinese trigger**
292
+ ```
293
+ User: 评审这个需求文档
294
+ → Auto-detects delphi-review trigger → dispatches experts
295
+ ```
296
+
297
+ ---
298
+
205
299
  ## Output Format (MANDATORY)
206
- Every review round output MUST follow this exact JSON structure:
300
+
301
+ Every review round output MUST follow this exact JSON structure for design mode:
207
302
 
208
303
  ```json
209
304
  {
210
305
  "expert_id": "A|B|C",
211
306
  "round": 1,
212
- "mode": "design|code-walkthrough",
307
+ "mode": "design",
213
308
  "verdict": "APPROVED|REQUEST_CHANGES|REJECTED",
214
309
  "confidence": 9,
215
310
  "critical_issues": ["..."],
@@ -218,11 +313,14 @@ Every review round output MUST follow this exact JSON structure:
218
313
  "consensus_report": {
219
314
  "agreed_items": ["..."],
220
315
  "disagreed_items": ["..."],
221
- "final_verdict": "APPROVED|REQUEST_CHANGES"
316
+ "final_verdict": "APPROVED|REQUEST_CHANGES",
317
+ "consensus_ratio": 0.95
222
318
  }
223
319
  }
224
320
  ```
225
321
 
322
+ **For code-walkthrough mode**, output follows `.code-walkthrough-result.json` schema (see `references/code-walkthrough.md`).
323
+
226
324
  **Anti-patterns mapping to assertions:**
227
325
  - `Round 1 → 生成报告 → "评审完成"` → Output MUST NOT have `verdict: APPROVED` if `critical_issues` exist.
228
326
  - `只处理 Critical,忽略 Major` → Output MUST include `major_concerns` array, even if empty.
@@ -242,7 +340,7 @@ Every review round output MUST follow this exact JSON structure:
242
340
  - [ ] Round 2+ 完成(交换意见 / 最终立场)
243
341
 
244
342
  **CRITICAL — 共识验证:**
245
- - [ ] 问题共识比例 >=95%
343
+ - [ ] 问题共识比例 >=91%
246
344
  - [ ] 所有 Critical Issues 已解决
247
345
  - [ ] 所有 Major Concerns 已处理
248
346
 
@@ -324,7 +422,7 @@ Every review round output MUST follow this exact JSON structure:
324
422
  | 只处理 Critical,忽略 Major | 零容忍:Critical/Major 全部必须处理,不可跳过或降级 |
325
423
  | 单专家自评 | 至少 2 位不同 provider 的专家 |
326
424
  | 用户说"时间紧急"就跳过 | 评审是投资不是开销,跳过后期返工成本更高 |
327
- | "专家几乎一致"就通过 | "几乎" = 不一致,继续到 >=95% |
425
+ | "专家几乎一致"就通过 | "几乎" = 不一致,继续到 >=91% |
328
426
  | 使用 Anthropic/GPT/Gemini 等国外昂贵模型 | 必须使用国产开源模型(DeepSeek, Qwen, Kimi, GLM, MiniMax) |
329
427
  | 三个专家使用同一厂家模型 | 必须来自至少 2 家不同厂家 |
330
428
 
@@ -339,7 +437,7 @@ Every review round output MUST follow this exact JSON structure:
339
437
  | "这只是小变更" | 所有变更都需要评审 |
340
438
  | "Round 1 就够了" | 不够,必须多轮直到共识 |
341
439
  | "生成报告就完成了" | APPROVED 才算完成 |
342
- | "2/3 同意就是共识" | 还要检查问题共识比例 >=95% |
440
+ | "2/3 同意就是共识" | 还要检查问题共识比例 >=91% |
343
441
 
344
442
  ---
345
443
 
@@ -347,25 +445,10 @@ Every review round output MUST follow this exact JSON structure:
347
445
 
348
446
  **Delphi 评审完成的唯一标准:**
349
447
  1. ✅ 所有专家裁决 APPROVED
350
- 2. ✅ 问题共识 >=95%
448
+ 2. ✅ 问题共识 >=91%
351
449
  3. ✅ 所有 Critical Issues 已修复验证
352
450
  4. ✅ 所有 Major Concerns 已处理
353
451
  5. ✅ 共识报告已生成
354
452
  6. ✅ 用户已确认
355
453
 
356
454
  **缺少任何一项 = 未完成**
357
- ## Output Format (MANDATORY)
358
- Every delphi review round MUST output valid JSON:
359
- ```json
360
- {
361
- "skill_name": "delphi-review",
362
- "mode": "design|code-walkthrough",
363
- "phase": "Round 1|Round 2|Round 3|Consensus",
364
- "expert_id": "A|B|C",
365
- "verdict": "APPROVED|REQUEST_CHANGES|REJECTED",
366
- "confidence": 8,
367
- "issues": [{"id": "string", "severity": "critical|major|minor", "description": "string"}],
368
- "consensus_report": {"status": "pending|consensus|disagreement"}
369
- }
370
- ```
371
- **Eval assertions check for:** `verdict` enum values, `confidence` range, `issues` structure, `consensus_report.status`.