viepilot 2.49.0 → 3.7.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.
Files changed (49) hide show
  1. package/CHANGELOG.md +234 -0
  2. package/README.md +1 -1
  3. package/bin/viepilot.cjs +1 -0
  4. package/bin/vp-tools.cjs +123 -1
  5. package/docs/brainstorm/session-2026-05-22.md +472 -0
  6. package/docs/dev/agents.md +51 -41
  7. package/lib/adapter-context.cjs +294 -0
  8. package/lib/adapters/antigravity.cjs +8 -2
  9. package/lib/adapters/claude-code.cjs +4 -0
  10. package/lib/audit/browser-runner.cjs +102 -0
  11. package/lib/intake/adapters/browser.cjs +58 -0
  12. package/lib/intake/adapters/excel-m365.cjs +114 -29
  13. package/lib/intake/auto-intake.cjs +194 -0
  14. package/lib/intake/channels.cjs +44 -3
  15. package/lib/intake/classifier.cjs +22 -4
  16. package/lib/intake/manifest.cjs +81 -0
  17. package/lib/intake/setup-wizard.cjs +215 -0
  18. package/lib/intake/triage-ux.cjs +10 -2
  19. package/lib/intake/validator.cjs +97 -0
  20. package/lib/intake/writeback.cjs +169 -3
  21. package/lib/request/url-enricher.cjs +69 -0
  22. package/lib/viepilot-install.cjs +15 -0
  23. package/package.json +1 -1
  24. package/skills/vp-audit/SKILL.md +99 -3
  25. package/skills/vp-auto/SKILL.md +54 -4
  26. package/skills/vp-brainstorm/SKILL.md +69 -3
  27. package/skills/vp-crystallize/SKILL.md +52 -3
  28. package/skills/vp-debug/SKILL.md +52 -3
  29. package/skills/vp-design/SKILL.md +52 -3
  30. package/skills/vp-docs/SKILL.md +52 -3
  31. package/skills/vp-evolve/SKILL.md +52 -3
  32. package/skills/vp-info/SKILL.md +52 -3
  33. package/skills/vp-intake/SKILL.md +349 -14
  34. package/skills/vp-pause/SKILL.md +52 -3
  35. package/skills/vp-persona/SKILL.md +52 -3
  36. package/skills/vp-proposal/SKILL.md +52 -3
  37. package/skills/vp-request/SKILL.md +72 -3
  38. package/skills/vp-resume/SKILL.md +52 -3
  39. package/skills/vp-rollback/SKILL.md +52 -3
  40. package/skills/vp-skills/SKILL.md +52 -3
  41. package/skills/vp-status/SKILL.md +52 -3
  42. package/skills/vp-task/SKILL.md +52 -3
  43. package/skills/vp-ui-components/SKILL.md +52 -3
  44. package/skills/vp-update/SKILL.md +52 -3
  45. package/workflows/autonomous.md +268 -18
  46. package/workflows/brainstorm.md +222 -7
  47. package/workflows/crystallize.md +124 -6
  48. package/workflows/design.md +62 -1
  49. package/workflows/request.md +54 -8
