@papi-ai/server 0.7.52 → 0.7.54

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.
@@ -25,6 +25,7 @@ __export(git_exports, {
25
25
  detectUnrecordedCommits: () => detectUnrecordedCommits,
26
26
  ensureLatestDevelop: () => ensureLatestDevelop,
27
27
  ensureTagAtHead: () => ensureTagAtHead,
28
+ findTaskCommitsOnBase: () => findTaskCommitsOnBase,
28
29
  getBranchDiff: () => getBranchDiff,
29
30
  getCommitsSinceTag: () => getCommitsSinceTag,
30
31
  getCurrentBranch: () => getCurrentBranch,
@@ -718,11 +719,29 @@ function escapeRegexLiteral(s) {
718
719
  return s.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
719
720
  }
720
721
  function detectMergedInProgress(cwd, preferredBase, tasks) {
721
- if (!isGitAvailable() || !isGitRepo(cwd)) return [];
722
722
  const inProgress = tasks.filter((t) => t.status === "In Progress");
723
723
  if (inProgress.length === 0) return [];
724
+ const landed = findTaskCommitsOnBase(cwd, preferredBase, inProgress.map((t) => t.displayId));
725
+ const hits = [];
726
+ for (const task of inProgress) {
727
+ const hit = landed.get(task.displayId);
728
+ if (!hit) continue;
729
+ hits.push({
730
+ displayId: task.displayId,
731
+ title: task.title,
732
+ commit: hit.commit,
733
+ subject: hit.subject,
734
+ pr: hit.pr
735
+ });
736
+ }
737
+ return hits;
738
+ }
739
+ function findTaskCommitsOnBase(cwd, preferredBase, displayIds) {
740
+ const out = /* @__PURE__ */ new Map();
741
+ if (displayIds.length === 0) return out;
742
+ if (!isGitAvailable() || !isGitRepo(cwd)) return out;
724
743
  const base = resolveDefaultBranch(cwd, preferredBase);
725
- if (!branchExists(cwd, base)) return [];
744
+ if (!branchExists(cwd, base)) return out;
726
745
  let raw;
727
746
  try {
728
747
  raw = execFileSync(
@@ -731,28 +750,25 @@ function detectMergedInProgress(cwd, preferredBase, tasks) {
731
750
  { cwd, encoding: "utf-8", stdio: ["ignore", "pipe", "ignore"] }
732
751
  );
733
752
  } catch {
734
- return [];
753
+ return out;
735
754
  }
736
755
  const commits = raw.split("\n").map((line) => {
737
756
  const idx = line.indexOf("");
738
757
  if (idx === -1) return null;
739
758
  return { hash: line.slice(0, idx).trim(), subject: line.slice(idx + 1).trim() };
740
759
  }).filter((c) => c !== null && c.hash !== "");
741
- const hits = [];
742
- for (const task of inProgress) {
743
- const re = new RegExp(`(^|[^\\w-])${escapeRegexLiteral(task.displayId)}([^\\w-]|$)`);
760
+ for (const displayId of displayIds) {
761
+ const re = new RegExp(`(^|[^\\w-])${escapeRegexLiteral(displayId)}([^\\w-]|$)`);
744
762
  const hit = commits.find((c) => re.test(c.subject));
745
763
  if (!hit) continue;
746
764
  const prMatch = hit.subject.match(/#(\d+)/);
747
- hits.push({
748
- displayId: task.displayId,
749
- title: task.title,
765
+ out.set(displayId, {
750
766
  commit: hit.hash,
751
767
  subject: hit.subject,
752
768
  pr: prMatch ? `#${prMatch[1]}` : null
753
769
  });
754
770
  }
755
- return hits;
771
+ return out;
756
772
  }
757
773
  function detectUnrecordedCommits(cwd, baseBranch) {
758
774
  if (!isGitAvailable() || !isGitRepo(cwd)) return [];
@@ -1164,21 +1180,27 @@ var init_proxy_adapter = __esm({
1164
1180
  // getToolCallCount + updatePhaseStatus are ABSENT: they now have edge handlers and
1165
1181
  // are served through the forwarder (getToolCallCount = SUP-2026-026 handler #1).
1166
1182
  "createOwnerAction",
1167
- "findPendingDocActionsForTask",
1168
1183
  "getContributorRole",
1169
- "getDecisionScorePatterns",
1170
- "getModuleEstimationStats",
1171
- "correctLatestBuildReportEffort",
1172
1184
  "recordContributorReleasePr",
1173
1185
  "setContributorReleasePrStatus",
1174
1186
  "listContributorReleasePrs",
1175
- "resolveLearningsForDoneTasks",
1176
- "markCycleLearningResolved",
1177
- "updateStageExitCriteria",
1178
- "updateDocAction",
1179
1187
  "claimReview",
1180
1188
  "getSiblingAds",
1181
1189
  "getSiblingRepoTasks"
1190
+ // task-2394 (C329) — Batch A wired: findPendingDocActionsForTask,
1191
+ // getModuleEstimationStats and getDecisionScorePatterns now have edge case handlers
1192
+ // (each backed by a SECURITY DEFINER RPC, migration 20260714140000) plus
1193
+ // ALLOWED_METHODS entries, so they forward. The two planner-context reads returned
1194
+ // EMPTY for every hosted user before this — the planner ran on worse context than
1195
+ // the owner's on the only install path external users have (AD-72).
1196
+ // task-2412 (C329) — listOwnerActionsForBlockerScan + linkOwnerActionToTask wired.
1197
+ // First USER-scoped ([C]) methods to forward: the edge binds both to the bearer's
1198
+ // user_id and discards the client-supplied one, so the typed-blocker scan (task-2343)
1199
+ // now works for hosted users without exposing one member's owner actions to another.
1200
+ // task-2393 (C329) — Batch B wired: markCycleLearningResolved (the P1 — hosted
1201
+ // discovered_issue_resolve hard-errored), correctLatestBuildReportEffort,
1202
+ // updateStageExitCriteria, updateDocAction, resolveLearningsForDoneTasks all have
1203
+ // edge case handlers + ALLOWED_METHODS/WRITE_METHODS entries now, so they forward.
1182
1204
  // task-2489 (C320): recordProgressStep is now wired to the edge data-proxy
1183
1205
  // (case handler + ALLOWED_METHODS/WRITE_METHODS entries), so it forwards for
1184
1206
  // hosted callers and persists a project-scoped cycle_progress_steps row. Removed
@@ -4535,6 +4557,7 @@ Check PAPI_PROJECT_ID in your .mcp.json config. Find your project ID in the PAPI
4535
4557
  }
4536
4558
 
4537
4559
  // src/lib/formatters.ts
4560
+ var PLAN_FULL_NOTES_BUDGET_BYTES = Number(process.env.PAPI_PLAN_NOTES_BUDGET) || 6e4;
4538
4561
  function effortWeight(size) {
4539
4562
  switch ((size || "").toUpperCase()) {
4540
4563
  case "XS":
@@ -4554,6 +4577,29 @@ function effortWeight(size) {
4554
4577
  return 3;
4555
4578
  }
4556
4579
  }
4580
+ function computeCycleEffort(cycleTaskRows, cycleReports) {
4581
+ if (cycleTaskRows && cycleTaskRows.length > 0) {
4582
+ const done = cycleTaskRows.filter((t) => t.status === "Done");
4583
+ const reportByTask = /* @__PURE__ */ new Map();
4584
+ for (const r of cycleReports) if (r.taskId) reportByTask.set(r.taskId, r);
4585
+ return {
4586
+ completed: done.length,
4587
+ total: cycleTaskRows.length,
4588
+ plannedPoints: done.reduce((s, t) => s + effortWeight(t.complexity), 0),
4589
+ deliveredPoints: done.reduce((s, t) => {
4590
+ const actual = reportByTask.get(t.id)?.actualEffort;
4591
+ return s + effortWeight(actual || t.complexity);
4592
+ }, 0)
4593
+ };
4594
+ }
4595
+ const completed = cycleReports.filter((r) => r.completed === "Yes").length;
4596
+ return {
4597
+ completed,
4598
+ total: cycleReports.length,
4599
+ plannedPoints: cycleReports.reduce((s, r) => s + effortWeight(r.estimatedEffort || r.actualEffort), 0),
4600
+ deliveredPoints: cycleReports.reduce((s, r) => s + effortWeight(r.actualEffort || r.estimatedEffort), 0)
4601
+ };
4602
+ }
4557
4603
  function computeSnapshotsFromBuildReports(reports, tasks) {
4558
4604
  const reportsByCycle = /* @__PURE__ */ new Map();
4559
4605
  for (const r of reports) {
@@ -4577,24 +4623,19 @@ function computeSnapshotsFromBuildReports(reports, tasks) {
4577
4623
  const withEffort = cycleReports.filter((r) => r.estimatedEffort && r.actualEffort);
4578
4624
  const accurate = withEffort.filter((r) => r.estimatedEffort === r.actualEffort).length;
4579
4625
  const matchRate = withEffort.length > 0 ? Math.round(accurate / withEffort.length * 100) : 0;
4580
- let completed;
4581
- let total;
4582
- let effortPoints;
4583
- if (cycleTaskRows && cycleTaskRows.length > 0) {
4584
- const done = cycleTaskRows.filter((t) => t.status === "Done");
4585
- completed = done.length;
4586
- total = cycleTaskRows.length;
4587
- effortPoints = done.reduce((s, t) => s + effortWeight(t.complexity), 0);
4588
- } else {
4589
- completed = cycleReports.filter((r) => r.completed === "Yes").length;
4590
- total = cycleReports.length;
4591
- effortPoints = cycleReports.reduce((s, r) => s + effortWeight(r.actualEffort), 0);
4592
- }
4626
+ const { completed, total, plannedPoints, deliveredPoints } = computeCycleEffort(cycleTaskRows, cycleReports);
4593
4627
  snapshots.push({
4594
4628
  cycle: sn,
4595
4629
  date: (/* @__PURE__ */ new Date()).toISOString(),
4596
4630
  accuracy: [{ cycle: sn, reports: cycleReports.length, matchRate, mae: 0, bias: 0 }],
4597
- velocity: [{ cycle: sn, completed, partial: 0, failed: Math.max(0, total - completed), effortPoints }]
4631
+ velocity: [{
4632
+ cycle: sn,
4633
+ completed,
4634
+ partial: 0,
4635
+ failed: Math.max(0, total - completed),
4636
+ effortPoints: plannedPoints,
4637
+ deliveredPoints
4638
+ }]
4598
4639
  });
4599
4640
  }
4600
4641
  snapshots.sort((a, b) => a.cycle - b.cycle);