@papi-ai/server 0.7.1 → 0.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.
- package/dist/index.js +205 -87
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -7674,6 +7674,31 @@ ${r.content}` + (r.carry_forward ? `
|
|
|
7674
7674
|
`;
|
|
7675
7675
|
}
|
|
7676
7676
|
// -------------------------------------------------------------------------
|
|
7677
|
+
// Bug Reports
|
|
7678
|
+
// -------------------------------------------------------------------------
|
|
7679
|
+
async submitBugReport(report) {
|
|
7680
|
+
const [row] = await this.sql`
|
|
7681
|
+
INSERT INTO bug_reports (project_id, user_id, description, diagnostics, status)
|
|
7682
|
+
VALUES (
|
|
7683
|
+
${report.projectId},
|
|
7684
|
+
${report.userId ?? null},
|
|
7685
|
+
${report.description},
|
|
7686
|
+
${JSON.stringify(report.diagnostics)},
|
|
7687
|
+
${report.status}
|
|
7688
|
+
)
|
|
7689
|
+
RETURNING id, created_at
|
|
7690
|
+
`;
|
|
7691
|
+
return {
|
|
7692
|
+
id: row.id,
|
|
7693
|
+
projectId: report.projectId,
|
|
7694
|
+
userId: report.userId,
|
|
7695
|
+
description: report.description,
|
|
7696
|
+
diagnostics: report.diagnostics,
|
|
7697
|
+
status: report.status,
|
|
7698
|
+
createdAt: row.created_at
|
|
7699
|
+
};
|
|
7700
|
+
}
|
|
7701
|
+
// -------------------------------------------------------------------------
|
|
7677
7702
|
// Task Comments (for plan context)
|
|
7678
7703
|
// -------------------------------------------------------------------------
|
|
7679
7704
|
async getRecentTaskComments(limit = 20) {
|
|
@@ -8488,6 +8513,10 @@ Check PAPI_PROJECT_ID in your .mcp.json config. Find your project ID in the PAPI
|
|
|
8488
8513
|
getBuildReportCountForTask(taskId) {
|
|
8489
8514
|
return this.invoke("getBuildReportCountForTask", [taskId]);
|
|
8490
8515
|
}
|
|
8516
|
+
// --- Bug Reports ---
|
|
8517
|
+
submitBugReport(report) {
|
|
8518
|
+
return this.invoke("submitBugReport", [report]);
|
|
8519
|
+
}
|
|
8491
8520
|
// --- Atomic plan write-back ---
|
|
8492
8521
|
planWriteBack(payload) {
|
|
8493
8522
|
return this.invoke("planWriteBack", [payload]);
|
|
@@ -11558,41 +11587,47 @@ async function assembleContext(adapter2, mode, _config, filters, focus) {
|
|
|
11558
11587
|
}
|
|
11559
11588
|
timings["metricsAndReviews"] = t();
|
|
11560
11589
|
t = startTimer();
|
|
11590
|
+
const leanTargetCycle = health.totalCycles + 1;
|
|
11591
|
+
const [
|
|
11592
|
+
reviewPatternsResult,
|
|
11593
|
+
pendingRecsResult,
|
|
11594
|
+
taskCommentsResult,
|
|
11595
|
+
discoveryCanvasResult,
|
|
11596
|
+
calibrationResult,
|
|
11597
|
+
docsResult,
|
|
11598
|
+
cycleLogResult,
|
|
11599
|
+
preAssignedResult,
|
|
11600
|
+
reportsForCapsResult,
|
|
11601
|
+
contextHashesResult
|
|
11602
|
+
] = await Promise.allSettled([
|
|
11603
|
+
detectReviewPatterns(reviews2, health.totalCycles, 5),
|
|
11604
|
+
adapter2.getPendingRecommendations(),
|
|
11605
|
+
assembleTaskComments(adapter2),
|
|
11606
|
+
assembleDiscoveryCanvasText(adapter2),
|
|
11607
|
+
Promise.all([
|
|
11608
|
+
adapter2.getEstimationCalibration?.(),
|
|
11609
|
+
adapter2.getModuleEstimationStats?.()
|
|
11610
|
+
]),
|
|
11611
|
+
adapter2.searchDocs?.({ status: "active", limit: 5 }),
|
|
11612
|
+
adapter2.getCycleLog(5),
|
|
11613
|
+
adapter2.queryBoard({ status: ["Backlog", "In Cycle", "Ready"] }),
|
|
11614
|
+
adapter2.getRecentBuildReports(10),
|
|
11615
|
+
adapter2.getContextHashes?.(health.totalCycles) ?? Promise.resolve(null)
|
|
11616
|
+
]);
|
|
11617
|
+
timings["parallelReads"] = t();
|
|
11561
11618
|
let reviewPatternsText2;
|
|
11562
|
-
|
|
11563
|
-
|
|
11564
|
-
reviewPatternsText2 = hasReviewPatterns(reviewPatterns) ? formatReviewPatterns(reviewPatterns) : void 0;
|
|
11565
|
-
} catch {
|
|
11619
|
+
if (reviewPatternsResult.status === "fulfilled") {
|
|
11620
|
+
reviewPatternsText2 = hasReviewPatterns(reviewPatternsResult.value) ? formatReviewPatterns(reviewPatternsResult.value) : void 0;
|
|
11566
11621
|
}
|
|
11567
11622
|
let strategyRecommendationsText2;
|
|
11568
|
-
|
|
11569
|
-
|
|
11570
|
-
if (pendingRecs.length > 0) {
|
|
11571
|
-
strategyRecommendationsText2 = formatStrategyRecommendations(pendingRecs, health.totalCycles);
|
|
11572
|
-
}
|
|
11573
|
-
} catch {
|
|
11623
|
+
if (pendingRecsResult.status === "fulfilled" && pendingRecsResult.value.length > 0) {
|
|
11624
|
+
strategyRecommendationsText2 = formatStrategyRecommendations(pendingRecsResult.value, health.totalCycles);
|
|
11574
11625
|
}
|
|
11575
|
-
|
|
11576
|
-
|
|
11577
|
-
{ label: "cycleHealth", hasData: !!health },
|
|
11578
|
-
{ label: "productBrief", hasData: warnIfEmpty("productBrief", productBrief) },
|
|
11579
|
-
{ label: "activeDecisions", hasData: warnIfEmpty("activeDecisions (lean)", leanSummary.activeDecisions) },
|
|
11580
|
-
{ label: "buildIntelligence", hasData: warnIfEmpty("buildIntelligence (lean)", leanSummary.buildIntelligence) },
|
|
11581
|
-
{ label: "cycleLog", hasData: warnIfEmpty("cycleLog (lean)", leanSummary.cycleLog) },
|
|
11582
|
-
{ label: "board", hasData: warnIfEmpty("board (lean)", leanSummary.board) },
|
|
11583
|
-
{ label: "metricsSnapshots", hasData: warnIfEmpty("readCycleMetrics", metricsSnapshots2) },
|
|
11584
|
-
{ label: "reviews", hasData: warnIfEmpty("getRecentReviews", reviews2) }
|
|
11585
|
-
]);
|
|
11586
|
-
timings["total"] = totalTimer();
|
|
11587
|
-
console.error(`[plan-perf] assembleContext (lean): ${JSON.stringify(timings)}ms`);
|
|
11588
|
-
const taskCommentsText = await assembleTaskComments(adapter2);
|
|
11589
|
-
const discoveryCanvasText = await assembleDiscoveryCanvasText(adapter2);
|
|
11626
|
+
const taskCommentsText = taskCommentsResult.status === "fulfilled" ? taskCommentsResult.value : void 0;
|
|
11627
|
+
const discoveryCanvasText = discoveryCanvasResult.status === "fulfilled" ? discoveryCanvasResult.value : void 0;
|
|
11590
11628
|
let estimationCalibrationText;
|
|
11591
|
-
|
|
11592
|
-
const [calibrationRows, moduleStats] =
|
|
11593
|
-
adapter2.getEstimationCalibration?.(),
|
|
11594
|
-
adapter2.getModuleEstimationStats?.()
|
|
11595
|
-
]);
|
|
11629
|
+
if (calibrationResult.status === "fulfilled") {
|
|
11630
|
+
const [calibrationRows, moduleStats] = calibrationResult.value;
|
|
11596
11631
|
if (calibrationRows && calibrationRows.length > 0) {
|
|
11597
11632
|
estimationCalibrationText = formatEstimationCalibration(calibrationRows);
|
|
11598
11633
|
}
|
|
@@ -11606,39 +11641,40 @@ async function assembleContext(adapter2, mode, _config, filters, focus) {
|
|
|
11606
11641
|
].join("\n");
|
|
11607
11642
|
estimationCalibrationText = (estimationCalibrationText ?? "") + moduleLines;
|
|
11608
11643
|
}
|
|
11609
|
-
} catch {
|
|
11610
11644
|
}
|
|
11611
11645
|
let registeredDocsText;
|
|
11612
|
-
|
|
11613
|
-
const docs =
|
|
11614
|
-
|
|
11615
|
-
|
|
11616
|
-
registeredDocsText = `${docs.length} active research doc(s):
|
|
11646
|
+
if (docsResult.status === "fulfilled" && docsResult.value && docsResult.value.length > 0) {
|
|
11647
|
+
const docs = docsResult.value;
|
|
11648
|
+
const lines = docs.map((d) => `- **${d.title}** (${d.type}) \u2014 ${d.summary}`);
|
|
11649
|
+
registeredDocsText = `${docs.length} active research doc(s):
|
|
11617
11650
|
${lines.join("\n")}`;
|
|
11618
|
-
}
|
|
11619
|
-
} catch {
|
|
11620
11651
|
}
|
|
11621
11652
|
const boardFlags = detectBoardFlagsFromText(leanSummary.board);
|
|
11622
11653
|
let carryForwardStalenessLean;
|
|
11623
|
-
|
|
11624
|
-
|
|
11625
|
-
carryForwardStalenessLean = computeCarryForwardStaleness(recentLog);
|
|
11626
|
-
} catch {
|
|
11654
|
+
if (cycleLogResult.status === "fulfilled") {
|
|
11655
|
+
carryForwardStalenessLean = computeCarryForwardStaleness(cycleLogResult.value);
|
|
11627
11656
|
}
|
|
11628
|
-
const leanTargetCycle = health.totalCycles + 1;
|
|
11629
11657
|
let preAssignedTextLean;
|
|
11630
|
-
|
|
11631
|
-
const
|
|
11632
|
-
const preAssigned2 = preAssignedTasks.filter((t2) => t2.cycle === leanTargetCycle);
|
|
11658
|
+
if (preAssignedResult.status === "fulfilled") {
|
|
11659
|
+
const preAssigned2 = preAssignedResult.value.filter((t2) => t2.cycle === leanTargetCycle);
|
|
11633
11660
|
preAssignedTextLean = formatPreAssignedTasks(preAssigned2, leanTargetCycle);
|
|
11634
|
-
} catch {
|
|
11635
11661
|
}
|
|
11636
11662
|
let recentlyShippedLean;
|
|
11637
|
-
|
|
11638
|
-
|
|
11639
|
-
recentlyShippedLean = formatRecentlyShippedCapabilities(reportsForCaps);
|
|
11640
|
-
} catch {
|
|
11663
|
+
if (reportsForCapsResult.status === "fulfilled") {
|
|
11664
|
+
recentlyShippedLean = formatRecentlyShippedCapabilities(reportsForCapsResult.value);
|
|
11641
11665
|
}
|
|
11666
|
+
logDataSourceSummary("plan (lean)", [
|
|
11667
|
+
{ label: "cycleHealth", hasData: !!health },
|
|
11668
|
+
{ label: "productBrief", hasData: warnIfEmpty("productBrief", productBrief) },
|
|
11669
|
+
{ label: "activeDecisions", hasData: warnIfEmpty("activeDecisions (lean)", leanSummary.activeDecisions) },
|
|
11670
|
+
{ label: "buildIntelligence", hasData: warnIfEmpty("buildIntelligence (lean)", leanSummary.buildIntelligence) },
|
|
11671
|
+
{ label: "cycleLog", hasData: warnIfEmpty("cycleLog (lean)", leanSummary.cycleLog) },
|
|
11672
|
+
{ label: "board", hasData: warnIfEmpty("board (lean)", leanSummary.board) },
|
|
11673
|
+
{ label: "metricsSnapshots", hasData: warnIfEmpty("readCycleMetrics", metricsSnapshots2) },
|
|
11674
|
+
{ label: "reviews", hasData: warnIfEmpty("getRecentReviews", reviews2) }
|
|
11675
|
+
]);
|
|
11676
|
+
timings["total"] = totalTimer();
|
|
11677
|
+
console.error(`[plan-perf] assembleContext (lean): ${JSON.stringify(timings)}ms`);
|
|
11642
11678
|
let ctx2 = {
|
|
11643
11679
|
mode,
|
|
11644
11680
|
cycleNumber: health.totalCycles,
|
|
@@ -11663,7 +11699,7 @@ ${lines.join("\n")}`;
|
|
|
11663
11699
|
recentlyShippedCapabilities: recentlyShippedLean
|
|
11664
11700
|
};
|
|
11665
11701
|
t = startTimer();
|
|
11666
|
-
const prevHashes2 =
|
|
11702
|
+
const prevHashes2 = contextHashesResult.status === "fulfilled" ? contextHashesResult.value : null;
|
|
11667
11703
|
const { ctx: diffedCtx2, newHashes: newHashes2, savedBytes: savedBytes2 } = applyContextDiff(ctx2, prevHashes2);
|
|
11668
11704
|
ctx2 = diffedCtx2;
|
|
11669
11705
|
timings["contextDiff"] = t();
|
|
@@ -11686,30 +11722,52 @@ ${lines.join("\n")}`;
|
|
|
11686
11722
|
timings["fullQueries"] = t();
|
|
11687
11723
|
const reports = reportsSinceCycle.length > 0 ? reportsSinceCycle : await adapter2.getRecentBuildReports(5);
|
|
11688
11724
|
t = startTimer();
|
|
11725
|
+
const [
|
|
11726
|
+
allReportsResult,
|
|
11727
|
+
reviewPatternsResultFull,
|
|
11728
|
+
pendingRecsResultFull,
|
|
11729
|
+
discoveryCanvasResultFull,
|
|
11730
|
+
taskCommentsResultFull,
|
|
11731
|
+
docsResultFull,
|
|
11732
|
+
contextHashesResultFull
|
|
11733
|
+
] = await Promise.allSettled([
|
|
11734
|
+
adapter2.getRecentBuildReports(50),
|
|
11735
|
+
detectReviewPatterns(reviews, health.totalCycles, 5),
|
|
11736
|
+
adapter2.getPendingRecommendations(),
|
|
11737
|
+
assembleDiscoveryCanvasText(adapter2),
|
|
11738
|
+
assembleTaskComments(adapter2),
|
|
11739
|
+
adapter2.searchDocs?.({ status: "active", limit: 5 }),
|
|
11740
|
+
adapter2.getContextHashes?.(health.totalCycles) ?? Promise.resolve(null)
|
|
11741
|
+
]);
|
|
11742
|
+
timings["parallelAdvisory"] = t();
|
|
11689
11743
|
let buildPatternsText;
|
|
11690
11744
|
let allReportsForPatterns = [];
|
|
11691
|
-
|
|
11692
|
-
allReportsForPatterns =
|
|
11693
|
-
|
|
11694
|
-
|
|
11695
|
-
|
|
11745
|
+
if (allReportsResult.status === "fulfilled") {
|
|
11746
|
+
allReportsForPatterns = allReportsResult.value;
|
|
11747
|
+
try {
|
|
11748
|
+
const patterns = await detectBuildPatterns(allReportsForPatterns, health.totalCycles, 5);
|
|
11749
|
+
buildPatternsText = hasBuildPatterns(patterns) ? formatBuildPatterns(patterns) : void 0;
|
|
11750
|
+
} catch {
|
|
11751
|
+
}
|
|
11696
11752
|
}
|
|
11697
11753
|
let reviewPatternsText;
|
|
11698
|
-
|
|
11699
|
-
|
|
11700
|
-
reviewPatternsText = hasReviewPatterns(reviewPatterns) ? formatReviewPatterns(reviewPatterns) : void 0;
|
|
11701
|
-
} catch {
|
|
11754
|
+
if (reviewPatternsResultFull.status === "fulfilled") {
|
|
11755
|
+
reviewPatternsText = hasReviewPatterns(reviewPatternsResultFull.value) ? formatReviewPatterns(reviewPatternsResultFull.value) : void 0;
|
|
11702
11756
|
}
|
|
11703
11757
|
let strategyRecommendationsText;
|
|
11704
|
-
|
|
11705
|
-
|
|
11706
|
-
if (pendingRecs.length > 0) {
|
|
11707
|
-
strategyRecommendationsText = formatStrategyRecommendations(pendingRecs);
|
|
11708
|
-
}
|
|
11709
|
-
} catch {
|
|
11758
|
+
if (pendingRecsResultFull.status === "fulfilled" && pendingRecsResultFull.value.length > 0) {
|
|
11759
|
+
strategyRecommendationsText = formatStrategyRecommendations(pendingRecsResultFull.value);
|
|
11710
11760
|
}
|
|
11711
|
-
timings["advisory"] = t();
|
|
11712
11761
|
const metricsSnapshots = allReportsForPatterns.length > 0 ? computeSnapshotsFromBuildReports(allReportsForPatterns) : rawMetricsSnapshots.filter((s) => s.accuracy.length > 0 || s.velocity.length > 0);
|
|
11762
|
+
const discoveryCanvasTextFull = discoveryCanvasResultFull.status === "fulfilled" ? discoveryCanvasResultFull.value : void 0;
|
|
11763
|
+
const taskCommentsTextFull = taskCommentsResultFull.status === "fulfilled" ? taskCommentsResultFull.value : void 0;
|
|
11764
|
+
let registeredDocsTextFull;
|
|
11765
|
+
if (docsResultFull.status === "fulfilled" && docsResultFull.value && docsResultFull.value.length > 0) {
|
|
11766
|
+
const docs = docsResultFull.value;
|
|
11767
|
+
const lines = docs.map((d) => `- **${d.title}** (${d.type}) \u2014 ${d.summary}`);
|
|
11768
|
+
registeredDocsTextFull = `${docs.length} active research doc(s):
|
|
11769
|
+
${lines.join("\n")}`;
|
|
11770
|
+
}
|
|
11713
11771
|
logDataSourceSummary("plan (full)", [
|
|
11714
11772
|
{ label: "cycleHealth", hasData: !!health },
|
|
11715
11773
|
{ label: "productBrief", hasData: warnIfEmpty("productBrief", productBrief) },
|
|
@@ -11723,18 +11781,6 @@ ${lines.join("\n")}`;
|
|
|
11723
11781
|
]);
|
|
11724
11782
|
timings["total"] = totalTimer();
|
|
11725
11783
|
console.error(`[plan-perf] assembleContext (full): ${JSON.stringify(timings)}ms`);
|
|
11726
|
-
const discoveryCanvasTextFull = await assembleDiscoveryCanvasText(adapter2);
|
|
11727
|
-
const taskCommentsTextFull = await assembleTaskComments(adapter2);
|
|
11728
|
-
let registeredDocsTextFull;
|
|
11729
|
-
try {
|
|
11730
|
-
const docs = await adapter2.searchDocs?.({ status: "active", limit: 5 });
|
|
11731
|
-
if (docs && docs.length > 0) {
|
|
11732
|
-
const lines = docs.map((d) => `- **${d.title}** (${d.type}) \u2014 ${d.summary}`);
|
|
11733
|
-
registeredDocsTextFull = `${docs.length} active research doc(s):
|
|
11734
|
-
${lines.join("\n")}`;
|
|
11735
|
-
}
|
|
11736
|
-
} catch {
|
|
11737
|
-
}
|
|
11738
11784
|
const MAX_PLAN_BUILD_REPORT_CYCLES = 3;
|
|
11739
11785
|
const cappedReports = reports.length > 0 ? (() => {
|
|
11740
11786
|
const maxCycle = Math.max(...reports.map((r) => r.cycle ?? 0));
|
|
@@ -11773,7 +11819,7 @@ ${lines.join("\n")}`;
|
|
|
11773
11819
|
preAssignedTasks: preAssignedText,
|
|
11774
11820
|
recentlyShippedCapabilities: formatRecentlyShippedCapabilities(allReportsForPatterns)
|
|
11775
11821
|
};
|
|
11776
|
-
const prevHashes =
|
|
11822
|
+
const prevHashes = contextHashesResultFull.status === "fulfilled" ? contextHashesResultFull.value : null;
|
|
11777
11823
|
const { ctx: diffedCtx, newHashes, savedBytes } = applyContextDiff(ctx, prevHashes);
|
|
11778
11824
|
ctx = diffedCtx;
|
|
11779
11825
|
if (savedBytes > 0) {
|
|
@@ -14220,6 +14266,26 @@ ${result.slackWarning}` : "";
|
|
|
14220
14266
|
const header = `**Strategy Review \u2014 Cycle ${result.cycleNumber}**
|
|
14221
14267
|
|
|
14222
14268
|
`;
|
|
14269
|
+
let recsCloseOut = "";
|
|
14270
|
+
try {
|
|
14271
|
+
const pendingRecs = await adapter2.getPendingRecommendations();
|
|
14272
|
+
if (pendingRecs.length > 0) {
|
|
14273
|
+
const recLines = pendingRecs.map(
|
|
14274
|
+
(rec) => `- **[${rec.type}]** ${rec.content.slice(0, 120)}${rec.content.length > 120 ? "..." : ""}${rec.target ? ` (target: ${rec.target})` : ""}`
|
|
14275
|
+
);
|
|
14276
|
+
recsCloseOut = `
|
|
14277
|
+
|
|
14278
|
+
---
|
|
14279
|
+
|
|
14280
|
+
## Pending Recommendations (${pendingRecs.length})
|
|
14281
|
+
|
|
14282
|
+
${recLines.join("\n")}
|
|
14283
|
+
|
|
14284
|
+
**Review these recommendations before running \`plan\`.** Use \`idea\` to convert any into backlog tasks, or dismiss by noting which ones don't apply.
|
|
14285
|
+
`;
|
|
14286
|
+
}
|
|
14287
|
+
} catch {
|
|
14288
|
+
}
|
|
14223
14289
|
const actionReminder = `
|
|
14224
14290
|
|
|
14225
14291
|
---
|
|
@@ -14228,9 +14294,9 @@ ${result.slackWarning}` : "";
|
|
|
14228
14294
|
1. Review the AD changes above \u2014 are any resolved/modified ADs still referenced by active tasks?
|
|
14229
14295
|
2. Act on strategic recommendations \u2014 cancel, defer, or reprioritise tasks as suggested.
|
|
14230
14296
|
3. Run \`strategy_change\` if any recommendation requires an AD update not already captured.
|
|
14231
|
-
4. Run \`/
|
|
14297
|
+
4. Run \`/patch-notes\` to post curated patch notes to Discord.
|
|
14232
14298
|
5. Then run \`plan\` for the next cycle.`;
|
|
14233
|
-
const response = textResponse(header + result.displayText + slackNote + actionReminder);
|
|
14299
|
+
const response = textResponse(header + result.displayText + slackNote + recsCloseOut + actionReminder);
|
|
14234
14300
|
return {
|
|
14235
14301
|
...response,
|
|
14236
14302
|
...contextBytes !== void 0 ? { _contextBytes: contextBytes } : {},
|
|
@@ -17666,6 +17732,7 @@ Re-submit with \`notes: "... Reference: <path>"\` to link one, or ignore if none
|
|
|
17666
17732
|
}
|
|
17667
17733
|
|
|
17668
17734
|
// src/tools/bug.ts
|
|
17735
|
+
import os2 from "os";
|
|
17669
17736
|
init_git();
|
|
17670
17737
|
|
|
17671
17738
|
// src/services/bug.ts
|
|
@@ -17714,15 +17781,26 @@ async function captureBug(adapter2, input) {
|
|
|
17714
17781
|
}
|
|
17715
17782
|
|
|
17716
17783
|
// src/tools/bug.ts
|
|
17784
|
+
function collectDiagnostics(config2) {
|
|
17785
|
+
return {
|
|
17786
|
+
nodeVersion: process.version,
|
|
17787
|
+
platform: os2.platform(),
|
|
17788
|
+
arch: os2.arch(),
|
|
17789
|
+
adapterType: config2.adapterType,
|
|
17790
|
+
projectRoot: config2.projectRoot,
|
|
17791
|
+
hasEndpoint: !!config2.papiEndpoint,
|
|
17792
|
+
lightMode: config2.lightMode
|
|
17793
|
+
};
|
|
17794
|
+
}
|
|
17717
17795
|
var bugTool = {
|
|
17718
17796
|
name: "bug",
|
|
17719
|
-
description:
|
|
17797
|
+
description: "Report a bug. Two modes: (1) Default \u2014 creates a Backlog task with severity-based priority for the project board. (2) With report=true \u2014 submits a diagnostic bug report with system info for cross-project visibility (external user issue reporting). Does not call the Anthropic API.",
|
|
17720
17798
|
inputSchema: {
|
|
17721
17799
|
type: "object",
|
|
17722
17800
|
properties: {
|
|
17723
17801
|
text: {
|
|
17724
17802
|
type: "string",
|
|
17725
|
-
description: "The bug description \u2014 becomes the task title."
|
|
17803
|
+
description: "The bug description \u2014 becomes the task title (default mode) or report description (report mode)."
|
|
17726
17804
|
},
|
|
17727
17805
|
severity: {
|
|
17728
17806
|
type: "string",
|
|
@@ -17744,6 +17822,10 @@ var bugTool = {
|
|
|
17744
17822
|
phase: {
|
|
17745
17823
|
type: "string",
|
|
17746
17824
|
description: "Target phase (default: current active phase)."
|
|
17825
|
+
},
|
|
17826
|
+
report: {
|
|
17827
|
+
type: "boolean",
|
|
17828
|
+
description: "When true, submits a diagnostic bug report with system info instead of creating a board task. Use this to report issues to PAPI maintainers."
|
|
17747
17829
|
}
|
|
17748
17830
|
},
|
|
17749
17831
|
required: ["text"]
|
|
@@ -17754,6 +17836,38 @@ async function handleBug(adapter2, config2, args) {
|
|
|
17754
17836
|
if (!text) {
|
|
17755
17837
|
return errorResponse("text is required \u2014 describe the bug you want to report.");
|
|
17756
17838
|
}
|
|
17839
|
+
if (args.report === true) {
|
|
17840
|
+
if (!adapter2.submitBugReport) {
|
|
17841
|
+
return errorResponse("Bug reports require a database adapter (pg or proxy). The md adapter does not support bug reports.");
|
|
17842
|
+
}
|
|
17843
|
+
const diagnostics = collectDiagnostics(config2);
|
|
17844
|
+
const notes = args.notes?.trim();
|
|
17845
|
+
if (notes) {
|
|
17846
|
+
diagnostics.userNotes = notes;
|
|
17847
|
+
}
|
|
17848
|
+
let projectId;
|
|
17849
|
+
try {
|
|
17850
|
+
const health = await adapter2.getCycleHealth();
|
|
17851
|
+
projectId = adapter2.projectId ?? "unknown";
|
|
17852
|
+
diagnostics.cycleNumber = health.totalCycles;
|
|
17853
|
+
} catch {
|
|
17854
|
+
projectId = "unknown";
|
|
17855
|
+
}
|
|
17856
|
+
const report = await adapter2.submitBugReport({
|
|
17857
|
+
projectId,
|
|
17858
|
+
description: text,
|
|
17859
|
+
diagnostics,
|
|
17860
|
+
status: "open"
|
|
17861
|
+
});
|
|
17862
|
+
return textResponse(
|
|
17863
|
+
`**Bug report submitted** \u2014 ID: \`${report.id}\`
|
|
17864
|
+
|
|
17865
|
+
Description: ${text}
|
|
17866
|
+
Diagnostics collected: Node ${diagnostics.nodeVersion}, ${diagnostics.platform}/${diagnostics.arch}, adapter=${diagnostics.adapterType}
|
|
17867
|
+
|
|
17868
|
+
This report is visible to PAPI maintainers. No further action needed from you.`
|
|
17869
|
+
);
|
|
17870
|
+
}
|
|
17757
17871
|
const MAX_NOTES_LENGTH = 2e3;
|
|
17758
17872
|
let rawNotes = args.notes?.trim();
|
|
17759
17873
|
let notesTruncated = false;
|
|
@@ -17808,10 +17922,14 @@ async function recordAdHoc(adapter2, input) {
|
|
|
17808
17922
|
if (!existing) {
|
|
17809
17923
|
throw new Error(`Task "${input.taskId}" not found on the board. Check the task ID and try again.`);
|
|
17810
17924
|
}
|
|
17811
|
-
|
|
17925
|
+
const updatePayload = {
|
|
17812
17926
|
notes: existing.notes ? `${existing.notes}
|
|
17813
17927
|
[ad-hoc] ${input.notes || "Work recorded via ad_hoc"}` : `[ad-hoc] ${input.notes || "Work recorded via ad_hoc"}`
|
|
17814
|
-
}
|
|
17928
|
+
};
|
|
17929
|
+
if (existing.status === "In Progress") {
|
|
17930
|
+
updatePayload.status = "In Review";
|
|
17931
|
+
}
|
|
17932
|
+
await adapter2.updateTask(input.taskId, updatePayload);
|
|
17815
17933
|
task = await adapter2.getTask(input.taskId);
|
|
17816
17934
|
} else {
|
|
17817
17935
|
const phase = resolveCurrentPhase(phases);
|
package/package.json
CHANGED