@papi-ai/server 0.7.54 → 0.7.56
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/backfill-cycle-metrics.js +12 -8
- package/dist/index.js +70 -36
- package/package.json +2 -2
|
@@ -1065,7 +1065,7 @@ var init_install_id = __esm({
|
|
|
1065
1065
|
function reportTelemetryEmitFailure(reason, ctx) {
|
|
1066
1066
|
consecutiveTelemetryFailures += 1;
|
|
1067
1067
|
console.error(
|
|
1068
|
-
`[telemetry] emit failed (${reason}) tool=${ctx.toolName} event=${ctx.eventType} project=${ctx.projectId}`
|
|
1068
|
+
`[telemetry] emit failed (${reason}) tool=${ctx.toolName} event=${ctx.eventType} project=${ctx.projectId ?? "(none)"}`
|
|
1069
1069
|
);
|
|
1070
1070
|
if (consecutiveTelemetryFailures >= TELEMETRY_BLACKOUT_THRESHOLD) {
|
|
1071
1071
|
console.error(
|
|
@@ -1179,8 +1179,11 @@ var init_proxy_adapter = __esm({
|
|
|
1179
1179
|
// (2) not-yet-wired hosted gaps — shrink as data-proxy handlers land (task-2390).
|
|
1180
1180
|
// getToolCallCount + updatePhaseStatus are ABSENT: they now have edge handlers and
|
|
1181
1181
|
// are served through the forwarder (getToolCallCount = SUP-2026-026 handler #1).
|
|
1182
|
-
"createOwnerAction",
|
|
1183
1182
|
"getContributorRole",
|
|
1183
|
+
// task-2728 (C331): createOwnerAction REMOVED from NO_FORWARD — the PRODUCER half
|
|
1184
|
+
// of the owner-action queue. Six readers were wired C329 (task-2412) but the
|
|
1185
|
+
// producer stayed here, so the hosted Owner Action Queue was structurally empty
|
|
1186
|
+
// (AD-74 inverted). Now forwards; the edge binds user_id to the bearer ([C]).
|
|
1184
1187
|
"recordContributorReleasePr",
|
|
1185
1188
|
"setContributorReleasePrStatus",
|
|
1186
1189
|
"listContributorReleasePrs",
|
|
@@ -1561,18 +1564,19 @@ Check PAPI_PROJECT_ID in your .mcp.json config. Find your project ID in the PAPI
|
|
|
1561
1564
|
*/
|
|
1562
1565
|
emitTelemetry(event) {
|
|
1563
1566
|
const ctx = { projectId: event.projectId, toolName: event.toolName, eventType: event.eventType };
|
|
1567
|
+
const payload = {
|
|
1568
|
+
toolName: event.toolName,
|
|
1569
|
+
eventType: event.eventType,
|
|
1570
|
+
metadata: event.metadata ?? {}
|
|
1571
|
+
};
|
|
1572
|
+
if (event.projectId) payload["projectId"] = event.projectId;
|
|
1564
1573
|
fetch(`${this.endpoint}/telemetry`, {
|
|
1565
1574
|
method: "POST",
|
|
1566
1575
|
headers: {
|
|
1567
1576
|
"Content-Type": "application/json",
|
|
1568
1577
|
"Authorization": `Bearer ${this.apiKey}`
|
|
1569
1578
|
},
|
|
1570
|
-
body: JSON.stringify(
|
|
1571
|
-
projectId: event.projectId,
|
|
1572
|
-
toolName: event.toolName,
|
|
1573
|
-
eventType: event.eventType,
|
|
1574
|
-
metadata: event.metadata ?? {}
|
|
1575
|
-
}),
|
|
1579
|
+
body: JSON.stringify(payload),
|
|
1576
1580
|
signal: AbortSignal.timeout(5e3)
|
|
1577
1581
|
}).then((res) => {
|
|
1578
1582
|
if (res.ok) noteTelemetryEmitSuccess();
|
package/dist/index.js
CHANGED
|
@@ -1103,7 +1103,7 @@ function isEnabled() {
|
|
|
1103
1103
|
function reportTelemetryEmitFailure(reason, ctx) {
|
|
1104
1104
|
consecutiveTelemetryFailures += 1;
|
|
1105
1105
|
console.error(
|
|
1106
|
-
`[telemetry] emit failed (${reason}) tool=${ctx.toolName} event=${ctx.eventType} project=${ctx.projectId}`
|
|
1106
|
+
`[telemetry] emit failed (${reason}) tool=${ctx.toolName} event=${ctx.eventType} project=${ctx.projectId ?? "(none)"}`
|
|
1107
1107
|
);
|
|
1108
1108
|
if (consecutiveTelemetryFailures >= TELEMETRY_BLACKOUT_THRESHOLD) {
|
|
1109
1109
|
console.error(
|
|
@@ -1120,11 +1120,11 @@ function emitTelemetryEvent(event) {
|
|
|
1120
1120
|
if (!apiKey) return;
|
|
1121
1121
|
const endpoint = process.env["PAPI_DATA_ENDPOINT"] ?? DEFAULT_TELEMETRY_ENDPOINT;
|
|
1122
1122
|
const body = {
|
|
1123
|
-
projectId: event.project_id,
|
|
1124
1123
|
toolName: event.tool_name,
|
|
1125
1124
|
eventType: event.event_type,
|
|
1126
1125
|
metadata: event.metadata ?? {}
|
|
1127
1126
|
};
|
|
1127
|
+
if (event.project_id) body["projectId"] = event.project_id;
|
|
1128
1128
|
const ctx = {
|
|
1129
1129
|
projectId: event.project_id,
|
|
1130
1130
|
toolName: event.tool_name,
|
|
@@ -1296,8 +1296,11 @@ var init_proxy_adapter = __esm({
|
|
|
1296
1296
|
// (2) not-yet-wired hosted gaps — shrink as data-proxy handlers land (task-2390).
|
|
1297
1297
|
// getToolCallCount + updatePhaseStatus are ABSENT: they now have edge handlers and
|
|
1298
1298
|
// are served through the forwarder (getToolCallCount = SUP-2026-026 handler #1).
|
|
1299
|
-
"createOwnerAction",
|
|
1300
1299
|
"getContributorRole",
|
|
1300
|
+
// task-2728 (C331): createOwnerAction REMOVED from NO_FORWARD — the PRODUCER half
|
|
1301
|
+
// of the owner-action queue. Six readers were wired C329 (task-2412) but the
|
|
1302
|
+
// producer stayed here, so the hosted Owner Action Queue was structurally empty
|
|
1303
|
+
// (AD-74 inverted). Now forwards; the edge binds user_id to the bearer ([C]).
|
|
1301
1304
|
"recordContributorReleasePr",
|
|
1302
1305
|
"setContributorReleasePrStatus",
|
|
1303
1306
|
"listContributorReleasePrs",
|
|
@@ -1678,18 +1681,19 @@ Check PAPI_PROJECT_ID in your .mcp.json config. Find your project ID in the PAPI
|
|
|
1678
1681
|
*/
|
|
1679
1682
|
emitTelemetry(event) {
|
|
1680
1683
|
const ctx = { projectId: event.projectId, toolName: event.toolName, eventType: event.eventType };
|
|
1684
|
+
const payload = {
|
|
1685
|
+
toolName: event.toolName,
|
|
1686
|
+
eventType: event.eventType,
|
|
1687
|
+
metadata: event.metadata ?? {}
|
|
1688
|
+
};
|
|
1689
|
+
if (event.projectId) payload["projectId"] = event.projectId;
|
|
1681
1690
|
fetch(`${this.endpoint}/telemetry`, {
|
|
1682
1691
|
method: "POST",
|
|
1683
1692
|
headers: {
|
|
1684
1693
|
"Content-Type": "application/json",
|
|
1685
1694
|
"Authorization": `Bearer ${this.apiKey}`
|
|
1686
1695
|
},
|
|
1687
|
-
body: JSON.stringify(
|
|
1688
|
-
projectId: event.projectId,
|
|
1689
|
-
toolName: event.toolName,
|
|
1690
|
-
eventType: event.eventType,
|
|
1691
|
-
metadata: event.metadata ?? {}
|
|
1692
|
-
}),
|
|
1696
|
+
body: JSON.stringify(payload),
|
|
1693
1697
|
signal: AbortSignal.timeout(5e3)
|
|
1694
1698
|
}).then((res) => {
|
|
1695
1699
|
if (res.ok) noteTelemetryEmitSuccess();
|
|
@@ -8168,20 +8172,27 @@ function formatDecisionLifecycleSummary(decisions) {
|
|
|
8168
8172
|
}
|
|
8169
8173
|
return parts.join(", ");
|
|
8170
8174
|
}
|
|
8171
|
-
function formatBuildReports(reports) {
|
|
8175
|
+
function formatBuildReports(reports, opts) {
|
|
8172
8176
|
if (reports.length === 0) return "No build reports yet.";
|
|
8173
|
-
|
|
8177
|
+
const capped = opts?.maxReports != null ? reports.slice(0, opts.maxReports) : reports;
|
|
8178
|
+
const budget = opts?.fieldBudget;
|
|
8179
|
+
const field = (v) => budget != null ? truncateNotes(v, budget) : v ?? "";
|
|
8180
|
+
const body = capped.map(
|
|
8174
8181
|
(r) => `### ${r.taskName} \u2014 ${r.date} \u2014 Cycle ${r.cycle}
|
|
8175
8182
|
|
|
8176
8183
|
- **Completed:** ${r.completed}
|
|
8177
8184
|
- **Actual Effort:** ${r.actualEffort} vs estimated ${r.estimatedEffort}
|
|
8178
8185
|
` + (r.correctionsCount ? `- **Corrections:** ${r.correctionsCount}
|
|
8179
8186
|
` : "") + (Array.isArray(r.briefImplications) && r.briefImplications.length ? `- **Brief Implications:** ${r.briefImplications.map((bi) => `[${bi.canvasSection}/${bi.type}] ${bi.detail}`).join("; ")}
|
|
8180
|
-
` : "") + `- **Surprises:** ${r.surprises}
|
|
8181
|
-
- **Discovered Issues:** ${r.discoveredIssues}
|
|
8182
|
-
- **Architecture Notes:** ${r.architectureNotes}` + (r.deadEnds ? `
|
|
8183
|
-
- **Dead Ends:** ${r.deadEnds}` : "")
|
|
8187
|
+
` : "") + `- **Surprises:** ${field(r.surprises)}
|
|
8188
|
+
- **Discovered Issues:** ${field(r.discoveredIssues)}
|
|
8189
|
+
- **Architecture Notes:** ${field(r.architectureNotes)}` + (r.deadEnds ? `
|
|
8190
|
+
- **Dead Ends:** ${field(r.deadEnds)}` : "")
|
|
8184
8191
|
).join("\n\n---\n\n");
|
|
8192
|
+
const omitted = capped.length < reports.length ? `
|
|
8193
|
+
|
|
8194
|
+
_\u2026and ${reports.length - capped.length} older build report(s) omitted to bound context size._` : "";
|
|
8195
|
+
return body + omitted;
|
|
8185
8196
|
}
|
|
8186
8197
|
function formatRecentlyShippedCapabilities(reports) {
|
|
8187
8198
|
const completed = reports.filter((r) => r.completed === "Yes" || r.completed === "Partial");
|
|
@@ -8411,6 +8422,9 @@ function computeCycleEffort(cycleTaskRows, cycleReports) {
|
|
|
8411
8422
|
deliveredPoints: cycleReports.reduce((s, r) => s + effortWeight(r.actualEffort || r.estimatedEffort), 0)
|
|
8412
8423
|
};
|
|
8413
8424
|
}
|
|
8425
|
+
function velocityPoints(v) {
|
|
8426
|
+
return v.deliveredPoints ?? v.effortPoints;
|
|
8427
|
+
}
|
|
8414
8428
|
function computeSnapshotsFromBuildReports(reports, tasks) {
|
|
8415
8429
|
const reportsByCycle = /* @__PURE__ */ new Map();
|
|
8416
8430
|
for (const r of reports) {
|
|
@@ -8461,22 +8475,22 @@ function formatCycleMetrics(snapshots) {
|
|
|
8461
8475
|
const avgPlanned = Math.round(
|
|
8462
8476
|
recentVelocities.reduce((sum, v) => sum + v.effortPoints, 0) / recentVelocities.length * 10
|
|
8463
8477
|
) / 10;
|
|
8464
|
-
const
|
|
8465
|
-
|
|
8466
|
-
|
|
8478
|
+
const avgDelivered = Math.round(
|
|
8479
|
+
recentVelocities.reduce((sum, v) => sum + velocityPoints(v), 0) / recentVelocities.length * 10
|
|
8480
|
+
) / 10;
|
|
8481
|
+
const anyDelivered = recentVelocities.some((v) => v.deliveredPoints !== void 0);
|
|
8482
|
+
lines.push("**Velocity \u2014 delivered effort points (size the next cycle from this)**");
|
|
8467
8483
|
lines.push(
|
|
8468
|
-
`- Last ${recentVelocities.length} cycles: ` + recentVelocities.map((v) => v.deliveredPoints !== void 0 ? `S${v.cycle}=${v.
|
|
8484
|
+
`- Last ${recentVelocities.length} cycles: ` + recentVelocities.map((v) => v.deliveredPoints !== void 0 ? `S${v.cycle}=${v.deliveredPoints} delivered/${v.effortPoints} planned` : `S${v.cycle}=${v.effortPoints} planned (no delivered data \u2014 using planned)`).join(", ")
|
|
8469
8485
|
);
|
|
8470
|
-
|
|
8486
|
+
lines.push(`- Velocity (avg delivered): ${avgDelivered} pts/cycle (XS=1, S=2, M=3, L=5, XL=8)`);
|
|
8487
|
+
if (anyDelivered) {
|
|
8471
8488
|
const delta = Math.round((avgDelivered - avgPlanned) * 10) / 10;
|
|
8472
8489
|
const sign = delta > 0 ? "+" : "";
|
|
8473
8490
|
const read = delta === 0 ? "delivered matches planned" : delta > 0 ? "cycles cost MORE than scoped (under-scoping)" : "cycles cost LESS than scoped (over-scoping)";
|
|
8474
|
-
lines.push(`-
|
|
8475
|
-
lines.push(`- Scope accuracy: ${sign}${delta} pts/cycle \u2014 ${read}.`);
|
|
8476
|
-
} else {
|
|
8477
|
-
lines.push(`- Average: ${avgPlanned} planned effort points/cycle (XS=1, S=2, M=3, L=5, XL=8)`);
|
|
8491
|
+
lines.push(`- Scope accuracy (drift vs planned): planned averaged ${avgPlanned} pts/cycle \u2014 ${sign}${delta} pts, ${read}.`);
|
|
8478
8492
|
}
|
|
8479
|
-
lines.push(`- Size cycles on what the selected tasks actually
|
|
8493
|
+
lines.push(`- Size cycles on what the selected tasks actually cost \u2014 delivered is the signal, planned is the estimate that was wrong.`);
|
|
8480
8494
|
}
|
|
8481
8495
|
return lines.join("\n");
|
|
8482
8496
|
}
|
|
@@ -8490,7 +8504,9 @@ function formatDerivedMetrics(snapshots, backlogTasks) {
|
|
|
8490
8504
|
const latest = recent[recent.length - 1];
|
|
8491
8505
|
lines.push("**Cycle History (5-cycle avg)**");
|
|
8492
8506
|
lines.push(`- Average: ${avg.toFixed(1)} tasks/cycle`);
|
|
8493
|
-
|
|
8507
|
+
const latestDelivered = velocityPoints(latest);
|
|
8508
|
+
const plannedNote = latest.deliveredPoints !== void 0 && latest.deliveredPoints !== latest.effortPoints ? ` (planned ${latest.effortPoints})` : "";
|
|
8509
|
+
lines.push(`- Latest (Cycle ${latest.cycle}): ${latest.completed} tasks, ${latestDelivered} effort points delivered${plannedNote}`);
|
|
8494
8510
|
}
|
|
8495
8511
|
}
|
|
8496
8512
|
const activeTasks = backlogTasks.filter(
|
|
@@ -10419,7 +10435,9 @@ async function prepareHandoffs(adapter2, _config, taskIds, force = false) {
|
|
|
10419
10435
|
// buildHandoffsOnlyUserMessage adds +1 internally
|
|
10420
10436
|
preAssignedTasks: tasksNeedingHandoffs,
|
|
10421
10437
|
activeDecisions: formatActiveDecisionsForPlan(decisions),
|
|
10422
|
-
|
|
10438
|
+
// task-2681: truncate verbose report bodies — a couple of audit reports alone
|
|
10439
|
+
// (e.g. task-2413/2655) can push this payload past the overflow range.
|
|
10440
|
+
recentBuildReports: formatBuildReports(reports, { maxReports: 10, fieldBudget: 280 }),
|
|
10423
10441
|
productBrief: brief,
|
|
10424
10442
|
northStar
|
|
10425
10443
|
});
|
|
@@ -10940,6 +10958,7 @@ async function resolveOwnerGate(adapter2, config2) {
|
|
|
10940
10958
|
}
|
|
10941
10959
|
|
|
10942
10960
|
// src/services/plan.ts
|
|
10961
|
+
var PLAN_BUILD_REPORT_BUDGET = { maxReports: 12, fieldBudget: 280 };
|
|
10943
10962
|
async function resolvePlanScope(adapter2, config2) {
|
|
10944
10963
|
const gate = await resolveOwnerGate(adapter2, config2);
|
|
10945
10964
|
return { callerUserId: gate.callerUserId, ownerUserId: gate.ownerUserId, callerIsOwner: gate.callerIsOwner };
|
|
@@ -11788,7 +11807,7 @@ ${logLines}`);
|
|
|
11788
11807
|
cycleNumber: health.totalCycles,
|
|
11789
11808
|
productBrief,
|
|
11790
11809
|
activeDecisions: formatActiveDecisionsForPlan(decisions),
|
|
11791
|
-
recentBuildReports: formatBuildReports(cappedReports),
|
|
11810
|
+
recentBuildReports: formatBuildReports(cappedReports, PLAN_BUILD_REPORT_BUDGET),
|
|
11792
11811
|
cycleLog: formatCycleLog(log2),
|
|
11793
11812
|
board: formatBoardForPlan(plannerTasks, filters, health.totalCycles, deferredTasks),
|
|
11794
11813
|
northStar,
|
|
@@ -12574,7 +12593,7 @@ async function preparePlan(adapter2, config2, filters, focus, force, handoffsOnl
|
|
|
12574
12593
|
cycleNumber,
|
|
12575
12594
|
preAssignedTasks: preAssigned,
|
|
12576
12595
|
activeDecisions: formatActiveDecisionsForPlan(decisions),
|
|
12577
|
-
recentBuildReports: formatBuildReports(reports),
|
|
12596
|
+
recentBuildReports: formatBuildReports(reports, PLAN_BUILD_REPORT_BUDGET),
|
|
12578
12597
|
productBrief: brief,
|
|
12579
12598
|
northStar
|
|
12580
12599
|
});
|
|
@@ -14072,6 +14091,7 @@ function extractTrendPoints(snapshots) {
|
|
|
14072
14091
|
matchRate: accuracyRow.matchRate,
|
|
14073
14092
|
bias: accuracyRow.bias,
|
|
14074
14093
|
effortPoints: velocityRow.effortPoints,
|
|
14094
|
+
deliveredPoints: velocityPoints(velocityRow),
|
|
14075
14095
|
completed: velocityRow.completed
|
|
14076
14096
|
});
|
|
14077
14097
|
}
|
|
@@ -14085,7 +14105,8 @@ function generateValueReport(snapshots) {
|
|
|
14085
14105
|
const first = recent[0];
|
|
14086
14106
|
const last = recent[recent.length - 1];
|
|
14087
14107
|
const matchRateDelta = last.matchRate - first.matchRate;
|
|
14088
|
-
const effortDelta = last.
|
|
14108
|
+
const effortDelta = last.deliveredPoints - first.deliveredPoints;
|
|
14109
|
+
const plannedDelta = last.effortPoints - first.effortPoints;
|
|
14089
14110
|
const completedDelta = last.completed - first.completed;
|
|
14090
14111
|
const biasTrend = assessBiasTrend(first.bias, last.bias);
|
|
14091
14112
|
const lines = [];
|
|
@@ -14094,7 +14115,8 @@ function generateValueReport(snapshots) {
|
|
|
14094
14115
|
lines.push("");
|
|
14095
14116
|
lines.push(`- **Scope accuracy:** ${first.matchRate}% \u2192 ${last.matchRate}% (${formatDelta(matchRateDelta, "pp")})`);
|
|
14096
14117
|
lines.push(`- **Estimation bias:** ${formatBias(first.bias)} \u2192 ${formatBias(last.bias)} (${biasTrend})`);
|
|
14097
|
-
lines.push(`- **Velocity:** ${first.
|
|
14118
|
+
lines.push(`- **Velocity (delivered):** ${first.deliveredPoints} \u2192 ${last.deliveredPoints} effort points/cycle (${formatDelta(effortDelta, "")})`);
|
|
14119
|
+
lines.push(`- **Planned (for drift):** ${first.effortPoints} \u2192 ${last.effortPoints} effort points/cycle (${formatDelta(plannedDelta, "")})`);
|
|
14098
14120
|
lines.push(`- **Throughput:** ${first.completed} \u2192 ${last.completed} tasks/cycle (${formatDelta(completedDelta, "")})`);
|
|
14099
14121
|
return lines.join("\n");
|
|
14100
14122
|
}
|
|
@@ -20909,7 +20931,9 @@ async function completeBuild(adapter2, config2, taskId, input, options = {}, cli
|
|
|
20909
20931
|
}
|
|
20910
20932
|
}
|
|
20911
20933
|
}
|
|
20934
|
+
const AUTO_TRIAGE_MIN_SEVERITY = /* @__PURE__ */ new Set(["P0", "P1", "P2"]);
|
|
20912
20935
|
let autoTriagedCount = 0;
|
|
20936
|
+
let autoTriagedSoftSkipped = 0;
|
|
20913
20937
|
const autoTriagedIds = [];
|
|
20914
20938
|
const autoTriagedDupes = [];
|
|
20915
20939
|
if (input.discoveredIssues && input.discoveredIssues !== "None" && typeof adapter2.createTask === "function") {
|
|
@@ -20929,6 +20953,10 @@ async function completeBuild(adapter2, config2, taskId, input, options = {}, cli
|
|
|
20929
20953
|
const sevMatch = line.match(/^(P[0-3])[\s:]+/i);
|
|
20930
20954
|
if (!sevMatch) continue;
|
|
20931
20955
|
const severityLabel = sevMatch[1].toUpperCase();
|
|
20956
|
+
if (!AUTO_TRIAGE_MIN_SEVERITY.has(severityLabel)) {
|
|
20957
|
+
autoTriagedSoftSkipped++;
|
|
20958
|
+
continue;
|
|
20959
|
+
}
|
|
20932
20960
|
const priority = severityLabel === "P0" ? "P0 Critical" : severityLabel === "P1" ? "P1 High" : severityLabel === "P2" ? "P2 Medium" : "P3 Low";
|
|
20933
20961
|
const titleRaw = line.replace(/^P[0-3][\s:]+/i, "").trim();
|
|
20934
20962
|
const title = titleRaw.length > 120 ? titleRaw.slice(0, 120) : titleRaw;
|
|
@@ -21178,6 +21206,7 @@ async function completeBuild(adapter2, config2, taskId, input, options = {}, cli
|
|
|
21178
21206
|
autoTriagedCount: autoTriagedCount > 0 ? autoTriagedCount : void 0,
|
|
21179
21207
|
autoTriagedIds: autoTriagedIds.length > 0 ? autoTriagedIds : void 0,
|
|
21180
21208
|
autoTriagedDupes: autoTriagedDupes.length > 0 ? autoTriagedDupes : void 0,
|
|
21209
|
+
autoTriagedSoftSkipped: autoTriagedSoftSkipped > 0 ? autoTriagedSoftSkipped : void 0,
|
|
21181
21210
|
reportWriteVerified,
|
|
21182
21211
|
localPreview
|
|
21183
21212
|
};
|
|
@@ -22291,7 +22320,7 @@ function formatCompleteResult(result) {
|
|
|
22291
22320
|
if (result.learningsLinkedCount) {
|
|
22292
22321
|
lines.push("", `Linked ${result.learningsLinkedCount} unactioned learning(s) to this task.`);
|
|
22293
22322
|
}
|
|
22294
|
-
if (result.autoTriagedCount || result.autoTriagedDupes?.length) {
|
|
22323
|
+
if (result.autoTriagedCount || result.autoTriagedDupes?.length || result.autoTriagedSoftSkipped) {
|
|
22295
22324
|
const parts = [];
|
|
22296
22325
|
if (result.autoTriagedCount) {
|
|
22297
22326
|
const ids = result.autoTriagedIds?.length ? ` (${result.autoTriagedIds.join(", ")})` : "";
|
|
@@ -22300,6 +22329,9 @@ function formatCompleteResult(result) {
|
|
|
22300
22329
|
if (result.autoTriagedDupes?.length) {
|
|
22301
22330
|
parts.push(`Skipped ${result.autoTriagedDupes.length} duplicate issue(s) already in Backlog: ${result.autoTriagedDupes.join(", ")}.`);
|
|
22302
22331
|
}
|
|
22332
|
+
if (result.autoTriagedSoftSkipped) {
|
|
22333
|
+
parts.push(`${result.autoTriagedSoftSkipped} low-severity (P3) observation(s) recorded to learnings, not filed as tasks.`);
|
|
22334
|
+
}
|
|
22303
22335
|
lines.push("", parts.join(" "));
|
|
22304
22336
|
}
|
|
22305
22337
|
if (result.reportWriteVerified === false) {
|
|
@@ -24992,7 +25024,7 @@ function computeHealthScore(cycleNumber, snapshots, activeTasks, decisionUsage)
|
|
|
24992
25024
|
const recentSnaps = snapshots.slice(-3);
|
|
24993
25025
|
const baselineSnaps = snapshots.slice(-10);
|
|
24994
25026
|
if (recentSnaps.length > 0 && baselineSnaps.length > 0) {
|
|
24995
|
-
const avg = (snaps) => snaps.reduce((s, sn) => s + (sn.velocity[0]
|
|
25027
|
+
const avg = (snaps) => snaps.reduce((s, sn) => s + (sn.velocity[0] ? velocityPoints(sn.velocity[0]) : 0), 0) / snaps.length;
|
|
24996
25028
|
const recentAvg = avg(recentSnaps);
|
|
24997
25029
|
const baselineAvg = avg(baselineSnaps);
|
|
24998
25030
|
const velocityScore = baselineAvg > 0 ? Math.min(100, Math.round(recentAvg / baselineAvg * 100)) : 50;
|
|
@@ -29055,16 +29087,18 @@ ${usageLine(decision.usage)}`;
|
|
|
29055
29087
|
const clientName = server2.getClientVersion()?.name;
|
|
29056
29088
|
const metric = buildMetric(name, elapsed, usage, void 0, contextBytes, contextUtilisation, clientName);
|
|
29057
29089
|
metric.success = !isError;
|
|
29058
|
-
adapter2.appendToolMetric(metric).catch(() => {
|
|
29090
|
+
adapter2.appendToolMetric(metric).catch((err) => {
|
|
29091
|
+
console.error(`[metrics] appendToolMetric failed (non-blocking): ${err instanceof Error ? err.message : String(err)}`);
|
|
29059
29092
|
});
|
|
29060
|
-
} catch {
|
|
29093
|
+
} catch (err) {
|
|
29094
|
+
console.error(`[metrics] buildMetric/appendToolMetric threw (non-blocking): ${err instanceof Error ? err.message : String(err)}`);
|
|
29061
29095
|
}
|
|
29062
29096
|
if (config2.adapterType === "md") {
|
|
29063
29097
|
const mdProjectSlug = config2.projectRoot ? config2.projectRoot.split("/").pop() : void 0;
|
|
29064
29098
|
emitMdAdapterPing(name, { duration_ms: elapsed, success: !isError }, config2.userId, mdProjectSlug);
|
|
29065
29099
|
}
|
|
29066
29100
|
const telemetryProjectId = resolveTelemetryProjectId(config2);
|
|
29067
|
-
|
|
29101
|
+
{
|
|
29068
29102
|
const adapterEmit = adapter2.emitTelemetry?.bind(adapter2) ?? null;
|
|
29069
29103
|
if (adapterEmit) {
|
|
29070
29104
|
adapterEmit({
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@papi-ai/server",
|
|
3
|
-
"version": "0.7.
|
|
4
|
-
"description": "PAPI MCP server
|
|
3
|
+
"version": "0.7.56",
|
|
4
|
+
"description": "PAPI MCP server — AI-powered sprint planning, build execution, and strategy review for software projects",
|
|
5
5
|
"license": "Elastic-2.0",
|
|
6
6
|
"mcpName": "io.github.getpapi/papi",
|
|
7
7
|
"type": "module",
|