@papi-ai/server 0.7.74 → 0.7.75
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 +109 -24
- package/dist/prompts.js +4 -4
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -5041,7 +5041,7 @@ var setup_exports = {};
|
|
|
5041
5041
|
__export(setup_exports, {
|
|
5042
5042
|
runSetup: () => runSetup
|
|
5043
5043
|
});
|
|
5044
|
-
import { existsSync as existsSync15, readFileSync as readFileSync17, writeFileSync as writeFileSync8, chmodSync as chmodSync2, statSync as
|
|
5044
|
+
import { existsSync as existsSync15, readFileSync as readFileSync17, writeFileSync as writeFileSync8, chmodSync as chmodSync2, statSync as statSync9 } from "fs";
|
|
5045
5045
|
import { join as join24 } from "path";
|
|
5046
5046
|
function baseUrl() {
|
|
5047
5047
|
const fromEnv = process.env["PAPI_HOST"] ?? process.env["PAPI_BASE_URL"];
|
|
@@ -5101,7 +5101,7 @@ function writeMcpJson(opts) {
|
|
|
5101
5101
|
parsed.mcpServers = mcpServers;
|
|
5102
5102
|
writeFileSync8(path7, JSON.stringify(parsed, null, 2) + "\n", "utf-8");
|
|
5103
5103
|
try {
|
|
5104
|
-
const mode =
|
|
5104
|
+
const mode = statSync9(path7).mode & 511;
|
|
5105
5105
|
if (mode !== 384) chmodSync2(path7, 384);
|
|
5106
5106
|
} catch {
|
|
5107
5107
|
}
|
|
@@ -5211,7 +5211,7 @@ var init_setup = __esm({
|
|
|
5211
5211
|
// src/index.ts
|
|
5212
5212
|
import { readFileSync as readFileSync18 } from "fs";
|
|
5213
5213
|
import { dirname as dirname6, join as join25, basename as basename2 } from "path";
|
|
5214
|
-
import { fileURLToPath as
|
|
5214
|
+
import { fileURLToPath as fileURLToPath5 } from "url";
|
|
5215
5215
|
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
|
|
5216
5216
|
import { Server as Server2 } from "@modelcontextprotocol/sdk/server/index.js";
|
|
5217
5217
|
import {
|
|
@@ -8257,7 +8257,7 @@ Check PAPI_PROJECT_ID in your .mcp.json config. Find your project ID in the PAPI
|
|
|
8257
8257
|
import { readFileSync as readFileSync13 } from "fs";
|
|
8258
8258
|
import { access as access4, readdir as readdir4, readFile as readFile9 } from "fs/promises";
|
|
8259
8259
|
import { join as join20, dirname as dirname5 } from "path";
|
|
8260
|
-
import { fileURLToPath as
|
|
8260
|
+
import { fileURLToPath as fileURLToPath4 } from "url";
|
|
8261
8261
|
import { Server } from "@modelcontextprotocol/sdk/server/index.js";
|
|
8262
8262
|
import {
|
|
8263
8263
|
CallToolRequestSchema,
|
|
@@ -8284,6 +8284,8 @@ var UNIVERSAL_FRAME = `PAPI gives this project a structured plan \u2192 build \u
|
|
|
8284
8284
|
|
|
8285
8285
|
5. VERIFY BEFORE DONE. Test the change and confirm it works before reporting a task complete. Report failures honestly, with the output.
|
|
8286
8286
|
|
|
8287
|
+
6. NAME THE PROJECT WHEN YOU KNOW IT. If you know which repo this session is working in, pass \`project="<slug>"\` on the call rather than relying on whatever the connection defaults to. An account with more than one project cannot be resolved from a connection with no project bound \u2014 PAPI will stop and ask which one rather than guess, and answering costs a round trip. If PAPI asks, put the list to the user, then re-call with their choice; run \`project_switch\` to make it stick.
|
|
8288
|
+
|
|
8287
8289
|
PAPI reads and writes all project state through these tools \u2014 they are the source of truth, not local files.`;
|
|
8288
8290
|
|
|
8289
8291
|
// src/lib/response.ts
|
|
@@ -9034,7 +9036,7 @@ PRE-BUILD VERIFICATION
|
|
|
9034
9036
|
[List 2-5 specific file paths the builder should read BEFORE implementing to check if the functionality already exists. Derive these from FILES LIKELY TOUCHED \u2014 pick the files most likely to already contain the target functionality. ALSO mandate a docs sweep, not just file-existence (task-2161): name any docs the builder should check via doc_search or the docs index \u2014 a design/research/status:final doc or a prior task may already cover the work. If >80% of the scope is already implemented, the builder should report "already built" instead of re-implementing. Include this section for EVERY task \u2014 it prevents wasted build slots on already-shipped code.]
|
|
9035
9037
|
|
|
9036
9038
|
FILES LIKELY TOUCHED
|
|
9037
|
-
[files \u2014 real paths only. TEST FILE LOCATIONS (task-2606): PAPI tests are NOT co-located next to source in a src/**/__tests__/ folder. Use the actual layout: server tests \u2192 packages/server/tests/<name>.test.ts; adapter-pg tests \u2192 packages/adapter-pg/src/__tests__/<name>.test.ts; dashboard/root tests \u2192 tests/<area>/<name>.test.ts. Do NOT invent packages/server/src/**/__tests__/ paths \u2014 they do not exist.]
|
|
9039
|
+
[files \u2014 real paths only. TEST FILE LOCATIONS (task-2606): PAPI tests are NOT co-located next to source in a src/**/__tests__/ folder. Use the actual layout: server tests \u2192 packages/server/tests/<name>.test.ts; adapter-pg tests \u2192 packages/adapter-pg/src/__tests__/<name>.test.ts; dashboard/root tests \u2192 tests/<area>/<name>.test.ts. Do NOT invent packages/server/src/**/__tests__/ paths \u2014 they do not exist. MCP RESTART RULE (task-2978): whenever FILES LIKELY TOUCHED includes any \`packages/server/**\` path, append this line verbatim to the handoff \u2014 "MCP RESTART REQUIRED: a mid-session \`npm run mcp-build\` writes a dist the already-booted MCP process never loads, so verifying this change through PAPI's own tools before an explicit MCP reconnect is INVALID. Implement \u2192 mcp-build \u2192 reconnect \u2192 only then verify." This is one line inside this section, not a new section.]
|
|
9038
9040
|
|
|
9039
9041
|
EFFORT
|
|
9040
9042
|
[XS/S/M/L/XL]
|
|
@@ -9048,7 +9050,7 @@ After your natural language output, include this EXACT format on its own line:
|
|
|
9048
9050
|
{
|
|
9049
9051
|
"cycleLogTitle": "string \u2014 short descriptive title WITHOUT 'Cycle N' prefix. Should capture the cycle theme in 3-5 words (e.g. 'MCP Quality + Product Readiness' not 'Cycle 5 \u2014 Board Triage \u2014 Bug Fix'). This is the canonical theme label for the cycle.",
|
|
9050
9052
|
"cycleLogContent": "string \u2014 5-10 line cycle log body in markdown, NO heading (the ### heading is generated automatically)",
|
|
9051
|
-
"cycleLogCarryForward": "string or null \u2014 carry-forward
|
|
9053
|
+
"cycleLogCarryForward": "string or null \u2014 carry-forward for the next cycle, in TWO NAMED SECTIONS, product signal FIRST. Section 1 begins with the literal label 'WHAT SHIPS FOR USERS:' and names, concretely, what a person using this project can now see or do, and how to check it \u2014 never a deploy step. Section 2 begins with the literal label 'RELEASE MECHANICS:' and carries everything operational: deploy, publish, migrations, gate order, branch counts, spot-checks. The mechanics are load-bearing and must NOT be dropped or shortened \u2014 they go second, not away. orient parses these two labels and renders the product half first, so the labels are a contract, not decoration. If a cycle genuinely ships nothing user-visible, say so in one line under section 1 rather than omitting the label.",
|
|
9052
9054
|
"cycleLogNotes": "string or null \u2014 1-3 lines of cycle-level observations: estimation accuracy, recurring blockers, velocity trends, dependency signals. Omit if no noteworthy observations.",
|
|
9053
9055
|
"nextMode": "Full",
|
|
9054
9056
|
"boardHealth": "string \u2014 e.g. 5 tasks (3 backlog, 2 done)",
|
|
@@ -9912,7 +9914,7 @@ After your natural language output, include this EXACT format on its own line:
|
|
|
9912
9914
|
\`\`\`json
|
|
9913
9915
|
{
|
|
9914
9916
|
"sessionLogTitle": "string \u2014 Strategy Review title WITHOUT 'Cycle N' prefix (e.g. 'Strategy Review' not 'Cycle 5 \u2014 Strategy Review')",
|
|
9915
|
-
"sessionLogContent": "string \u2014 5-10 line cycle log body summarizing the review, NO heading (the ### heading is generated automatically)",
|
|
9917
|
+
"sessionLogContent": "string \u2014 5-10 line cycle log body summarizing the review, NO heading (the ### heading is generated automatically). LEAD WITH TANGIBLE PRODUCT INSIGHT: open with what was learned about the product, its users, or the market \u2014 a specific finding a reader can act on. Board hygiene, cadence, cycle counts, branch state and other housekeeping are legitimate content but they TRAIL; they must never be the opening line. If the review's most important finding genuinely is an operational one, say why it matters to the product in the same breath rather than reporting it as admin.",
|
|
9916
9918
|
"velocityAssessment": "string \u2014 2-3 sentence velocity summary",
|
|
9917
9919
|
"strategicRecommendations": "string \u2014 key recommendations in markdown",
|
|
9918
9920
|
"activeDecisionUpdates": [
|
|
@@ -10276,7 +10278,7 @@ REFERENCE DOCS
|
|
|
10276
10278
|
[Optional \u2014 paths to docs/ files with background context. Omit if not needed.]
|
|
10277
10279
|
|
|
10278
10280
|
FILES LIKELY TOUCHED
|
|
10279
|
-
[files \u2014 real paths only. TEST FILE LOCATIONS (task-2606): PAPI tests are NOT co-located next to source in a src/**/__tests__/ folder. Use the actual layout: server tests \u2192 packages/server/tests/<name>.test.ts; adapter-pg tests \u2192 packages/adapter-pg/src/__tests__/<name>.test.ts; dashboard/root tests \u2192 tests/<area>/<name>.test.ts. Do NOT invent packages/server/src/**/__tests__/ paths \u2014 they do not exist.]
|
|
10281
|
+
[files \u2014 real paths only. TEST FILE LOCATIONS (task-2606): PAPI tests are NOT co-located next to source in a src/**/__tests__/ folder. Use the actual layout: server tests \u2192 packages/server/tests/<name>.test.ts; adapter-pg tests \u2192 packages/adapter-pg/src/__tests__/<name>.test.ts; dashboard/root tests \u2192 tests/<area>/<name>.test.ts. Do NOT invent packages/server/src/**/__tests__/ paths \u2014 they do not exist. MCP RESTART RULE (task-2978): whenever FILES LIKELY TOUCHED includes any \`packages/server/**\` path, append this line verbatim to the handoff \u2014 "MCP RESTART REQUIRED: a mid-session \`npm run mcp-build\` writes a dist the already-booted MCP process never loads, so verifying this change through PAPI's own tools before an explicit MCP reconnect is INVALID. Implement \u2192 mcp-build \u2192 reconnect \u2192 only then verify." This is one line inside this section, not a new section.]
|
|
10280
10282
|
|
|
10281
10283
|
EFFORT
|
|
10282
10284
|
[XS/S/M/L/XL]`;
|
|
@@ -10641,9 +10643,9 @@ async function getPrompt(name) {
|
|
|
10641
10643
|
if (!endpoint) {
|
|
10642
10644
|
return LOCAL_PROMPTS[name];
|
|
10643
10645
|
}
|
|
10644
|
-
const
|
|
10645
|
-
if (
|
|
10646
|
-
return
|
|
10646
|
+
const cached2 = cache.get(name);
|
|
10647
|
+
if (cached2 && Date.now() - cached2.fetchedAt < CACHE_TTL_MS) {
|
|
10648
|
+
return cached2.content;
|
|
10647
10649
|
}
|
|
10648
10650
|
try {
|
|
10649
10651
|
const url = endpoint.endsWith("/") ? `${endpoint}${name}` : `${endpoint}/${name}`;
|
|
@@ -10656,19 +10658,19 @@ async function getPrompt(name) {
|
|
|
10656
10658
|
}
|
|
10657
10659
|
const response = await fetch(url, { headers, signal: AbortSignal.timeout(1e4) });
|
|
10658
10660
|
if (!response.ok) {
|
|
10659
|
-
if (
|
|
10661
|
+
if (cached2) return cached2.content;
|
|
10660
10662
|
return LOCAL_PROMPTS[name];
|
|
10661
10663
|
}
|
|
10662
10664
|
const data = await response.json();
|
|
10663
10665
|
const content = data.content;
|
|
10664
10666
|
if (typeof content !== "string" || content.length === 0) {
|
|
10665
|
-
if (
|
|
10667
|
+
if (cached2) return cached2.content;
|
|
10666
10668
|
return LOCAL_PROMPTS[name];
|
|
10667
10669
|
}
|
|
10668
10670
|
cache.set(name, { content, fetchedAt: Date.now() });
|
|
10669
10671
|
return content;
|
|
10670
10672
|
} catch {
|
|
10671
|
-
if (
|
|
10673
|
+
if (cached2) return cached2.content;
|
|
10672
10674
|
return LOCAL_PROMPTS[name];
|
|
10673
10675
|
}
|
|
10674
10676
|
}
|
|
@@ -24283,7 +24285,7 @@ var ideaTool = {
|
|
|
24283
24285
|
},
|
|
24284
24286
|
project: {
|
|
24285
24287
|
type: "string",
|
|
24286
|
-
description: "Project id (UUID) or slug to write this idea to, overriding the session project for THIS call only. Must be a project on your account \u2014 fails closed otherwise. Use project_switch to change the session default."
|
|
24288
|
+
description: "Project id (UUID) or slug to write this idea to, overriding the session project for THIS call only. Must be a project on your account \u2014 fails closed otherwise. Use project_switch to change the session default. PASS THIS WHENEVER YOU KNOW WHICH REPO THE SESSION IS IN: on a multi-project account a connection with no project bound cannot be resolved, and PAPI will stop and ask rather than guess."
|
|
24287
24289
|
}
|
|
24288
24290
|
},
|
|
24289
24291
|
required: ["text"]
|
|
@@ -24730,7 +24732,7 @@ var backlogImportTool = {
|
|
|
24730
24732
|
},
|
|
24731
24733
|
project: {
|
|
24732
24734
|
type: "string",
|
|
24733
|
-
description: "Project id (UUID) or slug to import into, overriding the session project for THIS call only. Must be a project on your account \u2014 fails closed otherwise."
|
|
24735
|
+
description: "Project id (UUID) or slug to import into, overriding the session project for THIS call only. Must be a project on your account \u2014 fails closed otherwise. PASS THIS WHENEVER YOU KNOW WHICH REPO THE SESSION IS IN: on a multi-project account a connection with no project bound cannot be resolved, and PAPI will stop and ask rather than guess."
|
|
24734
24736
|
}
|
|
24735
24737
|
},
|
|
24736
24738
|
required: ["source"]
|
|
@@ -24938,7 +24940,7 @@ var bugTool = {
|
|
|
24938
24940
|
},
|
|
24939
24941
|
project: {
|
|
24940
24942
|
type: "string",
|
|
24941
|
-
description: "BOARD MODE ONLY. Project id (UUID) or slug to file this bug under, overriding the session project for THIS call only. Must be a project on your account \u2014 fails closed otherwise. It CANNOT redirect an upstream (report=true) submission \u2014 those always go to PAPI maintainers. Use project_switch to change the session default."
|
|
24943
|
+
description: "BOARD MODE ONLY. Project id (UUID) or slug to file this bug under, overriding the session project for THIS call only. Must be a project on your account \u2014 fails closed otherwise. It CANNOT redirect an upstream (report=true) submission \u2014 those always go to PAPI maintainers. Use project_switch to change the session default. PASS THIS WHENEVER YOU KNOW WHICH REPO THE SESSION IS IN: on a multi-project account a connection with no project bound cannot be resolved, and PAPI will stop and ask rather than guess."
|
|
24942
24944
|
}
|
|
24943
24945
|
},
|
|
24944
24946
|
required: ["text"]
|
|
@@ -27841,6 +27843,50 @@ function formatUnblockSection(candidates) {
|
|
|
27841
27843
|
return lines.join("\n");
|
|
27842
27844
|
}
|
|
27843
27845
|
|
|
27846
|
+
// src/lib/carry-forward-shape.ts
|
|
27847
|
+
var PRODUCT_MARKER = /WHAT SHIPS FOR USERS\b[^\n:]*:/i;
|
|
27848
|
+
var MECHANICS_MARKER = /RELEASE MECHANICS\b[^\n:]*:/i;
|
|
27849
|
+
function splitCarryForward(raw) {
|
|
27850
|
+
const productMatch = PRODUCT_MARKER.exec(raw);
|
|
27851
|
+
const mechanicsMatch = MECHANICS_MARKER.exec(raw);
|
|
27852
|
+
if (!productMatch && !mechanicsMatch) {
|
|
27853
|
+
return { product: raw.trim(), mechanics: "", split: false };
|
|
27854
|
+
}
|
|
27855
|
+
if (!productMatch && mechanicsMatch) {
|
|
27856
|
+
const head = raw.slice(0, mechanicsMatch.index).trim();
|
|
27857
|
+
const tail = raw.slice(mechanicsMatch.index + mechanicsMatch[0].length).trim();
|
|
27858
|
+
return { product: head, mechanics: tail, split: true };
|
|
27859
|
+
}
|
|
27860
|
+
const productStart = productMatch.index + productMatch[0].length;
|
|
27861
|
+
if (!mechanicsMatch) {
|
|
27862
|
+
return { product: raw.slice(productStart).trim(), mechanics: "", split: true };
|
|
27863
|
+
}
|
|
27864
|
+
if (mechanicsMatch.index < productMatch.index) {
|
|
27865
|
+
return {
|
|
27866
|
+
product: raw.slice(productStart).trim(),
|
|
27867
|
+
mechanics: raw.slice(mechanicsMatch.index + mechanicsMatch[0].length, productMatch.index).trim(),
|
|
27868
|
+
split: true
|
|
27869
|
+
};
|
|
27870
|
+
}
|
|
27871
|
+
return {
|
|
27872
|
+
product: raw.slice(productStart, mechanicsMatch.index).trim(),
|
|
27873
|
+
mechanics: raw.slice(mechanicsMatch.index + mechanicsMatch[0].length).trim(),
|
|
27874
|
+
split: true
|
|
27875
|
+
};
|
|
27876
|
+
}
|
|
27877
|
+
function renderCarryForward(raw, decorate = (t) => t) {
|
|
27878
|
+
const { product, mechanics, split } = splitCarryForward(raw);
|
|
27879
|
+
if (!split) return [decorate(product)];
|
|
27880
|
+
const lines = [];
|
|
27881
|
+
if (product) lines.push(decorate(product));
|
|
27882
|
+
if (mechanics) {
|
|
27883
|
+
if (product) lines.push("");
|
|
27884
|
+
lines.push("**Release mechanics** \u2014 needed at release, not now:");
|
|
27885
|
+
lines.push(decorate(mechanics));
|
|
27886
|
+
}
|
|
27887
|
+
return lines;
|
|
27888
|
+
}
|
|
27889
|
+
|
|
27844
27890
|
// src/lib/deferred-gate.ts
|
|
27845
27891
|
var GATE_PHRASES = [
|
|
27846
27892
|
"depends on",
|
|
@@ -28420,7 +28466,7 @@ function formatOrientSummary(health, buildInfo, hierarchy, latestTag, projectRoo
|
|
|
28420
28466
|
const hasCarryForward = health.carryForward !== "None found" && !health.carryForward.startsWith("No carry-forward");
|
|
28421
28467
|
if (hasCarryForward) {
|
|
28422
28468
|
lines.push("## Carry-Forward");
|
|
28423
|
-
lines.push(
|
|
28469
|
+
lines.push(...renderCarryForward(health.carryForward, (t) => annotateTaskRefs(t, taskRefs)));
|
|
28424
28470
|
lines.push("");
|
|
28425
28471
|
}
|
|
28426
28472
|
const hasMetrics = health.metricsSection !== "Could not read methodology metrics." && !health.metricsSection.includes("undefined");
|
|
@@ -30375,6 +30421,36 @@ ${d.body}`;
|
|
|
30375
30421
|
${formatted}`, meta));
|
|
30376
30422
|
}
|
|
30377
30423
|
|
|
30424
|
+
// src/lib/dist-staleness.ts
|
|
30425
|
+
import { statSync as statSync8 } from "fs";
|
|
30426
|
+
import { fileURLToPath as fileURLToPath3 } from "url";
|
|
30427
|
+
var BOOT_MS = Date.now();
|
|
30428
|
+
var DEFAULT_SKEW_MS = 2e3;
|
|
30429
|
+
var STAT_TTL_MS = 1e4;
|
|
30430
|
+
function isDistStale({ bootMs, distMtimeMs, skewMs = DEFAULT_SKEW_MS }) {
|
|
30431
|
+
if (distMtimeMs === null || !Number.isFinite(distMtimeMs)) return false;
|
|
30432
|
+
return distMtimeMs > bootMs + skewMs;
|
|
30433
|
+
}
|
|
30434
|
+
var cached = null;
|
|
30435
|
+
function checkDistStaleness(now = Date.now()) {
|
|
30436
|
+
if (cached && now - cached.at < STAT_TTL_MS) return cached.stale;
|
|
30437
|
+
let distMtimeMs = null;
|
|
30438
|
+
try {
|
|
30439
|
+
distMtimeMs = statSync8(fileURLToPath3(import.meta.url)).mtimeMs;
|
|
30440
|
+
} catch {
|
|
30441
|
+
distMtimeMs = null;
|
|
30442
|
+
}
|
|
30443
|
+
const stale = isDistStale({ bootMs: BOOT_MS, distMtimeMs });
|
|
30444
|
+
cached = { at: now, stale };
|
|
30445
|
+
return stale;
|
|
30446
|
+
}
|
|
30447
|
+
function stalenessWarning(now = Date.now()) {
|
|
30448
|
+
const age = Math.round((now - BOOT_MS) / 1e3);
|
|
30449
|
+
return `\u26A0\uFE0F This PAPI MCP server process booted ${age}s ago and packages/server has been REBUILT since. It is still running the code it booted with, so anything you verify through these tools right now reflects the OLD bundle. Reconnect / restart the PAPI MCP server before trusting this output.
|
|
30450
|
+
|
|
30451
|
+
`;
|
|
30452
|
+
}
|
|
30453
|
+
|
|
30378
30454
|
// src/tools/learning-action.ts
|
|
30379
30455
|
var learningActionTool = {
|
|
30380
30456
|
name: "learning_action",
|
|
@@ -31346,9 +31422,9 @@ async function checkMeter(adapter2, toolName, cacheKey) {
|
|
|
31346
31422
|
if (!adapter2.getMeteredUsage) return { blocked: false };
|
|
31347
31423
|
try {
|
|
31348
31424
|
let usage;
|
|
31349
|
-
const
|
|
31350
|
-
if (
|
|
31351
|
-
usage =
|
|
31425
|
+
const cached2 = usageCache.get(cacheKey);
|
|
31426
|
+
if (cached2 && Date.now() - cached2.at < CACHE_TTL_MS3) {
|
|
31427
|
+
usage = cached2.usage;
|
|
31352
31428
|
} else {
|
|
31353
31429
|
usage = await adapter2.getMeteredUsage();
|
|
31354
31430
|
usageCache.set(cacheKey, { usage, at: Date.now() });
|
|
@@ -31537,7 +31613,7 @@ function getToolMetadata() {
|
|
|
31537
31613
|
return PAPI_TOOLS.map((t) => ({ name: t.name, description: t.description }));
|
|
31538
31614
|
}
|
|
31539
31615
|
function createServer(adapter2, config2) {
|
|
31540
|
-
const __pkgFilename =
|
|
31616
|
+
const __pkgFilename = fileURLToPath4(import.meta.url);
|
|
31541
31617
|
const __pkgDir = dirname5(__pkgFilename);
|
|
31542
31618
|
let serverVersion = "unknown";
|
|
31543
31619
|
try {
|
|
@@ -31557,7 +31633,7 @@ function createServer(adapter2, config2) {
|
|
|
31557
31633
|
"\n\u26A0 PAPI is running in md mode \u2014 your cycles are not visible on the hosted dashboard.\n Configure DATABASE_URL or sign up at https://getpapi.ai/setup to enable observability.\n\n"
|
|
31558
31634
|
);
|
|
31559
31635
|
}
|
|
31560
|
-
const __filename =
|
|
31636
|
+
const __filename = fileURLToPath4(import.meta.url);
|
|
31561
31637
|
const __dirname2 = dirname5(__filename);
|
|
31562
31638
|
const skillsDir = join20(__dirname2, "..", "skills");
|
|
31563
31639
|
function parseSkillFrontmatter(content) {
|
|
@@ -31859,6 +31935,15 @@ ${usageLine(decision.usage)}`;
|
|
|
31859
31935
|
}
|
|
31860
31936
|
const footer = formatMetricsFooter(elapsed, usage, contextBytes);
|
|
31861
31937
|
result.content.push({ type: "text", text: footer });
|
|
31938
|
+
try {
|
|
31939
|
+
if (checkDistStaleness() && result.content.length > 0) {
|
|
31940
|
+
const first = result.content[0];
|
|
31941
|
+
if (first && typeof first.text === "string") {
|
|
31942
|
+
first.text = stalenessWarning() + first.text;
|
|
31943
|
+
}
|
|
31944
|
+
}
|
|
31945
|
+
} catch {
|
|
31946
|
+
}
|
|
31862
31947
|
return result;
|
|
31863
31948
|
});
|
|
31864
31949
|
return server2;
|
|
@@ -32304,7 +32389,7 @@ async function dispatchRequest(args) {
|
|
|
32304
32389
|
}
|
|
32305
32390
|
|
|
32306
32391
|
// src/index.ts
|
|
32307
|
-
var __dirname = dirname6(
|
|
32392
|
+
var __dirname = dirname6(fileURLToPath5(import.meta.url));
|
|
32308
32393
|
var pkgVersion = "unknown";
|
|
32309
32394
|
try {
|
|
32310
32395
|
const pkg = JSON.parse(readFileSync18(join25(__dirname, "..", "package.json"), "utf-8"));
|
package/dist/prompts.js
CHANGED
|
@@ -69,7 +69,7 @@ PRE-BUILD VERIFICATION
|
|
|
69
69
|
[List 2-5 specific file paths the builder should read BEFORE implementing to check if the functionality already exists. Derive these from FILES LIKELY TOUCHED \u2014 pick the files most likely to already contain the target functionality. ALSO mandate a docs sweep, not just file-existence (task-2161): name any docs the builder should check via doc_search or the docs index \u2014 a design/research/status:final doc or a prior task may already cover the work. If >80% of the scope is already implemented, the builder should report "already built" instead of re-implementing. Include this section for EVERY task \u2014 it prevents wasted build slots on already-shipped code.]
|
|
70
70
|
|
|
71
71
|
FILES LIKELY TOUCHED
|
|
72
|
-
[files \u2014 real paths only. TEST FILE LOCATIONS (task-2606): PAPI tests are NOT co-located next to source in a src/**/__tests__/ folder. Use the actual layout: server tests \u2192 packages/server/tests/<name>.test.ts; adapter-pg tests \u2192 packages/adapter-pg/src/__tests__/<name>.test.ts; dashboard/root tests \u2192 tests/<area>/<name>.test.ts. Do NOT invent packages/server/src/**/__tests__/ paths \u2014 they do not exist.]
|
|
72
|
+
[files \u2014 real paths only. TEST FILE LOCATIONS (task-2606): PAPI tests are NOT co-located next to source in a src/**/__tests__/ folder. Use the actual layout: server tests \u2192 packages/server/tests/<name>.test.ts; adapter-pg tests \u2192 packages/adapter-pg/src/__tests__/<name>.test.ts; dashboard/root tests \u2192 tests/<area>/<name>.test.ts. Do NOT invent packages/server/src/**/__tests__/ paths \u2014 they do not exist. MCP RESTART RULE (task-2978): whenever FILES LIKELY TOUCHED includes any \`packages/server/**\` path, append this line verbatim to the handoff \u2014 "MCP RESTART REQUIRED: a mid-session \`npm run mcp-build\` writes a dist the already-booted MCP process never loads, so verifying this change through PAPI's own tools before an explicit MCP reconnect is INVALID. Implement \u2192 mcp-build \u2192 reconnect \u2192 only then verify." This is one line inside this section, not a new section.]
|
|
73
73
|
|
|
74
74
|
EFFORT
|
|
75
75
|
[XS/S/M/L/XL]
|
|
@@ -83,7 +83,7 @@ After your natural language output, include this EXACT format on its own line:
|
|
|
83
83
|
{
|
|
84
84
|
"cycleLogTitle": "string \u2014 short descriptive title WITHOUT 'Cycle N' prefix. Should capture the cycle theme in 3-5 words (e.g. 'MCP Quality + Product Readiness' not 'Cycle 5 \u2014 Board Triage \u2014 Bug Fix'). This is the canonical theme label for the cycle.",
|
|
85
85
|
"cycleLogContent": "string \u2014 5-10 line cycle log body in markdown, NO heading (the ### heading is generated automatically)",
|
|
86
|
-
"cycleLogCarryForward": "string or null \u2014 carry-forward
|
|
86
|
+
"cycleLogCarryForward": "string or null \u2014 carry-forward for the next cycle, in TWO NAMED SECTIONS, product signal FIRST. Section 1 begins with the literal label 'WHAT SHIPS FOR USERS:' and names, concretely, what a person using this project can now see or do, and how to check it \u2014 never a deploy step. Section 2 begins with the literal label 'RELEASE MECHANICS:' and carries everything operational: deploy, publish, migrations, gate order, branch counts, spot-checks. The mechanics are load-bearing and must NOT be dropped or shortened \u2014 they go second, not away. orient parses these two labels and renders the product half first, so the labels are a contract, not decoration. If a cycle genuinely ships nothing user-visible, say so in one line under section 1 rather than omitting the label.",
|
|
87
87
|
"cycleLogNotes": "string or null \u2014 1-3 lines of cycle-level observations: estimation accuracy, recurring blockers, velocity trends, dependency signals. Omit if no noteworthy observations.",
|
|
88
88
|
"nextMode": "Full",
|
|
89
89
|
"boardHealth": "string \u2014 e.g. 5 tasks (3 backlog, 2 done)",
|
|
@@ -947,7 +947,7 @@ After your natural language output, include this EXACT format on its own line:
|
|
|
947
947
|
\`\`\`json
|
|
948
948
|
{
|
|
949
949
|
"sessionLogTitle": "string \u2014 Strategy Review title WITHOUT 'Cycle N' prefix (e.g. 'Strategy Review' not 'Cycle 5 \u2014 Strategy Review')",
|
|
950
|
-
"sessionLogContent": "string \u2014 5-10 line cycle log body summarizing the review, NO heading (the ### heading is generated automatically)",
|
|
950
|
+
"sessionLogContent": "string \u2014 5-10 line cycle log body summarizing the review, NO heading (the ### heading is generated automatically). LEAD WITH TANGIBLE PRODUCT INSIGHT: open with what was learned about the product, its users, or the market \u2014 a specific finding a reader can act on. Board hygiene, cadence, cycle counts, branch state and other housekeeping are legitimate content but they TRAIL; they must never be the opening line. If the review's most important finding genuinely is an operational one, say why it matters to the product in the same breath rather than reporting it as admin.",
|
|
951
951
|
"velocityAssessment": "string \u2014 2-3 sentence velocity summary",
|
|
952
952
|
"strategicRecommendations": "string \u2014 key recommendations in markdown",
|
|
953
953
|
"activeDecisionUpdates": [
|
|
@@ -1311,7 +1311,7 @@ REFERENCE DOCS
|
|
|
1311
1311
|
[Optional \u2014 paths to docs/ files with background context. Omit if not needed.]
|
|
1312
1312
|
|
|
1313
1313
|
FILES LIKELY TOUCHED
|
|
1314
|
-
[files \u2014 real paths only. TEST FILE LOCATIONS (task-2606): PAPI tests are NOT co-located next to source in a src/**/__tests__/ folder. Use the actual layout: server tests \u2192 packages/server/tests/<name>.test.ts; adapter-pg tests \u2192 packages/adapter-pg/src/__tests__/<name>.test.ts; dashboard/root tests \u2192 tests/<area>/<name>.test.ts. Do NOT invent packages/server/src/**/__tests__/ paths \u2014 they do not exist.]
|
|
1314
|
+
[files \u2014 real paths only. TEST FILE LOCATIONS (task-2606): PAPI tests are NOT co-located next to source in a src/**/__tests__/ folder. Use the actual layout: server tests \u2192 packages/server/tests/<name>.test.ts; adapter-pg tests \u2192 packages/adapter-pg/src/__tests__/<name>.test.ts; dashboard/root tests \u2192 tests/<area>/<name>.test.ts. Do NOT invent packages/server/src/**/__tests__/ paths \u2014 they do not exist. MCP RESTART RULE (task-2978): whenever FILES LIKELY TOUCHED includes any \`packages/server/**\` path, append this line verbatim to the handoff \u2014 "MCP RESTART REQUIRED: a mid-session \`npm run mcp-build\` writes a dist the already-booted MCP process never loads, so verifying this change through PAPI's own tools before an explicit MCP reconnect is INVALID. Implement \u2192 mcp-build \u2192 reconnect \u2192 only then verify." This is one line inside this section, not a new section.]
|
|
1315
1315
|
|
|
1316
1316
|
EFFORT
|
|
1317
1317
|
[XS/S/M/L/XL]`;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@papi-ai/server",
|
|
3
|
-
"version": "0.7.
|
|
3
|
+
"version": "0.7.75",
|
|
4
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",
|