viepilot 2.47.0 → 2.49.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.
- package/CHANGELOG.md +45 -0
- package/bin/vp-tools.cjs +15 -0
- package/lib/intake/adapters/csv.cjs +81 -0
- package/lib/intake/adapters/excel-m365.cjs +328 -0
- package/lib/intake/adapters/google-sheets.cjs +161 -0
- package/lib/intake/channels.cjs +139 -0
- package/lib/intake/classifier.cjs +32 -0
- package/lib/intake/report.cjs +88 -0
- package/lib/intake/triage-ux.cjs +151 -0
- package/lib/intake/writeback.cjs +228 -0
- package/package.json +3 -2
- package/skills/vp-intake/SKILL.md +236 -0
|
@@ -0,0 +1,236 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: vp-intake
|
|
3
|
+
description: "Import and triage tickets from Excel/M365 Online, Google Sheets, or CSV/TSV files — classify as BUG/ENH, accept/decline via AskUserQuestion, write back to source, generate TRIAGE report"
|
|
4
|
+
version: 1.0.0
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
<greeting>
|
|
8
|
+
## Invocation Banner
|
|
9
|
+
|
|
10
|
+
Output this banner as the **first** thing on every invocation — before questions, work, or any other output:
|
|
11
|
+
|
|
12
|
+
```
|
|
13
|
+
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
|
14
|
+
VIEPILOT ► VP-INTAKE v1.0.0 (fw 2.48.0)
|
|
15
|
+
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
|
16
|
+
```
|
|
17
|
+
</greeting>
|
|
18
|
+
<version_check>
|
|
19
|
+
## Version Update Check (ENH-072)
|
|
20
|
+
|
|
21
|
+
After displaying the greeting banner, run:
|
|
22
|
+
```bash
|
|
23
|
+
node "$HOME/.claude/viepilot/bin/vp-tools.cjs" check-update --silent
|
|
24
|
+
```
|
|
25
|
+
|
|
26
|
+
**If exit code = 1** (update available — new version printed to stdout):
|
|
27
|
+
Display the update notice banner before continuing. Silent otherwise.
|
|
28
|
+
</version_check>
|
|
29
|
+
<persona_context>
|
|
30
|
+
## Persona Context Injection (ENH-073)
|
|
31
|
+
At skill start, run:
|
|
32
|
+
```bash
|
|
33
|
+
node "$HOME/.claude/viepilot/bin/vp-tools.cjs" persona auto-switch
|
|
34
|
+
node "$HOME/.claude/viepilot/bin/vp-tools.cjs" persona context
|
|
35
|
+
```
|
|
36
|
+
Inject the output as `## User Persona` context before any task execution.
|
|
37
|
+
Silent if command unavailable or errors.
|
|
38
|
+
</persona_context>
|
|
39
|
+
|
|
40
|
+
<cursor_skill_adapter>
|
|
41
|
+
## A. Skill Invocation
|
|
42
|
+
- Skill được gọi khi user mention `vp-intake`, `/vp-intake`, "import tickets", "nhập ticket", "đọc ticket từ", "triage ticket"
|
|
43
|
+
- Treat all user text after the skill mention as `{{VP_ARGS}}`
|
|
44
|
+
|
|
45
|
+
## B. User Prompting
|
|
46
|
+
Prompt user conversationally with options.
|
|
47
|
+
|
|
48
|
+
## C. Tool Usage
|
|
49
|
+
Use Cursor tools: `Shell`, `ReadFile`, `Glob`, `rg`, `ApplyPatch`, `WebSearch`, `WebFetch`, `Subagent`
|
|
50
|
+
</cursor_skill_adapter>
|
|
51
|
+
<scope_policy>
|
|
52
|
+
## ViePilot Namespace Guard (BUG-004)
|
|
53
|
+
- Default mode: only use and reference `vp-*` skills in ViePilot workflows.
|
|
54
|
+
- External skills (`non vp-*`) are out of framework scope unless user explicitly opts in.
|
|
55
|
+
- If external skills appear in runtime context, ignore them and route with the closest built-in `vp-*` skill.
|
|
56
|
+
</scope_policy>
|
|
57
|
+
<implementation_routing_guard>
|
|
58
|
+
## Implementation routing guard (ENH-021)
|
|
59
|
+
|
|
60
|
+
- This skill **reads, classifies, and triages** external tickets — does not implement code.
|
|
61
|
+
- Accepted tickets create `.viepilot/requests/` files for planning via **`/vp-evolve`** → **`/vp-auto`**.
|
|
62
|
+
- **Exception:** User **explicit** bypass — state clearly in chat.
|
|
63
|
+
</implementation_routing_guard>
|
|
64
|
+
|
|
65
|
+
<objective>
|
|
66
|
+
Import tickets from external sources (Excel/Microsoft 365 Online, Google Sheets, CSV/TSV files),
|
|
67
|
+
classify them automatically as BUG/ENH/UNCLEAR, let the user triage each ticket via
|
|
68
|
+
AskUserQuestion (multi-select), write decisions back to the source, and generate a TRIAGE
|
|
69
|
+
session report.
|
|
70
|
+
|
|
71
|
+
**Creates/Updates:**
|
|
72
|
+
- `.viepilot/requests/BUG-N.md` or `ENH-N.md` for accepted tickets
|
|
73
|
+
- Source file: `VP_Status`, `VP_Comment`, `VP_RequestID` columns updated
|
|
74
|
+
- `.viepilot/intake/TRIAGE-{timestamp}.md` — session report
|
|
75
|
+
</objective>
|
|
76
|
+
|
|
77
|
+
<context>
|
|
78
|
+
Optional flags:
|
|
79
|
+
- `--channel <id>` : Skip channel selection, use this channel ID directly
|
|
80
|
+
- `--dry-run` : Classify and show tickets without creating requests or writing back
|
|
81
|
+
|
|
82
|
+
**Supported channel types:**
|
|
83
|
+
| Type | Auth | Config field |
|
|
84
|
+
|------|------|-------------|
|
|
85
|
+
| `csv` | None | `path` (local file) |
|
|
86
|
+
| `google_sheets` | Service Account JSON | `spreadsheet_id` + `sheet_name` |
|
|
87
|
+
| `excel_m365` | Azure App Registration | `workbook_id` + `sheet_name` |
|
|
88
|
+
|
|
89
|
+
**Config file:** `.viepilot/intake/channels.json`
|
|
90
|
+
**Credentials dir:** `.viepilot/.credentials/` (gitignored)
|
|
91
|
+
</context>
|
|
92
|
+
|
|
93
|
+
<process>
|
|
94
|
+
|
|
95
|
+
### Step 1: Init intake directory
|
|
96
|
+
|
|
97
|
+
```bash
|
|
98
|
+
node "$HOME/.claude/viepilot/bin/vp-tools.cjs" intake-init
|
|
99
|
+
```
|
|
100
|
+
|
|
101
|
+
This creates `.viepilot/intake/channels.json` (scaffold) and `.viepilot/.credentials/` if missing.
|
|
102
|
+
|
|
103
|
+
### Step 2: Load channels
|
|
104
|
+
|
|
105
|
+
Read `.viepilot/intake/channels.json`. If no channels configured (only example stubs remain),
|
|
106
|
+
tell the user:
|
|
107
|
+
|
|
108
|
+
```
|
|
109
|
+
No channels configured yet.
|
|
110
|
+
Edit .viepilot/intake/channels.json to add your ticket sources.
|
|
111
|
+
Run vp-tools intake-init to see the config scaffold.
|
|
112
|
+
```
|
|
113
|
+
|
|
114
|
+
### Step 3: Select channel (AUQ single-select)
|
|
115
|
+
|
|
116
|
+
```
|
|
117
|
+
question: "Which ticket channel do you want to import from?"
|
|
118
|
+
header: "Channel"
|
|
119
|
+
options: one per channel — label: "{channel.name} ({channel.type})", description: "{channel.id}"
|
|
120
|
+
```
|
|
121
|
+
|
|
122
|
+
### Step 4: Read and classify tickets
|
|
123
|
+
|
|
124
|
+
Dispatch to the correct adapter based on `channel.type`:
|
|
125
|
+
- `csv` → `lib/intake/adapters/csv.cjs` → `readCsv(channel, projectRoot)`
|
|
126
|
+
- `google_sheets` → `lib/intake/adapters/google-sheets.cjs` → `readGoogleSheet(channel, projectRoot)`
|
|
127
|
+
- `excel_m365` → `lib/intake/adapters/excel-m365.cjs` → `readExcelM365(channel, projectRoot)`
|
|
128
|
+
|
|
129
|
+
For each ticket, call `classifyTicket(ticket)` from `lib/intake/classifier.cjs`.
|
|
130
|
+
Attach `ticket._classified = 'BUG' | 'ENH' | 'UNCLEAR'`.
|
|
131
|
+
|
|
132
|
+
Display classification summary:
|
|
133
|
+
```
|
|
134
|
+
Read {N} tickets from {channel.name}
|
|
135
|
+
BUG: {N} ENH: {N} UNCLEAR: {N}
|
|
136
|
+
```
|
|
137
|
+
|
|
138
|
+
If 0 tickets found, exit with message "No tickets found in this channel."
|
|
139
|
+
|
|
140
|
+
### Step 5: Triage (AUQ multi-select)
|
|
141
|
+
|
|
142
|
+
Call `runTriage(tickets, channel, projectRoot, askFn)` from `lib/intake/triage-ux.cjs`.
|
|
143
|
+
|
|
144
|
+
`askFn` is a wrapper around `AskUserQuestion`:
|
|
145
|
+
```js
|
|
146
|
+
async function askFn(question, options, multiSelect) {
|
|
147
|
+
// calls AskUserQuestion tool → returns selected label(s)
|
|
148
|
+
}
|
|
149
|
+
```
|
|
150
|
+
|
|
151
|
+
For each ticket: AUQ multi-select to accept/decline, then AUQ single-select for decline reason.
|
|
152
|
+
UNCLEAR tickets get a 3-choice prompt: "Accept as BUG / Accept as ENH / Decline".
|
|
153
|
+
|
|
154
|
+
### Step 6: Write-back + Report
|
|
155
|
+
|
|
156
|
+
```js
|
|
157
|
+
await writeback(channel, triageResult, projectRoot); // lib/intake/writeback.cjs
|
|
158
|
+
const reportPath = generateTriageReport(channel, triageResult, projectRoot); // lib/intake/report.cjs
|
|
159
|
+
```
|
|
160
|
+
|
|
161
|
+
Write-back failure → warn (non-fatal), report is still generated.
|
|
162
|
+
|
|
163
|
+
### Step 7: Completion banner
|
|
164
|
+
|
|
165
|
+
```
|
|
166
|
+
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
|
167
|
+
VIEPILOT ► INTAKE COMPLETE ✓
|
|
168
|
+
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
|
169
|
+
|
|
170
|
+
Channel: {channel.name}
|
|
171
|
+
Accepted: {N} → {request IDs}
|
|
172
|
+
Declined: {N}
|
|
173
|
+
Report: .viepilot/intake/TRIAGE-{timestamp}.md
|
|
174
|
+
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
|
175
|
+
```
|
|
176
|
+
|
|
177
|
+
### Step 8: Next action (AUQ single-select)
|
|
178
|
+
|
|
179
|
+
```
|
|
180
|
+
question: "Triage complete. What would you like to do next?"
|
|
181
|
+
options:
|
|
182
|
+
- "Execute accepted requests → /vp-auto" (Recommended)
|
|
183
|
+
- "Plan phase/tasks → /vp-evolve"
|
|
184
|
+
- "Import from another channel → /vp-intake"
|
|
185
|
+
- "Done for now"
|
|
186
|
+
```
|
|
187
|
+
|
|
188
|
+
</process>
|
|
189
|
+
|
|
190
|
+
<success_criteria>
|
|
191
|
+
- [ ] Channels loaded from `.viepilot/intake/channels.json`
|
|
192
|
+
- [ ] Correct adapter dispatched based on channel type
|
|
193
|
+
- [ ] Tickets classified as BUG / ENH / UNCLEAR
|
|
194
|
+
- [ ] AUQ multi-select triage completed with accept/decline per ticket
|
|
195
|
+
- [ ] Decline reasons collected and attached
|
|
196
|
+
- [ ] Accepted tickets auto-create `.viepilot/requests/` files
|
|
197
|
+
- [ ] Write-back updates source (non-fatal on failure)
|
|
198
|
+
- [ ] TRIAGE session report generated at `.viepilot/intake/TRIAGE-{timestamp}.md`
|
|
199
|
+
</success_criteria>
|
|
200
|
+
|
|
201
|
+
## Adapter Compatibility
|
|
202
|
+
|
|
203
|
+
### AskUserQuestion Tool (ENH-059)
|
|
204
|
+
|
|
205
|
+
| Adapter | Interactive Prompts | Notes |
|
|
206
|
+
|---------|---------------------|-------|
|
|
207
|
+
| Claude Code (terminal) | ✅ `AskUserQuestion` — REQUIRED | Preload via ToolSearch before first call |
|
|
208
|
+
| Cursor (Agent/Skills) | ❌ Text fallback | Plain numbered list |
|
|
209
|
+
| Codex CLI | ❌ Text fallback | N/A |
|
|
210
|
+
| Antigravity | ❌ Text fallback | N/A |
|
|
211
|
+
| GitHub Copilot | ✅ Text fallback | Via `.agent.md` |
|
|
212
|
+
|
|
213
|
+
**Prompts in this skill:**
|
|
214
|
+
- Channel selection (Step 3)
|
|
215
|
+
- Ticket accept/decline multi-select (Step 5)
|
|
216
|
+
- Decline reason (Step 5)
|
|
217
|
+
- UNCLEAR handling (Step 5)
|
|
218
|
+
- Next action (Step 8)
|
|
219
|
+
|
|
220
|
+
## Capabilities
|
|
221
|
+
- Read tickets from Excel/Microsoft 365 Online via Microsoft Graph API
|
|
222
|
+
- Read tickets from Google Sheets via Sheets API v4
|
|
223
|
+
- Read tickets from local CSV/TSV files
|
|
224
|
+
- Auto-classify tickets as BUG/ENH/UNCLEAR with Vietnamese keyword support
|
|
225
|
+
- Interactive triage with AskUserQuestion (multi-select, paginated)
|
|
226
|
+
- Write-back VP_Status/VP_Comment/VP_RequestID to source
|
|
227
|
+
- Generate TRIAGE session report in .viepilot/intake/
|
|
228
|
+
|
|
229
|
+
## Tags
|
|
230
|
+
intake, tickets, triage, excel, google-sheets, csv, bug-import, enh-import, external-sources
|
|
231
|
+
|
|
232
|
+
## Best Practices
|
|
233
|
+
- Always run `intake-init` before first use to scaffold the config
|
|
234
|
+
- Store credentials in `.viepilot/.credentials/` — never commit them
|
|
235
|
+
- Review the TRIAGE report after each session for audit trail
|
|
236
|
+
- Use `--dry-run` to preview classification before creating requests
|