@vibecodetown/mcp-server 2.1.0

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 (172) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +269 -0
  3. package/build/auth/gate.js +225 -0
  4. package/build/auth/index.js +55 -0
  5. package/build/auth/public_key.js +27 -0
  6. package/build/auth/token_cache.js +122 -0
  7. package/build/auth/token_verifier.js +103 -0
  8. package/build/bootstrap/doctor.js +115 -0
  9. package/build/bootstrap/installer.js +673 -0
  10. package/build/bootstrap/lock.js +37 -0
  11. package/build/bootstrap/platform.js +26 -0
  12. package/build/bootstrap/registry.js +37 -0
  13. package/build/cache/index.js +147 -0
  14. package/build/cli.js +101 -0
  15. package/build/contracts.js +22 -0
  16. package/build/control_plane/gate.js +161 -0
  17. package/build/control_plane/index.js +6 -0
  18. package/build/dx/activity.js +139 -0
  19. package/build/engine.js +106 -0
  20. package/build/errors.js +171 -0
  21. package/build/generated/activate_input.js +2 -0
  22. package/build/generated/activate_output.js +57 -0
  23. package/build/generated/advisory_review_input.js +2 -0
  24. package/build/generated/advisory_review_output.js +35 -0
  25. package/build/generated/auth_token_file.js +2 -0
  26. package/build/generated/briefing_input.js +2 -0
  27. package/build/generated/briefing_output.js +2 -0
  28. package/build/generated/clinic_bridge_file.js +13 -0
  29. package/build/generated/contracts_bundle_info.js +5 -0
  30. package/build/generated/create_work_order_input.js +2 -0
  31. package/build/generated/create_work_order_output.js +2 -0
  32. package/build/generated/current_work_order_file.js +2 -0
  33. package/build/generated/doctor_input.js +2 -0
  34. package/build/generated/doctor_output.js +24 -0
  35. package/build/generated/execution_result.js +2 -0
  36. package/build/generated/execution_task.js +2 -0
  37. package/build/generated/export_output_input.js +2 -0
  38. package/build/generated/export_output_output.js +2 -0
  39. package/build/generated/finalize_work_input.js +2 -0
  40. package/build/generated/finalize_work_output.js +2 -0
  41. package/build/generated/gate_input.js +2 -0
  42. package/build/generated/gate_output.js +2 -0
  43. package/build/generated/gate_result_v1.js +2 -0
  44. package/build/generated/get_decision_input.js +2 -0
  45. package/build/generated/get_decision_output.js +13 -0
  46. package/build/generated/handoff_to_clinic.js +2 -0
  47. package/build/generated/index.js +75 -0
  48. package/build/generated/inspect_code_input.js +2 -0
  49. package/build/generated/inspect_code_output.js +13 -0
  50. package/build/generated/memory_retrieve_output.js +2 -0
  51. package/build/generated/memory_state_file.js +2 -0
  52. package/build/generated/memory_status_input.js +2 -0
  53. package/build/generated/memory_status_output.js +13 -0
  54. package/build/generated/memory_sync_input.js +2 -0
  55. package/build/generated/memory_sync_output.js +13 -0
  56. package/build/generated/plugin_result.js +2 -0
  57. package/build/generated/react_perf_check_patterns_input.js +2 -0
  58. package/build/generated/react_perf_check_patterns_output.js +2 -0
  59. package/build/generated/react_perf_generate_report_input.js +2 -0
  60. package/build/generated/react_perf_generate_report_output.js +2 -0
  61. package/build/generated/repair_plan_input.js +2 -0
  62. package/build/generated/repair_plan_output.js +2 -0
  63. package/build/generated/run_app_input.js +2 -0
  64. package/build/generated/run_app_output.js +2 -0
  65. package/build/generated/run_state_file.js +13 -0
  66. package/build/generated/scaffold_input.js +2 -0
  67. package/build/generated/scaffold_output.js +2 -0
  68. package/build/generated/search_oss_input.js +2 -0
  69. package/build/generated/search_oss_output.js +2 -0
  70. package/build/generated/selection_validation_result.js +2 -0
  71. package/build/generated/signal_agent_input.js +2 -0
  72. package/build/generated/spec_high_ask_queue_items_file.js +2 -0
  73. package/build/generated/spec_high_clinic_bridge_output.js +2 -0
  74. package/build/generated/spec_high_decision_draft_output.js +2 -0
  75. package/build/generated/spec_high_validate_output.js +2 -0
  76. package/build/generated/status_input.js +2 -0
  77. package/build/generated/status_output.js +2 -0
  78. package/build/generated/submit_decision_input.js +2 -0
  79. package/build/generated/submit_decision_output.js +2 -0
  80. package/build/generated/tool_error_output.js +2 -0
  81. package/build/generated/undo_last_task_input.js +2 -0
  82. package/build/generated/undo_last_task_output.js +2 -0
  83. package/build/generated/update_input.js +2 -0
  84. package/build/generated/update_output.js +2 -0
  85. package/build/generated/vibe_pm_inspection_result.js +2 -0
  86. package/build/generated/vibe_pm_report_markdown.js +2 -0
  87. package/build/generated/vibe_pm_verdict.js +2 -0
  88. package/build/generated/vibe_repo_config.js +2 -0
  89. package/build/generated/vibecoding_helper_answer_output.js +2 -0
  90. package/build/generated/vibecoding_helper_one_loop_selection_output.js +2 -0
  91. package/build/generated/vibecoding_helper_show_ask_queue_output.js +2 -0
  92. package/build/generated/work_order_v1.js +2 -0
  93. package/build/generated/zoekt_evidence_input.js +2 -0
  94. package/build/generated/zoekt_evidence_output.js +2 -0
  95. package/build/index.js +111 -0
  96. package/build/legacy_alias.js +65 -0
  97. package/build/local-mode/bash.js +61 -0
  98. package/build/local-mode/config.js +171 -0
  99. package/build/local-mode/git.js +33 -0
  100. package/build/local-mode/init.js +110 -0
  101. package/build/local-mode/paths.js +24 -0
  102. package/build/local-mode/templates.js +856 -0
  103. package/build/local-mode/work-order.js +41 -0
  104. package/build/resources/index.js +246 -0
  105. package/build/security/input-validator.js +119 -0
  106. package/build/security/path-policy.js +289 -0
  107. package/build/security/sandbox.js +228 -0
  108. package/build/tools/react_perf/check_patterns.js +172 -0
  109. package/build/tools/react_perf/generate_report.js +337 -0
  110. package/build/tools/react_perf/index.js +119 -0
  111. package/build/tools/react_perf/rules/advanced.js +325 -0
  112. package/build/tools/react_perf/rules/async.js +104 -0
  113. package/build/tools/react_perf/rules/bundle.js +101 -0
  114. package/build/tools/react_perf/rules/client.js +186 -0
  115. package/build/tools/react_perf/rules/index.js +74 -0
  116. package/build/tools/react_perf/rules/js.js +148 -0
  117. package/build/tools/react_perf/rules/rendering.js +166 -0
  118. package/build/tools/react_perf/rules/rerender.js +161 -0
  119. package/build/tools/react_perf/rules/server.js +141 -0
  120. package/build/tools/react_perf/types.js +127 -0
  121. package/build/tools/vibe_pm/activate.js +102 -0
  122. package/build/tools/vibe_pm/advisory_review.js +77 -0
  123. package/build/tools/vibe_pm/briefing.js +178 -0
  124. package/build/tools/vibe_pm/context.js +439 -0
  125. package/build/tools/vibe_pm/create_work_order.js +271 -0
  126. package/build/tools/vibe_pm/doc_status_gate.js +370 -0
  127. package/build/tools/vibe_pm/doctor.js +262 -0
  128. package/build/tools/vibe_pm/entity_gate/preflight.js +78 -0
  129. package/build/tools/vibe_pm/export_output.js +135 -0
  130. package/build/tools/vibe_pm/finalize_work.js +393 -0
  131. package/build/tools/vibe_pm/gate.js +33 -0
  132. package/build/tools/vibe_pm/get_decision.js +281 -0
  133. package/build/tools/vibe_pm/index.js +593 -0
  134. package/build/tools/vibe_pm/inspect_code.js +828 -0
  135. package/build/tools/vibe_pm/intent/generator.js +294 -0
  136. package/build/tools/vibe_pm/intent/index.js +5 -0
  137. package/build/tools/vibe_pm/intent/prompt_density.js +227 -0
  138. package/build/tools/vibe_pm/intent/types.js +70 -0
  139. package/build/tools/vibe_pm/intent/verifier.js +237 -0
  140. package/build/tools/vibe_pm/kce/doc_usage.js +51 -0
  141. package/build/tools/vibe_pm/kce/on_finalize.js +11 -0
  142. package/build/tools/vibe_pm/kce/preflight.js +232 -0
  143. package/build/tools/vibe_pm/local_memory.js +26 -0
  144. package/build/tools/vibe_pm/memory_status.js +82 -0
  145. package/build/tools/vibe_pm/memory_sync.js +134 -0
  146. package/build/tools/vibe_pm/modules/decision_snapshot.js +29 -0
  147. package/build/tools/vibe_pm/modules/ensure.js +100 -0
  148. package/build/tools/vibe_pm/modules/fingerprint.js +30 -0
  149. package/build/tools/vibe_pm/modules/fix_dependencies.js +394 -0
  150. package/build/tools/vibe_pm/modules/planning_v1.js +110 -0
  151. package/build/tools/vibe_pm/modules/repo_context.js +56 -0
  152. package/build/tools/vibe_pm/modules/research_v1.js +114 -0
  153. package/build/tools/vibe_pm/modules/skills_v1.js +100 -0
  154. package/build/tools/vibe_pm/pm_language.js +222 -0
  155. package/build/tools/vibe_pm/repair_plan.js +199 -0
  156. package/build/tools/vibe_pm/run_app.js +597 -0
  157. package/build/tools/vibe_pm/run_app_podman.js +64 -0
  158. package/build/tools/vibe_pm/scaffold.js +550 -0
  159. package/build/tools/vibe_pm/search_oss.js +124 -0
  160. package/build/tools/vibe_pm/status.js +153 -0
  161. package/build/tools/vibe_pm/submit_decision.js +87 -0
  162. package/build/tools/vibe_pm/system_design/issue_mapping.js +47 -0
  163. package/build/tools/vibe_pm/system_design/rulebook.js +112 -0
  164. package/build/tools/vibe_pm/system_design/semgrep.js +132 -0
  165. package/build/tools/vibe_pm/types.js +229 -0
  166. package/build/tools/vibe_pm/undo_last_task.js +163 -0
  167. package/build/tools/vibe_pm/update.js +146 -0
  168. package/build/tools/vibe_pm/zoekt_evidence.js +96 -0
  169. package/build/tools.js +269 -0
  170. package/build/version-check.js +239 -0
  171. package/build/vibe-cli.js +631 -0
  172. package/package.json +76 -0
