@vibesharingapp/mcp-server 0.5.0 → 0.6.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.
- package/README.md +8 -4
- package/dist/index.js +283 -3
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -73,11 +73,13 @@ Sign up at [vibesharing.app](https://vibesharing.app), then go to [Account Setti
|
|
|
73
73
|
### 2. Configure Claude Code
|
|
74
74
|
|
|
75
75
|
```bash
|
|
76
|
-
claude mcp add vibesharing \
|
|
77
|
-
-e VIBESHARING_TOKEN=
|
|
76
|
+
claude mcp add vibesharing -s user \
|
|
77
|
+
-e VIBESHARING_TOKEN=vs_PASTE_YOUR_TOKEN \
|
|
78
78
|
-- npx -y @vibesharingapp/mcp-server@latest
|
|
79
79
|
```
|
|
80
80
|
|
|
81
|
+
> **Important:** Replace `vs_PASTE_YOUR_TOKEN` with your actual token. Use `-s user` so it works in all projects. Then restart Claude Code.
|
|
82
|
+
|
|
81
83
|
Or add to your Claude Code settings manually:
|
|
82
84
|
|
|
83
85
|
```json
|
|
@@ -199,7 +201,9 @@ VibeSharing isn't just another tool to check. It's infrastructure for teams buil
|
|
|
199
201
|
**Stop building in isolation. Start shipping with your team.**
|
|
200
202
|
|
|
201
203
|
```bash
|
|
202
|
-
claude mcp add vibesharing \
|
|
203
|
-
-e VIBESHARING_TOKEN=
|
|
204
|
+
claude mcp add vibesharing -s user \
|
|
205
|
+
-e VIBESHARING_TOKEN=vs_PASTE_YOUR_TOKEN \
|
|
204
206
|
-- npx -y @vibesharingapp/mcp-server@latest
|
|
205
207
|
```
|
|
208
|
+
|
|
209
|
+
> **Important:** Replace `vs_PASTE_YOUR_TOKEN` with your actual token. Use `-s user` so it works in all projects. Then restart Claude Code.
|
package/dist/index.js
CHANGED
|
@@ -78,6 +78,7 @@ class VibesharingClient {
|
|
|
78
78
|
status: updates.status,
|
|
79
79
|
priority: updates.priority,
|
|
80
80
|
assignedTo: updates.assigned_to,
|
|
81
|
+
resolutionNote: updates.resolution_note,
|
|
81
82
|
}),
|
|
82
83
|
});
|
|
83
84
|
}
|
|
@@ -88,6 +89,7 @@ class VibesharingClient {
|
|
|
88
89
|
status: updates.status,
|
|
89
90
|
priority: updates.priority,
|
|
90
91
|
assignedTo: updates.assigned_to,
|
|
92
|
+
resolutionNote: updates.resolution_note,
|
|
91
93
|
}),
|
|
92
94
|
});
|
|
93
95
|
}
|
|
@@ -162,6 +164,31 @@ class VibesharingClient {
|
|
|
162
164
|
method: "DELETE",
|
|
163
165
|
});
|
|
164
166
|
}
|
|
167
|
+
async generateFeedbackTopics(projectId, topics) {
|
|
168
|
+
return this.request("/api/feedback-topics", {
|
|
169
|
+
method: "POST",
|
|
170
|
+
body: JSON.stringify({
|
|
171
|
+
projectId,
|
|
172
|
+
topics,
|
|
173
|
+
source: "auto",
|
|
174
|
+
}),
|
|
175
|
+
});
|
|
176
|
+
}
|
|
177
|
+
async notifyFeedbackResolved(projectId, feedbackIds, deployUrl) {
|
|
178
|
+
return this.request("/api/feedback/notify-resolved", {
|
|
179
|
+
method: "POST",
|
|
180
|
+
body: JSON.stringify({ projectId, feedbackIds, deployUrl }),
|
|
181
|
+
});
|
|
182
|
+
}
|
|
183
|
+
async updateFeedbackBrief(projectId, brief, focus) {
|
|
184
|
+
const updates = { feedback_brief: brief };
|
|
185
|
+
if (focus)
|
|
186
|
+
updates.feedback_focus = focus;
|
|
187
|
+
return this.request(`/api/prototypes/${projectId}`, {
|
|
188
|
+
method: "PATCH",
|
|
189
|
+
body: JSON.stringify(updates),
|
|
190
|
+
});
|
|
191
|
+
}
|
|
165
192
|
}
|
|
166
193
|
/**
|
|
167
194
|
* Simple fuzzy text matching. Scores based on:
|
|
@@ -207,8 +234,18 @@ function fuzzyMatch(query, items, getName, threshold = 0.3) {
|
|
|
207
234
|
.sort((a, b) => b.score - a.score);
|
|
208
235
|
}
|
|
209
236
|
// ---- Version tracking & What's New ----
|
|
210
|
-
const CURRENT_VERSION = "0.
|
|
237
|
+
const CURRENT_VERSION = "0.6.0";
|
|
211
238
|
const WHATS_NEW = {
|
|
239
|
+
"0.6.0": [
|
|
240
|
+
"🆕 VibeSharing MCP v0.6.0 — What's New:",
|
|
241
|
+
"",
|
|
242
|
+
"• Auto-generated feedback questions — After deploying, use generate_feedback_topics",
|
|
243
|
+
" to create 3-5 targeted questions that guide stakeholders toward useful feedback.",
|
|
244
|
+
" Questions are categorized by theme: vision alignment, feasibility, design fidelity,",
|
|
245
|
+
" or interaction design. Previous auto-generated questions are replaced on each deploy.",
|
|
246
|
+
"• Feedback briefs — Include a brief parameter to set context stakeholders see in the",
|
|
247
|
+
" Context tab. Also auto-extracted from ## Feedback Brief in CLAUDE.md at deploy time.",
|
|
248
|
+
].join("\n"),
|
|
212
249
|
"0.5.0": [
|
|
213
250
|
"🆕 VibeSharing MCP v0.5.0 — What's New:",
|
|
214
251
|
"",
|
|
@@ -266,13 +303,25 @@ const VIBESHARING_TOKEN = process.env.VIBESHARING_TOKEN;
|
|
|
266
303
|
if (!VIBESHARING_TOKEN) {
|
|
267
304
|
console.error("Error: VIBESHARING_TOKEN environment variable is required");
|
|
268
305
|
console.error("Get your deploy token from VibeSharing → Account Settings");
|
|
306
|
+
console.error("");
|
|
307
|
+
console.error("Quick setup:");
|
|
308
|
+
console.error(" claude mcp add vibesharing -s user -e VIBESHARING_TOKEN=vs_YOUR_TOKEN -- npx -y @vibesharingapp/mcp-server@latest");
|
|
309
|
+
process.exit(1);
|
|
310
|
+
}
|
|
311
|
+
if (VIBESHARING_TOKEN === "vs_your_token_here" || VIBESHARING_TOKEN.length < 10) {
|
|
312
|
+
console.error("Error: VIBESHARING_TOKEN is still the placeholder value");
|
|
313
|
+
console.error("Replace it with your actual deploy token from VibeSharing → Account Settings");
|
|
314
|
+
console.error("");
|
|
315
|
+
console.error("Fix:");
|
|
316
|
+
console.error(" claude mcp remove vibesharing");
|
|
317
|
+
console.error(" claude mcp add vibesharing -s user -e VIBESHARING_TOKEN=vs_YOUR_TOKEN -- npx -y @vibesharingapp/mcp-server@latest");
|
|
269
318
|
process.exit(1);
|
|
270
319
|
}
|
|
271
320
|
const client = new VibesharingClient(VIBESHARING_URL, VIBESHARING_TOKEN);
|
|
272
321
|
// Create MCP server
|
|
273
322
|
const server = new index_js_1.Server({
|
|
274
323
|
name: "vibesharing",
|
|
275
|
-
version: "0.
|
|
324
|
+
version: "0.6.1",
|
|
276
325
|
}, {
|
|
277
326
|
capabilities: {
|
|
278
327
|
tools: {},
|
|
@@ -398,10 +447,55 @@ server.setRequestHandler(types_js_1.ListToolsRequestSchema, async () => {
|
|
|
398
447
|
type: "string",
|
|
399
448
|
description: "User ID to assign to. Use empty string to unassign.",
|
|
400
449
|
},
|
|
450
|
+
resolution_note: {
|
|
451
|
+
type: "string",
|
|
452
|
+
description: "Brief explanation of how the feedback was addressed (shown to the stakeholder). Only meaningful when status is resolved/wont_fix/deferred.",
|
|
453
|
+
},
|
|
401
454
|
},
|
|
402
455
|
required: ["feedback_ids"],
|
|
403
456
|
},
|
|
404
457
|
},
|
|
458
|
+
{
|
|
459
|
+
name: "close_feedback_loop",
|
|
460
|
+
description: "CALL THIS AFTER DEPLOYING when there is open feedback. Matches what you just built to open feedback items, resolves them with explanations, and notifies the original stakeholders with a personalized digest. The stakeholder sees exactly what happened to their feedback.\n\nFlow:\n1. Pull open feedback via get_feedback\n2. Look at what you built and match changes to feedback items\n3. Call this tool with the resolutions\n4. Stakeholders get email: 'Your feedback was addressed' with per-item explanations",
|
|
461
|
+
inputSchema: {
|
|
462
|
+
type: "object",
|
|
463
|
+
properties: {
|
|
464
|
+
project_id: {
|
|
465
|
+
type: "string",
|
|
466
|
+
description: "The VibeSharing prototype ID",
|
|
467
|
+
},
|
|
468
|
+
resolutions: {
|
|
469
|
+
type: "array",
|
|
470
|
+
items: {
|
|
471
|
+
type: "object",
|
|
472
|
+
properties: {
|
|
473
|
+
feedback_id: {
|
|
474
|
+
type: "string",
|
|
475
|
+
description: "The feedback item ID being resolved",
|
|
476
|
+
},
|
|
477
|
+
status: {
|
|
478
|
+
type: "string",
|
|
479
|
+
enum: ["resolved", "wont_fix", "deferred", "in_progress"],
|
|
480
|
+
description: "What happened: resolved (fixed), wont_fix (intentional), deferred (later), in_progress (started but not done)",
|
|
481
|
+
},
|
|
482
|
+
note: {
|
|
483
|
+
type: "string",
|
|
484
|
+
description: "Brief explanation of what changed or why it was deferred. This is shown directly to the stakeholder. Be specific: 'Nav restructured to separate admin and user flows' not 'Fixed the navigation'.",
|
|
485
|
+
},
|
|
486
|
+
},
|
|
487
|
+
required: ["feedback_id", "status", "note"],
|
|
488
|
+
},
|
|
489
|
+
description: "Array of feedback items to resolve with explanations",
|
|
490
|
+
},
|
|
491
|
+
deploy_url: {
|
|
492
|
+
type: "string",
|
|
493
|
+
description: "Optional: URL of the new deploy (included in notification so stakeholders can see the update)",
|
|
494
|
+
},
|
|
495
|
+
},
|
|
496
|
+
required: ["project_id", "resolutions"],
|
|
497
|
+
},
|
|
498
|
+
},
|
|
405
499
|
{
|
|
406
500
|
name: "sync_context",
|
|
407
501
|
description: "Sync your CLAUDE.md, AGENTS.md, or project context to VibeSharing. This helps maintain context across AI sessions and team members.",
|
|
@@ -654,6 +748,52 @@ server.setRequestHandler(types_js_1.ListToolsRequestSchema, async () => {
|
|
|
654
748
|
required: ["link_id"],
|
|
655
749
|
},
|
|
656
750
|
},
|
|
751
|
+
{
|
|
752
|
+
name: "generate_feedback_topics",
|
|
753
|
+
description: "Auto-generate feedback questions for a prototype based on what was built. IMPORTANT: Before generating questions, ask the user: 'What type of feedback is most important for this deploy?' and present these options:\n\n 1. Awareness only — just sharing progress, no feedback needed\n 2. Design direction — brand, visual, layout feedback\n 3. Technical feasibility — is this buildable, are these features doable\n 4. Vision alignment — does this match where we're going\n 5. Interaction design — usability, flow, UX patterns\n 6. Full review — all feedback welcome (default)\n\nUse their answer as the 'focus' parameter. If 'awareness', skip topic generation and just set the brief. Otherwise generate 3-5 questions, weighting toward the chosen focus theme.",
|
|
754
|
+
inputSchema: {
|
|
755
|
+
type: "object",
|
|
756
|
+
properties: {
|
|
757
|
+
project_id: {
|
|
758
|
+
type: "string",
|
|
759
|
+
description: "The VibeSharing prototype ID",
|
|
760
|
+
},
|
|
761
|
+
focus: {
|
|
762
|
+
type: "string",
|
|
763
|
+
enum: ["awareness", "design", "feasibility", "vision", "interaction", "full"],
|
|
764
|
+
description: "The type of feedback the designer wants. 'awareness' = no questions, just FYI. Others emphasize that theme. 'full' = all themes equally. Default: 'full'.",
|
|
765
|
+
},
|
|
766
|
+
brief: {
|
|
767
|
+
type: "string",
|
|
768
|
+
description: "A short (2-4 sentence) feedback brief explaining what this prototype is and what's ready for review. Stored on the prototype and shown to stakeholders in the Context tab.",
|
|
769
|
+
},
|
|
770
|
+
topics: {
|
|
771
|
+
type: "array",
|
|
772
|
+
items: {
|
|
773
|
+
type: "object",
|
|
774
|
+
properties: {
|
|
775
|
+
title: {
|
|
776
|
+
type: "string",
|
|
777
|
+
description: "The feedback question (e.g., 'Does this navigation flow match how your team actually works?')",
|
|
778
|
+
},
|
|
779
|
+
description: {
|
|
780
|
+
type: "string",
|
|
781
|
+
description: "Optional: Additional context for the question",
|
|
782
|
+
},
|
|
783
|
+
theme: {
|
|
784
|
+
type: "string",
|
|
785
|
+
enum: ["vision", "feasibility", "design", "interaction"],
|
|
786
|
+
description: "Question theme: 'vision' (alignment with goals), 'feasibility' (technical possibility), 'design' (brand/visual fidelity), 'interaction' (usability/UX patterns)",
|
|
787
|
+
},
|
|
788
|
+
},
|
|
789
|
+
required: ["title"],
|
|
790
|
+
},
|
|
791
|
+
description: "Array of feedback questions to create. Generate 3-5 based on what you built. Weight toward the focus theme (e.g., if focus is 'feasibility', 2-3 questions should be feasibility-themed). Not required when focus is 'awareness'.",
|
|
792
|
+
},
|
|
793
|
+
},
|
|
794
|
+
required: ["project_id"],
|
|
795
|
+
},
|
|
796
|
+
},
|
|
657
797
|
],
|
|
658
798
|
};
|
|
659
799
|
});
|
|
@@ -828,7 +968,7 @@ server.setRequestHandler(types_js_1.CallToolRequestSchema, async (request) => {
|
|
|
828
968
|
};
|
|
829
969
|
}
|
|
830
970
|
case "triage_feedback": {
|
|
831
|
-
const { feedback_ids, status: newStatus, priority: newPriority, assigned_to: newAssignee } = args;
|
|
971
|
+
const { feedback_ids, status: newStatus, priority: newPriority, assigned_to: newAssignee, resolution_note } = args;
|
|
832
972
|
if (!feedback_ids || feedback_ids.length === 0) {
|
|
833
973
|
return {
|
|
834
974
|
content: [{ type: "text", text: "Error: feedback_ids array is required" }],
|
|
@@ -841,6 +981,8 @@ server.setRequestHandler(types_js_1.CallToolRequestSchema, async (request) => {
|
|
|
841
981
|
updates.priority = newPriority;
|
|
842
982
|
if (newAssignee !== undefined)
|
|
843
983
|
updates.assigned_to = newAssignee || null;
|
|
984
|
+
if (resolution_note)
|
|
985
|
+
updates.resolution_note = resolution_note;
|
|
844
986
|
const result = await client.triageFeedback(feedback_ids, updates);
|
|
845
987
|
const changes = [];
|
|
846
988
|
if (newStatus)
|
|
@@ -849,6 +991,8 @@ server.setRequestHandler(types_js_1.CallToolRequestSchema, async (request) => {
|
|
|
849
991
|
changes.push(`priority → ${newPriority}`);
|
|
850
992
|
if (newAssignee !== undefined)
|
|
851
993
|
changes.push(newAssignee ? `assigned → ${newAssignee}` : "unassigned");
|
|
994
|
+
if (resolution_note)
|
|
995
|
+
changes.push(`note: "${resolution_note}"`);
|
|
852
996
|
return {
|
|
853
997
|
content: [
|
|
854
998
|
{
|
|
@@ -858,6 +1002,63 @@ server.setRequestHandler(types_js_1.CallToolRequestSchema, async (request) => {
|
|
|
858
1002
|
],
|
|
859
1003
|
};
|
|
860
1004
|
}
|
|
1005
|
+
case "close_feedback_loop": {
|
|
1006
|
+
const { project_id, resolutions, deploy_url } = args;
|
|
1007
|
+
if (!resolutions || resolutions.length === 0) {
|
|
1008
|
+
return {
|
|
1009
|
+
content: [{ type: "text", text: "Error: At least one resolution is required." }],
|
|
1010
|
+
};
|
|
1011
|
+
}
|
|
1012
|
+
// Step 1: Resolve each feedback item with its note
|
|
1013
|
+
const resolvedIds = [];
|
|
1014
|
+
const errors = [];
|
|
1015
|
+
for (const res of resolutions) {
|
|
1016
|
+
try {
|
|
1017
|
+
await client.triageFeedback([res.feedback_id], {
|
|
1018
|
+
status: res.status,
|
|
1019
|
+
resolution_note: res.note,
|
|
1020
|
+
});
|
|
1021
|
+
resolvedIds.push(res.feedback_id);
|
|
1022
|
+
}
|
|
1023
|
+
catch (err) {
|
|
1024
|
+
errors.push(`Failed to update ${res.feedback_id}: ${err}`);
|
|
1025
|
+
}
|
|
1026
|
+
}
|
|
1027
|
+
// Step 2: Notify stakeholders
|
|
1028
|
+
let notifyResult = { notified: 0, emailed: 0, stakeholders: 0 };
|
|
1029
|
+
if (resolvedIds.length > 0) {
|
|
1030
|
+
try {
|
|
1031
|
+
notifyResult = await client.notifyFeedbackResolved(project_id, resolvedIds, deploy_url);
|
|
1032
|
+
}
|
|
1033
|
+
catch (err) {
|
|
1034
|
+
errors.push(`Notification failed: ${err}`);
|
|
1035
|
+
}
|
|
1036
|
+
}
|
|
1037
|
+
const statusLabels = {
|
|
1038
|
+
resolved: "Resolved",
|
|
1039
|
+
wont_fix: "Won't fix",
|
|
1040
|
+
deferred: "Deferred",
|
|
1041
|
+
in_progress: "In progress",
|
|
1042
|
+
};
|
|
1043
|
+
const lines = [
|
|
1044
|
+
`✅ Feedback loop closed — ${resolvedIds.length} item${resolvedIds.length === 1 ? "" : "s"} updated:`,
|
|
1045
|
+
"",
|
|
1046
|
+
...resolutions.map((r, i) => {
|
|
1047
|
+
const label = statusLabels[r.status] || r.status;
|
|
1048
|
+
const success = resolvedIds.includes(r.feedback_id) ? "✓" : "✗";
|
|
1049
|
+
return ` ${success} [${label}] ${r.note}`;
|
|
1050
|
+
}),
|
|
1051
|
+
];
|
|
1052
|
+
if (notifyResult.stakeholders > 0) {
|
|
1053
|
+
lines.push("", `📬 ${notifyResult.stakeholders} stakeholder${notifyResult.stakeholders === 1 ? "" : "s"} notified (${notifyResult.emailed} email${notifyResult.emailed === 1 ? "" : "s"} sent)`, "Each stakeholder received a personalized digest showing what happened to their specific feedback.");
|
|
1054
|
+
}
|
|
1055
|
+
if (errors.length > 0) {
|
|
1056
|
+
lines.push("", `⚠️ ${errors.length} error(s):`, ...errors.map(e => ` - ${e}`));
|
|
1057
|
+
}
|
|
1058
|
+
return {
|
|
1059
|
+
content: [{ type: "text", text: lines.join("\n") }],
|
|
1060
|
+
};
|
|
1061
|
+
}
|
|
861
1062
|
case "sync_context": {
|
|
862
1063
|
const { project_id, content } = args;
|
|
863
1064
|
await client.syncContext(project_id, content);
|
|
@@ -1284,6 +1485,85 @@ server.setRequestHandler(types_js_1.CallToolRequestSchema, async (request) => {
|
|
|
1284
1485
|
],
|
|
1285
1486
|
};
|
|
1286
1487
|
}
|
|
1488
|
+
case "generate_feedback_topics": {
|
|
1489
|
+
const { project_id, topics, brief, focus } = args;
|
|
1490
|
+
const feedbackFocus = focus || "full";
|
|
1491
|
+
const themeLabels = {
|
|
1492
|
+
vision: "Vision Alignment",
|
|
1493
|
+
feasibility: "Feasibility",
|
|
1494
|
+
design: "Design Fidelity",
|
|
1495
|
+
interaction: "Interaction Design",
|
|
1496
|
+
};
|
|
1497
|
+
const focusLabels = {
|
|
1498
|
+
awareness: "Awareness only",
|
|
1499
|
+
design: "Design direction",
|
|
1500
|
+
feasibility: "Technical feasibility",
|
|
1501
|
+
vision: "Vision alignment",
|
|
1502
|
+
interaction: "Interaction design",
|
|
1503
|
+
full: "Full review",
|
|
1504
|
+
};
|
|
1505
|
+
// Store brief and focus
|
|
1506
|
+
try {
|
|
1507
|
+
await client.updateFeedbackBrief(project_id, brief || "", feedbackFocus);
|
|
1508
|
+
}
|
|
1509
|
+
catch (err) {
|
|
1510
|
+
console.error("Failed to store feedback brief/focus:", err);
|
|
1511
|
+
}
|
|
1512
|
+
// Awareness mode: no questions, just the brief
|
|
1513
|
+
if (feedbackFocus === "awareness") {
|
|
1514
|
+
// Clear any existing auto-generated questions
|
|
1515
|
+
try {
|
|
1516
|
+
await client.generateFeedbackTopics(project_id, []);
|
|
1517
|
+
}
|
|
1518
|
+
catch {
|
|
1519
|
+
// OK if this fails — just means no old auto topics to clear
|
|
1520
|
+
}
|
|
1521
|
+
const lines = [
|
|
1522
|
+
`📢 Prototype set to awareness mode — no feedback questions will be shown.`,
|
|
1523
|
+
];
|
|
1524
|
+
if (brief) {
|
|
1525
|
+
lines.push("", `📋 Brief saved: "${brief.substring(0, 100)}${brief.length > 100 ? "..." : ""}"`);
|
|
1526
|
+
}
|
|
1527
|
+
lines.push("", "Stakeholders will see this as an FYI with the Context tab available.", "They can still leave general comments if they choose to.");
|
|
1528
|
+
return {
|
|
1529
|
+
content: [{ type: "text", text: lines.join("\n") }],
|
|
1530
|
+
};
|
|
1531
|
+
}
|
|
1532
|
+
// All other modes: generate questions
|
|
1533
|
+
if (!topics || topics.length === 0) {
|
|
1534
|
+
return {
|
|
1535
|
+
content: [{ type: "text", text: "Error: At least one topic is required when focus is not 'awareness'." }],
|
|
1536
|
+
};
|
|
1537
|
+
}
|
|
1538
|
+
// Sort topics: focused theme first, then others
|
|
1539
|
+
const sortedTopics = feedbackFocus !== "full"
|
|
1540
|
+
? [
|
|
1541
|
+
...topics.filter(t => t.theme === feedbackFocus),
|
|
1542
|
+
...topics.filter(t => t.theme !== feedbackFocus),
|
|
1543
|
+
]
|
|
1544
|
+
: topics;
|
|
1545
|
+
const result = await client.generateFeedbackTopics(project_id, sortedTopics);
|
|
1546
|
+
const created = result.topics || [];
|
|
1547
|
+
const lines = [
|
|
1548
|
+
`✅ Created ${created.length} feedback question${created.length === 1 ? "" : "s"} (focus: ${focusLabels[feedbackFocus] || feedbackFocus}):`,
|
|
1549
|
+
"",
|
|
1550
|
+
...created.map((t, i) => {
|
|
1551
|
+
const tag = t.theme ? ` [${themeLabels[t.theme] || t.theme}]` : "";
|
|
1552
|
+
const star = t.theme === feedbackFocus ? " ★" : "";
|
|
1553
|
+
return ` ${i + 1}. ${t.title}${tag}${star}`;
|
|
1554
|
+
}),
|
|
1555
|
+
];
|
|
1556
|
+
if (brief) {
|
|
1557
|
+
lines.push("", `📋 Feedback brief saved — stakeholders can see it in the Context tab.`);
|
|
1558
|
+
}
|
|
1559
|
+
if (feedbackFocus !== "full") {
|
|
1560
|
+
lines.push("", `${themeLabels[feedbackFocus] || feedbackFocus} questions are pinned to the top for stakeholders.`);
|
|
1561
|
+
}
|
|
1562
|
+
lines.push("", "Previous auto-generated questions were replaced. Manual questions are untouched.");
|
|
1563
|
+
return {
|
|
1564
|
+
content: [{ type: "text", text: lines.join("\n") }],
|
|
1565
|
+
};
|
|
1566
|
+
}
|
|
1287
1567
|
default:
|
|
1288
1568
|
return {
|
|
1289
1569
|
content: [
|
package/package.json
CHANGED