@papi-ai/server 0.7.67 → 0.7.70

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.
Files changed (3) hide show
  1. package/dist/index.js +1486 -428
  2. package/dist/prompts.js +65 -21
  3. package/package.json +1 -1
package/dist/prompts.js CHANGED
@@ -565,11 +565,16 @@ function buildPlanUserMessage(ctx) {
565
565
  ""
566
566
  );
567
567
  }
568
- if (ctx.buildPatterns) {
569
- parts.push("### Build Patterns", "", ctx.buildPatterns, "");
568
+ const enrichment = [];
569
+ const addEnrichment = (label, ...lines) => {
570
+ enrichment.push({ label, block: lines.join("\n") });
571
+ };
572
+ if (ctx.strategyRecommendations) {
573
+ addEnrichment("Strategy Recommendations (Pending)", "### Strategy Recommendations (Pending)", "", ctx.strategyRecommendations, "");
570
574
  }
571
575
  if (ctx.learningPatterns) {
572
- parts.push(
576
+ addEnrichment(
577
+ "Recurring Learning Patterns",
573
578
  "### Recurring Learning Patterns (cross-cycle)",
574
579
  "",
575
580
  "Tags from cycle learnings (surprises, issues, dead-ends, estimation misses) that keep recurring. Treat a module/theme that recurs across many cycles as a signal: size its tasks up and write a sharper pre-mortem.",
@@ -579,7 +584,8 @@ function buildPlanUserMessage(ctx) {
579
584
  );
580
585
  }
581
586
  if (ctx.decisionScorePatterns) {
582
- parts.push(
587
+ addEnrichment(
588
+ "Decision Risk Scores",
583
589
  "### Decision Risk Scores (high-risk + movement)",
584
590
  "",
585
591
  "Per-decision risk scores (effort+risk+reversibility+scaleCost+lockIn, /25; lower = safer). Decisions flagged \u26A0 high-risk (>15/25) or whose score moved since the last scoring. When a task depends on or advances a \u26A0 high-risk or \u2191 riskier decision, name that decision in the BUILD HANDOFF pre-mortem and lean toward the larger estimate. Do NOT re-score decisions here \u2014 this is read-only input.",
@@ -588,38 +594,39 @@ function buildPlanUserMessage(ctx) {
588
594
  ""
589
595
  );
590
596
  }
597
+ if (ctx.estimationCalibration) {
598
+ addEnrichment("Estimation Calibration", "### Estimation Calibration (Historical)", "", ctx.estimationCalibration, "");
599
+ }
591
600
  if (ctx.reviewPatterns) {
592
- parts.push("### Review Patterns", "", ctx.reviewPatterns, "");
601
+ addEnrichment("Review Patterns", "### Review Patterns", "", ctx.reviewPatterns, "");
593
602
  }
594
603
  if (ctx.methodologyMetrics) {
595
- parts.push("### Methodology Trends", "", ctx.methodologyMetrics, "");
596
- }
597
- if (ctx.estimationCalibration) {
598
- parts.push("### Estimation Calibration (Historical)", "", ctx.estimationCalibration, "");
604
+ addEnrichment("Methodology Trends", "### Methodology Trends", "", ctx.methodologyMetrics, "");
599
605
  }
600
606
  if (ctx.horizonContext) {
601
- parts.push("### Forward Horizon", "", ctx.horizonContext, "");
602
- }
603
- if (ctx.strategyRecommendations) {
604
- parts.push("### Strategy Recommendations (Pending)", "", ctx.strategyRecommendations, "");
607
+ addEnrichment("Forward Horizon", "### Forward Horizon", "", ctx.horizonContext, "");
605
608
  }
606
- if (ctx.dogfoodEntries) {
607
- parts.push("### Dogfood Observations (Recent)", "", ctx.dogfoodEntries, "");
609
+ if (ctx.buildPatterns) {
610
+ addEnrichment("Build Patterns", "### Build Patterns", "", ctx.buildPatterns, "");
608
611
  }
609
612
  if (ctx.taskComments) {
610
- parts.push("### Task Discussion Threads", "", ctx.taskComments, "");
613
+ addEnrichment("Task Discussion Threads", "### Task Discussion Threads", "", ctx.taskComments, "");
611
614
  }
612
615
  if (ctx.recentReviews) {
613
- parts.push("### Human Reviews", "", ctx.recentReviews, "");
616
+ addEnrichment("Human Reviews", "### Human Reviews", "", ctx.recentReviews, "");
617
+ }
618
+ if (ctx.dogfoodEntries) {
619
+ addEnrichment("Dogfood Observations", "### Dogfood Observations (Recent)", "", ctx.dogfoodEntries, "");
614
620
  }
615
621
  if (ctx.discoveryCanvas) {
616
- parts.push("### Discovery Canvas", "", ctx.discoveryCanvas, "");
622
+ addEnrichment("Discovery Canvas", "### Discovery Canvas", "", ctx.discoveryCanvas, "");
617
623
  }
618
624
  if (ctx.registeredDocs) {
619
- parts.push("### Relevant Research Docs", "", ctx.registeredDocs, "");
625
+ addEnrichment("Relevant Research Docs", "### Relevant Research Docs", "", ctx.registeredDocs, "");
620
626
  }
621
627
  if (ctx.unactionedDocs) {
622
- parts.push(
628
+ addEnrichment(
629
+ "Unactioned Research",
623
630
  "### Unactioned Research (soft-warn)",
624
631
  "",
625
632
  "These registered docs still have pending actions. Before adding net-new tasks, consider whether one of these unactioned items should be promoted into this cycle via `doc_action_promote`. Surface this in your plan output so the user can decide.",
@@ -629,7 +636,31 @@ function buildPlanUserMessage(ctx) {
629
636
  );
630
637
  }
631
638
  if (ctx.carryForwardStaleness) {
632
- parts.push("### Carry-Forward Staleness", "", ctx.carryForwardStaleness, "");
639
+ addEnrichment("Carry-Forward Staleness", "### Carry-Forward Staleness", "", ctx.carryForwardStaleness, "");
640
+ }
641
+ const contextBudget = Number(process.env.PAPI_PLAN_CONTEXT_BUDGET) || 9e4;
642
+ const coreBytes = Buffer.byteLength(parts.join("\n"), "utf-8");
643
+ let enrichmentSpent = 0;
644
+ const elidedLabels = [];
645
+ for (const { label, block } of enrichment) {
646
+ const cost = Buffer.byteLength(`
647
+ ${block}`, "utf-8");
648
+ if (coreBytes + enrichmentSpent + cost > contextBudget) {
649
+ elidedLabels.push(label);
650
+ continue;
651
+ }
652
+ parts.push(block);
653
+ enrichmentSpent += cost;
654
+ }
655
+ if (elidedLabels.length > 0) {
656
+ parts.push(
657
+ "### Context Budget \u2014 enrichment sections trimmed",
658
+ "",
659
+ `${elidedLabels.length} non-essential context section(s) were omitted to keep this plan payload under ${Math.round(contextBudget / 1024)} KB \u2014 a mature board otherwise overflows the client's tool-result ceiling and the plan output is spilled to a file. Trimmed (lowest-value first): ${elidedLabels.join(", ")}.`,
660
+ "",
661
+ "These are cross-cycle analytics/enrichment, NOT task-selection inputs \u2014 the Board, Active Decisions, Product Brief, Full Notes, and Recent Build Reports above are complete and untrimmed. Plan normally. If you specifically need one of the trimmed sections, raise `PAPI_PLAN_CONTEXT_BUDGET` in the MCP server env and re-run.",
662
+ ""
663
+ );
633
664
  }
634
665
  }
635
666
  return parts.join("\n");
@@ -1018,6 +1049,19 @@ function buildReviewUserMessage(ctx) {
1018
1049
  } else {
1019
1050
  parts.push("(Showing build reports and cycle log entries since last strategy review.)");
1020
1051
  }
1052
+ if (ctx.earnedPushback) {
1053
+ parts.push(
1054
+ "",
1055
+ "---",
1056
+ "",
1057
+ "## \u26A0\uFE0F EARNED ADVERSARIAL PUSHBACK",
1058
+ "",
1059
+ "This section appears ONLY because concrete signals crossed a threshold this window. Address each item in your review with a clearly-labelled pushback callout: verify the claim against the actual build reports / code / decisions before accepting it, and push back proportionally to the stakes. If verification shows a signal is benign, say so and move on. Do NOT manufacture additional pushback beyond what these signals support.",
1060
+ "",
1061
+ ctx.earnedPushback,
1062
+ ""
1063
+ );
1064
+ }
1021
1065
  parts.push(
1022
1066
  "",
1023
1067
  "---",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@papi-ai/server",
3
- "version": "0.7.67",
3
+ "version": "0.7.70",
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",