@pcircle/memesh 2.8.11 → 2.9.1

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.
Files changed (79) hide show
  1. package/LICENSE +21 -661
  2. package/README.de.md +171 -0
  3. package/README.es.md +171 -0
  4. package/README.fr.md +171 -0
  5. package/README.id.md +171 -0
  6. package/README.ja.md +171 -0
  7. package/README.ko.md +171 -0
  8. package/README.md +73 -100
  9. package/README.th.md +171 -0
  10. package/README.vi.md +171 -0
  11. package/README.zh-CN.md +171 -0
  12. package/README.zh-TW.md +71 -98
  13. package/dist/knowledge-graph/index.d.ts +22 -1
  14. package/dist/knowledge-graph/index.d.ts.map +1 -1
  15. package/dist/knowledge-graph/index.js +144 -3
  16. package/dist/knowledge-graph/index.js.map +1 -1
  17. package/dist/mcp/ServerInitializer.d.ts.map +1 -1
  18. package/dist/mcp/ServerInitializer.js +1 -1
  19. package/dist/mcp/ServerInitializer.js.map +1 -1
  20. package/dist/mcp/ToolDefinitions.d.ts.map +1 -1
  21. package/dist/mcp/ToolDefinitions.js +47 -55
  22. package/dist/mcp/ToolDefinitions.js.map +1 -1
  23. package/dist/mcp/ToolRouter.d.ts.map +1 -1
  24. package/dist/mcp/ToolRouter.js +4 -4
  25. package/dist/mcp/ToolRouter.js.map +1 -1
  26. package/dist/mcp/daemon/StdioProxyClient.d.ts.map +1 -1
  27. package/dist/mcp/daemon/StdioProxyClient.js +9 -1
  28. package/dist/mcp/daemon/StdioProxyClient.js.map +1 -1
  29. package/dist/mcp/handlers/BuddyHandlers.d.ts +3 -1
  30. package/dist/mcp/handlers/BuddyHandlers.d.ts.map +1 -1
  31. package/dist/mcp/handlers/BuddyHandlers.js +6 -5
  32. package/dist/mcp/handlers/BuddyHandlers.js.map +1 -1
  33. package/dist/mcp/handlers/ToolHandlers.d.ts.map +1 -1
  34. package/dist/mcp/handlers/ToolHandlers.js +1 -2
  35. package/dist/mcp/handlers/ToolHandlers.js.map +1 -1
  36. package/dist/mcp/resources/quick-reference.md +1 -1
  37. package/dist/mcp/schemas/OutputSchemas.d.ts +116 -53
  38. package/dist/mcp/schemas/OutputSchemas.d.ts.map +1 -1
  39. package/dist/mcp/schemas/OutputSchemas.js +64 -26
  40. package/dist/mcp/schemas/OutputSchemas.js.map +1 -1
  41. package/dist/mcp/server-bootstrap.js +89 -9
  42. package/dist/mcp/server-bootstrap.js.map +1 -1
  43. package/dist/mcp/tools/buddy-do.d.ts +2 -1
  44. package/dist/mcp/tools/buddy-do.d.ts.map +1 -1
  45. package/dist/mcp/tools/buddy-do.js +91 -4
  46. package/dist/mcp/tools/buddy-do.js.map +1 -1
  47. package/dist/mcp/tools/buddy-remember.d.ts +0 -5
  48. package/dist/mcp/tools/buddy-remember.d.ts.map +1 -1
  49. package/dist/mcp/tools/buddy-remember.js.map +1 -1
  50. package/dist/mcp/tools/memesh-agent-register.d.ts +20 -0
  51. package/dist/mcp/tools/memesh-agent-register.d.ts.map +1 -0
  52. package/dist/mcp/tools/memesh-agent-register.js +80 -0
  53. package/dist/mcp/tools/memesh-agent-register.js.map +1 -0
  54. package/dist/mcp/tools/memesh-cloud-sync.js +27 -8
  55. package/dist/mcp/tools/memesh-cloud-sync.js.map +1 -1
  56. package/dist/mcp/tools/memesh-metrics.d.ts +13 -0
  57. package/dist/mcp/tools/memesh-metrics.d.ts.map +1 -0
  58. package/dist/mcp/tools/memesh-metrics.js +193 -0
  59. package/dist/mcp/tools/memesh-metrics.js.map +1 -0
  60. package/dist/memory/UnifiedMemoryStore.d.ts +1 -1
  61. package/dist/memory/UnifiedMemoryStore.d.ts.map +1 -1
  62. package/dist/memory/UnifiedMemoryStore.js +4 -3
  63. package/dist/memory/UnifiedMemoryStore.js.map +1 -1
  64. package/package.json +9 -12
  65. package/plugin.json +2 -2
  66. package/scripts/hooks/README.md +230 -0
  67. package/scripts/hooks/__tests__/hook-test-harness.js +218 -0
  68. package/scripts/hooks/__tests__/hooks.test.js +267 -0
  69. package/scripts/hooks/hook-utils.js +899 -0
  70. package/scripts/hooks/post-commit.js +307 -0
  71. package/scripts/hooks/post-tool-use.js +812 -0
  72. package/scripts/hooks/pre-tool-use.js +462 -0
  73. package/scripts/hooks/session-start.js +544 -0
  74. package/scripts/hooks/stop.js +673 -0
  75. package/scripts/hooks/subagent-stop.js +184 -0
  76. package/scripts/hooks/templates/planning-template.md +46 -0
  77. package/scripts/postinstall-lib.js +8 -4
  78. package/scripts/postinstall-new.js +110 -7
  79. package/scripts/skills/comprehensive-code-review/SKILL.md +276 -0
