yapout 0.3.1 → 0.4.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/dist/index.js +166 -5
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -291,6 +291,29 @@ def main():
|
|
|
291
291
|
prompt += f" about {topic}"
|
|
292
292
|
if persona and persona != "tech lead":
|
|
293
293
|
prompt += f" \u2014 be a {persona}"
|
|
294
|
+
elif action == "compact":
|
|
295
|
+
elif action == "enrich-bundle":
|
|
296
|
+
bundle_id = ticket_id
|
|
297
|
+
prompt = (
|
|
298
|
+
f'Use yapout to enrich a bundle as a single cohesive unit.\\n'
|
|
299
|
+
f'\\n'
|
|
300
|
+
f'1. Call yapout_enrich_bundle with bundleId "{bundle_id}" to claim it and get all findings\\n'
|
|
301
|
+
f'2. Read the codebase to understand the full scope of the bundle\\n'
|
|
302
|
+
f'3. Ask me any clarifying questions about the bundle as a whole (not individual findings)\\n'
|
|
303
|
+
f'4. For each finding, formulate:\\n'
|
|
304
|
+
f' - A refined title\\n'
|
|
305
|
+
f' - A specific description\\n'
|
|
306
|
+
f' - Concrete acceptance criteria\\n'
|
|
307
|
+
f' - An implementation brief\\n'
|
|
308
|
+
f'5. Also formulate bundle-level:\\n'
|
|
309
|
+
f' - An overall description of what the bundle delivers\\n'
|
|
310
|
+
f' - Combined acceptance criteria\\n'
|
|
311
|
+
f' - An architecture/approach brief that covers the full scope\\n'
|
|
312
|
+
f'6. Call yapout_save_bundle_enrichment with ALL enrichment data at once\\n'
|
|
313
|
+
f'\\n'
|
|
314
|
+
f'Treat this as ONE problem, not separate findings. Understand how they relate,\\n'
|
|
315
|
+
f'identify dependencies, and write briefs that reference each other.'
|
|
316
|
+
)
|
|
294
317
|
elif action == "compact":
|
|
295
318
|
prompt = "Run yapout_compact to update the project context summary."
|
|
296
319
|
else:
|
|
@@ -2055,7 +2078,7 @@ This tool saves the enrichment, then automatically creates the Linear issue with
|
|
|
2055
2078
|
- Clarification Q&A as a branded comment (if any)
|
|
2056
2079
|
- Implementation brief as attachment metadata
|
|
2057
2080
|
|
|
2058
|
-
The finding transitions: enriching \u2192 enriched \u2192
|
|
2081
|
+
The finding transitions: enriching \u2192 enriched \u2192 ready.`,
|
|
2059
2082
|
{
|
|
2060
2083
|
findingId: z11.string().describe("The finding ID to enrich (from yapout_get_unenriched_finding)"),
|
|
2061
2084
|
title: z11.string().describe("Refined finding title \u2014 improve it if the original was vague"),
|
|
@@ -2115,7 +2138,7 @@ The finding transitions: enriching \u2192 enriched \u2192 synced.`,
|
|
|
2115
2138
|
linearIssueId: finding?.linearIssueId ?? null,
|
|
2116
2139
|
linearIssueUrl: finding?.linearIssueUrl ?? null,
|
|
2117
2140
|
compactionHint,
|
|
2118
|
-
message: finding?.linearIssueUrl ? `Finding enriched and
|
|
2141
|
+
message: finding?.linearIssueUrl ? `Finding enriched and ready in Linear: ${finding.linearIssueUrl}` : "Finding enriched and ready in Linear."
|
|
2119
2142
|
};
|
|
2120
2143
|
if (args.isOversized && args.suggestedSplit?.length) {
|
|
2121
2144
|
response.warning = `This finding is oversized. Suggested split: ${args.suggestedSplit.join(", ")}`;
|
|
@@ -2996,6 +3019,121 @@ When done=true, all findings have been processed.`,
|
|
|
2996
3019
|
);
|
|
2997
3020
|
}
|
|
2998
3021
|
|
|
3022
|
+
// src/mcp/tools/enrich-bundle.ts
|
|
3023
|
+
import { z as z20 } from "zod";
|
|
3024
|
+
function registerEnrichBundleTool(server, ctx) {
|
|
3025
|
+
server.tool(
|
|
3026
|
+
"yapout_enrich_bundle",
|
|
3027
|
+
`Claim an entire bundle for enrichment. Returns ALL findings in the bundle at once
|
|
3028
|
+
with their relationships, source quotes, and project context.
|
|
3029
|
+
|
|
3030
|
+
This is for enriching a bundle as a single cohesive unit \u2014 NOT individual findings.
|
|
3031
|
+
The agent should understand the full scope, ask questions about the bundle as a whole,
|
|
3032
|
+
then call yapout_save_bundle_enrichment with enrichment data for every finding.
|
|
3033
|
+
|
|
3034
|
+
The bundle and all its findings transition to "enriching" status.`,
|
|
3035
|
+
{
|
|
3036
|
+
bundleId: z20.string().describe("The bundle ID to enrich")
|
|
3037
|
+
},
|
|
3038
|
+
async (args) => {
|
|
3039
|
+
try {
|
|
3040
|
+
const result = await ctx.client.mutation(
|
|
3041
|
+
anyApi2.functions.bundles.claimBundleForEnrichment,
|
|
3042
|
+
{ bundleId: args.bundleId }
|
|
3043
|
+
);
|
|
3044
|
+
if (!result) {
|
|
3045
|
+
return {
|
|
3046
|
+
content: [{ type: "text", text: "Failed to claim bundle for enrichment." }],
|
|
3047
|
+
isError: true
|
|
3048
|
+
};
|
|
3049
|
+
}
|
|
3050
|
+
return {
|
|
3051
|
+
content: [
|
|
3052
|
+
{
|
|
3053
|
+
type: "text",
|
|
3054
|
+
text: JSON.stringify(result, null, 2)
|
|
3055
|
+
}
|
|
3056
|
+
]
|
|
3057
|
+
};
|
|
3058
|
+
} catch (err) {
|
|
3059
|
+
return {
|
|
3060
|
+
content: [{ type: "text", text: `Error claiming bundle: ${err.message}` }],
|
|
3061
|
+
isError: true
|
|
3062
|
+
};
|
|
3063
|
+
}
|
|
3064
|
+
}
|
|
3065
|
+
);
|
|
3066
|
+
}
|
|
3067
|
+
|
|
3068
|
+
// src/mcp/tools/save-bundle-enrichment.ts
|
|
3069
|
+
import { z as z21 } from "zod";
|
|
3070
|
+
function registerSaveBundleEnrichmentTool(server, ctx) {
|
|
3071
|
+
server.tool(
|
|
3072
|
+
"yapout_save_bundle_enrichment",
|
|
3073
|
+
`Save enrichment for an entire bundle at once. Call this after you've analyzed all
|
|
3074
|
+
findings in the bundle as a cohesive unit, read the codebase, and asked any questions.
|
|
3075
|
+
|
|
3076
|
+
Provide:
|
|
3077
|
+
- Bundle-level: overall description, combined acceptance criteria, implementation brief
|
|
3078
|
+
- Per-finding: each finding gets its own refined title, description, acceptance criteria, and brief
|
|
3079
|
+
|
|
3080
|
+
The bundle and all findings transition from "enriching" to "enriched".
|
|
3081
|
+
Call yapout_sync_bundle_to_linear afterwards to create the Linear project.`,
|
|
3082
|
+
{
|
|
3083
|
+
bundleId: z21.string().describe("The bundle ID"),
|
|
3084
|
+
title: z21.string().optional().describe("Refined bundle title (optional, keeps existing if omitted)"),
|
|
3085
|
+
enrichedDescription: z21.string().describe("Bundle-level description \u2014 the cohesive story of what this bundle delivers"),
|
|
3086
|
+
acceptanceCriteria: z21.array(z21.string()).describe("Bundle-level acceptance criteria"),
|
|
3087
|
+
implementationBrief: z21.string().describe("Bundle-level implementation brief \u2014 overall approach, architecture decisions, key files"),
|
|
3088
|
+
findings: z21.array(z21.object({
|
|
3089
|
+
findingId: z21.string().describe("Finding ID"),
|
|
3090
|
+
title: z21.string().describe("Refined finding title"),
|
|
3091
|
+
enrichedDescription: z21.string().describe("Finding-specific description"),
|
|
3092
|
+
acceptanceCriteria: z21.array(z21.string()).describe("Finding-specific acceptance criteria"),
|
|
3093
|
+
implementationBrief: z21.string().describe("Finding-specific implementation brief")
|
|
3094
|
+
})).describe("Per-finding enrichment data \u2014 one entry per finding in the bundle")
|
|
3095
|
+
},
|
|
3096
|
+
async (args) => {
|
|
3097
|
+
try {
|
|
3098
|
+
await ctx.client.mutation(
|
|
3099
|
+
anyApi2.functions.bundles.saveBundleEnrichment,
|
|
3100
|
+
{
|
|
3101
|
+
bundleId: args.bundleId,
|
|
3102
|
+
title: args.title,
|
|
3103
|
+
enrichedDescription: args.enrichedDescription,
|
|
3104
|
+
acceptanceCriteria: args.acceptanceCriteria,
|
|
3105
|
+
implementationBrief: args.implementationBrief,
|
|
3106
|
+
findings: args.findings.map((f) => ({
|
|
3107
|
+
findingId: f.findingId,
|
|
3108
|
+
title: f.title,
|
|
3109
|
+
enrichedDescription: f.enrichedDescription,
|
|
3110
|
+
acceptanceCriteria: f.acceptanceCriteria,
|
|
3111
|
+
implementationBrief: f.implementationBrief
|
|
3112
|
+
}))
|
|
3113
|
+
}
|
|
3114
|
+
);
|
|
3115
|
+
return {
|
|
3116
|
+
content: [
|
|
3117
|
+
{
|
|
3118
|
+
type: "text",
|
|
3119
|
+
text: JSON.stringify({
|
|
3120
|
+
bundleId: args.bundleId,
|
|
3121
|
+
findingsEnriched: args.findings.length,
|
|
3122
|
+
message: `Bundle enriched successfully (${args.findings.length} findings). Call yapout_sync_bundle_to_linear to create the Linear project.`
|
|
3123
|
+
}, null, 2)
|
|
3124
|
+
}
|
|
3125
|
+
]
|
|
3126
|
+
};
|
|
3127
|
+
} catch (err) {
|
|
3128
|
+
return {
|
|
3129
|
+
content: [{ type: "text", text: `Error saving bundle enrichment: ${err.message}` }],
|
|
3130
|
+
isError: true
|
|
3131
|
+
};
|
|
3132
|
+
}
|
|
3133
|
+
}
|
|
3134
|
+
);
|
|
3135
|
+
}
|
|
3136
|
+
|
|
2999
3137
|
// src/mcp/server.ts
|
|
3000
3138
|
async function startMcpServer() {
|
|
3001
3139
|
const cwd = process.cwd();
|
|
@@ -3050,6 +3188,8 @@ async function startMcpServer() {
|
|
|
3050
3188
|
registerGetLinearProjectsTool(server, ctx);
|
|
3051
3189
|
registerStartEnrichmentTool(server, ctx);
|
|
3052
3190
|
registerEnrichNextTool(server, ctx);
|
|
3191
|
+
registerEnrichBundleTool(server, ctx);
|
|
3192
|
+
registerSaveBundleEnrichmentTool(server, ctx);
|
|
3053
3193
|
const transport = new StdioServerTransport();
|
|
3054
3194
|
await server.connect(transport);
|
|
3055
3195
|
}
|
|
@@ -4141,7 +4281,7 @@ import { Command as Command15 } from "commander";
|
|
|
4141
4281
|
import { spawn as spawn2 } from "child_process";
|
|
4142
4282
|
import { platform as platform2 } from "os";
|
|
4143
4283
|
import chalk16 from "chalk";
|
|
4144
|
-
var VALID_ACTIONS = ["claim", "enrich", "enrich-bulk", "yap", "compact"];
|
|
4284
|
+
var VALID_ACTIONS = ["claim", "enrich", "enrich-bulk", "enrich-bundle", "yap", "compact"];
|
|
4145
4285
|
function parseYapoutUri(raw) {
|
|
4146
4286
|
const url = new URL(raw);
|
|
4147
4287
|
const action = url.hostname;
|
|
@@ -4151,8 +4291,8 @@ function parseYapoutUri(raw) {
|
|
|
4151
4291
|
);
|
|
4152
4292
|
}
|
|
4153
4293
|
const ticketId = url.pathname.replace(/^\//, "") || void 0;
|
|
4154
|
-
if ((action === "claim" || action === "enrich") && !ticketId) {
|
|
4155
|
-
throw new Error(`Missing
|
|
4294
|
+
if ((action === "claim" || action === "enrich" || action === "enrich-bundle") && !ticketId) {
|
|
4295
|
+
throw new Error(`Missing ID in URI: ${raw}`);
|
|
4156
4296
|
}
|
|
4157
4297
|
return {
|
|
4158
4298
|
action,
|
|
@@ -4209,6 +4349,27 @@ function buildPrompt(parsed) {
|
|
|
4209
4349
|
}
|
|
4210
4350
|
return lines.join("\n");
|
|
4211
4351
|
}
|
|
4352
|
+
case "enrich-bundle":
|
|
4353
|
+
return [
|
|
4354
|
+
`Use yapout to enrich a bundle as a single cohesive unit.`,
|
|
4355
|
+
``,
|
|
4356
|
+
`1. Call yapout_enrich_bundle with bundleId "${parsed.ticketId}" to claim it and get all findings`,
|
|
4357
|
+
`2. Read the codebase to understand the full scope of the bundle`,
|
|
4358
|
+
`3. Ask me any clarifying questions about the bundle as a whole (not individual findings)`,
|
|
4359
|
+
`4. For each finding, formulate:`,
|
|
4360
|
+
` - A refined title`,
|
|
4361
|
+
` - A specific description`,
|
|
4362
|
+
` - Concrete acceptance criteria`,
|
|
4363
|
+
` - An implementation brief`,
|
|
4364
|
+
`5. Also formulate bundle-level:`,
|
|
4365
|
+
` - An overall description of what the bundle delivers`,
|
|
4366
|
+
` - Combined acceptance criteria`,
|
|
4367
|
+
` - An architecture/approach brief that covers the full scope`,
|
|
4368
|
+
`6. Call yapout_save_bundle_enrichment with ALL enrichment data at once`,
|
|
4369
|
+
``,
|
|
4370
|
+
`Treat this as ONE problem, not separate findings. Understand how they relate,`,
|
|
4371
|
+
`identify dependencies, and write briefs that reference each other.`
|
|
4372
|
+
].join("\n");
|
|
4212
4373
|
case "yap": {
|
|
4213
4374
|
const parts = ["Let's have a yap session"];
|
|
4214
4375
|
if (parsed.topic) parts[0] += ` about ${parsed.topic}`;
|