@papi-ai/server 0.7.61 → 0.7.62

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.
@@ -88,6 +88,13 @@ Your output is **not done** if ANY of these is true (these are falsifiable — c
88
88
  - [ ] Guidance, state, or a next action explained in a sentence of helper text where a visual cue
89
89
  (position, size, colour, icon, a signpost, motion-on-change) would carry it — prose used as a
90
90
  crutch for missing visual steering.
91
+ - [ ] A label, its value, and its explanation each taking their own line ("The Stacked Caption").
92
+ Anywhere the three exist, they share ONE line.
93
+ - [ ] A new datum added as a sibling row beside a row it could extend ("The Siblinged Row").
94
+ Extend the existing row — inline suffix, extra cell, chip on the same baseline — never stack
95
+ a twin row underneath.
96
+ - [ ] An eyebrow label or an explanatory subtitle above/below a heading ("The Eyebrow Crutch").
97
+ Labels carry themselves; if a heading needs a subtitle to be understood, the heading is wrong.
91
98
  - [ ] More than ~3 sections fully visible above the fold.
92
99
  - [ ] Identical-sized cards in a uniform row (flat hierarchy — needs a dominant 2×+ cell).
93
100
  - [ ] Monospace on labels, status, timestamps, or nav.
@@ -108,6 +108,12 @@ Run through every named anti-pattern and flag matches. Common universal ones:
108
108
  - Guidance, state, or a next action carried by a sentence of helper text where a visual cue
109
109
  (position, size, colour, an icon, a signpost, motion-on-change) would do — prose as a crutch for
110
110
  missing visual steering. Prefer showing over telling.
111
+ - A label, its value, and its explanation each taking their own line ("The Stacked Caption") —
112
+ anywhere the three exist, they share ONE line.
113
+ - A new datum added as a sibling row beside a row it could extend ("The Siblinged Row") — extend
114
+ the existing row (inline suffix, extra cell, chip on the same baseline), never stack a twin row.
115
+ - An eyebrow label or explanatory subtitle above/below a heading ("The Eyebrow Crutch") — labels
116
+ carry themselves; a heading that needs a subtitle to be understood is the wrong heading.
111
117
  - Identical-sized cards in a uniform row (flat hierarchy).
112
118
  - Monospace on labels / status / timestamps / nav.
113
119
  - Header, label, and value at the same size+weight.
package/dist/index.js CHANGED
@@ -5059,7 +5059,7 @@ var init_setup = __esm({
5059
5059
 
5060
5060
  // src/index.ts
5061
5061
  import { readFileSync as readFileSync16 } from "fs";
5062
- import { dirname as dirname6, join as join24 } from "path";
5062
+ import { dirname as dirname6, join as join24, basename as basename2 } from "path";
5063
5063
  import { fileURLToPath as fileURLToPath4 } from "url";
5064
5064
  import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
5065
5065
  import { Server as Server2 } from "@modelcontextprotocol/sdk/server/index.js";
@@ -12765,6 +12765,7 @@ async function preparePlan(adapter2, config2, filters, focus, force, handoffsOnl
12765
12765
  const contextBytes2 = Buffer.byteLength(userMessage2, "utf-8");
12766
12766
  console.error(`[plan-perf] contextBytes=${contextBytes2} (handoffs-only)`);
12767
12767
  const planSystemPrompt2 = await getPrompt("plan-system");
12768
+ await recordPlanGenerationActive(tracker, incomingCycle);
12768
12769
  return {
12769
12770
  mode: "full",
12770
12771
  // apply phase treats it the same
@@ -12825,6 +12826,7 @@ async function preparePlan(adapter2, config2, filters, focus, force, handoffsOnl
12825
12826
  } catch {
12826
12827
  }
12827
12828
  const planSystemPrompt = await getPrompt("plan-system");
12829
+ await recordPlanGenerationActive(tracker, incomingCycle);
12828
12830
  return {
12829
12831
  mode,
12830
12832
  cycleNumber,
@@ -12848,6 +12850,15 @@ async function streamPlanStageSteps(tracker, newCycleNumber) {
12848
12850
  await tracker.recordStep(step);
12849
12851
  }
12850
12852
  }
12853
+ async function recordPlanGenerationActive(tracker, incomingCycleNumber) {
12854
+ if (!tracker) return;
12855
+ await tracker.recordStep("recommendation", {
12856
+ cycle: incomingCycleNumber,
12857
+ stage: "plan",
12858
+ status: "active",
12859
+ metadata: { phase: "generating" }
12860
+ });
12861
+ }
12851
12862
  async function applyPlan(adapter2, config2, rawLlmOutput, mode, cycleNumber, strategyReviewWarning, contextHashes, planRunMeta, tracker) {
12852
12863
  const applyTimer = startTimer();
12853
12864
  console.error(`[plan-perf] applyPlan: start (llm_response=${rawLlmOutput.length} chars)`);
@@ -22436,6 +22447,27 @@ ${entries}`;
22436
22447
  }
22437
22448
  } catch {
22438
22449
  }
22450
+ let openIssuesSection = "";
22451
+ try {
22452
+ if (adapter2.getCycleLearnings) {
22453
+ const issues = (await adapter2.getCycleLearnings({ category: "issue", limit: 20 })).filter((l) => !l.resolvedAt && l.id);
22454
+ const taskIds = new Set([result.task.id, result.task.displayId].filter(Boolean));
22455
+ const moduleTag = result.task.module?.trim().toLowerCase();
22456
+ const score = (l) => (taskIds.has(l.taskId) ? 2 : 0) + (moduleTag && l.tags.some((t) => t.toLowerCase() === moduleTag) ? 1 : 0);
22457
+ const top = issues.sort((a, b2) => score(b2) - score(a)).slice(0, 8);
22458
+ if (top.length > 0) {
22459
+ const rows = top.map((l) => `- \`${l.id}\` \xB7 ${l.severity ?? "P3"} \xB7 ${l.summary}`).join("\n");
22460
+ openIssuesSection = `
22461
+
22462
+ ---
22463
+
22464
+ **OPEN DISCOVERED ISSUES** (${top.length} shown):
22465
+ ${rows}
22466
+ If this build fixes any of these, pass their UUIDs in \`fixed_issues\` on complete \u2014 that stamps them FIXED on the caught\u2192fixed ledger. Do not fix out-of-scope issues just to clear the list.`;
22467
+ }
22468
+ }
22469
+ } catch {
22470
+ }
22439
22471
  const moduleInstructions = getModuleInstructions(result.task.module);
22440
22472
  const moduleContext = await getModuleContext(adapter2, result.task);
22441
22473
  const filesToWriteSection = result.filesToWrite ? formatFilesToWriteSection(result.filesToWrite) : "";
@@ -22444,7 +22476,7 @@ ${entries}`;
22444
22476
  formatModelRecommendation(result.task.buildHandoff?.effort ?? result.task.complexity)
22445
22477
  ) ?? "";
22446
22478
  const gestaltNote = buildGestaltPreBuildDirective(caps) ?? "";
22447
- return textResponse(header + serializeBuildHandoff(result.task.buildHandoff) + modelNote + gestaltNote + adSection + moduleInstructions + moduleContext + dogfoodSection + verificationNote + buildDisciplineNote + chainInstruction + phaseNote + filesToWriteSection);
22479
+ return textResponse(header + serializeBuildHandoff(result.task.buildHandoff) + modelNote + gestaltNote + adSection + moduleInstructions + moduleContext + dogfoodSection + openIssuesSection + verificationNote + buildDisciplineNote + chainInstruction + phaseNote + filesToWriteSection);
22448
22480
  } catch (err) {
22449
22481
  if (isNoHandoffError(err)) {
22450
22482
  const lines = [
@@ -22618,9 +22650,14 @@ async function handleExecuteComplete(adapter2, config2, taskId, args, light = fa
22618
22650
  batchRollupNote = "";
22619
22651
  }
22620
22652
  }
22621
- const fixedNote = fixedResolvedCount > 0 ? `
22653
+ let fixedNote = "";
22654
+ if (fixedResolvedCount > 0) {
22655
+ fixedNote = `
22622
22656
 
22623
- \u2705 Marked ${fixedResolvedCount} discovered issue(s) FIXED \u2014 resolved_at stamped, now counted as fixed on the hub's caught\u2192fixed ledger.` : "";
22657
+ \u2705 Marked ${fixedResolvedCount} discovered issue(s) FIXED \u2014 resolved_at stamped, now counted as fixed on the hub's caught\u2192fixed ledger.`;
22658
+ } else if (discoveredIssues && discoveredIssues.trim() !== "" && !/^none\b/i.test(discoveredIssues.trim())) {
22659
+ fixedNote = "\n\n\u2139\uFE0F This build filed discovered issues but passed no `fixed_issues`. When a future build fixes one, pass its UUID in `fixed_issues` so it counts as FIXED (not just auto-cleared) on the hub ledger.";
22660
+ }
22624
22661
  return textResponse(formatCompleteResult(result) + fixedNote + docsNote + batchRollupNote);
22625
22662
  } catch (err) {
22626
22663
  const message = err instanceof Error ? err.message : String(err);
@@ -23088,7 +23125,11 @@ async function handleBug(adapter2, config2, args) {
23088
23125
  type,
23089
23126
  description: text,
23090
23127
  diagnostics,
23091
- status: "open",
23128
+ // Canonical triage vocabulary (submitted|investigating|fixed|wont_fix).
23129
+ // Was 'open' — a third vocabulary that made the owner triage console
23130
+ // render new upstream reports as un-triaged. Adapters pass status through,
23131
+ // so emitting canonical here keeps hosted + pg writes consistent.
23132
+ status: "submitted",
23092
23133
  notifyRequested,
23093
23134
  contactOk
23094
23135
  });
@@ -30199,4 +30240,10 @@ if (isHttpMode && httpPort !== void 0) {
30199
30240
  }
30200
30241
  const transport = new StdioServerTransport();
30201
30242
  await server.connect(transport);
30243
+ const projectName = basename2(config.projectRoot);
30244
+ const projectIdShort = config.projectId ? ` (${config.projectId.slice(0, 8)})` : process.env.PAPI_PROJECT_ID ? ` (${process.env.PAPI_PROJECT_ID.slice(0, 8)})` : "";
30245
+ process.stderr.write(
30246
+ `[papi] Connected \u2014 project: ${projectName}${projectIdShort}, adapter: ${config.adapterType}, v${pkgVersion}
30247
+ `
30248
+ );
30202
30249
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@papi-ai/server",
3
- "version": "0.7.61",
3
+ "version": "0.7.62",
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",