@@ -0,0 +1,294 @@
1
+ 'use strict';
2
+
3
+ /**
4
+ * ADAPTER_CONTEXT — per-adapter capability map for ViePilot v3.
5
+ *
6
+ * Each adapter entry defines:
7
+ * tools{} — canonical tool name for each abstract operation
8
+ * interactive — "AUQ" | "text" | "text-plan-only" | "none"
9
+ * orchestration{} — parallel dispatch capability
10
+ * hooks{} — hook event support
11
+ * mcp{} — MCP support constraints
12
+ * subagent — "multi-level" | "single-level" | "command-only" | "none"
13
+ *
14
+ * Skills read ADAPTER_CONTEXT instead of maintaining inline compat tables.
15
+ */
16
+
17
+ const ADAPTER_CONTEXTS = {
18
+
19
+ 'claude-code': {
20
+ id: 'claude-code',
21
+ name: 'Claude Code',
22
+ tools: {
23
+ shell: 'Bash',
24
+ read: 'Read',
25
+ write: 'Write',
26
+ edit: 'Edit',
27
+ multi_edit: 'MultiEdit',
28
+ search: 'Grep',
29
+ glob: 'Glob',
30
+ ls: 'LS',
31
+ web_search: 'WebSearch',
32
+ web_fetch: 'WebFetch',
33
+ notebook_read: 'NotebookRead',
34
+ notebook_edit: 'NotebookEdit',
35
+ tool_search: 'ToolSearch',
36
+ todo_read: 'TodoRead',
37
+ todo_write: 'TodoWrite',
38
+ agent: 'Agent',
39
+ interactive: 'AskUserQuestion', // deferred — preload via ToolSearch first
40
+ },
41
+ interactive: 'AUQ', // must call ToolSearch before first AUQ
42
+ subagent: 'multi-level', // Agent tool supports nested spawning
43
+ orchestration: {
44
+ mode: 'agent-tool', // Agent tool = callable from skill
45
+ parallel: true,
46
+ teams: true, // CLAUDE_CODE_EXPERIMENTAL_AGENT_TEAMS=1
47
+ background: true,
48
+ model_override: {
49
+ worker: 'claude-haiku-4-5',
50
+ orchestrator: 'claude-sonnet-4-6',
51
+ },
52
+ max_parallel_tasks: 5,
53
+ },
54
+ hooks: {
55
+ count: 28,
56
+ supported_events: [
57
+ 'SessionStart', 'SessionEnd', 'Stop', 'StopFailure',
58
+ 'UserPromptSubmit', 'PreToolUse', 'PostToolUse', 'PostToolUseFailure',
59
+ 'FileChanged', 'SubagentStart', 'SubagentStop',
60
+ 'TaskCreated', 'TaskCompleted', 'PreCompact', 'PostCompact',
61
+ ],
62
+ },
63
+ mcp: { supported: true, tool_limit: null },
64
+ skill_path_project: '.claude/skills',
65
+ skill_path_global: '~/.claude/skills',
66
+ agents_dir: '.claude/agents',
67
+ },
68
+
69
+ 'cursor-agent': {
70
+ id: 'cursor-agent',
71
+ name: 'Cursor (Agent Mode)',
72
+ tools: {
73
+ shell: 'run_terminal_cmd',
74
+ read: 'read_file',
75
+ write: 'edit_file',
76
+ edit: 'edit_file',
77
+ multi_edit: 'edit_file',
78
+ search: 'grep_search',
79
+ glob: 'file_search',
80
+ ls: 'list_dir',
81
+ web_search: 'web_search',
82
+ web_fetch: null, // not available
83
+ notebook_read: null,
84
+ notebook_edit: null,
85
+ tool_search: null,
86
+ todo_read: null,
87
+ todo_write: null,
88
+ agent: null, // /multitask is user command, not callable tool
89
+ interactive: null, // AskQuestion only in Plan Mode
90
+ },
91
+ interactive: 'text', // plain-text numbered list fallback
92
+ subagent: 'command-only', // /multitask user cmd, single-level, not callable
93
+ orchestration: {
94
+ mode: 'sequential',
95
+ parallel: false,
96
+ teams: false,
97
+ background: false,
98
+ model_override: null,
99
+ max_parallel_tasks: 1,
100
+ },
101
+ hooks: {
102
+ count: 5,
103
+ supported_events: [
104
+ 'beforeShellExecution', 'beforeMCPExecution',
105
+ 'beforeReadFile', 'afterFileEdit', 'stop',
106
+ ],
107
+ },
108
+ mcp: { supported: true, tool_limit: 40 },
109
+ skill_path_project: '.cursor/skills',
110
+ skill_path_global: '~/.cursor/skills',
111
+ agents_dir: null,
112
+ },
113
+
114
+ 'antigravity': {
115
+ id: 'antigravity',
116
+ name: 'Antigravity (Google)',
117
+ tools: {
118
+ shell: 'shell',
119
+ read: 'file_read',
120
+ write: 'file_write',
121
+ edit: 'file_write',
122
+ multi_edit: 'file_write',
123
+ search: null, // via shell or MCP
124
+ glob: null, // via shell
125
+ ls: null, // via shell
126
+ web_search: null, // via MCP plugin
127
+ web_fetch: null, // via MCP plugin
128
+ notebook_read: null,
129
+ notebook_edit: null,
130
+ tool_search: null,
131
+ todo_read: null,
132
+ todo_write: null,
133
+ agent: null, // async TUI dispatch only
134
+ interactive: null, // TUI-based, no formal AUQ
135
+ },
136
+ interactive: 'none',
137
+ subagent: 'none',
138
+ orchestration: {
139
+ mode: 'sequential',
140
+ parallel: false,
141
+ teams: false,
142
+ background: false,
143
+ model_override: null,
144
+ max_parallel_tasks: 1,
145
+ },
146
+ hooks: {
147
+ count: 3,
148
+ supported_events: ['before_tool', 'after_file_edit', 'session_start'],
149
+ },
150
+ mcp: { supported: true, tool_limit: null },
151
+ skill_path_project: '.agents/skills',
152
+ skill_path_global: '~/.gemini/antigravity/skills',
153
+ agents_dir: null,
154
+ deprecation_notice: 'Gemini CLI was deprecated June 18, 2026. Use Antigravity CLI instead.',
155
+ },
156
+
157
+ 'codex': {
158
+ id: 'codex',
159
+ name: 'OpenAI Codex CLI',
160
+ tools: {
161
+ shell: 'container.exec', // sandboxed shell
162
+ read: null, // patch-based — no explicit read tool
163
+ write: 'apply_patch',
164
+ edit: 'apply_patch',
165
+ multi_edit: 'apply_patch',
166
+ search: null, // via shell
167
+ glob: null, // via shell
168
+ ls: null, // via shell
169
+ web_search: 'web_search', // native or MCP
170
+ web_fetch: null,
171
+ notebook_read: null,
172
+ notebook_edit: null,
173
+ tool_search: null,
174
+ todo_read: null,
175
+ todo_write: null,
176
+ agent: 'subagent', // subagents supported
177
+ interactive: null, // TUI Tab/Enter injection only
178
+ },
179
+ interactive: 'none',
180
+ subagent: 'single-level',
181
+ orchestration: {
182
+ mode: 'sequential',
183
+ parallel: false,
184
+ teams: false,
185
+ background: false,
186
+ model_override: null,
187
+ max_parallel_tasks: 1,
188
+ },
189
+ hooks: {
190
+ count: 0,
191
+ supported_events: [],
192
+ },
193
+ mcp: { supported: true, tool_limit: null },
194
+ skill_path_project: null,
195
+ skill_path_global: '~/.codex',
196
+ agents_dir: null,
197
+ },
198
+
199
+ 'copilot': {
200
+ id: 'copilot',
201
+ name: 'GitHub Copilot',
202
+ tools: {
203
+ shell: 'runCommands',
204
+ read: 'read',
205
+ write: 'editFiles',
206
+ edit: 'edit',
207
+ multi_edit: 'editFiles',
208
+ search: 'code_search',
209
+ glob: null,
210
+ ls: null,
211
+ web_search: null,
212
+ web_fetch: null,
213
+ notebook_read: null,
214
+ notebook_edit: null,
215
+ tool_search: null,
216
+ todo_read: null,
217
+ todo_write: null,
218
+ agent: null, // explore/task are built-in agents, not callable
219
+ // askQuestions available in main agent ONLY — not in subagents (VS Code #293745)
220
+ interactive: 'askQuestions',
221
+ },
222
+ interactive: 'text', // askQuestions not available in subagents
223
+ subagent: 'none',
224
+ orchestration: {
225
+ mode: 'sequential',
226
+ parallel: false,
227
+ teams: false,
228
+ background: false,
229
+ model_override: null,
230
+ max_parallel_tasks: 1,
231
+ },
232
+ hooks: {
233
+ count: 0,
234
+ supported_events: [],
235
+ },
236
+ mcp: { supported: true, tool_limit: null },
237
+ skill_path_project: '.github/agents',
238
+ skill_path_global: null,
239
+ agents_dir: '.github/agents',
240
+ },
241
+ };
242
+
243
+ // Aliases
244
+ ADAPTER_CONTEXTS['cursor'] = ADAPTER_CONTEXTS['cursor-agent'];
245
+ ADAPTER_CONTEXTS['cursor-ide'] = ADAPTER_CONTEXTS['cursor-agent'];
246
+
247
+ /**
248
+ * Get ADAPTER_CONTEXT for a given adapter ID. Throws if unknown.
249
+ */
250
+ function getAdapterContext(id) {
251
+ const ctx = ADAPTER_CONTEXTS[id];
252
+ if (!ctx) {
253
+ throw new Error(`Unknown adapter: "${id}". Known: ${Object.keys(ADAPTER_CONTEXTS).filter(k => !['cursor','cursor-ide'].includes(k)).join(', ')}`);
254
+ }
255
+ return ctx;
256
+ }
257
+
258
+ /**
259
+ * List all canonical adapter IDs (no aliases).
260
+ */
261
+ function listAdapterIds() {
262
+ return ['claude-code', 'cursor-agent', 'antigravity', 'codex', 'copilot'];
263
+ }
264
+
265
+ /**
266
+ * Detect the active adapter from environment heuristics.
267
+ * Returns the adapter ID string.
268
+ */
269
+ function detectAdapter() {
270
+ const env = process.env;
271
+
272
+ // Env-var signals (strongest signals first)
273
+ if (env.CURSOR_TRACE || env.CURSOR_CHANNEL || env.CURSOR_ENABLED) return 'cursor-agent';
274
+ if (env.ANTIGRAVITY_SESSION || env.GEMINI_ANTIGRAVITY_SESSION) return 'antigravity';
275
+ if (env.CODEX_SESSION || env.OPENAI_CODEX_SESSION) return 'codex';
276
+ if (env.GITHUB_COPILOT_AGENT || env.COPILOT_AGENT) return 'copilot';
277
+
278
+ // TERM_PROGRAM / process name signals
279
+ const termProgram = (env.TERM_PROGRAM || '').toLowerCase();
280
+ if (termProgram === 'claude' || termProgram === 'claude-code') return 'claude-code';
281
+
282
+ // ~/.claude directory exists → likely Claude Code
283
+ const os = require('os');
284
+ const fs = require('fs');
285
+ const path = require('path');
286
+ const home = os.homedir();
287
+ if (fs.existsSync(path.join(home, '.claude', 'settings.json'))) return 'claude-code';
288
+ if (fs.existsSync(path.join(home, '.claude'))) return 'claude-code';
289
+
290
+ // Fallback: claude-code (most common in ViePilot context)
291
+ return 'claude-code';
292
+ }
293
+
294
+ module.exports = { ADAPTER_CONTEXTS, getAdapterContext, listAdapterIds, detectAdapter };
@@ -6,16 +6,21 @@ const fs = require('fs');
6
6
  module.exports = {
7
7
  id: 'antigravity',
8
8
  name: 'Antigravity',
9
+ // Global install path (unchanged)
9
10
  skillsDir: (home) => path.join(home, '.gemini', 'antigravity', 'skills'),
10
11
  viepilotDir: (home) => path.join(home, '.gemini', 'antigravity', 'viepilot'),
12
+ // Phase 131 (FEAT-021): project-level install path (Antigravity v1 uses .agents/skills/)
13
+ projectSkillsDir: '.agents/skills',
11
14
  // {envToolDir} in SKILL.md files resolves to this value at install time (ENH-035)
12
15
  executionContextBase: '.gemini/antigravity/viepilot',
13
16
  // Post-install hint shown in "Next actions" after viepilot install
14
17
  postInstallHint: 'Open project and run /vp-status',
18
+ // Phase 131 (FEAT-021): Gemini CLI was deprecated June 18, 2026
19
+ deprecationNotice: '⚠️ Gemini CLI was deprecated June 18, 2026. This installs for Antigravity CLI (the successor). Skill path: .agents/skills/ (project) or ~/.gemini/antigravity/skills/ (global).',
15
20
  hooks: {
16
21
  configFile: null, // Antigravity has no programmatic hooks system
17
22
  schema: 'antigravity',
18
- supportedEvents: []
23
+ supportedEvents: ['before_tool', 'after_file_edit', 'session_start']
19
24
  },
20
25
  installSubdirs: [
21
26
  'workflows',
@@ -30,6 +35,7 @@ module.exports = {
30
35
  isAvailable: (home) => {
31
36
  const h = home || os.homedir();
32
37
  return fs.existsSync(path.join(h, '.gemini', 'antigravity'))
33
- || fs.existsSync(path.join(h, '.antigravity'));
38
+ || fs.existsSync(path.join(h, '.antigravity'))
39
+ || fs.existsSync(path.join(process.cwd(), '.agents'));
34
40
  }
35
41
  };
@@ -35,6 +35,10 @@ module.exports = {
35
35
  'ui-components',
36
36
  'agents'
37
37
  ],
38
+ // Phase 130 (FEAT-021): native Claude Code subagent definitions (.claude/agents/)
39
+ // Installed to ~/.claude/agents/ (Claude Code's native agent directory)
40
+ claudeAgentsDir: (home) => path.join(home, '.claude', 'agents'),
41
+ claudeAgentsSrc: 'agents/claude-code',
38
42
  // Detection: is this platform available on the current machine?
39
43
  isAvailable: (home) => {
40
44
  const h = home || os.homedir();
@@ -0,0 +1,102 @@
1
+ 'use strict';
2
+
3
+ const path = require('path');
4
+ const fs = require('fs');
5
+
6
+ const DEFAULT_BASE_URL = 'http://localhost:3000';
7
+
8
+ /**
9
+ * Resolve base URL for browser audit.
10
+ * Priority: options.baseUrl → config.json audit.baseUrl → DEFAULT_BASE_URL
11
+ * @param {object} options - { baseUrl?: string }
12
+ * @param {string} projectRoot
13
+ * @returns {string}
14
+ */
15
+ function resolveBaseUrl(options, projectRoot) {
16
+ if (options && options.baseUrl) return options.baseUrl;
17
+ try {
18
+ const configPath = path.join(projectRoot, '.viepilot', 'config.json');
19
+ if (fs.existsSync(configPath)) {
20
+ const cfg = JSON.parse(fs.readFileSync(configPath, 'utf8'));
21
+ if (cfg.audit && cfg.audit.baseUrl) return cfg.audit.baseUrl;
22
+ }
23
+ } catch { /* config missing or malformed — use default */ }
24
+ return DEFAULT_BASE_URL;
25
+ }
26
+
27
+ /**
28
+ * Write a Markdown audit report to .viepilot/audit/visual-report-{timestamp}.md
29
+ * @param {object} report - structured audit report from browser-audit-agent
30
+ * @param {string} projectRoot
31
+ * @returns {string} absolute path to report file
32
+ */
33
+ function writeAuditReport(report, projectRoot) {
34
+ const auditDir = path.join(projectRoot, '.viepilot', 'audit');
35
+ fs.mkdirSync(auditDir, { recursive: true });
36
+
37
+ const timestamp = Date.now();
38
+ const reportPath = path.join(auditDir, `visual-report-${timestamp}.md`);
39
+
40
+ const routes = report.routes || [];
41
+ const routeTable = routes.map(r => {
42
+ const status = r.status === 'ok' ? '✅ ok' : `❌ ${r.status}`;
43
+ const issues = (r.errors && r.errors.length > 0) ? r.errors.join(', ') : '—';
44
+ return `| ${r.url} | ${status} | ${issues} |`;
45
+ }).join('\n');
46
+
47
+ const accessibilitySection = routes
48
+ .filter(r => r.accessibility_issues && r.accessibility_issues.length > 0)
49
+ .map(r => `### ${r.url}\n${r.accessibility_issues.map(i => `- **${i.type}**: ${i.description}`).join('\n')}`)
50
+ .join('\n\n') || '_No accessibility issues found._';
51
+
52
+ const screenshotSection = routes
53
+ .filter(r => r.screenshot)
54
+ .map(r => `- \`${r.url}\`: \`${r.screenshot}\``)
55
+ .join('\n') || '_No screenshots captured._';
56
+
57
+ const content = `# Browser Audit Report — ${new Date(timestamp).toISOString()}
58
+
59
+ **Base URL**: ${report.baseUrl || DEFAULT_BASE_URL}
60
+ **Routes checked**: ${routes.length}
61
+ **Op**: ${report.op || 'audit_routes'}
62
+
63
+ ## Routes
64
+
65
+ | Route | Status | Issues |
66
+ |-------|--------|--------|
67
+ ${routeTable}
68
+
69
+ ## Accessibility Issues
70
+
71
+ ${accessibilitySection}
72
+
73
+ ## Screenshots
74
+
75
+ ${screenshotSection}
76
+ `;
77
+
78
+ fs.writeFileSync(reportPath, content, 'utf8');
79
+ return reportPath;
80
+ }
81
+
82
+ /**
83
+ * Run browser audit by dispatching browser-audit-agent (CC adapter only).
84
+ * On non-CC: throws with install instructions.
85
+ * @param {object} options - { baseUrl?, routes?, op?, updateBaseline? }
86
+ * @param {string} projectRoot
87
+ * @returns {Promise<object>} - report object
88
+ */
89
+ async function runBrowserAudit(options, projectRoot) {
90
+ const baseUrl = resolveBaseUrl(options, projectRoot);
91
+ const op = (options && options.op) || 'audit_routes';
92
+
93
+ // CC adapter: Agent dispatch is handled by vp-audit SKILL.md (orchestrator layer).
94
+ // This module is for direct Node callers — emit clear error.
95
+ throw new Error(
96
+ `Browser audit requires Claude Code with the agent-browser skill.\n` +
97
+ `Install: npx skills add vercel-labs/agent-browser\n` +
98
+ `Then run: /vp-audit --visual --browser ${baseUrl}`
99
+ );
100
+ }
101
+
102
+ module.exports = { runBrowserAudit, resolveBaseUrl, writeAuditReport, DEFAULT_BASE_URL };
@@ -0,0 +1,58 @@
1
+ 'use strict';
2
+
3
+ const URL_PATTERNS = {
4
+ 'google-sheets': /docs\.google\.com\/spreadsheets/,
5
+ 'github-issues': /github\.com\/[^/]+\/[^/]+\/issues/,
6
+ 'jira': /atlassian\.net\/browse\/[A-Z]+-\d+|atlassian\.net\/jira\/software\/projects/,
7
+ 'trello': /trello\.com\/[bc]\//,
8
+ 'notion': /notion\.so\/[a-f0-9]{8,}/,
9
+ 'sharepoint-xlsx': /sharepoint\.com\/:[a-z]:\/[a-z]\//,
10
+ };
11
+
12
+ /**
13
+ * Detect source type from URL string.
14
+ * @param {string} url
15
+ * @returns {'google-sheets'|'github-issues'|'jira'|'trello'|'notion'|'sharepoint-xlsx'|'generic-table'}
16
+ */
17
+ function detectUrlType(url) {
18
+ if (!url || typeof url !== 'string') return 'generic-table';
19
+ for (const [type, pattern] of Object.entries(URL_PATTERNS)) {
20
+ if (pattern.test(url)) return type;
21
+ }
22
+ return 'generic-table';
23
+ }
24
+
25
+ /**
26
+ * Read ticket rows from a public URL via browser-intake-agent (CC adapter only).
27
+ * Non-CC adapters receive a clear unsupported error.
28
+ * @param {object} channel - channel config with `url` field
29
+ * @param {string} projectRoot - absolute path to project root
30
+ * @returns {Promise<Array<{title,description,labels,priority,status}>>}
31
+ */
32
+ async function readBrowserUrl(channel, projectRoot) {
33
+ if (!channel || !channel.url) {
34
+ throw new Error('browser channel requires a "url" field in channel config');
35
+ }
36
+
37
+ const sourceType = detectUrlType(channel.url);
38
+
39
+ // CC adapter: Agent dispatch is handled by vp-intake SKILL.md (orchestrator layer).
40
+ // This module is used by non-CC adapters or direct Node callers — emit clear error.
41
+ throw new Error(
42
+ `Browser channel (${sourceType}) requires Claude Code with the agent-browser skill.\n` +
43
+ `Install: npx skills add vercel-labs/agent-browser\n` +
44
+ `Then run vp-intake from Claude Code.`
45
+ );
46
+ }
47
+
48
+ /**
49
+ * Check whether a URL appears to be a publicly accessible intake source.
50
+ * Does not make network requests — pattern-match only.
51
+ * @param {string} url
52
+ * @returns {boolean}
53
+ */
54
+ function isKnownPublicSource(url) {
55
+ return detectUrlType(url) !== 'generic-table';
56
+ }
57
+
58
+ module.exports = { readBrowserUrl, detectUrlType, isKnownPublicSource, URL_PATTERNS };