@@ -0,0 +1,184 @@
1
+ #!/usr/bin/env node
2
+
3
+ /**
4
+ * SubagentStop Hook - Capture Subagent Results to MeMesh Knowledge Graph
5
+ *
6
+ * Triggered when a subagent finishes execution.
7
+ *
8
+ * Features:
9
+ * - Saves code review findings to MeMesh KG (high-value results)
10
+ * - Tracks code review completion for pre-commit enforcement
11
+ * - Updates session state with subagent activity
12
+ * - Silent operation (no console output)
13
+ */
14
+
15
+ import {
16
+ STATE_DIR,
17
+ MEMESH_DB_PATH,
18
+ readJSONFile,
19
+ writeJSONFile,
20
+ sqliteBatchEntity,
21
+ getDateString,
22
+ readStdin,
23
+ logError,
24
+ logMemorySave,
25
+ } from './hook-utils.js';
26
+ import fs from 'fs';
27
+ import path from 'path';
28
+
29
+ // ============================================================================
30
+ // Constants
31
+ // ============================================================================
32
+
33
+ const CURRENT_SESSION_FILE = path.join(STATE_DIR, 'current-session.json');
34
+
35
+ /** Agent types that count as code review */
36
+ const CODE_REVIEWER_TYPES = [
37
+ 'code-reviewer',
38
+ 'code-review',
39
+ 'superpowers:code-reviewer',
40
+ 'pr-review-toolkit:code-reviewer',
41
+ 'feature-dev:code-reviewer',
42
+ ];
43
+
44
+ // ============================================================================
45
+ // Code Review Detection
46
+ // ============================================================================
47
+
48
+ /**
49
+ * Check if this subagent is a code reviewer
50
+ * @param {string} agentType - Subagent type identifier
51
+ * @returns {boolean}
52
+ */
53
+ function isCodeReviewer(agentType) {
54
+ if (!agentType) return false;
55
+ const lower = agentType.toLowerCase();
56
+ return CODE_REVIEWER_TYPES.some(t => lower.includes(t.toLowerCase()));
57
+ }
58
+
59
+ /**
60
+ * Mark code review as done in session state.
61
+ * This flag is checked by pre-tool-use.js before git commits.
62
+ */
63
+ function markCodeReviewDone() {
64
+ const session = readJSONFile(CURRENT_SESSION_FILE, {});
65
+ session.codeReviewDone = true;
66
+ session.codeReviewTimestamp = new Date().toISOString();
67
+ writeJSONFile(CURRENT_SESSION_FILE, session);
68
+ }
69
+
70
+ // ============================================================================
71
+ // MeMesh KG Save
72
+ // ============================================================================
73
+
74
+ /**
75
+ * Save code review results to MeMesh knowledge graph.
76
+ * Only saves code reviewer subagent results (high-value findings).
77
+ *
78
+ * @param {string} agentType - Subagent type
79
+ * @param {string} lastMessage - Agent's final response
80
+ * @returns {boolean} True if saved
81
+ */
82
+ function saveSubagentToKG(agentType, lastMessage) {
83
+ try {
84
+ if (!fs.existsSync(MEMESH_DB_PATH)) return false;
85
+ if (!lastMessage || lastMessage.length < 50) return false;
86
+
87
+ // Truncate very long messages
88
+ const shortMessage = lastMessage.length > 1000
89
+ ? lastMessage.substring(0, 1000) + '...'
90
+ : lastMessage;
91
+
92
+ const entityName = `Code Review: ${getDateString()} ${Date.now()} ${agentType}`;
93
+ const metadata = JSON.stringify({
94
+ agentType,
95
+ messageLength: lastMessage.length,
96
+ source: 'subagent-stop-hook',
97
+ });
98
+
99
+ const tags = [
100
+ 'code-review',
101
+ `agent:${agentType}`,
102
+ `date:${getDateString()}`,
103
+ 'auto-tracked',
104
+ 'scope:project',
105
+ ];
106
+
107
+ const entityId = sqliteBatchEntity(
108
+ MEMESH_DB_PATH,
109
+ { name: entityName, type: 'code_review', metadata },
110
+ [`[${agentType}] ${shortMessage}`],
111
+ tags
112
+ );
113
+
114
+ if (entityId === null) return false;
115
+
116
+ logMemorySave(`Code review saved: ${agentType} (${lastMessage.length} chars)`);
117
+ return true;
118
+ } catch (error) {
119
+ logError('saveSubagentToKG', error);
120
+ return false;
121
+ }
122
+ }
123
+
124
+ // ============================================================================
125
+ // Session State Update
126
+ // ============================================================================
127
+
128
+ /**
129
+ * Track subagent activity in session state
130
+ * @param {string} agentType - Subagent type
131
+ */
132
+ function trackSubagentInSession(agentType) {
133
+ const session = readJSONFile(CURRENT_SESSION_FILE, { subagents: [] });
134
+ if (!session.subagents) session.subagents = [];
135
+
136
+ session.subagents.push({
137
+ type: agentType,
138
+ completedAt: new Date().toISOString(),
139
+ });
140
+
141
+ // Keep only last 20 subagent entries
142
+ if (session.subagents.length > 20) {
143
+ session.subagents = session.subagents.slice(-20);
144
+ }
145
+
146
+ writeJSONFile(CURRENT_SESSION_FILE, session);
147
+ }
148
+
149
+ // ============================================================================
150
+ // Main
151
+ // ============================================================================
152
+
153
+ async function subagentStop() {
154
+ try {
155
+ const input = await readStdin(3000);
156
+ if (!input || input.trim() === '') {
157
+ process.exit(0);
158
+ }
159
+
160
+ const data = JSON.parse(input);
161
+ const agentType = data.agent_type || data.agentType || 'unknown';
162
+ const lastMessage = data.last_assistant_message || data.lastAssistantMessage || '';
163
+
164
+ // Track all subagent completions in session state
165
+ trackSubagentInSession(agentType);
166
+
167
+ // Track code review completion (for pre-commit enforcement)
168
+ if (isCodeReviewer(agentType)) {
169
+ markCodeReviewDone();
170
+ }
171
+
172
+ // Save code reviewer results to MeMesh KG (high-value findings)
173
+ if (isCodeReviewer(agentType) && lastMessage.length > 50) {
174
+ saveSubagentToKG(agentType, lastMessage);
175
+ }
176
+
177
+ process.exit(0);
178
+ } catch (error) {
179
+ logError('SubagentStop', error);
180
+ process.exit(0); // Never block on hook errors
181
+ }
182
+ }
183
+
184
+ subagentStop();
@@ -0,0 +1,46 @@
1
+ ## Required Plan Sections
2
+
3
+ Your plan MUST include all of the following sections. Incomplete plans will be rejected.
4
+
5
+ ### 1. System Design Description (SDD)
6
+ - Component architecture and responsibilities
7
+ - Data flow between components
8
+ - Interface contracts (input/output types)
9
+ - Dependencies and integration points
10
+
11
+ ### 2. Behavior-Driven Design (BDD)
12
+ For EACH feature, write Gherkin scenarios:
13
+
14
+ ```gherkin
15
+ Scenario: [descriptive name]
16
+ Given [precondition]
17
+ When [action]
18
+ Then [expected outcome]
19
+ ```
20
+
21
+ Cover: happy path, error path, edge cases.
22
+
23
+ ### 3. Edge Case Handling
24
+
25
+ | Edge Case | How Handled | Test Coverage |
26
+ |-----------|------------|---------------|
27
+ | [case] | [strategy] | [yes/no] |
28
+
29
+ Include at minimum: empty input, null/undefined, boundary values, concurrent access, timeout, large data.
30
+
31
+ ### 4. Dry-Run Test Plan
32
+ Before dispatching heavy tasks, verify:
33
+ - [ ] Core function compiles (`tsc --noEmit` or `node --check`)
34
+ - [ ] Unit test for critical path passes
35
+ - [ ] Integration point verified with real call
36
+ - [ ] No regressions in existing tests
37
+
38
+ ### 5. Risk Assessment
39
+
40
+ | Risk | Probability | Impact | Mitigation |
41
+ |------|------------|--------|------------|
42
+ | [risk] | High/Med/Low | High/Med/Low | [strategy] |
43
+
44
+ ---
45
+
46
+ **IMPORTANT**: After completing this plan, present it to the user and wait for explicit approval before proceeding to implementation. Do NOT auto-execute.
@@ -203,31 +203,35 @@ export async function ensurePluginEnabled(claudeDir = join(homedir(), '.claude')
203
203
  */
204
204
  export async function ensureMCPConfigured(installPath, mode, claudeDir = join(homedir(), '.claude')) {
205
205
  const mcpSettingsFile = join(claudeDir, 'mcp_settings.json');
206
+
206
207
  // Read existing config or create new
207
208
  let config = readJSONFile(mcpSettingsFile) || { mcpServers: {} };
208
209
  if (!config.mcpServers) {
209
210
  config.mcpServers = {};
210
211
  }
212
+
211
213
  // Configure memesh entry based on mode
212
214
  if (mode === 'global') {
215
+ // Global install: use npx (always uses latest published version)
213
216
  config.mcpServers.memesh = {
214
217
  command: 'npx',
215
218
  args: ['-y', '@pcircle/memesh'],
216
219
  env: { NODE_ENV: 'production' }
217
220
  };
218
- }
219
- else {
221
+ } else {
222
+ // Local dev: use node + absolute path (for testing)
220
223
  const serverPath = join(installPath, 'dist', 'mcp', 'server-bootstrap.js');
221
224
  config.mcpServers.memesh = {
222
225
  command: 'node',
223
- args: [serverPath],
224
- env: { NODE_ENV: 'production' }
226
+ args: [serverPath]
225
227
  };
226
228
  }
229
+
227
230
  // Remove legacy claude-code-buddy entry if exists
228
231
  if (config.mcpServers['claude-code-buddy']) {
229
232
  delete config.mcpServers['claude-code-buddy'];
230
233
  }
234
+
231
235
  // Write back
232
236
  writeJSONFile(mcpSettingsFile, config);
233
237
  }
@@ -16,6 +16,7 @@
16
16
  import { fileURLToPath } from 'url';
17
17
  import { dirname, join } from 'path';
18
18
  import { homedir } from 'os';
19
+ import { existsSync, mkdirSync, readdirSync, readFileSync, writeFileSync, statSync } from 'fs';
19
20
  import chalk from 'chalk';
20
21
  import boxen from 'boxen';
21
22
 
@@ -34,6 +35,81 @@ import {
34
35
  detectAndFixLegacyInstall
35
36
  } from './postinstall-lib.js';
36
37
 
38
+ // ============================================================================
39
+ // Bundled Skills Installation
40
+ // ============================================================================
41
+
42
+ /**
43
+ * Install bundled skills to ~/.claude/skills/sa:<name>/
44
+ * Skills are shipped in scripts/skills/<name>/SKILL.md
45
+ * Only installs if skill doesn't exist or bundled version is newer.
46
+ *
47
+ * @param {string} claudeDir - Path to ~/.claude
48
+ * @returns {{ installed: string[], skipped: string[], errors: string[] }}
49
+ */
50
+ function installBundledSkills(claudeDir) {
51
+ const result = { installed: [], skipped: [], errors: [] };
52
+ const bundledDir = join(__dirname, 'skills');
53
+ const skillsDir = join(claudeDir, 'skills');
54
+
55
+ if (!existsSync(bundledDir)) {
56
+ return result;
57
+ }
58
+
59
+ // Ensure skills directory exists
60
+ mkdirSync(skillsDir, { recursive: true });
61
+
62
+ // Read all bundled skills
63
+ let entries;
64
+ try {
65
+ entries = readdirSync(bundledDir, { withFileTypes: true });
66
+ } catch {
67
+ return result;
68
+ }
69
+
70
+ for (const entry of entries) {
71
+ if (!entry.isDirectory()) continue;
72
+
73
+ const skillName = entry.name;
74
+ const prefixedName = `sa:${skillName}`;
75
+ const sourceFile = join(bundledDir, skillName, 'SKILL.md');
76
+ const targetDir = join(skillsDir, prefixedName);
77
+ const targetFile = join(targetDir, 'SKILL.md');
78
+
79
+ try {
80
+ // Read source first — if it doesn't exist, skip (no TOCTOU with existsSync)
81
+ let content;
82
+ let sourceStat;
83
+ try {
84
+ content = readFileSync(sourceFile, 'utf-8');
85
+ sourceStat = statSync(sourceFile);
86
+ } catch {
87
+ continue; // source doesn't exist, skip
88
+ }
89
+
90
+ // Skip if target exists and is newer than source
91
+ try {
92
+ const targetStat = statSync(targetFile);
93
+ if (targetStat.mtimeMs >= sourceStat.mtimeMs) {
94
+ result.skipped.push(skillName);
95
+ continue;
96
+ }
97
+ } catch {
98
+ // target doesn't exist yet, proceed to install
99
+ }
100
+
101
+ // Install: create dir + write SKILL.md
102
+ mkdirSync(targetDir, { recursive: true });
103
+ writeFileSync(targetFile, content, 'utf-8');
104
+ result.installed.push(skillName);
105
+ } catch (error) {
106
+ result.errors.push(`${skillName}: ${error.message}`);
107
+ }
108
+ }
109
+
110
+ return result;
111
+ }
112
+
37
113
  // ============================================================================
38
114
  // Main Installation Flow
39
115
  // ============================================================================
@@ -97,13 +173,21 @@ async function main() {
97
173
  }
98
174
 
99
175
  // Step 5: MCP Configuration
100
- try {
101
- await ensureMCPConfigured(installPath, mode, claudeDir);
102
- results.mcpConfigured = true;
103
- console.log(chalk.green(' MCP configured'));
104
- } catch (error) {
105
- results.errors.push(`MCP: ${error.message}`);
106
- console.log(chalk.yellow(` ⚠️ MCP configuration failed (non-fatal)`));
176
+ // IMPORTANT: Skip MCP config for local dev to prevent path pollution
177
+ // (see v2.9.0 Issue 2: Local Development Path Pollution)
178
+ if (mode === 'local') {
179
+ console.log(chalk.yellow(' ⚠️ Skipping MCP configuration (local development mode)'));
180
+ console.log(chalk.gray(' This prevents writing local dev paths to ~/.claude/mcp_settings.json'));
181
+ results.mcpConfigured = false;
182
+ } else {
183
+ try {
184
+ await ensureMCPConfigured(installPath, mode, claudeDir);
185
+ results.mcpConfigured = true;
186
+ console.log(chalk.green(' ✅ MCP configured'));
187
+ } catch (error) {
188
+ results.errors.push(`MCP: ${error.message}`);
189
+ console.log(chalk.yellow(` ⚠️ MCP configuration failed (non-fatal)`));
190
+ }
107
191
  }
108
192
 
109
193
  // Step 6: Legacy Installation Fix
@@ -120,6 +204,25 @@ async function main() {
120
204
  console.log(chalk.dim(' ℹ️ Legacy check skipped'));
121
205
  }
122
206
 
207
+ // Step 7: Install Bundled Skills
208
+ try {
209
+ const skillResult = installBundledSkills(claudeDir);
210
+ results.skillsInstalled = skillResult.installed;
211
+ results.skillsSkipped = skillResult.skipped;
212
+
213
+ if (skillResult.installed.length > 0) {
214
+ console.log(chalk.green(` ✅ Skills installed: ${skillResult.installed.join(', ')}`));
215
+ } else if (skillResult.skipped.length > 0) {
216
+ console.log(chalk.dim(` ℹ️ Skills up to date (${skillResult.skipped.length} already installed)`));
217
+ }
218
+
219
+ if (skillResult.errors.length > 0) {
220
+ results.errors.push(`Skills: ${skillResult.errors.join('; ')}`);
221
+ }
222
+ } catch (error) {
223
+ console.log(chalk.dim(' ℹ️ Skills installation skipped'));
224
+ }
225
+
123
226
  } catch (error) {
124
227
  console.error(chalk.red('\n❌ Installation failed:'), error.message);
125
228
  console.error(chalk.yellow('\n💡 You can configure manually (see instructions below)\n'));
@@ -0,0 +1,276 @@
1
+ ---
2
+ name: comprehensive-code-review
3
+ description: |
4
+ Complete code review framework with mandatory tool-verified checks and anti-hallucination enforcement.
5
+ Use when: performing code reviews, reviewing PRs, checking code quality before merge.
6
+ Keywords: code review, review code, 代碼審查, PR review, pull request, 檢查代碼.
7
+ Auto-triggers on: "code review", "review the code", "run code review".
8
+ ---
9
+
10
+ # Comprehensive Code Review Framework v4.0
11
+
12
+ **Philosophy**: 不信任自己。用工具證明一切。沒有 evidence 的 check 等於沒做。
13
+
14
+ **v4.0 vs v3.0**: v3.0 說了「應該檢查什麼」但沒強制怎麼做。v4.0 的每一步都是**必須用工具執行並產出 evidence** 的指令,不是建議。
15
+
16
+ ---
17
+
18
+ ## 🔴 Step 0: Ripple Map(強制首步,不可跳過)
19
+
20
+ **PURPOSE**: 在做任何 review 之前,先找出所有「改了 A 就必須改 B」的連鎖反應。
21
+
22
+ **這是 v4.0 最重要的改變。** 之前的 review 只看「已改的檔案寫得對不對」,從不問「還有哪些檔案該改但沒改」。
23
+
24
+ ### 執行方式(必須用工具)
25
+
26
+ ```
27
+ FOR EACH modified file:
28
+ 1. 找出這個文件中被新增/修改的 export(type, function, constant)
29
+ 2. Grep 整個 codebase 找出所有 import 這些 export 的文件
30
+ 3. 這些文件是否也在本次修改範圍內?
31
+ - 是 → 後續 review 時檢查一致性
32
+ - 否 → 🔴 SUSPECT: 可能遺漏。立即 Read 該文件確認是否需要更新
33
+ ```
34
+
35
+ ### 必須執行的工具命令
36
+
37
+ ```bash
38
+ # 1. 列出所有修改的文件
39
+ git diff --name-only HEAD # 或 review 指定的文件列表
40
+
41
+ # 2. 對每個被修改的 interface/type/function,搜尋所有引用
42
+ Grep: pattern="DeliverParams" # 每個被修改的型別名
43
+ Grep: pattern="deliverOrder" # 每個被修改的函數名
44
+ Grep: pattern="delivery_result" # 每個被新增的 DB column
45
+
46
+ # 3. 比對:引用這些東西的文件 vs 本次修改的文件
47
+ # 差集 = 可能遺漏的文件
48
+ ```
49
+
50
+ ### Ripple Map Output 格式(必須產出)
51
+
52
+ ```
53
+ ## Ripple Map
54
+
55
+ | Changed Symbol | Files That Reference It | In Scope? | Verified? |
56
+ |----------------|------------------------|-----------|-----------|
57
+ | `DeliverParams` | sdk/types.ts, sdk/client.ts, deliver/route.ts | ✅/❌ | Read 確認 |
58
+ | `deliverOrder()` | client.ts, sdk/client.ts, example/index.ts | ✅/❌ | Read 確認 |
59
+ | `delivery_result` | supabase.ts, api-utils.ts, deliver/route.ts | ✅/❌ | Read 確認 |
60
+
61
+ 🔴 Unsynchronized: [列出所有引用但未修改的文件]
62
+ ```
63
+
64
+ **如果 Ripple Map 發現 unsynchronized 文件,直接列為 CRITICAL issue,不需要進入後續維度。**
65
+
66
+ ---
67
+
68
+ ## Step 1: Scope Analysis
69
+
70
+ 確認審查範圍:
71
+ - 哪些文件被修改?(用 git diff 或文件列表,不可憑記憶)
72
+ - 變更的目的是什麼?
73
+ - **有幾個 package/module 邊界被跨越?**
74
+ - **Ripple Map 發現多少個 unsynchronized 文件?**
75
+
76
+ ---
77
+
78
+ ## Step 2: Mandatory Verification Dimensions
79
+
80
+ **12 個維度。Dim 11 和 12 是最高優先級,必須用 Explore subagent 或多個 Read/Grep 並行執行。**
81
+
82
+ **每個 check 必須產出 evidence。格式:**
83
+ ```
84
+ [DIM-11a] ✅ PASS — import { validateOutputSchema } from '@/lib/api-utils'
85
+ Evidence: Read api-utils.ts → line 118: export function validateOutputSchema(...)
86
+
87
+ [DIM-12d] 🔴 FAIL — SDK DeliverParams missing deliveryResult
88
+ Evidence: Read packages/sdk/src/types.ts:177-180 → only has deliveryHash, deliveryMetadata
89
+ ```
90
+
91
+ **沒有 evidence 的 ✅ 等於 ❌。**
92
+
93
+ ---
94
+
95
+ ### 🔴 Dim 11: Reality Check(必須用 Explore subagent 執行)
96
+
97
+ **IMPORTANT: 這個維度必須 dispatch 至少一個 Explore subagent 來獨立驗證。不可自己看一眼就說 PASS。**
98
+
99
+ **Subagent prompt 模板**:
100
+ ```
101
+ In [project_path], verify the following for files [list]:
102
+ 1. Every import resolves to a real export (read the source file to confirm)
103
+ 2. Every method call references a method that exists in the target class
104
+ 3. Every DB column referenced exists in migrations
105
+ 4. Search for TODO/FIXME/STUB in all modified files
106
+ 5. For every new function: grep for callers — is it actually called from somewhere?
107
+ Report exact findings with file:line evidence for each.
108
+ ```
109
+
110
+ **11a-11f 檢查項目**(subagent 必須全部執行):
111
+
112
+ | Check | Tool | What to verify |
113
+ |-------|------|----------------|
114
+ | 11a. Import/Export | Read 被 import 的文件 | export 真的存在 |
115
+ | 11b. Method calls | Read 被呼叫的 class | method 真的定義了 |
116
+ | 11c. DB schema | Read migration files | column 在 migration 裡 |
117
+ | 11d. Example code | Read constructor + method 簽名 | 參數和回傳值匹配 |
118
+ | 11e. Stubs | Grep TODO/FIXME/STUB/throw.*not.impl | 無假完成 |
119
+ | 11f. Dead wire | Grep function name across codebase | 有 caller 存在 |
120
+
121
+ ---
122
+
123
+ ### 🔴 Dim 12: Cross-boundary Sync(必須用 Explore subagent 執行)
124
+
125
+ **IMPORTANT: Monorepo 或多 package 專案時,此維度必須 dispatch 獨立 subagent。**
126
+
127
+ **Subagent prompt 模板**:
128
+ ```
129
+ In [project_path], check cross-boundary type synchronization:
130
+ 1. Compare [platform types file] with [SDK types file] — list every interface
131
+ that exists in both. For each, compare field-by-field.
132
+ 2. Compare [platform client file] with [SDK client file] — list every method
133
+ that exists in both. For each, compare signature.
134
+ 3. For every API route that accepts a body: read the route handler AND the SDK
135
+ method that calls it. Do the field names match?
136
+ 4. Trace: migration column → DbType → mapResponse → API type → SDK type.
137
+ Report any broken links.
138
+ Report ALL mismatches with exact file:line evidence.
139
+ ```
140
+
141
+ **12a-12d 檢查項目**(subagent 必須全部執行):
142
+
143
+ | Check | What | How |
144
+ |-------|------|-----|
145
+ | 12a. Type parity | 同名 interface 欄位一致 | Read 兩個 type 文件,逐欄比對 |
146
+ | 12b. Client parity | 同名 method 簽名一致 | Read 兩個 client 文件,逐方法比對 |
147
+ | 12c. Route↔SDK match | Route body 欄位 = SDK params 欄位 | Read route + SDK method |
148
+ | 12d. Full chain | migration→DbType→mapper→ApiType→SdkType | 追蹤新增欄位通過每一層 |
149
+
150
+ ---
151
+
152
+ ### Dim 1-10: Standard Quality Dimensions
153
+
154
+ #### 1. 🔒 Security
155
+ - Injection attacks (SQL, Command, Path traversal)
156
+ - Sensitive data exposure
157
+ - Auth/AuthZ gaps, hardcoded secrets
158
+
159
+ #### 2. 🔄 Concurrency
160
+ - Race conditions (TOCTOU), deadlocks
161
+ - Atomic operation needs
162
+
163
+ #### 3. 💾 Resource Management
164
+ - Resource leaks, unbounded buffers
165
+ - Timer/listener cleanup
166
+
167
+ #### 4. ❌ Error Handling
168
+ - Uncaught exceptions, empty catch
169
+ - Unhandled Promise rejections
170
+
171
+ #### 5. 📊 Edge Cases
172
+ - Empty/null/NaN/zero/MAX values
173
+ - First run / cold start
174
+
175
+ #### 6. ✅ Input Validation
176
+ - Type, range, format, length validation
177
+
178
+ #### 7. ⚡ Performance
179
+ - O(n²), blocking I/O, N+1 queries
180
+
181
+ #### 8. 📝 Code Quality
182
+ - Dead code, magic numbers, naming
183
+
184
+ #### 9. 📖 Documentation
185
+ - API docs, outdated comments
186
+
187
+ #### 10. 🧪 Test Coverage
188
+ - Happy/error/edge paths tested
189
+ - New functions have corresponding tests
190
+
191
+ ---
192
+
193
+ ## Step 3: Issue Classification
194
+
195
+ | Level | Symbol | Criteria | Action |
196
+ |-------|--------|----------|--------|
197
+ | CRITICAL | 🔴 | Security, crash, **hallucination, broken integration, missing sync** | Fix immediately |
198
+ | MAJOR | 🟠 | Bugs, leaks, performance, type mismatch | Fix before merge |
199
+ | MINOR | 🟡 | Quality, maintenance | Document |
200
+
201
+ **鐵則**: Dim 11/12 的 issue 最低 MAJOR,大部分 CRITICAL。
202
+
203
+ ---
204
+
205
+ ## Step 4: Fix Dispatch
206
+
207
+ ```
208
+ Dispatch subagents in parallel (max 6):
209
+ - Group by file or logical module
210
+ - Each subagent: fix root cause → run related tests → validate no regression
211
+ - After all complete: run full test suite
212
+ - After full suite: re-run Ripple Map to verify no new gaps
213
+ ```
214
+
215
+ ---
216
+
217
+ ## Step 5: Final Verification Gate
218
+
219
+ **在宣稱 review 完成前,必須全部通過:**
220
+
221
+ ```
222
+ □ Ripple Map 無 unsynchronized 文件
223
+ □ Dim 11 所有 check 有 evidence 且 PASS
224
+ □ Dim 12 所有 check 有 evidence 且 PASS
225
+ □ 所有 CRITICAL issues 已修復
226
+ □ 所有 MAJOR issues 已修復
227
+ □ MINOR issues 已記錄
228
+ □ tsc --noEmit pass(主專案)
229
+ □ tsc --noEmit pass(每個子 package 獨立跑)
230
+ □ 全部測試 pass
231
+ □ Build pass
232
+ ```
233
+
234
+ **如果任何 check 缺少 evidence,整個 review 標記為 INCOMPLETE。**
235
+
236
+ ---
237
+
238
+ ## AI 幻想模式速查表
239
+
240
+ | # | Pattern | 怎麼偵測 | 工具 |
241
+ |---|---------|---------|------|
242
+ | 1 | **Ghost Method** — 呼叫不存在的方法 | Read class file, search method | Read |
243
+ | 2 | **Phantom Import** — import 不存在的 export | Read source file | Read/Grep |
244
+ | 3 | **Schema Drift** — 讀寫不存在的 DB column | Read all migrations | Read |
245
+ | 4 | **Type Island** — 只改一邊的 type | Ripple Map 自動抓 | Grep |
246
+ | 5 | **Dead Wire** — 定義了但沒被呼叫 | Grep function name | Grep |
247
+ | 6 | **Stub Disguise** — TODO/return {} 偽裝完成 | Grep TODO/FIXME/STUB | Grep |
248
+ | 7 | **Constructor Lie** — 參數不匹配 | Read constructor | Read |
249
+ | 8 | **Mock Leak** — test mock 了但 prod 沒實作 | Check real implementation | Read |
250
+ | 9 | **One-side Fix** — 改了 A 忘改 B | Ripple Map 自動抓 | Grep |
251
+ | 10 | **Verify Theater** — tsc pass 但只跑主 package | 獨立跑每個子 package tsc | Bash |
252
+
253
+ ---
254
+
255
+ ## 何時執行
256
+
257
+ | 觸發條件 | 執行範圍 |
258
+ |---------|---------|
259
+ | 新功能 > 100 lines | Full review (all 12 dims) |
260
+ | API/DB schema 變更 | Full review + 強制 Dim 11/12 |
261
+ | 跨 package 變更 | Full review + 強制 Dim 12 |
262
+ | Bug fix < 50 lines | Quick review (Dim 11 + 改動相關維度) |
263
+ | 任何 monorepo 變更 | 至少 Ripple Map + Dim 12 |
264
+
265
+ ---
266
+
267
+ **Version**: 4.0
268
+ **Last Updated**: 2026-02-22
269
+ **Changelog**:
270
+ - v4.0: 新增 Step 0 Ripple Map — 強制發現遺漏的連鎖修改
271
+ - v4.0: Dim 11/12 必須 dispatch Explore subagent 獨立驗證
272
+ - v4.0: 每個 check 必須產出 evidence,無 evidence = 未完成
273
+ - v4.0: 新增 Verify Theater pattern(tsc pass 但只跑主 package)
274
+ - v4.0: 新增 Final Verification Gate — 子 package 必須獨立跑 tsc
275
+ - v3.0: Added Dim 11/12, hallucination pattern table
276
+ - v2.0: Initial 10-dimension framework