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