@papi-ai/server 0.7.45 → 0.7.47

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.
@@ -1163,6 +1163,10 @@ var init_proxy_adapter = __esm({
1163
1163
  "claimReview",
1164
1164
  "getSiblingAds",
1165
1165
  "getSiblingRepoTasks"
1166
+ // task-2489 (C320): recordProgressStep is now wired to the edge data-proxy
1167
+ // (case handler + ALLOWED_METHODS/WRITE_METHODS entries), so it forwards for
1168
+ // hosted callers and persists a project-scoped cycle_progress_steps row. Removed
1169
+ // from NO_FORWARD (was the task-2484 pg-only gap) — hosted parity restored.
1166
1170
  ]);
1167
1171
  ProxyPapiAdapter = class _ProxyPapiAdapter {
1168
1172
  endpoint;
@@ -1883,27 +1887,14 @@ import { execSync } from "child_process";
1883
1887
  import { readFile, writeFile, access } from "fs/promises";
1884
1888
  import { randomUUID as randomUUID6 } from "crypto";
1885
1889
  import { join } from "path";
1886
-
1887
- // ../shared/dist/index.js
1888
- var VALID_TRANSITIONS = {
1889
- "Backlog": ["In Cycle", "Ready", "In Progress", "Blocked", "Cancelled", "Deferred", "Done"],
1890
- "In Cycle": ["In Progress", "Backlog", "Blocked", "Cancelled"],
1891
- "Ready": ["In Progress", "Backlog", "Blocked", "Cancelled"],
1892
- "In Progress": ["In Review", "Backlog", "Blocked", "Cancelled"],
1893
- "In Review": ["Done", "In Progress", "Blocked", "Cancelled"],
1894
- "Done": [],
1895
- "Blocked": ["Backlog", "Ready", "In Cycle", "In Progress", "Cancelled"],
1896
- "Cancelled": [],
1897
- "Deferred": ["Backlog", "Cancelled"]
1898
- };
1899
- var RETIRED_DECISION_OUTCOMES = ["resolved", "abandoned", "superseded"];
1900
- function isLiveDecision(d) {
1901
- if (d.superseded === true) return false;
1902
- if (d.outcome != null && RETIRED_DECISION_OUTCOMES.includes(d.outcome)) return false;
1903
- return true;
1904
- }
1905
-
1906
- // ../adapter-md/dist/index.js
1890
+ import {
1891
+ VALID_TRANSITIONS as _VALID_TRANSITIONS,
1892
+ isValidTransition as _isValidTransition,
1893
+ validateTransition as _validateTransition,
1894
+ isValidStatus as _isValidStatus,
1895
+ isLiveDecision as _isLiveDecision,
1896
+ RETIRED_DECISION_OUTCOMES as _RETIRED_DECISION_OUTCOMES
1897
+ } from "@papi-ai/shared";
1907
1898
  import { randomUUID } from "crypto";
1908
1899
  import { randomUUID as randomUUID3 } from "crypto";
1909
1900
  import yaml from "js-yaml";
@@ -1912,8 +1903,8 @@ import { randomUUID as randomUUID4 } from "crypto";
1912
1903
  import { randomUUID as randomUUID5 } from "crypto";
1913
1904
  import yaml2 from "js-yaml";
1914
1905
  import yaml3 from "js-yaml";
1915
- var VALID_TRANSITIONS2 = VALID_TRANSITIONS;
1916
- var isLiveDecision2 = isLiveDecision;
1906
+ var VALID_TRANSITIONS = _VALID_TRANSITIONS;
1907
+ var isLiveDecision = _isLiveDecision;
1917
1908
  function extractSection(content, heading) {
1918
1909
  const headingPattern = new RegExp(`^## ${heading}\\s*$`, "m");
1919
1910
  const start = content.search(headingPattern);
@@ -3106,6 +3097,7 @@ function toCycle(raw) {
3106
3097
  };
3107
3098
  if (raw.end_date) cycle.endDate = raw.end_date;
3108
3099
  if (raw.user_id) cycle.userId = raw.user_id;
3100
+ if (raw.dependency_chain) cycle.dependencyChain = raw.dependency_chain;
3109
3101
  return cycle;
3110
3102
  }
3111
3103
  function fromCycle(cycle) {
@@ -3120,6 +3112,7 @@ function fromCycle(cycle) {
3120
3112
  };
3121
3113
  if (cycle.endDate) raw.end_date = cycle.endDate;
3122
3114
  if (cycle.userId) raw.user_id = cycle.userId;
3115
+ if (cycle.dependencyChain) raw.dependency_chain = cycle.dependencyChain;
3123
3116
  return raw;
3124
3117
  }
3125
3118
  function extractYamlBlock2(content) {
@@ -3164,7 +3157,7 @@ function prependCycle(cycle, content) {
3164
3157
  const yamlStr = yaml2.dump({ cycles: [raw] }, { lineWidth: 120, quotingType: '"' });
3165
3158
  return header + YAML_START2 + "\n" + yamlStr + YAML_END2 + "\n";
3166
3159
  }
3167
- const existing = parseCycles(content);
3160
+ const existing = parseCycles(content).filter((c) => c.number !== cycle.number);
3168
3161
  const merged = [cycle, ...existing];
3169
3162
  return serializeCycles(merged, content);
3170
3163
  }
@@ -3261,7 +3254,7 @@ var MdFileAdapter = class {
3261
3254
  if (!content) return [];
3262
3255
  const all = parseActiveDecisions(content);
3263
3256
  if (options?.includeRetired) return all;
3264
- return all.filter(isLiveDecision2);
3257
+ return all.filter(isLiveDecision);
3265
3258
  }
3266
3259
  /** Read cycle log entries (newest first), optionally limited to {@link limit} entries. */
3267
3260
  async getCycleLog(limit) {
@@ -3429,7 +3422,7 @@ var MdFileAdapter = class {
3429
3422
  }
3430
3423
  if (updates.status && updates.status !== tasks[idx].status && !options?.force) {
3431
3424
  const from = tasks[idx].status;
3432
- const allowed = VALID_TRANSITIONS2[from];
3425
+ const allowed = VALID_TRANSITIONS[from];
3433
3426
  if (!allowed.includes(updates.status)) {
3434
3427
  console.warn(`[papi] Warning: invalid status transition "${from}" \u2192 "${updates.status}" for task ${id}. Allowed from "${from}": ${allowed.length > 0 ? allowed.join(", ") : "none"}`);
3435
3428
  }
@@ -4526,31 +4519,66 @@ Check PAPI_PROJECT_ID in your .mcp.json config. Find your project ID in the PAPI
4526
4519
  }
4527
4520
 
4528
4521
  // src/lib/formatters.ts
4529
- var EFFORT_MAP = { XS: 1, S: 2, M: 3, L: 5, XL: 8 };
4530
- function computeSnapshotsFromBuildReports(reports) {
4531
- if (reports.length === 0) return [];
4532
- const byCycleMap = /* @__PURE__ */ new Map();
4522
+ function effortWeight(size) {
4523
+ switch ((size || "").toUpperCase()) {
4524
+ case "XS":
4525
+ return 1;
4526
+ case "S":
4527
+ case "SMALL":
4528
+ return 2;
4529
+ case "M":
4530
+ case "MEDIUM":
4531
+ return 3;
4532
+ case "L":
4533
+ case "LARGE":
4534
+ return 5;
4535
+ case "XL":
4536
+ return 8;
4537
+ default:
4538
+ return 3;
4539
+ }
4540
+ }
4541
+ function computeSnapshotsFromBuildReports(reports, tasks) {
4542
+ const reportsByCycle = /* @__PURE__ */ new Map();
4533
4543
  for (const r of reports) {
4534
- const existing = byCycleMap.get(r.cycle) ?? [];
4544
+ const existing = reportsByCycle.get(r.cycle) ?? [];
4535
4545
  existing.push(r);
4536
- byCycleMap.set(r.cycle, existing);
4546
+ reportsByCycle.set(r.cycle, existing);
4547
+ }
4548
+ const tasksByCycle = /* @__PURE__ */ new Map();
4549
+ for (const t of tasks ?? []) {
4550
+ if (t.cycle == null) continue;
4551
+ const existing = tasksByCycle.get(t.cycle) ?? [];
4552
+ existing.push(t);
4553
+ tasksByCycle.set(t.cycle, existing);
4537
4554
  }
4555
+ const cycleNumbers = /* @__PURE__ */ new Set([...reportsByCycle.keys(), ...tasksByCycle.keys()]);
4556
+ if (cycleNumbers.size === 0) return [];
4538
4557
  const snapshots = [];
4539
- for (const [sn, cycleReports] of byCycleMap) {
4540
- const completed = cycleReports.filter((r) => r.completed === "Yes").length;
4541
- const total = cycleReports.length;
4558
+ for (const sn of cycleNumbers) {
4559
+ const cycleReports = reportsByCycle.get(sn) ?? [];
4560
+ const cycleTaskRows = tasksByCycle.get(sn);
4542
4561
  const withEffort = cycleReports.filter((r) => r.estimatedEffort && r.actualEffort);
4543
4562
  const accurate = withEffort.filter((r) => r.estimatedEffort === r.actualEffort).length;
4544
4563
  const matchRate = withEffort.length > 0 ? Math.round(accurate / withEffort.length * 100) : 0;
4545
- let effortPoints = 0;
4546
- for (const r of cycleReports) {
4547
- effortPoints += EFFORT_MAP[r.actualEffort] ?? 3;
4564
+ let completed;
4565
+ let total;
4566
+ let effortPoints;
4567
+ if (cycleTaskRows && cycleTaskRows.length > 0) {
4568
+ const done = cycleTaskRows.filter((t) => t.status === "Done");
4569
+ completed = done.length;
4570
+ total = cycleTaskRows.length;
4571
+ effortPoints = done.reduce((s, t) => s + effortWeight(t.complexity), 0);
4572
+ } else {
4573
+ completed = cycleReports.filter((r) => r.completed === "Yes").length;
4574
+ total = cycleReports.length;
4575
+ effortPoints = cycleReports.reduce((s, r) => s + effortWeight(r.actualEffort), 0);
4548
4576
  }
4549
4577
  snapshots.push({
4550
4578
  cycle: sn,
4551
4579
  date: (/* @__PURE__ */ new Date()).toISOString(),
4552
- accuracy: [{ cycle: sn, reports: total, matchRate, mae: 0, bias: 0 }],
4553
- velocity: [{ cycle: sn, completed, partial: 0, failed: total - completed, effortPoints }]
4580
+ accuracy: [{ cycle: sn, reports: cycleReports.length, matchRate, mae: 0, bias: 0 }],
4581
+ velocity: [{ cycle: sn, completed, partial: 0, failed: Math.max(0, total - completed), effortPoints }]
4554
4582
  });
4555
4583
  }
4556
4584
  snapshots.sort((a, b) => a.cycle - b.cycle);