@@ -0,0 +1,161 @@
1
+ // adapters/mcp-ts/src/tools/react_perf/rules/rerender.ts
2
+ // Re-render Anti-patterns (Inline Props, Missing Memo, Context)
3
+ /**
4
+ * Rerender rules detect patterns that cause unnecessary re-renders
5
+ * including inline objects/functions and missing memoization.
6
+ */
7
+ export const RERENDER_RULES = [
8
+ {
9
+ id: "rerender-inline-object",
10
+ category: "rerender",
11
+ impact: "MEDIUM-HIGH",
12
+ // Detects: inline object literal as prop (style={{}} excluded by antiPattern)
13
+ pattern: /<[A-Z]\w+[^>]*\s(?:options|config|data|params|settings|initialValue)=\{\{/,
14
+ message: "Inline object prop creates new reference on every render",
15
+ suggestion: "Extract object to useMemo or move outside component",
16
+ fileFilter: /\.(tsx?|jsx?)$/,
17
+ examples: {
18
+ bad: `function Parent() {
19
+ return <Chart options={{ responsive: true, scales: {...} }} />;
20
+ }`,
21
+ good: `function Parent() {
22
+ const chartOptions = useMemo(() => ({
23
+ responsive: true,
24
+ scales: {...}
25
+ }), []);
26
+
27
+ return <Chart options={chartOptions} />;
28
+ }`
29
+ }
30
+ },
31
+ {
32
+ id: "rerender-inline-function",
33
+ category: "rerender",
34
+ impact: "MEDIUM-HIGH",
35
+ // Detects: inline arrow function as prop (excluding common safe patterns)
36
+ pattern: /<[A-Z]\w+[^>]*\s(?:on[A-Z]\w+|handler|callback|render\w*)=\{\s*\([^)]*\)\s*=>/,
37
+ antiPattern: /useCallback|memo\(/,
38
+ message: "Inline function prop creates new reference on every render",
39
+ suggestion: "Wrap with useCallback if passed to memoized child",
40
+ fileFilter: /\.(tsx?|jsx?)$/,
41
+ examples: {
42
+ bad: `function Parent() {
43
+ return <MemoizedList onItemClick={(id) => handleClick(id)} />;
44
+ }`,
45
+ good: `function Parent() {
46
+ const handleItemClick = useCallback((id) => {
47
+ handleClick(id);
48
+ }, [handleClick]);
49
+
50
+ return <MemoizedList onItemClick={handleItemClick} />;
51
+ }`
52
+ }
53
+ },
54
+ {
55
+ id: "rerender-context-value",
56
+ category: "rerender",
57
+ impact: "CRITICAL",
58
+ // Detects: Context Provider with inline value object
59
+ pattern: /<\w+Context\.Provider\s+value=\{\{/,
60
+ message: "Inline context value causes all consumers to re-render",
61
+ suggestion: "Memoize context value or split into separate contexts",
62
+ fileFilter: /\.(tsx?|jsx?)$/,
63
+ examples: {
64
+ bad: `function AppProvider({ children }) {
65
+ const [user, setUser] = useState(null);
66
+
67
+ return (
68
+ <AppContext.Provider value={{ user, setUser }}>
69
+ {children}
70
+ </AppContext.Provider>
71
+ );
72
+ }`,
73
+ good: `function AppProvider({ children }) {
74
+ const [user, setUser] = useState(null);
75
+
76
+ const value = useMemo(() => ({ user, setUser }), [user]);
77
+
78
+ return (
79
+ <AppContext.Provider value={value}>
80
+ {children}
81
+ </AppContext.Provider>
82
+ );
83
+ }
84
+
85
+ // Or split contexts
86
+ <UserContext.Provider value={user}>
87
+ <UserActionsContext.Provider value={setUser}>
88
+ {children}
89
+ </UserActionsContext.Provider>
90
+ </UserContext.Provider>`
91
+ }
92
+ },
93
+ {
94
+ id: "rerender-missing-memo",
95
+ category: "rerender",
96
+ impact: "LOW-MEDIUM",
97
+ // Detects: Component receiving many props without memo
98
+ pattern: /(?:export\s+)?(?:function|const)\s+([A-Z]\w+)\s*[=:]\s*(?:function\s*)?\(\s*\{[^}]{50,}\}/,
99
+ antiPattern: /memo\(|React\.memo/,
100
+ message: "Component with many props may benefit from React.memo",
101
+ suggestion: "Wrap with React.memo if parent re-renders frequently with same props",
102
+ fileFilter: /\.(tsx?|jsx?)$/,
103
+ examples: {
104
+ bad: `function UserCard({ id, name, email, avatar, role, lastActive, status }) {
105
+ return (
106
+ <div>
107
+ <img src={avatar} />
108
+ <h3>{name}</h3>
109
+ <p>{email}</p>
110
+ {/* More rendering... */}
111
+ </div>
112
+ );
113
+ }`,
114
+ good: `const UserCard = memo(function UserCard({
115
+ id, name, email, avatar, role, lastActive, status
116
+ }) {
117
+ return (
118
+ <div>
119
+ <img src={avatar} />
120
+ <h3>{name}</h3>
121
+ <p>{email}</p>
122
+ </div>
123
+ );
124
+ });`
125
+ }
126
+ },
127
+ {
128
+ id: "rerender-usestate-object",
129
+ category: "rerender",
130
+ impact: "LOW-MEDIUM",
131
+ // Detects: useState with complex object that could be split
132
+ pattern: /useState\s*<?\s*\{[^}]*\w+\s*:\s*[^}]*\w+\s*:\s*[^}]*\}>?\s*\(\s*\{/,
133
+ message: "useState with object may cause unnecessary re-renders",
134
+ suggestion: "Consider splitting into multiple useState or using useReducer",
135
+ fileFilter: /\.(tsx?|jsx?)$/,
136
+ examples: {
137
+ bad: `function Form() {
138
+ const [state, setState] = useState({
139
+ name: '',
140
+ email: '',
141
+ phone: '',
142
+ address: ''
143
+ });
144
+
145
+ // Updating one field re-renders everything
146
+ setState({ ...state, name: newName });
147
+ }`,
148
+ good: `function Form() {
149
+ const [name, setName] = useState('');
150
+ const [email, setEmail] = useState('');
151
+ const [phone, setPhone] = useState('');
152
+ const [address, setAddress] = useState('');
153
+
154
+ // Or use useReducer for complex state
155
+ }
156
+
157
+ // Or with useReducer
158
+ const [state, dispatch] = useReducer(formReducer, initialState);`
159
+ }
160
+ }
161
+ ];
@@ -0,0 +1,141 @@
1
+ // adapters/mcp-ts/src/tools/react_perf/rules/server.ts
2
+ // Server Action Anti-patterns (Auth, Validation, Security)
3
+ /**
4
+ * Server rules detect common mistakes in Next.js Server Actions
5
+ * and Server Components that can cause security or performance issues.
6
+ *
7
+ * Based on Vercel agent-skills react-best-practices
8
+ */
9
+ export const SERVER_RULES = [
10
+ {
11
+ id: "server-action-no-auth",
12
+ category: "server",
13
+ impact: "CRITICAL",
14
+ // Detects: 'use server' without auth check nearby
15
+ pattern: /['"]use server['"]\s*;?\s*\n\s*(?:export\s+)?(?:async\s+)?function\s+\w+/,
16
+ antiPattern: /(?:auth|session|getUser|currentUser|requireAuth|withAuth)/i,
17
+ message: "Server Action may lack authentication check",
18
+ suggestion: "Always verify user authentication at the start of Server Actions",
19
+ fileFilter: /\.(tsx?|jsx?)$/,
20
+ examples: {
21
+ bad: `'use server'
22
+ export async function deletePost(id: string) {
23
+ await db.posts.delete(id);
24
+ }`,
25
+ good: `'use server'
26
+ export async function deletePost(id: string) {
27
+ const user = await auth();
28
+ if (!user) throw new Error('Unauthorized');
29
+ await db.posts.delete(id);
30
+ }`
31
+ }
32
+ },
33
+ {
34
+ id: "server-action-no-validation",
35
+ category: "server",
36
+ impact: "HIGH",
37
+ // Detects: Server Action with direct db/API call without validation
38
+ pattern: /['"]use server['"][\s\S]{0,200}(?:db\.|prisma\.|fetch\()/,
39
+ antiPattern: /(?:z\.|zod|yup|validate|parse|schema)/i,
40
+ message: "Server Action may lack input validation",
41
+ suggestion: "Validate all inputs with Zod or similar before processing",
42
+ fileFilter: /\.(tsx?|jsx?)$/,
43
+ examples: {
44
+ bad: `'use server'
45
+ export async function updateUser(data: FormData) {
46
+ await db.users.update(data);
47
+ }`,
48
+ good: `'use server'
49
+ export async function updateUser(data: FormData) {
50
+ const validated = updateUserSchema.parse(Object.fromEntries(data));
51
+ await db.users.update(validated);
52
+ }`
53
+ }
54
+ },
55
+ {
56
+ id: "server-sensitive-in-client",
57
+ category: "server",
58
+ impact: "CRITICAL",
59
+ // Detects: 'use client' with sensitive env vars or secrets
60
+ pattern: /['"]use client['"][\s\S]{0,500}(?:process\.env\.(?!NEXT_PUBLIC)|API_KEY|SECRET|PASSWORD)/,
61
+ message: "Sensitive data may be exposed to client bundle",
62
+ suggestion: "Move sensitive logic to Server Component or Server Action",
63
+ fileFilter: /\.(tsx?|jsx?)$/,
64
+ examples: {
65
+ bad: `'use client'
66
+ const apiKey = process.env.API_KEY;`,
67
+ good: `// In Server Component or Server Action
68
+ const apiKey = process.env.API_KEY;`
69
+ }
70
+ },
71
+ {
72
+ id: "server-component-hooks",
73
+ category: "server",
74
+ impact: "HIGH",
75
+ // Detects: React hooks without 'use client'
76
+ pattern: /(?<!['"]use client['"][\s\S]{0,2000})(?:useState|useEffect|useContext|useReducer|useCallback|useMemo|useRef)\s*\(/,
77
+ antiPattern: /['"]use client['"]/,
78
+ message: "React hooks used in potential Server Component",
79
+ suggestion: "Add 'use client' directive if using React hooks, or move hooks to Client Component",
80
+ fileFilter: /\.(tsx?|jsx?)$/,
81
+ examples: {
82
+ bad: `// No 'use client' directive
83
+ export default function Page() {
84
+ const [state, setState] = useState(0);
85
+ }`,
86
+ good: `'use client'
87
+ export default function Page() {
88
+ const [state, setState] = useState(0);
89
+ }`
90
+ }
91
+ },
92
+ {
93
+ id: "server-action-try-catch",
94
+ category: "server",
95
+ impact: "MEDIUM-HIGH",
96
+ // Detects: Server Action without try-catch
97
+ pattern: /['"]use server['"]\s*;?\s*\n\s*(?:export\s+)?(?:async\s+)?function\s+\w+[^}]+\{(?![^}]*try\s*\{)/,
98
+ message: "Server Action may lack error handling",
99
+ suggestion: "Wrap Server Action logic in try-catch to handle errors gracefully",
100
+ fileFilter: /\.(tsx?|jsx?)$/,
101
+ examples: {
102
+ bad: `'use server'
103
+ export async function submitForm(data: FormData) {
104
+ await db.save(data);
105
+ }`,
106
+ good: `'use server'
107
+ export async function submitForm(data: FormData) {
108
+ try {
109
+ await db.save(data);
110
+ return { success: true };
111
+ } catch (error) {
112
+ return { success: false, error: 'Failed to save' };
113
+ }
114
+ }`
115
+ }
116
+ },
117
+ {
118
+ id: "server-redirect-after-action",
119
+ category: "server",
120
+ impact: "MEDIUM",
121
+ // Detects: Server Action without redirect for mutations
122
+ pattern: /['"]use server['"][\s\S]{0,300}(?:create|update|delete|insert)[\s\S]{0,200}(?:return|$)/,
123
+ antiPattern: /redirect\s*\(/,
124
+ message: "Server Action mutation may need redirect for proper revalidation",
125
+ suggestion: "Consider using redirect() after mutations to trigger revalidation",
126
+ fileFilter: /\.(tsx?|jsx?)$/,
127
+ examples: {
128
+ bad: `'use server'
129
+ export async function createPost(data: FormData) {
130
+ await db.posts.create(data);
131
+ return { success: true };
132
+ }`,
133
+ good: `'use server'
134
+ export async function createPost(data: FormData) {
135
+ await db.posts.create(data);
136
+ revalidatePath('/posts');
137
+ redirect('/posts');
138
+ }`
139
+ }
140
+ }
141
+ ];
@@ -0,0 +1,127 @@
1
+ // adapters/mcp-ts/src/tools/react_perf/types.ts
2
+ // React Performance Analysis Tool Types
3
+ import { z } from "zod";
4
+ // Output schemas are generated from JSON Schema SSOT.
5
+ import { ReactPerfCheckPatternsInputSchema } from "../../generated/react_perf_check_patterns_input.js";
6
+ import { ReactPerfCheckPatternsOutputSchema } from "../../generated/react_perf_check_patterns_output.js";
7
+ import { ReactPerfGenerateReportInputSchema } from "../../generated/react_perf_generate_report_input.js";
8
+ import { ReactPerfGenerateReportOutputSchema } from "../../generated/react_perf_generate_report_output.js";
9
+ // ============================================================
10
+ // Impact Levels (from Vercel agent-skills)
11
+ // ============================================================
12
+ export const impactLevelSchema = z.enum([
13
+ "CRITICAL", // Must fix: causes major performance issues
14
+ "HIGH", // Should fix: significant performance impact
15
+ "MEDIUM-HIGH", // Recommended: noticeable impact
16
+ "MEDIUM", // Consider: moderate impact
17
+ "LOW-MEDIUM", // Nice to have: minor impact
18
+ "LOW" // Optional: minimal impact
19
+ ]);
20
+ // Impact level priority for sorting
21
+ export const IMPACT_PRIORITY = {
22
+ "CRITICAL": 6,
23
+ "HIGH": 5,
24
+ "MEDIUM-HIGH": 4,
25
+ "MEDIUM": 3,
26
+ "LOW-MEDIUM": 2,
27
+ "LOW": 1
28
+ };
29
+ // ============================================================
30
+ // Rule Categories
31
+ // ============================================================
32
+ export const ruleCategorySchema = z.enum([
33
+ "async", // Async/await patterns (waterfalls, parallel)
34
+ "bundle", // Bundle size (barrel imports, dynamic imports)
35
+ "server", // Server Actions (auth, validation)
36
+ "client", // Client components (use client, hydration)
37
+ "rerender", // Re-render patterns (memo, callbacks)
38
+ "rendering", // Rendering patterns (suspense, loading)
39
+ "js", // General JS patterns
40
+ "advanced" // Advanced patterns
41
+ ]);
42
+ // ============================================================
43
+ // Input Schema
44
+ // ============================================================
45
+ // Input schema is generated from JSON Schema SSOT.
46
+ export const checkPatternsInputSchema = ReactPerfCheckPatternsInputSchema;
47
+ export const checkPatternsOutputSchema = ReactPerfCheckPatternsOutputSchema;
48
+ // ============================================================
49
+ // Helper Functions
50
+ // ============================================================
51
+ export function countViolationsByImpact(violations) {
52
+ const summary = {
53
+ critical: 0,
54
+ high: 0,
55
+ medium: 0,
56
+ low: 0
57
+ };
58
+ for (const v of violations) {
59
+ switch (v.impact) {
60
+ case "CRITICAL":
61
+ summary.critical++;
62
+ break;
63
+ case "HIGH":
64
+ summary.high++;
65
+ break;
66
+ case "MEDIUM-HIGH":
67
+ case "MEDIUM":
68
+ summary.medium++;
69
+ break;
70
+ case "LOW-MEDIUM":
71
+ case "LOW":
72
+ summary.low++;
73
+ break;
74
+ }
75
+ }
76
+ return summary;
77
+ }
78
+ export function filterByMinImpact(violations, minImpact) {
79
+ const minPriority = IMPACT_PRIORITY[minImpact];
80
+ return violations.filter(v => IMPACT_PRIORITY[v.impact] >= minPriority);
81
+ }
82
+ export function sortByImpact(violations) {
83
+ return [...violations].sort((a, b) => IMPACT_PRIORITY[b.impact] - IMPACT_PRIORITY[a.impact]);
84
+ }
85
+ export function getTopSuggestions(violations, limit = 3) {
86
+ const sorted = sortByImpact(violations);
87
+ const seen = new Set();
88
+ const suggestions = [];
89
+ for (const v of sorted) {
90
+ if (!seen.has(v.rule_id) && suggestions.length < limit) {
91
+ seen.add(v.rule_id);
92
+ suggestions.push(`[${v.impact}] ${v.suggestion}`);
93
+ }
94
+ }
95
+ return suggestions;
96
+ }
97
+ // ============================================================
98
+ // Generate Report Types
99
+ // ============================================================
100
+ export const reportFormatSchema = z.enum(["markdown", "html", "json"]);
101
+ // Input schema is generated from JSON Schema SSOT.
102
+ export const generateReportInputSchema = ReactPerfGenerateReportInputSchema;
103
+ export const generateReportOutputSchema = ReactPerfGenerateReportOutputSchema;
104
+ /**
105
+ * Map impact levels to severity for scoring
106
+ */
107
+ export function impactToSeverity(impact) {
108
+ switch (impact) {
109
+ case "CRITICAL":
110
+ case "HIGH":
111
+ return "error";
112
+ case "MEDIUM-HIGH":
113
+ case "MEDIUM":
114
+ return "warning";
115
+ case "LOW-MEDIUM":
116
+ case "LOW":
117
+ return "info";
118
+ }
119
+ }
120
+ /**
121
+ * Calculate performance score from violations
122
+ * score = 100 - (error × 10) - (warning × 3) - (info × 1)
123
+ */
124
+ export function calculateScore(bySeverity) {
125
+ const raw = 100 - (bySeverity.error * 10) - (bySeverity.warning * 3) - (bySeverity.info * 1);
126
+ return Math.max(0, Math.min(100, raw));
127
+ }
@@ -0,0 +1,102 @@
1
+ // adapters/mcp-ts/src/tools/vibe_pm/activate.ts
2
+ // vibe_pm.activate - Exchange a Gumroad license key for an offline-verifiable JWT token
3
+ import * as fs from "node:fs";
4
+ import * as path from "node:path";
5
+ import { fileURLToPath } from "node:url";
6
+ import { getAuthGate, getTokenCache } from "../../auth/index.js";
7
+ import { ActivateOutputSchema } from "../../generated/activate_output.js";
8
+ function isOfflineMode() {
9
+ const v = (process.env.VIBECODE_OFFLINE ?? "").trim().toLowerCase();
10
+ return v === "1" || v === "true" || v === "yes" || v === "on";
11
+ }
12
+ function readPackageVersion() {
13
+ try {
14
+ const __dirname = path.dirname(fileURLToPath(import.meta.url));
15
+ const pkgPath = path.join(__dirname, "..", "..", "..", "..", "package.json");
16
+ const raw = fs.readFileSync(pkgPath, "utf-8");
17
+ const parsed = JSON.parse(raw);
18
+ const v = (parsed.version ?? "").trim();
19
+ return v || "0.0.0";
20
+ }
21
+ catch {
22
+ return "0.0.0";
23
+ }
24
+ }
25
+ /**
26
+ * vibe_pm.activate
27
+ *
28
+ * Internal mapping:
29
+ * → Auth Proxy: POST /v1/auth/exchange (license_key)
30
+ * → Cache token locally for offline verification
31
+ */
32
+ export async function activate(input) {
33
+ const tokenCache = getTokenCache();
34
+ const tokenFile = tokenCache.getTokenFilePath();
35
+ if (isOfflineMode()) {
36
+ return ActivateOutputSchema.parse({
37
+ status: "OFFLINE",
38
+ summary: "오프라인 모드에서는 라이선스 활성화를 진행할 수 없습니다.",
39
+ token_file: tokenFile,
40
+ offline_mode: true,
41
+ entitlements: null,
42
+ policy: null,
43
+ subject_id: null,
44
+ expires_at: null,
45
+ issues: ["offline_mode: activation_blocked"],
46
+ next_action: { tool: "vibe_pm.doctor", reason: "네트워크/설정 상태를 점검하겠습니다." }
47
+ });
48
+ }
49
+ const licenseKey = (input.license_key ?? "").trim();
50
+ const appVersion = (input.app_version ?? "").trim() || readPackageVersion();
51
+ try {
52
+ if (input.force) {
53
+ await tokenCache.clear();
54
+ }
55
+ const gate = getAuthGate();
56
+ const exchanged = await gate.exchangeToken(licenseKey, appVersion);
57
+ if (!exchanged.success) {
58
+ return ActivateOutputSchema.parse({
59
+ status: "ERROR",
60
+ summary: "라이선스 활성화에 실패했습니다.",
61
+ token_file: tokenFile,
62
+ offline_mode: false,
63
+ entitlements: null,
64
+ policy: null,
65
+ subject_id: null,
66
+ expires_at: null,
67
+ issues: [exchanged.error ?? "unknown_error"],
68
+ next_action: { tool: "vibe_pm.activate", reason: "키를 확인한 뒤 다시 시도하세요." }
69
+ });
70
+ }
71
+ const cached = await tokenCache.get();
72
+ const expiresAt = cached?.expiresAt ?? null;
73
+ const subjectId = cached?.subjectId ?? null;
74
+ return ActivateOutputSchema.parse({
75
+ status: "OK",
76
+ summary: "라이선스 활성화가 완료되었습니다.",
77
+ token_file: tokenFile,
78
+ offline_mode: false,
79
+ entitlements: exchanged.entitlements ?? null,
80
+ policy: exchanged.policy ?? null,
81
+ subject_id: subjectId,
82
+ expires_at: expiresAt,
83
+ issues: [],
84
+ next_action: { tool: "vibe_pm.status", reason: "현재 상태를 확인하겠습니다." }
85
+ });
86
+ }
87
+ catch (e) {
88
+ const msg = e instanceof Error ? e.message : String(e);
89
+ return ActivateOutputSchema.parse({
90
+ status: "ERROR",
91
+ summary: "라이선스 활성화 중 오류가 발생했습니다.",
92
+ token_file: tokenFile,
93
+ offline_mode: false,
94
+ entitlements: null,
95
+ policy: null,
96
+ subject_id: null,
97
+ expires_at: null,
98
+ issues: [msg],
99
+ next_action: { tool: "vibe_pm.doctor", reason: "설치/네트워크 상태를 점검하겠습니다." }
100
+ });
101
+ }
102
+ }
@@ -0,0 +1,77 @@
1
+ // adapters/mcp-ts/src/tools/vibe_pm/advisory_review.ts
2
+ // vibe_pm.advisory_review - Advisory review (triage/quick/thorough) with routing + cache
3
+ import { runEngine } from "../../engine.js";
4
+ import { safeJsonParse } from "../../cli.js";
5
+ import { validateToolInput } from "../../security/input-validator.js";
6
+ import { resolveProjectId } from "./context.js";
7
+ import { AdvisoryReviewOutputSchema } from "../../generated/advisory_review_output.js";
8
+ function clipArg(value, maxChars) {
9
+ const v = value.trim();
10
+ if (v.length <= maxChars)
11
+ return v;
12
+ return v.slice(0, maxChars).trimEnd() + "…";
13
+ }
14
+ /**
15
+ * vibe_pm.advisory_review - Produce high-level advisory review output
16
+ *
17
+ * Internal mapping:
18
+ * → vibecoding-helper advisory-review --mode triage|quick|thorough ...
19
+ */
20
+ export async function advisoryReview(input) {
21
+ const basePath = process.cwd();
22
+ validateToolInput({
23
+ project_id: input.project_id,
24
+ custom_input: input.diff_context
25
+ });
26
+ const project_id = input.project_id ?? resolveProjectId(undefined, basePath);
27
+ const mode = input.mode ?? "triage";
28
+ const trigger = input.trigger ?? "on_demand";
29
+ const budget = input.budget ?? "low";
30
+ const changed = Array.isArray(input.changed_paths) ? input.changed_paths : [];
31
+ const targets = Array.isArray(input.target_paths) ? input.target_paths : [];
32
+ const changedCsv = changed.map((p) => p.trim()).filter(Boolean).join(",");
33
+ const targetCsv = targets.map((p) => p.trim()).filter(Boolean).join(",");
34
+ const args = [
35
+ "advisory-review",
36
+ "--project-id",
37
+ project_id,
38
+ "--mode",
39
+ mode,
40
+ "--trigger",
41
+ trigger,
42
+ "--budget",
43
+ budget
44
+ ];
45
+ if (input.run_id) {
46
+ args.push("--run-id", input.run_id);
47
+ }
48
+ if (changedCsv) {
49
+ args.push("--changed-paths", changedCsv);
50
+ }
51
+ else if (targetCsv) {
52
+ args.push("--target-paths", targetCsv);
53
+ }
54
+ if (input.diff_context && input.diff_context.trim()) {
55
+ args.push("--diff-context", clipArg(input.diff_context, 2000));
56
+ }
57
+ if (input.base_sha)
58
+ args.push("--base-sha", input.base_sha);
59
+ if (input.head_sha)
60
+ args.push("--head-sha", input.head_sha);
61
+ if (Array.isArray(input.focus) && input.focus.length > 0) {
62
+ args.push("--focus", input.focus.join(","));
63
+ }
64
+ if (Array.isArray(input.product_intent_refs) && input.product_intent_refs.length > 0) {
65
+ args.push("--product-intent-refs", input.product_intent_refs.join(","));
66
+ }
67
+ const timeoutMs = mode === "triage" ? 30_000 : 180_000;
68
+ const { code, stdout, stderr } = await runEngine("vibecoding-helper", args, { timeoutMs });
69
+ if (code !== 0) {
70
+ throw new Error(stderr?.trim() ? `advisory_review_engine_error: ${stderr.trim()}` : `advisory_review_exit_code: ${code}`);
71
+ }
72
+ const parsed = safeJsonParse(stdout);
73
+ if (!parsed.ok) {
74
+ throw new Error(`advisory_review_invalid_json: ${parsed.error}`);
75
+ }
76
+ return AdvisoryReviewOutputSchema.parse(parsed.value);
77
+ }