@papi-ai/server 0.7.0-alpha.1 → 0.7.1-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.
Files changed (2) hide show
  1. package/dist/index.js +43 -11
  2. package/package.json +1 -1
package/dist/index.js CHANGED
@@ -322,7 +322,29 @@ function parseBuildHandoff(markdown) {
322
322
  effort
323
323
  };
324
324
  }
325
- function serializeBuildHandoff(handoff) {
325
+ function ensureArray(value) {
326
+ if (Array.isArray(value)) return value;
327
+ if (typeof value === "string") {
328
+ try {
329
+ const parsed = JSON.parse(value);
330
+ if (Array.isArray(parsed)) return parsed;
331
+ } catch {
332
+ }
333
+ return value.trim() ? [value] : [];
334
+ }
335
+ return [];
336
+ }
337
+ function serializeBuildHandoff(raw) {
338
+ let handoff;
339
+ if (typeof raw === "string") {
340
+ try {
341
+ handoff = JSON.parse(raw);
342
+ } catch {
343
+ return raw;
344
+ }
345
+ } else {
346
+ handoff = raw;
347
+ }
326
348
  const lines = [];
327
349
  lines.push(`BUILD HANDOFF \u2014 ${handoff.taskId}`);
328
350
  if (handoff.uuid) lines.push(`UUID: ${handoff.uuid}`);
@@ -333,39 +355,40 @@ function serializeBuildHandoff(handoff) {
333
355
  lines.push(`Why now: ${handoff.whyNow}`);
334
356
  lines.push("");
335
357
  lines.push("SCOPE (DO THIS)");
336
- for (const item of handoff.scope) {
358
+ for (const item of ensureArray(handoff.scope)) {
337
359
  lines.push(`- ${item}`);
338
360
  }
339
361
  lines.push("");
340
362
  lines.push("SCOPE BOUNDARY (DO NOT DO THIS)");
341
- for (const item of handoff.scopeBoundary) {
363
+ for (const item of ensureArray(handoff.scopeBoundary)) {
342
364
  lines.push(`- ${item}`);
343
365
  }
344
366
  lines.push("");
345
367
  lines.push("ACCEPTANCE CRITERIA");
346
- for (const item of handoff.acceptanceCriteria) {
368
+ for (const item of ensureArray(handoff.acceptanceCriteria)) {
347
369
  lines.push(`[ ] ${item}`);
348
370
  }
349
371
  lines.push("");
350
372
  lines.push("SECURITY CONSIDERATIONS");
351
- lines.push(handoff.securityConsiderations);
352
- if (handoff.verificationFiles && handoff.verificationFiles.length > 0) {
373
+ lines.push(handoff.securityConsiderations ?? "");
374
+ const verificationFiles = ensureArray(handoff.verificationFiles);
375
+ if (verificationFiles.length > 0) {
353
376
  lines.push("");
354
377
  lines.push("PRE-BUILD VERIFICATION");
355
378
  lines.push("Before implementing, read these files and check if the functionality already exists:");
356
- for (const item of handoff.verificationFiles) {
379
+ for (const item of verificationFiles) {
357
380
  lines.push(`- ${item}`);
358
381
  }
359
382
  lines.push('If >80% of the scope is already implemented, call build_execute with completed="yes" and note "already built" in surprises instead of re-implementing.');
360
383
  }
361
384
  lines.push("");
362
385
  lines.push("FILES LIKELY TOUCHED");
363
- for (const item of handoff.filesLikelyTouched) {
386
+ for (const item of ensureArray(handoff.filesLikelyTouched)) {
364
387
  lines.push(`- ${item}`);
365
388
  }
366
389
  lines.push("");
367
390
  lines.push("EFFORT");
368
- lines.push(handoff.effort);
391
+ lines.push(handoff.effort ?? "M");
369
392
  return lines.join("\n");
370
393
  }
371
394
  function toCycleTask(raw) {
@@ -8019,6 +8042,15 @@ __export(proxy_adapter_exports, {
8019
8042
  function snakeToCamel(str) {
8020
8043
  return str.replace(/_([a-z0-9])/g, (_, c) => c.toUpperCase());
8021
8044
  }
8045
+ function parseIfDoubleEncoded(value) {
8046
+ if (typeof value !== "string") return value;
8047
+ try {
8048
+ const parsed = JSON.parse(value);
8049
+ return typeof parsed === "object" ? parsed : value;
8050
+ } catch {
8051
+ return value;
8052
+ }
8053
+ }
8022
8054
  function transformKeys(obj) {
8023
8055
  if (obj === null || obj === void 0) return obj;
8024
8056
  if (Array.isArray(obj)) return obj.map(transformKeys);
@@ -8026,7 +8058,7 @@ function transformKeys(obj) {
8026
8058
  const result = {};
8027
8059
  for (const [key, value] of Object.entries(obj)) {
8028
8060
  const camelKey = snakeToCamel(key);
8029
- result[camelKey] = JSONB_PASSTHROUGH_KEYS.has(camelKey) ? value : transformKeys(value);
8061
+ result[camelKey] = JSONB_PASSTHROUGH_KEYS.has(camelKey) ? parseIfDoubleEncoded(value) : transformKeys(value);
8030
8062
  }
8031
8063
  return result;
8032
8064
  }
@@ -11643,7 +11675,7 @@ ${lines.join("\n")}`;
11643
11675
  t = startTimer();
11644
11676
  const [decisions, reportsSinceCycle, log, tasks, rawMetricsSnapshots, reviews, phases, dogfoodEntries] = await Promise.all([
11645
11677
  adapter2.getActiveDecisions(),
11646
- adapter2.getBuildReportsSince(health.totalCycles),
11678
+ adapter2.getBuildReportsSince(health.totalCycles ?? 0),
11647
11679
  adapter2.getCycleLog(3),
11648
11680
  adapter2.queryBoard({ status: ["Backlog", "In Cycle", "Ready", "In Progress", "In Review", "Blocked"], contextTier: 2 }),
11649
11681
  adapter2.readCycleMetrics(),
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@papi-ai/server",
3
- "version": "0.7.0-alpha.1",
3
+ "version": "0.7.1-alpha.1",
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
  "type": "module",